一、简述仿射变换 一个任意的仿射变换都能表示为 乘以一个矩阵 (线性变换) 接着再加上一个向量 (平移),变换为另一个向量空间的过程。我们能够用仿射变换来表示翻转、旋转 (线性变换),平移 (向量加),缩放操作 (线性变换)等,其实, 仿射变换代表的是两幅图之间的关系
我们通常使用 2 x 3矩阵来表示仿射变换
文章图片
考虑到我们要使用矩阵 A 和B对二维向量
文章图片
做变换, 所以也能表示为下列形式:
文章图片
文章图片
以上仿射变换看不懂没关系,接着往下看
二、函数原型
1、flip函数
作用:图像翻转(上下翻转、左右翻转,以及同时均可)
c++原型:
文章图片
参数:
- src输入图像
- dst 输出图像(变换后的矩阵)
- flipCode翻转模式,有三种模式如下
文章图片
补充参数flipCode:
- 0 ----- 上下(垂直方向)翻转;
- 1 ----- 左右(水平方向)翻转;
- -1----- 水平、垂直方向同时翻转(即先沿X轴翻转,再沿Y轴翻转,等价于旋转180°)
利用opencv实现仿射变换一般会涉及到warpAffine和getRotationMatrix2D两个函数,其中warpAffine可以实现一些简单的重映射,而利用getRotationMatrix2D可以旋转图像(获得旋转矩阵)2、warpAffine函数
作用:对图像进行旋转 ,平移 ,缩放操作3、getRotationMatrix2D函数
c++原型:
文章图片
参数:
补充参数M:
- src:输入图像
- dst:输出图像(变换后的矩阵),尺寸由dsize指定,图像类型与输入图像一致
- M: 2X3的变换矩阵
- dsize: 指定图像输出尺寸(可选择跟原图一样或不一样)
- flags: 插值方式,默认为INTER_LINEAR线性插值,如果插值算法为WARP_INVERSE_MAP, warpAffine函数使用下图中方式进行图像转换
- borderMode: 边界像素模式,默认为BORDER_CONSTANT
- borderValue: 边界取值,默认为Scalar()即0,为黑色
2X3的矩阵的第三列是矩阵平移的时候原来中心点在(0,0),现在你平移到哪边去,要通过这两个参数来声明,如图M13 和M23
文章图片
文章图片
作用:获取旋转矩阵三、实现效果 1、flip函数实现翻转
c++原型:
文章图片
参数:
- center: Point2f类型,原图像的旋转中心
- angle: double类型,图像旋转角度,角度为正则表示顺时针旋转,角度为负表示逆时针旋转(坐标原点是图像左上角)
- scale: 缩放系数,为0.5表示我们缩小一半,不需要就1.0
原图
文章图片
三种翻转后的效果,翻转模式分别对应 0 1 2
2、warpAffine实现仿射变换
2.1背景默认为黑色
文章图片
2.2更换背景
文章图片
文章图片
2.3基于旋转测算出旋转后真正的大小
文章图片
四、代码 1、flip函数实现翻转
void test1::flip_demo(Mat &image)
{
Mat dst;
flip(image,dst,0);
//左右
imshow("flipCode0 to image",dst);
flip(image,dst,1);
//上下
imshow("flipCode1 to image",dst);
flip(image,dst,-1);
//180度旋转
imshow("flipCode-1 to image",dst);
}
2、warpAffine实现仿射变换
void test1::rotate_demo(Mat &image)
{
Mat dst,M;
int w = image.cols;
int h = image.rows;
M = getRotationMatrix2D(Point2f(w/2,h/2),45,1.0);
//第一个参数为旋转中心
double cos = abs(M.at(0,0));
//0,0为矩阵中的cos
double sin = abs(M.at(0,1));
//0,1为矩阵中的sin
//计算旋转后新的宽高
int nw = cos * w + sin * h;
int nh = sin * w + cos * h;
//M.at(0, 2) 为M矩阵第一行最后一列的值,即新的宽度减去原来的宽度的差值
M.at(0, 2) += (nw / 2 - w / 2);
//计算M矩阵第二行最后一列的值
M.at(1, 2) += (nh / 2 - h / 2);
//参数1原来图像的中心位置。参数2角度是多少。参数3是图像本身大小的放大缩小
//warpAffine(image,dst,M,image.size(),INTER_LINEAR,0,Scalar(147,112,219));
//203,192,255
//新的图像:测算出旋转后真正的大小
warpAffine(image,dst,M,Size(nw,nh),INTER_LINEAR,0,Scalar(147,112,219));
imshow("rotate_image",dst);
}
注:
1、要保证求出来的cos、sin是正数,用abs()求绝对值即可
2、基于旋转测算出旋转后真正的大小,利用下图可以得出
int nw = cos * w + sin * h;
int nh = sin * w + cos * h;
文章图片
文章图片
3、代码中M.at(0, 2) += (nw / 2 - w / 2);
其中M.at(0, 2) 为M矩阵第一行最后一列的值,即新的宽度减去原来的宽度的差值
原创不易,转载请注明出处:
【Qt实战|Qt+OpenCV联合开发(二十一)--图像翻转与旋转】Qt+OpenCV联合开发(二十一)--图像翻转与旋转
推荐阅读
- c/c++|有感 Visual Studio 2015 RTM 简介 - 八年后回归 Dot Net,终于迎来了 Mvc 时代,盼走了 Web 窗体时代...
- C/C++|C/C++ basis 02
- Qt实战|Qt+OpenCV联合开发(十四)--图像感兴趣区域(ROI)的提取
- Qt实战|Qt+OpenCV联合开发(十三)--通道分离与合并
- opencv|Qt+OpenCV联合开发(十六)--图像几何形状绘制
- Qt实战|Qt+OpenCV联合开发(十七)--随机数与随机颜色
- SNAT的MASQUERADE地址选择与端口选择
- IPTABLES的连接跟踪与NAT分析
- IPVS分析