仿射变换和透射变换
来源:互联网 发布:云南师范大学网络平台 编辑:程序博客网 时间:2024/04/30 02:03
仿射变换
定义:仿射变换的功能是从二维坐标到二维坐标之间的线性变换,且保持二维图形的“平直性”和“平行性”。仿射变换可以通过一系列的原子变换的复合来实现,包括平移,缩放,翻转,旋转和剪切。
这类变换可以用一个3*3的矩阵M来表示,其最后一行为(0,0,1)。该变换矩阵将原坐标为(x,y)变换为新坐标(x',y'),
即
OpenCV中相应的函数是:
void warpAffine(InputArray src, OutputArray dst, InputArray M, Size dsize, int flags=INTER_LINEAR, int borderMode=BORDER_CONSTANT, const Scalar& borderValue=Scalar())¶
Parameters:
- src – input image.
- dst – output image that has the size dsize and the same type as src .
- M – transformation matrix,最重要的东东了,本文中着重讲M的构造
- dsize – size of the output image.ansformation ( ).
- borderMode – pixel extrapolation method (see borderInterpolate()); when borderMode=BORDER_TRANSPARENT , it means that the pixels in the destination image corresponding to the “outliers” in the source image are not modified by the function.
- borderValue – value used in case of a constant border; by default, it is 0.
下面介绍一些典型的仿射变换:
(1)平移,将每一点移到到(x+t , y+t),变换矩阵为
(2)缩放变换 将每一点的横坐标放大或缩小sx倍,纵坐标放大(缩小)到sy倍,变换矩阵为
(3)旋转变换原点:目标图形围绕原点顺时针旋转Θ 弧度,变换矩阵为
(4) 旋转变换 :目标图形以(x , y )为轴心顺时针旋转θ弧度,变换矩阵为
相当于两次平移与一次原点旋转变换的复合,即先将轴心(x,y)移到到原点,然后做旋转变换,最后将图片的左上角置为图片的原点,即
有的人可能会说为什么这么复杂呢,那是因为在opencv的图像处理中,所有对图像的处理都是从原点进行的,而图像的原点默认为图像的左上角,而我们对图像作旋转处理时一般以图像的中点为轴心,因此就需要做如下处理
如果你觉得这样很麻烦,可以使用opencv中自带的Mat getRotationMatrix2D(Point2f center, double angle, double scale)函数获得变换矩阵M,
center:旋转中心
angle:旋转弧度,一定要将角度转换成弧度
scale:缩放尺度
它得到的矩阵是:
其中α = scale * cos( angle ) , β = scale * sing( angle ) , ( center.x , center.y ) 表示旋转轴心
但是不得不说opencv的文档以及相关书籍中都把这个矩阵写错了,如下:
建议大家自己通过下式验证一下,即首先将轴心(x,y)移到原点,然后做旋转平绽放变换,最后再将图像的左上角转换为原点
没有去研究该函数的源码,不晓得源码中到底怎么写的,但是在别人的博客中看到这个函数貌似需要修正
opencv中还有一个函数:Mat getAffineTransform(InputArray src, InputArray dst)¶
它通过三组点对就可以获得它们之间的仿射变换,如果我们在一组图像变换中知道变换后的三组点,那么我们就可以利用该函数求得变换矩阵,然后对整张图片进行仿射变换
还有一种与仿射变换经常混淆的变换为透视变换,透视变换需要四组点对才能确定变换矩阵,由于仿射变换保持“平直性”与“平行性”,因此只需要三组点对,而透视变换没有这种约束,故需要四组点对
warpPerspective函数
主要作用:对图像进行透视变换,就是变形
函数的调用形式:
C++: void warpPerspective(InputArray src, OutputArray dst, InputArray M, Size dsize, int flags=INTER_LINEAR, int borderMode=BORDER_CONSTANT, const Scalar& borderValue=Scalar())
参数详解:
InputArray src:输入的图像
OutputArray dst:输出的图像
InputArray M:透视变换的矩阵
Size dsize:输出图像的大小
int flags=INTER_LINEAR:输出图像的插值方法,
combination of interpolation methods (INTER_LINEAR or INTER_NEAREST) and the optional flagWARP_INVERSE_MAP, that sets M as the inverse transformation ( )
int borderMode=BORDER_CONSTANT:图像边界的处理方式
const Scalar& borderValue=Scalar():边界的颜色设置,一般默认是0
函数原理:
透视变换(Perspective Transformation)是将图片投影到一个新的视平面(Viewing Plane),也称作投影映射(Projective Mapping)。通用的变换公式为:
u,v是原始图片左边,对应得到变换后的图片坐标x,y,其中。
变换矩阵可以拆成4部分,表示线性变换,比如scaling,shearing和ratotion。用于平移,产生透视变换。所以可以理解成仿射等是透视变换的特殊形式。经过透视变换之后的图片通常不是平行四边形(除非映射视平面和原来平面平行的情况)。
重写之前的变换公式可以得到:
所以,已知变换对应的几个点就可以求取变换公式。反之,特定的变换公式也能新的变换后的图片。简单的看一个正方形到四边形的变换:
变换的4组对应点可以表示成:
根据变换公式得到:
定义几个辅助变量:
都为0时变换平面与原来是平行的,可以得到:
不为0时,得到:
求解出的变换矩阵就可以将一个正方形变换到四边形。反之,四边形变换到正方形也是一样的。于是,我们通过两次变换:四边形变换到正方形+正方形变换到四边形就可以将任意一个四边形变换到另一个四边形。
opencv代码:
- #include<cv.h>
- #include<highgui.h>
- #pragma comment(lib, "cv.lib")
- #pragma comment(lib, "cxcore.lib")
- #pragma comment(lib, "highgui.lib")
- int main()
- {
- CvPoint2D32f srcTri[4], dstTri[4];
- CvMat* warp_mat = cvCreateMat (3, 3, CV_32FC1);
- IplImage* src = NULL;
- IplImage* dst = NULL;
- src = cvLoadImage ("test.png", 1);
- dst = cvCloneImage (src);
- dst->origin = src->origin;
- cvZero (dst);
- srcTri[0].x = 0;
- srcTri[0].y = 0;
- srcTri[1].x = src->width - 1;
- srcTri[1].y = 0;
- srcTri[2].x = 0;
- srcTri[2].y = src->height - 1;
- srcTri[3].x = src->width - 1;
- srcTri[3].y = src->height - 1;
- dstTri[0].x = src->width * 0.05;
- dstTri[0].y = src->height * 0.33;
- dstTri[1].x = src->width * 0.9;
- dstTri[1].y = src->height * 0.25;
- dstTri[2].x = src->width * 0.2;
- dstTri[2].y = src->height * 0.7;
- dstTri[3].x = src->width * 0.8;
- dstTri[3].y = src->height * 0.9;
- cvGetPerspectiveTransform (srcTri, dstTri, warp_mat);
- cvWarpPerspective (src, dst, warp_mat);
- cvNamedWindow("src", 1);
- cvShowImage("src", src);
- cvNamedWindow ("Affine_Transform", 1);
- cvShowImage ("Affine_Transform", dst);
- cvWaitKey (0);
- cvReleaseImage (&src);
- cvReleaseImage (&dst);
- cvReleaseMat (&warp_mat);
- return 0;
- }
1.仿射变换
仿射变换代表是两幅图像之间的映射关系,可以表达为乘以一个矩阵再加上一个向量的形式;通常使用2×3的矩阵来表示仿射变换。
仿射变换可表达为Y=A×X+B的形式,在效果上等价于将向量X拓展成X’,并且只是将X’左乘T,即:
仿射变换可以表达成以下形式。一个平面内的任意平行四边形ABCD可以被仿射变换映射为另一个平行四边形A’B’C’D’。如果这些平行四边形的面积不等于0,这个隐含的仿射变换就被两个平行四边形唯一定义。可以把仿射变换想象成把一幅图像画到一个胶板上,在胶板的角上任意推拉改变形状得到不同类型的平行四边形。
2.透视变换
仿射变换可以将图像转换为平行四边形,透视变换提供了更大的灵活性,一个透视变换可以将矩形转变为梯形,平行四边形也是梯形,所以仿射变换是透视变换的子集。设透视变换矩阵:
则,透视变换的原图像与目标图像的映射关系为:
- 仿射变换和透射变换
- 仿射变换透射变换单应性矩阵
- 图像处理之重映射、仿射和透射变换
- 基础矩阵、本质矩阵、单应性矩阵、透射变换、仿射变换
- 仿射射变换vs透射变换
- 保距变换和仿射变换
- 仿射变换和透视变换
- 仿射变换和透视变换
- 透视变换和仿射变换
- 仿射变换和射影变换
- OpenCV: 密集透射变换
- 线性变换和仿射变换
- 仿射变换&透视变换
- 几何变换 -- 仿射变换
- opencv学习 密集透射变换
- Opencv——仿射变换和透视变换
- 关于仿射变换和透视变换的终极解释
- 透视变换和仿射变换(下)
- PHP-基础
- mysql 关联查询 修改 ssm mabits
- 【软工学习】第七章——软件工程知识总结
- 任意的进制转换
- JAVA 引入jar包后使用里面API函数的方法
- 仿射变换和透射变换
- git使用详细介绍
- 混淆矩阵之 ROC-AUC曲线、PRC曲线
- Oracle中的日期和字符串互相转换
- leetcode-26. Remove Duplicates from Sorted Array
- Python:Error: Inconsistent indentation detected!解决办法
- java面向对象浅解
- opencv形态学应用之连通域提取
- SSM框架——使用MyBatis Generator自动创建代码