前言
Opencv中是没有直接图像旋转的函数的,只能通过仿射变换实现,但在实现过程中会出现部门内容被裁剪的情况,在解决这个问题上,耗费了一点时间,走了一些弯路,故记录之。
Opencv各版本可在:https://www.ixxin.cn/software.html下载到,需要注意的是Opencv版本越高,支持的VS版本也越高。
主要问题
主要问题就是,旋转后,图像会变大,如图:
解决方法:
第二个问题就是,把图像比例放大后,旋转中心不会变,导致图像还是被裁切状态,如图:
解决方法就是把旋转中心移到新生成图像的中点。
代码
Opencv1代码:
IplImage* rotateImage1(IplImage* img,int degree){ double angle = degree * CV_PI / 180.; double a = sin(angle), b = cos(angle); int width = img->width; int height = img->height; int width_rotate= int(height * fabs(a) + width * fabs(b)); int height_rotate=int(width * fabs(a) + height * fabs(b)); // [ m0 m1 m2 ] ===> [ A11 A12 b1 ] // [ m3 m4 m5 ] ===> [ A21 A22 b2 ] float map[6]; CvMat map_matrix = cvMat(2, 3, CV_32F, map); CvPoint2D32f center = cvPoint2D32f(width / 2, height / 2); cv2DRotationMatrix(center, degree, 1.0, &map_matrix); map[2] += (width_rotate - width) / 2; map[5] += (height_rotate - height) / 2; IplImage* img_rotate = cvCreateImage(cvSize(width_rotate, height_rotate), 8, 3); cvWarpAffine( img,img_rotate, &map_matrix, CV_INTER_LINEAR | CV_WARP_FILL_OUTLIERS, cvScalarAll(0)); return img_rotate; }
Opencv2代码:(注:注释中有Opencv1的调试代码,可以忽略不看,本程序还实现了Opencv1跟Opencv2联合使用,转换的代码)
/* 作者:山科_xxin 时间:2017-03-19 23:04:38 功能:图像旋转 类别:Opencv学习 Opencv版本2.4.11 IDE:VS2010 */ #include<iostream> #include<stdlib.h> #include<opencv2\highgui\highgui.hpp> #include<opencv2\imgproc\imgproc.hpp> //#include<cv.h> //#include<highgui.h> using namespace std; using namespace cv; int fsbh(Mat srcimg) { Mat dstimg; Mat rotimg; int row,col; Point2f srcTri[3]; Point2f dstTri[3]; Mat warpMat(2,3,CV_32FC1);//2*3矩阵,float类型; srcimg = imread("G:/opencv/1.jpg"); if(!srcimg.data) { cout<<"读取错误"<<endl; return false; } row = srcimg.rows; col = srcimg.cols; cout<<"行:"<<row<<"列:"<<col<<endl; //三种方法创建 //dstimg = Mat::zeros(srcimg.rows,srcimg.cols,srcimg.type()); //dstimg = Mat::zeros(srcimg.size(),srcimg.type()); //dstimg.create(srcimg.size(),srcimg.type()); srcTri[0] = Point2f(0,0); srcTri[1] = Point2f(col-1,0); srcTri[2] = Point2f(0,row-1); dstTri[0] = Point2f( col*0.0, row*0.33 ); dstTri[1] = Point2f( col*0.85, row*0.25 ); dstTri[2] = Point2f( col*0.15, row*0.7 ); warpMat = getAffineTransform(srcTri,dstTri); warpAffine(srcimg,dstimg,warpMat,dstimg.size()); Point2f center(col/2,row/2); int degree = -30; double angle = degree*CV_PI/180; //转换为弧度 double scale = 1; double a = sin(angle); double b = cos(angle); int width = col; int height = row; int rewidth = int(height*fabs(a)+width*fabs(b)); int reheight = int(width*fabs(a)+height*fabs(b)); cout<<rewidth<<endl<<reheight<<endl; Mat rot = getRotationMatrix2D(center,degree,scale); double* p = (double*)rot.data; p[2] += (rewidth-width)/2; p[5] += (reheight-height)/2; //rotimg = Mat::zeros(rewidth,reheight,srcimg.type()); //warpAffine(srcimg,rotimg,rot,srcimg.size(),0,0,0); warpAffine(srcimg,rotimg,rot,cv::Size(rewidth,reheight),0,0,0); /* //IplImage->Mat IplImage *ipimg; ipimg = &IplImage(srcimg); float map[6]; CvMat map_matrix = cvMat(2,3,CV_32F,map); CvPoint2D32f center1 = cvPoint2D32f(width/2,height/2); cv2DRotationMatrix(center1, degree, 1.0, &map_matrix); map[2] += (rewidth - width)/2; map[5] += (reheight - height)/2; IplImage* img_rotate = cvCreateImage(cvSize(rewidth, reheight), 8, 3); cvWarpAffine(ipimg,img_rotate, &map_matrix, CV_INTER_LINEAR | CV_WARP_FILL_OUTLIERS, cvScalarAll(0)); Mat test = img_rotate; */ imshow("原图",srcimg); //imshow("变换后",dstimg); //namedWindow("30°旋转",1); imshow("30°旋转",rotimg); return 0; } int main() { Mat srcimg; string filepath; filepath = "G:\\opencv\\1.jpg"; srcimg = imread(filepath,1); fsbh(srcimg); waitKey(0); system("pause"); return 0; }
结果:
后语(更新预告)
接下来会更新两个Python的模块,很有用的模块,还会更新学习Opencv(C++),GDAL(C++,Python),ENVI二次开发。