仿射变换(Affine Transformation或Affine Map),又称仿射映射,是指在几何中,一个向量空间进行一次线性变换并接上一个平移,变换为另一个向量空间的过程。它保持了二维图形的“平直性”(直线经过变换之后依然是直线)和“平行性”(二维图形之间的相对位置关系保持不变,平行线依然是平行线,且直线上点的位置顺序不变)。
更多仿射变换的原理可参考:http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/imgproc/imgtrans/warp_affine/warp_affine.html
相关API:
void warpAffine ( InputArray src,OutputArray dst,InputArray M,Size dsize, int flags = INTER_LINEAR,int borderMode = BORDER_CONSTANT,const Scalar & borderValue = Scalar() )
warpAffine()函数的作用是按照下面的公式对图像进行变换:
第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。
第二个参数,OutputArray类型的dst,函数调用后的运算结果存在这里,需和源图片有一样的尺寸和类型。
第三个参数,InputArray类型的M,2×3的变换矩阵。
第四个参数,Size类型的size,表示输出图像的尺寸
第五个参数,int类型的fags,插值方法的标识符。此参数有默认值INTER LⅠNEAR(线性插值),可选的插值方式如表7.1所示。
第六个参数,int类型的borderMode,边界像素模式,默认值为BORDER CONSTANT。
第七个参数,const scalar&类型的border value,在恒定的边界情况下取的值,默认值为Scalar,即0。
Mat getPerspectiveTransform(InputArray src,InputArray dst,int solveMethod = DECOMP_LU )
getPerspectiveTransform()函数通过3点对应关系获得反射变换矩阵 ,返回类型是Mat
InputArray src是源图像
InputArray dst是目标图像
int solveMethod是计算方法,有默认值
Mat getRotationMatrix2D(Point2fcenter, double angle, double scale)
getRotationMatrix2D()函数用于计算二维旋转变换矩阵。变换会将旋转中心映射到它自身。
第一个参数, Point2f类型的 center,表示源图像的旋转中心。
第二个参数, double类型的 angle,旋转角度。角度为正值表示向逆时针旋转(坐标原点是左上角)。
第三个参数, double类型的 scale,缩放系数。此函数计算以下矩阵
代码如下:
#include "stdafx.h"
#include
#include
#include
#include
using namespace cv;
//全局变量
Mat src;
Mat warp_dst;
const char* remaptrackbarname = "remapvalue";
const char* warprotatetrackbarname = "warprotatevalue";
const char* warpscaletrackbarname = "warpscalevalue";
const char* remap_window = "Remap demo";
const char* warprotate_window = "warprotate demo";
const int remapmaxcount = 4, warprotatemaxcount = 360, warpscalemaxcount = 10;
int remapvalue, warprotatevalue = 180, warpscalevalue = 10;
// 函数声明
void remapcontrol(int, void*);
void warprotatecontrol(int, void*);
void warpaffinecontrol();
int main(int argc, char** argv)
{
//读取图像
src = imread("D:\\哀.jpg", 1);
//把原图变小一倍
resize(src, src, Size(0.5*src.cols, 0.5*src.rows));
//创建窗口
namedWindow(remap_window, CV_WINDOW_AUTOSIZE);
namedWindow(warprotate_window, CV_WINDOW_AUTOSIZE);
createTrackbar(remaptrackbarname, remap_window, &remapvalue, remapmaxcount, remapcontrol);
createTrackbar(warprotatetrackbarname, warprotate_window, &warprotatevalue, warprotatemaxcount, warprotatecontrol);
createTrackbar(warpscaletrackbarname, warprotate_window, &warpscalevalue, warpscalemaxcount, warprotatecontrol);
remapcontrol(0, 0);
warpaffinecontrol();
warprotatecontrol(0, 0);
waitKey();
return 0;
}
void remapcontrol(int, void*)
{
Mat dst, map_x, map_y;
dst.create(src.size(), src.type());
map_x.create(src.size(), CV_32FC1);
map_y.create(src.size(), CV_32FC1);
for (int j = 0; j < src.rows; j++)
{
for (int i = 0; i < src.cols; i++)
{
switch (remapvalue)
{
case 0:
map_x.at(j, i) = i;
map_y.at(j, i) = j;
break;
case 1:
if (i > src.cols*0.25 && i < src.cols*0.75 && j > src.rows*0.25 && j < src.rows*0.75)
{
map_x.at(j, i) = 2 * (i - src.cols*0.25) + 0.5;
map_y.at(j, i) = 2 * (j - src.rows*0.25) + 0.5;
}
else
{
map_x.at(j, i) = 0;
map_y.at(j, i) = 0;
}
break;
case 2:
map_x.at(j, i) = i;
map_y.at(j, i) = src.rows - j;
break;
case 3:
map_x.at(j, i) = src.cols - i;
map_y.at(j, i) = j;
break;
case 4:
map_x.at(j, i) = src.cols - i;
map_y.at(j, i) = src.rows - j;
break;
}
}
}
remap(src, dst, map_x, map_y, CV_INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0));
imshow(remap_window, dst);
}
void warprotatecontrol(int, void*)
{
Mat warp_rotate_dst;
Mat rot_mat(2, 3, CV_32FC1);
Point center = Point(warp_dst.cols / 2, warp_dst.rows / 2);
double angle = warprotatevalue - 180;
double scale = double(warpscalevalue) / 10;
printf("%f\n", scale);
// 通过上面的旋转细节信息求得旋转矩阵
rot_mat = getRotationMatrix2D(center, angle, scale);
// 旋转已扭曲图像
warpAffine(warp_dst, warp_rotate_dst, rot_mat, warp_dst.size());
imshow(warprotate_window, warp_rotate_dst);
}
void warpaffinecontrol()
{
Point2f srcTri[3];
Point2f dstTri[3];
Mat warp_mat(2, 3, CV_32FC1);
warp_dst = Mat::zeros(src.rows, src.cols, src.type());
srcTri[0] = Point2f(0, 0);
srcTri[1] = Point2f(src.cols - 1, 0);
srcTri[2] = Point2f(0, src.rows - 1);
dstTri[0] = Point2f(src.cols*0.0, src.rows*0.1);
dstTri[1] = Point2f(src.cols*0.85, src.rows*0.25);
dstTri[2] = Point2f(src.cols*0.15, src.rows*0.7);
warp_mat = getAffineTransform(srcTri, dstTri);
warpAffine(src, warp_dst, warp_mat, warp_dst.size());
};
源图像:
结果图: