文章目录
- 一、概述
- 二、GetRotationMatrix2D
- 三、warpAffine()
一、概述
介绍完图像的缩放和翻转后,接下来将要介绍图像的旋转,但是在OpenCV
4中并没有专门用于图像旋转的函数,而是通过图像的仿射变换实现图像的旋转。实现图像的旋转首先需要确定旋转角度和旋转中心,之后确定旋转矩阵,最终通过仿射变换实现图像旋转。
二、GetRotationMatrix2D
针对这个流程,OpenCV4提供了getRotationMatrix2D()函数用于计算旋转矩阵和warpAffine()函数用于实现图像的仿射变换。首先介绍计算旋转矩阵getRotationMatrix2D()函数,该函数的函数原型在代码清单3-31中给出。
Mat cv::getRotationMatrix2D (Point2f center,double angle,double scale)
- center:图像旋转的中心位置。
- angle:图像旋转的角度,单位为度,正值为逆时针旋转。
- scale:两个轴的比例因子,可以实现旋转过程中的图像缩放,不缩放输入1。
三、warpAffine()
函数进行仿射变换,就可以实现图像的旋转,在代码清单3-32中给出了warpAffine()函数的函数原型。
void cv::warpAffine(InputArray src,
OutputArray dst,
InputArray M,
Size dsize,
int flags = INTER_LINEAR,
int borderMode = BORDER_CONSTANT,
const Scalar& borderValue = Scalar()
)
- src:输入图像。
- dst:仿射变换后输出图像,与src数据类型相同,但是尺寸与dsize相同。
- M:2×3的变换矩阵。
- dsize:输出图像的尺寸。
- flags:插值方法标志,可选参数及含义在表3-3和表3-4中给出。
- borderMode:像素边界外推方法的标志。
- borderValue:填充边界使用的数值,默认情况下为0。
该函数拥有多个参数,但是多数都与前面介绍的图像尺寸变换具有相同的含义。函数中第三个参数为前面求取的图像旋转矩阵,第四个参数是输出图像的尺寸。函数第五个参数是仿射变换插值方法的标志,这里相比于图像尺寸变换多增加了两个类型,可以与其他插值方法一起使用,这两种类型在表3-4中给出。函数第六个参数为像素边界外推方法的标志,其可以的标志和对应的方法在表3-5中给出。第七个参数是外推标志选择BORDER_CONSTANT时的定值,默认情况下为0。
在了解函数每个参数的含义之后,为了更好的理解函数作用,需要介绍一下仿射变换的概念。仿射变换就是图像的旋转、平移和缩放操作的统称,可以表示为线性变换和平移变换的叠加。仿射变换的数学表示是先乘以一个线形变换矩阵再加上一个平移向量,其中线性变换矩阵为2×2的矩阵,平移向量为2×1的向量,至此你可能理解了为什么函数需要输入一个2×3的变换矩阵。假设我们存在一个线性变换矩阵和平移矩阵,两者与输入的矩阵之间的关系如式(3.13)中所示。
根据旋转矩阵和平移矩阵以及图像像素值,仿射变换的数学原理可以用式(3.14)来表示。
- src[]:原图像中的三个像素坐标。
- dst[]:目标图像中的三个像素坐标。
该函数两个输入量都是存放浮点坐标的数组,在生成数组的时候像素点的输入顺序无关,但是需要保证像素点的对应关系,函数的返回值是一个2×3的变换矩阵。
有了前面变换矩阵的求取,就可以利用warpAffine()函数实现矩阵的仿射变换,我们在代码清单3-34的例程中实现了图像的旋转以及图像三点映射的仿射变换,最终结果在图3-23中给出。
#include<iostream>
#include<vector>
#include<string>
#include <opencv2/opencv.hpp>
#include "opencv/highgui.h"
using namespace std;
using namespace cv;
int main(int argc,char** argv) {
cout<<"OpenCv Version: "<<CV_VERSION<<endl;
Mat img=imread("699342568.jpg");
if(img.empty()){
cout<<"请确认输入的图像;路径是否正确"<<endl;
return -1;
}
Mat img_;
resize(img,img_,Size(img.rows/2,img.cols/2));
imshow("src",img_);
Mat rotation0,rotation1,img_warp0,img_warp1;
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);//进行仿射变换
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[0]=Point2f((float)(img_.rows)*0.81,(float)(img_.cols)*0.85);
rotation1=getAffineTransform(src_points,dst_points);//根据对应点求取放射变换矩阵
warpAffine(img_,img_warp1,rotation1,dst_size);//进行放射变换
imshow("img_warp1",img_warp1);
waitKey(0);
return 0;
}