仿射变换我的理解就是图像在一个二维平面上进行不同程度的旋转或者拉伸,但是无论怎么变,他的图像都是平行四边形的,它的变换函数是一个2*3的矩阵。
透视变换是一个观察者在3维空间中以不同的角度来观察这个图像,所以这个图像就是投影在观察者那个二维平面上的影像,它的变换函数是3*3,或者4*4的矩阵。
仿射变换代码如下:
#include<cv.h> #include<highgui.h> int main() { CvPoint2D32f srcTri[3],dstTri[3]; CvMat* rot_mat=cvCreateMat(2,3,CV_32FC1); //旋转矩阵 CvMat* warp_mat=cvCreateMat(2,3,CV_32FC1); // IplImage *src,*dst; src=cvLoadImage("1.jpg",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; dstTri[0].x=src->width*0.0; dstTri[0].y=src->height*0.33; dstTri[1].x=src->width*0.85; dstTri[1].y=src->height*0.25; dstTri[2].x=src->width*0.15; dstTri[2].y=src->height*0.7; //-----------------------方法一------------------------ //----通过现有的变换后的点来求这个变换矩阵----------- cvGetAffineTransform(srcTri,dstTri,warp_mat); //求变换矩阵 cvWarpAffine(src,dst,warp_mat); //利用求得的变换矩阵来变换图像 cvNamedWindow("warp",1); cvShowImage("warp",dst); cvCopy(dst,src); //----------------------方法二------------------------- //通过已知的参数来旋转图像 CvPoint2D32f center=cvPoint2D32f(src->width/2,src->height/2); //旋转的中心点 double angle=-50.0; //需要旋转的角度 double scale=0.6; //图像的缩放系数要不然那四个角就出去了 cv2DRotationMatrix(center,angle,scale,rot_mat); //计算旋转矩阵 cvWarpAffine(src,dst,rot_mat); //旋转图像 cvNamedWindow("my",1); cvShowImage("my",dst); cvWaitKey(); return 0; }透视变换代码如下:
#include<cv.h> #include<highgui.h> int main() { CvPoint2D32f srcQuad[4],dstQuad[4]; CvMat* warp_matrix=cvCreateMat(3,3,CV_32FC1); IplImage *src,*dst; src=cvLoadImage("1.jpg",1); ///原图 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; dstQuad[0].x=src->width*0.05; dstQuad[0].y=src->height*0.33; dstQuad[1].x=src->width*0.9; dstQuad[1].y=src->height*0.25; dstQuad[2].x=src->width*0.2; dstQuad[2].y=src->height*0.7; dstQuad[3].x=src->width*0.8; dstQuad[3].y=src->height*0.9; //-----------------------方法一------------------------ //----通过现有的变换后的点来求这个变换矩阵----------- cvGetPerspectiveTransform(srcQuad,dstQuad,warp_matrix); //求变换矩阵 cvWarpPerspective(src,dst,warp_matrix); //利用求得的变换矩阵来变换图像 cvNamedWindow("warp",1); cvShowImage("warp",dst); cvWaitKey(); return 0; }
采用opencv2实现仿射变换
#include<opencv2/opencv.hpp> #include<opencv2/imgproc/imgproc.hpp> #include<iostream> using namespace cv; using namespace std; int main() { Point2f srcTriangle[3]; Point2f dstTriangle[3]; Mat rotMat(2,3,CV_32FC1); Mat warpMat(2,3,CV_32FC1); Mat srcImage,dstImage_warp,dstImage_warp_rotate; srcImage=imread("1.jpg",1); dstImage_warp=Mat::zeros(srcImage.rows,srcImage.cols,srcImage.type()); //仿射变换只需要3个点来确定,因为放射变换都是平行四边形 srcTriangle[0]=Point2f(0,0); //图像的左下角 srcTriangle[1]=Point2f(static_cast<float>(srcImage.cols-1),0); //图像的右下角 srcTriangle[2]=Point2f(0,static_cast<float>(srcImage.rows-1)); //图像的左上角 dstTriangle[0]=Point2f(static_cast<float>(srcImage.cols*0.0),static_cast<float>(srcImage.rows*0.33)); //(0,0)点变换后的坐标 dstTriangle[1]=Point2f(static_cast<float>(srcImage.cols*0.65),static_cast<float>(srcImage.rows*0.35)); // dstTriangle[2]=Point2f(static_cast<float>(srcImage.cols*0.15),static_cast<float>(srcImage.rows*0.6)); warpMat=getAffineTransform(srcTriangle,dstTriangle); //实际就是通过四个角的变换前后的位置来确定变换矩阵(前后四个角的位置上面给出) warpAffine(srcImage,dstImage_warp,warpMat,dstImage_warp.size()); //利用这个得到的变换矩阵来变换图像 //这里可以想象成先让图像上几个点以给定的规则排列(这里是四个角的点),然后其他的都按这个规则来排列 imshow("xiaoguo",dstImage_warp); //显示效果图 //----------------第二种方式------------------------------- Point center=Point(dstImage_warp.cols/2,dstImage_warp.rows/2); double angle=-30.0; double scale=0.8; rotMat=getRotationMatrix2D(center,angle,scale); //通过中心点,旋转角度,缩放大小构造旋转矩阵 warpAffine(dstImage_warp,dstImage_warp_rotate,rotMat,dstImage_warp_rotate.size()); //同前面一样 imshow("xiaoguo2",dstImage_warp_rotate); waitKey(0); return 0; }