关于OPencv里仿射变化和透射变换的理解和理论

来源:互联网 发布:蜂巢网络与无人机战争 编辑:程序博客网 时间:2024/05/22 02:25

1、仿射变换是透射变换的一个特例。其仿射变换是线性的,其需要的是2*3的矩阵和三个控点。透视变换是非线性的,

其需要的是3*3的矩阵和四个控点,具体的可以opencv2书里的,后面附带透射变换和仿射变换的程序



当我们绕着图像原点进行图像旋转时,其旋转矩阵M是: 




此变换如果在sin和cos前面加个系数,则是进行旋转和缩放。


如果要进行绕图像任意位置的旋转,则需计其:M=[
α β
βα(1α)centerxβcenteryβcenterx+(1α)centery
]   其中a的scale*cos(angle),


b为scale*sin(angle),这个是具有缩放因子的,把scale置1则是无缩放的,(记住其不是先绕原点旋转,

然后再平移的),这个矩阵可以

由OPencv提供的函数 getRotationMatrix2D获得。应用例子为


2、透视变换跟仿射变换不同,其需要的是3*3的矩阵,其例子如下:

透视变换(Perspective Transformation)是将图片投影到一个新的视平面(Viewing Plane),也称作投影映射(Projective Mapping)。通用的变换公式为:


u,v是原始图片左边,对应得到变换后的图片坐标x,y,其中。则原始图像点转换到目标图像时的

坐标如下:


#include "opencv2/highgui/highgui.hpp"#include "opencv2/imgproc/imgproc.hpp"#include <iostream>#include <stdio.h>using namespace cv;using namespace std;/// 全局变量char* source_window = "Source image";char* warp_window = "Warp";char* warp_rotate_window = "Warp + Rotate";/** @function main */ int main( int argc, char** argv ) {   Point2f srcTri[3];   Point2f dstTri[3];   Mat rot_mat( 2, 3, CV_32FC1 );   Mat warp_mat( 2, 3, CV_32FC1 );   Mat src, warp_dst, warp_rotate_dst;   /// 加载源图像   src = imread( argv[1], 1 );   /// 设置目标图像的大小和类型与源图像一致   warp_dst = Mat::zeros( src.rows, src.cols, src.type() );   /// 设置源图像和目标图像上的三组点以计算仿射变换   srcTri[0] = Point2f( 0,0 );   srcTri[1] = Point2f( src.cols - 1, 0 );   srcTri[2] = Point2f( 0, src.rows - 1 );   dstTri[0] = Point2f( src.cols*0.0, src.rows*0.33 );   dstTri[1] = Point2f( src.cols*0.85, src.rows*0.25 );   dstTri[2] = Point2f( src.cols*0.15, src.rows*0.7 );/*这里的getAffineTransform函数获得的是包含了这两个三角形之间的缩放平移和旋转关系,这里跟在稳像时用
<span style="line-height: 24px; text-align: center; font-family: Arial, Helvetica, sans-serif;"><span style="font-size:12px;">estimateRigidTransform获取三个最稳定的角点,然后计算其仿射变换矩阵,其实可以利用这个函数来获取,但是其利用随机抽样一致性算法计算得到的点</span></span>
<span style="line-height: 24px; text-align: center; font-family: Arial, Helvetica, sans-serif;"><span style="font-size: 17.5px;">可能大于三个,所以不能使用getaffinetransform获取,要使用<span style="font-family: dashicons, 'Segoe UI', 'WenQuanYi Micro Hei', 'WenQuanYi Micro Hei Mono', 'Microsoft Yahei', 'Microsoft Yahei Mono', 微软雅黑, sans-serif; font-size: 20px; line-height: 30px;"> </span></span></span><h1 style="margin: 0px; padding: 0px; font-family: dashicons, 'Segoe UI', 'WenQuanYi Micro Hei', 'WenQuanYi Micro Hei Mono', 'Microsoft Yahei', 'Microsoft Yahei Mono', 微软雅黑, sans-serif; display: inline; font-weight: normal; font-stretch: normal; font-size: 20px; line-height: 30px; vertical-align: middle;"><span class="link_title" style="margin: 0px; padding: 0px;"><a target=_blank href="http://blog.csdn.net/xdfyoga1/article/details/44263271" style="color: rgb(0, 0, 0); text-decoration: none; margin: 0px; padding: 0px;">icvGetRTMatrix</a>函数来获取变换矩阵,如果已知角度和旋转点则使用getrotationMatrix2D函数来获取矩阵</span></h1>*/
<span style="font-family: Arial, Helvetica, sans-serif; text-align: center;"> warp_mat = getAffineTransform( srcTri, dstTri );</span>
   /// 对源图像应用上面求得的仿射变换   warpAffine( src, warp_dst, warp_mat, warp_dst.size() );   /** 对图像扭曲后再旋转 */   /// 计算绕图像中点顺时针旋转50度缩放因子为0.6的旋转矩阵   Point center = Point( warp_dst.cols/2, warp_dst.rows/2 );   double angle = -50.0;   double scale = 0.6;   /// 通过上面的旋转细节信息求得旋转矩阵   rot_mat = getRotationMatrix2D( center, angle, scale );   /// 旋转已扭曲图像   warpAffine( warp_dst, warp_rotate_dst, rot_mat, warp_dst.size() );   /// 显示结果   namedWindow( source_window, CV_WINDOW_AUTOSIZE );   imshow( source_window, src );   <strong>namedWindow( warp_window, CV_WINDOW_AUTOSIZE );</strong>   imshow( warp_window, warp_dst );   namedWindow( warp_rotate_window, CV_WINDOW_AUTOSIZE );   imshow( warp_rotate_window, warp_rotate_dst );   /// 等待用户按任意按键退出程序   waitKey(0);   return 0;  }



两种变换的程序:

// 透射变换.cpp : Defines the entry point for the console application.//#include "stdafx.h"//透视变换  #include <cv.h>  #include  <highgui.h>  #include <math.h>  int main(int argc, char** argv){CvPoint2D32f srcQuad[4], dstQuad[4];CvMat* warp_matrix = cvCreateMat(3, 3, CV_32FC1);IplImage *src, *dst;src = cvLoadImage("lena.jpg", 1);if (!src)return -1;cvNamedWindow("Perspective_warp", 1);int pressKey;int df1(1), df2(1), df3(1), df4(1), df5(1), df6(1), df7(1), df8(1);//定义四个控点df1 = 5; df2 = 33; df3 = 90; df4 = 25; df5 = 20; df6 = 70; df7 = 80; df8 = 90;dst = cvCloneImage(src);dst->origin = src->origin;cvZero(dst);//这个是定义原先的四个点srcQuad[0].x = 0;srcQuad[0].y = 0;srcQuad[1].x = src->width - 1;srcQuad[1].y = 0;srcQuad[2].x = 0;srcQuad[2].y = src->height - 1;srcQuad[3].x = src->width - 1;srcQuad[3].y = src->height - 1;float delta = 0.01;while (1){ //定义变换后的四个点,目的是通过这八个点来求出其3*3的透视变换矩阵dstQuad[0].x = src->width*delta*abs(df1 % 101);dstQuad[0].y = src->height*delta*abs(df2 % 101);dstQuad[1].x = src->width*delta*abs(df3 % 101);dstQuad[1].y = src->height*delta*abs(df4 % 101);dstQuad[2].x = src->width*delta*abs(df5 % 101);dstQuad[2].y = src->height*delta*abs(df6 % 101);dstQuad[3].x = src->width*delta*abs(df7 % 101);dstQuad[3].y = src->height*delta*abs(df8 % 101);//这是透射变换的函数,其与仿射变换的函数不同 cvGetPerspectiveTransform(srcQuad, dstQuad, warp_matrix);cvWarpPerspective(src, dst, warp_matrix);//--------------------------字符显示-----------------------------------------  CvFont font = cvFont(1, 1);char buf[8];char dspStr1[32] = { '/0' };  //  char dspStr2[32] = { '/0' };  //  char dspStr3[32] = { '/0' };  //  memset(buf, '/0', sizeof(buf));strcat(dspStr1, "|");strcat(dspStr1, itoa(abs(df6 % 101), buf, 10));strcat(dspStr1, ",");strcat(dspStr1, itoa(abs(df7 % 101), buf, 10));strcat(dspStr1, ",");strcat(dspStr1, itoa(abs(df8 % 101), buf, 10));strcat(dspStr1, "|");strcat(dspStr2, "|");strcat(dspStr2, itoa(abs(df4 % 101), buf, 10));strcat(dspStr2, ",00,");strcat(dspStr2, itoa(abs(df5 % 101), buf, 10));strcat(dspStr2, "|"); strcat(dspStr3, "|");strcat(dspStr3, itoa(abs(df1 % 101), buf, 10));strcat(dspStr3, ",");strcat(dspStr3, itoa(abs(df2 % 101), buf, 10));strcat(dspStr3, ",");strcat(dspStr3, itoa(abs(df3 % 101), buf, 10));strcat(dspStr3, "|");cvPutText(dst, dspStr1, cvPoint(dst->width - 120, 20), &font, cvScalar(0, 0xff));cvPutText(dst, dspStr2, cvPoint(dst->width - 120, 40), &font, cvScalar(0, 0xff));cvPutText(dst, dspStr3, cvPoint(dst->width - 120, 60), &font, cvScalar(0, 0xff));//-------------------------------------------------------------------  cvShowImage("Perspective_warp", dst);pressKey = cvWaitKey(0);printf("%x pressed/n", pressKey);switch (pressKey){case '1':df1++;break;case 0x230000:df1--;break;case '2':df2++;break;case 0x280000:df2--;break;case '3':df3++;break;case 0x220000:df3--;break;case '4':df4++;break;case 0x250000:df4--;break;case '6':df5++;break;case 0x270000:df5--;break;case '7':df6++;break;case 0x240000:df6--;break;case '8':df7++;break;case 0x260000:df7--;break;case '9':df8++;break;case 0x210000:df8--;break;case 27:cvReleaseImage(&dst);cvDestroyWindow("Perspective_warp");cvReleaseMat(&warp_matrix);return 0;default:break;}}return 0;}/*//仿射变换#include <cv.h>#include <highgui.h>int main(int argc,char** argv){CvPoint2D32f srcTri[3],dstTri[3];CvMat* rot_mat = cvCreateMat(2,3,CV_32FC1);CvMat* warp_mat = cvCreateMat(2,3,CV_32FC1);IplImage *src,*dst, *srcBak;//int df1(0),df2(33),df3(85),df4(25),df5(15),df6(70);int df1(0),df2(0),df3(0),df4(0),df5(0),df6(0);double angle(-50.0),scale(0.6);float delta = 0.01;int pressKey;if(!(src=cvLoadImage("../ac.jpg",1)) ){return -1;}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;dst = cvCloneImage(src);srcBak = cvCloneImage(src);cvCopy(src,srcBak);dst->origin = src->origin;cvZero(dst);cvNamedWindow("at",1);CvFont font = cvFont(1,1);while(1){dstTri[0].x = srcBak->width*delta*(df1%101);dstTri[0].y = srcBak->height*delta*(df2%101);dstTri[1].x = src->width-1 + srcBak->width*delta*(df3%101);dstTri[1].y = srcBak->height*delta*(df4%101);dstTri[2].x = srcBak->width*delta*(df5%101);dstTri[2].y = src->height-1 + srcBak->height*delta*(df6%101);cvGetAffineTransform(srcTri,dstTri,warp_mat);cvWarpAffine(srcBak,dst,warp_mat);cvCopy(dst,src);//compute rotation matrixCvPoint2D32f center = cvPoint2D32f(src->width/2,src->height/2);cv2DRotationMatrix(center,angle,scale,rot_mat);//do the transformationcvWarpAffine(src,dst,rot_mat);//--------------------------字符显示-----------------------------------------char buf[8];char dspStr1[32] = {'/0'};  //char dspStr2[32] = {'/0'};  //char dspStr3[32] = {'/0'};  //memset(buf,'/0',sizeof(buf));strcat(dspStr1,"|");strcat(dspStr1,itoa(df4%101,buf,10));strcat(dspStr1,",");strcat(dspStr1,itoa(df5%101,buf,10));strcat(dspStr1,",");strcat(dspStr1,itoa(df6%101,buf,10));strcat(dspStr1,"|");strcat(dspStr2,"|angle=");strcat(dspStr2,itoa(int(angle),buf,10));strcat(dspStr2,",scale=");strcat(dspStr2,itoa(int(scale*100),buf,10));strcat(dspStr2,"%|");//「」┌└┘┐|strcat(dspStr3,"|");strcat(dspStr3,itoa(df1%101,buf,10));strcat(dspStr3,",");strcat(dspStr3,itoa(df2%101,buf,10));strcat(dspStr3,",");strcat(dspStr3,itoa(df3%101,buf,10));strcat(dspStr3,"|");cvPutText(dst,dspStr1,cvPoint(dst->width-120,20),&font,cvScalar(0,0xff));cvPutText(dst,dspStr2,cvPoint(dst->width-210,40),&font,cvScalar(0,0xff));cvPutText(dst,dspStr3,cvPoint(dst->width-120,60),&font,cvScalar(0,0xff));//-------------------------------------------------------------------------------------cvShowImage("at",dst);pressKey = cvWaitKey();//  printf("src->width:%d/n",src->width);printf("%c pressed/n",pressKey);switch(pressKey){case '1':df1++;break;case 0x230000:df1--;break;case '2':df2++;break;case 0x280000:df2--;break;case '3':df3++;break;case 0x220000:df3--;break;case '4':   //旋转角度angle++;break;case 0x250000:angle--;break;case '6':   //缩放scale+=0.01;break;case 0x270000:scale-=0.01;break;case '7':df4++;break;case 0x240000:df4--;break;case '8':df5++;break;case 0x260000:df5--;break;case '9':df6++;break;case 0x210000:df6--;break;case 27:cvReleaseImage(&dst);cvDestroyWindow("at");cvReleaseMat(&rot_mat);cvReleaseMat(&warp_mat);return 0;default:break;}}cvReleaseImage(&dst);cvReleaseMat(&rot_mat);cvReleaseMat(&warp_mat);return 0;}*/




2 0
原创粉丝点击