原图
#include <QApplication>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc.hpp>
using namespace cv;
static double PID2 = 3.141592653 * 0.5;
static double param1 = 0.25;
static double param2 = 0.25;
static double param3 = 0.25;
int SIGN(float x) {
if (x < 0)
return -1;
else
return 1;
}
int Eval(int mapping, double x, double y, double *xnew, double *ynew) {
double phi, radius, radius2;
double xtmp, ytmp;
double denom;
/* Some things that may be needed */
radius2 = x * x + y * y;
radius = sqrt(radius2);
phi = atan2(y, x);
switch (mapping) {
case 1:
/*
Square root radial function
Normally clamped to radius <= 1
*/
radius = sqrt(radius);
*xnew = radius * cos(phi);
*ynew = radius * sin(phi);
break;
case 2:
/*
arcsin radial function
*/
if (radius > 1) return (FALSE);
radius = asin(radius) / PID2;
*xnew = radius * cos(phi);
*ynew = radius * sin(phi);
break;
case 3:
/*
sin radial function
Normally clamped to radius <= 1
if (radius > 1)
return(FALSE);
*/
radius = sin(PID2 * radius);
*xnew = radius * cos(phi);
*ynew = radius * sin(phi);
break;
case 4:
/*
radius to a power, radial function
Normally clamped to radius <= 1
if (radius > 1)
return(FALSE);
*/
radius = pow(radius, param1);
*xnew = radius * cos(phi);
*ynew = radius * sin(phi);
break;
case 5:
/*
sin function cartesian function
*/
*xnew = sin(PID2 * x);
*ynew = sin(PID2 * y);
break;
case 6:
/*
square cartesian function
Includes quadrant preserving
*/
*xnew = x * x * SIGN(x);
*ynew = y * y * SIGN(y);
break;
case 7:
/*
arc sine cartesian function
*/
*xnew = asin(x) / PID2;
*ynew = asin(y) / PID2;
break;
case 8:
/*
(1-ar^2) cartesian function
*/
*xnew = x * (1 - param1 * radius2) / (1 - param1);
*ynew = y * (1 - param1 * radius2) / (1 - param1);
break;
case 9:
/*
Method by H. Farid and A.C. Popescu
Used for modest lens with good fit
*/
denom = 1 - param1 * radius2;
xtmp = x / denom;
ytmp = y / denom;
if (xtmp <= -1 || xtmp >= 1 || ytmp <= -1 || ytmp >= 1) return (FALSE);
denom = 1 - param1 * (xtmp * xtmp + ytmp * ytmp);
if (ABS(denom) < 0.000001) return (FALSE);
*xnew = x / denom;
*ynew = y / denom;
break;
case 10:
/*
Logarithmic relationship
eg: fitted to test pattern with 2 parameters
*/
radius = param1 * pow(10.0, param2 * radius) - param1;
*xnew = radius * cos(phi);
*ynew = radius * sin(phi);
break;
case 11:
/*
General third order polynomial
eg: fitted to test pattern with 3 parameters
*/
radius = param1 * radius2 * radius + param2 * radius2 + param3 * radius;
*xnew = radius * cos(phi);
*ynew = radius * sin(phi);
break;
case 12:
/*
Janez Pers, Stanislav Kovacic
Alternative Model o Radial Distortion in Wide-Angle Lenses
Single parameter model
*/
radius = -0.5 * param1 * (exp(-2 * radius / param1) - 1) /
(exp(-radius / param1));
*xnew = radius * cos(phi);
*ynew = radius * sin(phi);
break;
case 13:
/*
Image rotate by parameter1 in radians
*/
*xnew = radius * cos(phi + param1);
*ynew = radius * sin(phi + param1);
break;
case 0:
default:
/*
Unity mapping
*/
*xnew = x;
*ynew = y;
break;
}
return (TRUE);
}
void on_mouse(int event, int x, int y, int flags, void *ustc) {
if (event ==
cv::EVENT_LBUTTONDOWN) //左键按下
{
static int mapping = 1;
cv::Mat mat = *(Mat *)ustc;
int width = mat.cols;
int height = mat.rows;
double scaleX = 1.0;//控制视野
double scaleY = 1.0;//控制视野
int newWidth = width * 2; //放大两倍
int newHeight = height * 2; //放大两倍
Mat des(newHeight, newWidth, mat.type(), cv::Scalar(0, 0, 0));
static int antialias = 1; //简单的抗锯齿,取值1,2,4,8,16......
for (int i = 0; i < newHeight; ++i) {
for (int j = 0; j < newWidth; ++j) {
Vec3i vSum(0, 0, 0);
for (int ai = 0; ai < antialias; ai++) {
//先归一化像素坐标-1~1,x=2*i/width-1,y=2*j/width-1
double nx = 2.0 * (j + ai / (double)antialias) / newWidth - 1;
nx /= scaleX;
for (int aj = 0; aj < antialias; aj++) {
double ny = 2.0 * (i + aj / (double)antialias) / newHeight - 1;
ny /= scaleY;
double newNX, newNY;
//从当前坐标反推原始图像坐标(先归一化的坐标)
Eval(mapping, nx, ny, &newNX, &newNY);
//转换为原始图像坐标
int rx = ((newNX + 1) * width / 2.0);
int ry = ((newNY + 1) * height / 2.0);
if (rx < 0 || rx >= width || ry < 0 || ry >= height) { continue; }
vSum += mat.at<Vec3b>(ry, rx);
}
}
des.at<Vec3b>(i, j) = vSum / (antialias * antialias);
}
}
cv::imshow("des", des);
mapping++;
} else if (event == cv::EVENT_LBUTTONUP) {
}
}
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
cv::Mat mat = cv::imread("test0.bmp");
cv::namedWindow("test");
cv::setMouseCallback("test", on_mouse, &mat); //调用回调函数
cv::imshow("test", mat);
return a.exec();
}
下面图像是用不同的变换函数变换结果:
来源:oschina
链接:https://my.oschina.net/u/221120/blog/4290431