OpenCV—仿射变换warpAffine--旋转和缩放
2017-10-22 21:17
489 查看
首先用一个图来演示仿射变换:
来自维基百科:https://zh.wikipedia.org/wiki/%E4%BB%BF%E5%B0%84%E5%8F%98%E6%8D%A2
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/05/1351dd9bfc4dcf06892da03ffeddb9c6)
本文介绍仿射变换的两个应用:
旋转和缩放。
仿射变换的API函数如下:
几点补充:
1、旋转变换的原理:原图像素坐标乘以旋转矩阵。
旋转矩阵通过如下API获得:
该函数返回值为一个2×3的矩阵,其中矩阵前两列代表旋转,最后一列代表平移;
旋转矩阵的求解过程可参见博文:http://blog.csdn.net/csxiaoshui/article/details/65446125
2、由于图像旋转之后,部分数据就会超出原来图像的位置,出现截断,如下所示。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/05/8792c0004b5f2eb29c79340c55a0401b)
为了避免上面的问题,引入类RotatedRect,采用如下的构造函数:
下面的示例代码来自opencv官方示例代码:https://github.com/opencv/opencv/blob/master/samples/cpp/tutorial_code/ImgTrans/Geometric_Transforms_Demo.cpp
做了适当修改和注释如下:
运行结果如下:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/05/a436fda5dec112d43bbb8492f6339cbc)
另外还有两个函数,分别为:
getAffineTransform():计算3个二维点对之间的仿射变换矩阵H(2行x3列),自由度为6.
详细参数参见官方文档:https://docs.opencv.org/2.4.9/modules/imgproc/doc/geometric_transformations.html#getaffinetransform
estimateRigidTransform():计算多个二维点对或者图像之间的最优仿射变换矩阵 (2行x3列),H可以是部分自由度,比如各向一致的切变。
详细参数参见官方文档:https://docs.opencv.org/2.4.9/modules/video/doc/motion_analysis_and_object_tracking.html#estimaterigidtransform
已知两张旋转了一定角度的图片,通过上面的两个函数便可求解出旋转矩阵。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201909/05/dd542d149458dbee39b20f5fb64e2895)
源代码如下所示:
变换结果如下图所示:
来自维基百科:https://zh.wikipedia.org/wiki/%E4%BB%BF%E5%B0%84%E5%8F%98%E6%8D%A2
本文介绍仿射变换的两个应用:
旋转和缩放。
仿射变换的API函数如下:
void warpAffine(InputArray src, OutputArray dst, InputArray M, Size dsize, int flags=INTER_LINEAR, int borderMode=BORDER_CONSTANT, const Scalar& borderValue=Scalar())参数含义参见官方手册:https://docs.opencv.org/2.4.9/modules/imgproc/doc/geometric_transformations.html#warpaffine
几点补充:
1、旋转变换的原理:原图像素坐标乘以旋转矩阵。
旋转矩阵通过如下API获得:
Mat getRotationMatrix2D(Point2f center, double angle, double scale)参数含义参见官方手册:https://docs.opencv.org/2.4.9/modules/imgproc/doc/geometric_transformations.html#getrotationmatrix2d
该函数返回值为一个2×3的矩阵,其中矩阵前两列代表旋转,最后一列代表平移;
旋转矩阵的求解过程可参见博文:http://blog.csdn.net/csxiaoshui/article/details/65446125
2、由于图像旋转之后,部分数据就会超出原来图像的位置,出现截断,如下所示。
为了避免上面的问题,引入类RotatedRect,采用如下的构造函数:
RotatedRect(const Point2f& center, const Size2f& size, float angle)使用成员函数boundingRect()返回包含此旋转举行的最小up-right矩形。
下面的示例代码来自opencv官方示例代码:https://github.com/opencv/opencv/blob/master/samples/cpp/tutorial_code/ImgTrans/Geometric_Transforms_Demo.cpp
做了适当修改和注释如下:
#include "opencv2/opencv.hpp" #include <iostream> using namespace cv; using namespace std; /// 全局变量 const char* source_window = "Source image";; const char* rotate_window = "Rotate+Resize"; /** * @主函数 */ int main( ) { Mat rot_mat( 2, 3, CV_32FC1 ); Mat src, rotate_dst; /// 载入图像 src = imread("lena.bmp", IMREAD_COLOR ); /** 图像旋转 */ /// 计算关于图像中心的旋转矩阵 Point center = Point( src.cols/2, src.rows/2 ); double angle = 35.0; //旋转的同时也可以放缩 double scale = 0.8; /// 根据以上参数得到旋转矩阵 rot_mat = getRotationMatrix2D( center, angle, scale ); cout<<"旋转矩阵为:\n"<<rot_mat; //计算旋转后的画布大小,并将旋转中心平移到新的旋转中心 Rect bbox = RotatedRect(center, Size(src.cols*scale, src.rows*scale), angle).boundingRect(); rot_mat.at<double>(0, 2) += bbox.width / 2.0 - center.x; rot_mat.at<double>(1, 2) += bbox.height / 2.0 - center.y; /// 旋转图像 warpAffine( src, rotate_dst, rot_mat, bbox.size()); /// 显示原图和旋转结果 namedWindow( source_window, WINDOW_AUTOSIZE ); imshow( source_window, src ); namedWindow( rotate_window, WINDOW_AUTOSIZE ); imshow( rotate_window, rotate_dst ); /// 等待,知道用户退出 waitKey(0); return 0; }
运行结果如下:
另外还有两个函数,分别为:
getAffineTransform():计算3个二维点对之间的仿射变换矩阵H(2行x3列),自由度为6.
详细参数参见官方文档:https://docs.opencv.org/2.4.9/modules/imgproc/doc/geometric_transformations.html#getaffinetransform
estimateRigidTransform():计算多个二维点对或者图像之间的最优仿射变换矩阵 (2行x3列),H可以是部分自由度,比如各向一致的切变。
详细参数参见官方文档:https://docs.opencv.org/2.4.9/modules/video/doc/motion_analysis_and_object_tracking.html#estimaterigidtransform
已知两张旋转了一定角度的图片,通过上面的两个函数便可求解出旋转矩阵。
源代码如下所示:
#include "opencv2/opencv.hpp" #include <iostream> using namespace cv; using namespace std; /// 全局变量 const char* source_window = "Source image";; const char* warp_window = "warp"; /** * @主函数 */ int main( ) { Point2f srcTri[3]; Point2f dstTri[3]; vector<Point2f> srcTri7; vector<Point2f> dstTri7; Mat warp_mat( 2, 3, CV_32FC1 ); Mat src, warp_dst, warp_rotate_dst; /// Load the image src = imread( "1.jpg", IMREAD_COLOR ); /// Set the dst image the same type and size as src warp_dst = Mat::zeros( src.rows, src.cols, src.type() ); /// 设置三组点,求出变换矩阵 srcTri[0] = Point2f( 300,481 ); srcTri[1] = Point2f( 387,440 ); srcTri[2] = Point2f( 293,284 ); dstTri[0] = Point2f( 98,61 ); dstTri[1] = Point2f( 70,140 ); dstTri[2] = Point2f( 253,172 ); //相关的7个点,采用拟合的方法求出变换矩阵 srcTri7.push_back(Point2f( 300,481 )); srcTri7.push_back(Point2f( 387,440 )); srcTri7.push_back(Point2f( 293,284 )); srcTri7.push_back(Point2f( 497,286 )); srcTri7.push_back(Point2f( 369,123 )); srcTri7.push_back(Point2f( 383,35 )); srcTri7.push_back(Point2f( 51,136 )); dstTri7.push_back(Point2f( 98,61 )); dstTri7.push_back(Point2f( 70,140 )); dstTri7.push_back(Point2f( 253,172 )); dstTri7.push_back(Point2f( 120,310 )); dstTri7.push_back(Point2f( 326,329)); dstTri7.push_back(Point2f( 382,397)); dstTri7.push_back(Point2f( 511,92)); //计算3个二维点对之间的仿射变换矩阵(2行x3列) warp_mat = getAffineTransform( srcTri, dstTri ); //计算多个二维点对或者图像之间的最优仿射变换矩阵(2行x3列) //warp_mat = estimateRigidTransform(srcTri7,dstTri7,true); //扩大显示区域,以免显示不下 Rect bbox = RotatedRect(Point(src.cols/2,src.rows/2), Size(src. 4000 cols*1.2, src.rows*1.2), 45).boundingRect(); warp_mat.at<double>(0, 2) += bbox.width / 2.0 - src.cols/2; warp_mat.at<double>(1, 2) += bbox.height / 2.0 - src.rows/2; ///应用仿射变换,可以恢复出原图 warpAffine( src, warp_dst, warp_mat, bbox.size() ); //显示结果 namedWindow( source_window, WINDOW_AUTOSIZE ); imshow( source_window, src ); namedWindow( warp_window, WINDOW_AUTOSIZE ); imshow( warp_window, warp_dst ); /// 等待,知道用户退出 waitKey(0); return 0; }
变换结果如下图所示:
相关文章推荐
- OpenCV2.4.13中warpAffine函数理解,旋转,仿射变换,缩放,保持完整图片
- Python-OpenCv之图像基本处理-平移,缩放,旋转,翻转,裁剪及仿射变换
- opencv 图像仿射变换 计算仿射变换后对应特征点的新坐标 图像旋转、缩放、平移
- OpenCV之仿射变换:平移、缩放、旋转
- opencv 图像仿射变换 计算仿射变换后对应特征点的新坐标 图像旋转、缩放、平移
- 【OpenCV】仿射变换:坐标计算 旋转 缩放
- opencv 图像仿射变换 计算仿射变换后对应特征点的新坐标 图像旋转、缩放、平移
- 图像变换 - 图像拉伸、收缩、扭曲、旋转[1] - 仿射变换(cvWarpAffine)
- opencv学习(三十五)之仿射变换warpAffine
- OpenCV 图片旋转,缩放
- 第六章 - 图像变换 - 图像拉伸、收缩、扭曲、旋转[1] - 仿射变换(cvWarpAffine)
- 【OpenCV3图像处理】图像简单几何变换:旋转、平移、缩放
- 【OpenCV】图像几何变换:旋转,缩放,斜切
- 第六章 - 图像变换 - 图像拉伸、收缩、扭曲、旋转[1] - 仿射变换(cvWarpAffine)
- 小强学Python+OpenCV之-1.4.1平移、旋转、缩放、翻转-之实践
- OpenCV-图像旋转及仿射变换实现
- OPENCV 中的图像旋转与缩放
- OPENCV 中的图像旋转与缩放
- 图像处理中的旋转、平移、缩放——仿射变换的原理和优化
- OpenCV学习之图像的旋转与缩放