图像的仿射变换是指在空间直角坐标系中将一个二维坐标转换到另外一个二维坐标,仿射变换是一种线性变换,可以表示为线性变换(矩阵相乘)与平移过程。仿射变换主要用来实现平移、缩放、翻转、旋转及剪切等相关集合变换操作。
空间内的原始图像坐标(x,y)经过仿射变换为(x^,y^),在仿射变换中常见的变换如下:
图像仿射变换可以应用在大部分几何变换操作中
使用opencv进行仿射变换时,会先计算出一个仿射变换矩阵,getRotationMatrix2D函数首先将角度转换为了弧度,然后计算旋转矩阵。
Mat getRotationMatrix2D(Point2f center, double angle, double scale)
{
//角度转换
angle *= CV_PI / 180;
//计算旋转矩阵角度
double alpha = cos(angle) * scale;
double beta = sin(angle) * scale;
Mat M(2, 3, CV_64F);
double* m = (double*)M.data;
//构建旋转矩阵
m[0] = alpha;
m[1] = beta;
m[2] = (1 - alpha) * center.x - beta * center.y;
m[3] = -beta;
m[4] = alpha;
m[5] = beta * center.x + (1 - alpha) * center.y;
return M;
}
通过它计算得到二维旋转的仿射变换矩阵后,就可以通过warpAffine函数对源图像进行仿射变换。
应用举例(写下面这段代码的时候不需要把上面的 getRotationMatrix2D函数放进来)
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<iostream>
using namespace std;
using namespace cv;
int main()
{
Mat src = imread("C:\\Users\\32498\\Pictures\\16.png");
if (!src.data)
{
return -1;
}
imshow("src", src);
//①点仿射
int nRows = src.rows;
int nCols = src.cols;
//定义仿射变换的二维点数组
//源图像和目标图像对应映射的三个点
Point2f srcPoint[3];
Point2f resPoint[3];
srcPoint[0] = Point2f(0, 0);
srcPoint[1] = Point2f(nCols - 1, 0);
srcPoint[2] = Point2f(0, nRows - 1);
resPoint[0] = Point2f(nCols * 0, nRows * 0.33);
resPoint[1] = Point2f(nCols * 0.85, nRows * 0.25);
resPoint[2] = Point2f(nCols * 0.15, nRows * 0.7);
//定义仿射变换矩阵2*3
Mat warpMat(Size(2, 3), CV_32F);
Mat result = Mat::zeros(nRows, nCols, src.type());
//计算仿射变换矩阵
warpMat = getAffineTransform(srcPoint, resPoint);
//根据仿射变换矩阵计算图像仿射变换
warpAffine(src, result, warpMat, result.size());
imshow("result", result);
waitKey();
//②角仿射
//设置仿射变换参数
Point2f centerPoint = Point2f(nCols / 2, nRows / 2);
double angle = -50;
double scale = 0.7;
//获取仿射变换矩阵
warpMat = getRotationMatrix2D(centerPoint, angle, scale);
//对源图像进行仿射变换
warpAffine(src, result, warpMat, result.size());
imshow("result", result);
waitKey();
return 0;
}
结果如下:图2是点仿射变换、图3是角仿射变换(但是丢失了一部分信息)