如果知道原始图像中的三个点和变换后三个点的对应关系,那么就知道了唯一的仿射变换关系,使得原图像变化到变换后的图像,也就是说图像中三个点时一一对应的,通过三个点就知道对应关系,因此被称为三点变换。
如图仿射变换矩阵中有散列三列数据,前两列矩阵a表示我要旋转部分,第三列矩阵b可以称其为平移部分,通过三个点可以唯一确定一个m,这个m就是我们的仿射变换矩阵,通过这个变换矩阵和我们原图像中的像素位置,进行运算,就可以得到变换后的像素所在位置,从而进行图像的仿射变换。
仿射变换相关函数
warpAffine()
void cv::warpAffine(InputArray src,
OutputArray dst,
InputArray M,
Size dsize,
int flags = INTER_LINEAR,
bordeMode =
int BORDER_CONSTANT,
const Scalar & borderValue = Scalar()
)
·src:输入图像
·dst:仿射变换后输出图像,与src数据类型相同,但是尺寸与dsize相同
·M:2x3的变换矩阵
·dsize:输出图像的尺寸
·flags:插值方法标志
·dorderMode:像素边界外推方法的标志
·borderValue:填充边界使用的数值,默认情况下为0
边界填充方法和对应标志
我们最常用的时特定值的方式进行填充,往往我们并不关心这些填充的数据,它只是给我们的运算以及显示提供了一些帮助,它不含有真正的图像中的信息,因此我们采用最简单的方式即可,它的好处是0是黑色的,它既不影响图像中颜色信息,纹理信息等其它信息的表达,同时它又相对比较简单。
图像旋转
计算放射变换矩阵 = getRotationMatrix2D()
void cv::getRotationMatrix2D(Point2f center,
double angle,
double scale
)
·center:图像旋转的中心位置
·angle:图像旋转的角度,单位为度,正值为逆时针旋转
·scale:两个轴的比例因子,可以实现旋转过程中的图像缩放,不缩放输入1.
计算仿射变换矩阵
getAffine Transform()
Mat cv::getAffineTransform(const Point2f src[],
const Point2f dst[]
)
·src[]:原图像中的三个像素坐标。
·dst():目标图像中的三个像素坐标。
示例
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv; //opencv的命名空间
using namespace std;
int main()
{
Mat img = imread("E:/opencv/opencv-4.6.0-vc14_vc15/opencv/lenac.png");
if (img.empty())
{
cout << "请确认图像文件名称是否正确" << endl;
return -1;
}
Mat rotation0, img_warp0;
double angle = 30; //设置图像旋转的角度
Size dst_size(img.rows, img.cols);//设置输出图像尺寸
Point2f center(img.rows / 2.0, img.cols / 2.0); //设置图像的旋转中心
rotation0 = getRotationMatrix2D(center, angle, 1); //计算仿射变换矩阵
warpAffine(img, img_warp0, rotation0, dst_size, 1); //进行仿射变换
imshow("img_warp0", img_warp0);
//三点法计算仿射变换的仿射变换矩阵
Point2f src_points[3];
Point2f dst_points[3];
src_points[0] = Point2f(0, 0);//原始图像三中的三个点(选取的是三个顶点)
src_points[1] = Point2f(0, (float)(img.cols - 1));
src_points[2] = Point2f((float)(img.rows - 1),(float)(img.cols - 1));
dst_points[0] = Point2f((float)(img.rows)*0.11, (float)(img.cols)*0.20); //仿射变换后图像中的三个点
dst_points[1] = Point2f((float)(img.rows)*0.15, (float)(img.cols) * 0.70);
dst_points[2] = Point2f((float)(img.rows)*0.81, (float)(img.cols) * 0.85);
Mat rotation1, img_warp1;
rotation1 = getAffineTransform(src_points, dst_points); //根据对应点求取仿射变换矩阵
warpAffine(img, img_warp1, rotation1, dst_size); //进行仿射变换
imshow("img_warp1", img_warp1);
waitKey(0);
return 0;
}
结果: