前言
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二次开发。



