图像旋转矩阵为 T = [ cos(alpha) sin(alpha); -sin(alpha) cos(alpha) ], 该矩阵为顺时针旋转alpha角度的矩阵。但图像中原点位于左上角,施加该矩阵得到的是逆时针旋转alpha角度的图像,所以顺时针旋转的变换矩阵为T = [ cos(alpha) -sin(alpha); sin(alpha) cos(alpha) ]。
代码如下:
#include "opencv2/imgproc/imgproc.hpp" #include "opencv2/highgui/highgui.hpp" #include <iostream> #include <cmath> using namespace cv; using namespace std; #define PI 3.14159265 void MyRotation(Mat& src, Mat& dst, float TransMat[3][3]); /** * @function main */ int main( int argc, char** argv ) { // load image char* imageName = "images/Lenna_256.png"; Mat image; image = imread(imageName,1); if(!image.data) { cout << "No image data" << endl; return -1; } // show image namedWindow("image", CV_WINDOW_AUTOSIZE); imshow("image", image); Mat dst; float alpha = 36.0*PI/180; float transMat[3][3] = { {cos(alpha), -sin(alpha), 0}, {sin(alpha), cos(alpha), 0}, {0, 0, 1} };// !!! counter clockwise transform matrix, for clockwise rotation !!! MyRotation(image, dst, transMat); namedWindow("out_image", CV_WINDOW_AUTOSIZE); imshow("out_image", dst); //imwrite("Lenna_rotate.jpg", dst); waitKey(0); return 0; } void MyRotation(Mat& src, Mat& dst, float TransMat[3][3]) { CV_Assert(src.data); CV_Assert(src.depth() != sizeof(uchar)); // calculate margin point of dst image float left = 0; float right = 0; float top = 0; float down = 0; float x = src.cols * 1.0f; float y = 0.0f; float u1 = x * TransMat[0][0] + y * TransMat[0][1]; float v1 = x * TransMat[1][0] + y * TransMat[1][1]; x = src.cols * 1.0f; y = src.rows * 1.0f; float u2 = x * TransMat[0][0] + y * TransMat[0][1]; float v2 = x * TransMat[1][0] + y * TransMat[1][1]; x = 0.0f; y = src.rows * 1.0f; float u3 = x * TransMat[0][0] + y * TransMat[0][1]; float v3 = x * TransMat[1][0] + y * TransMat[1][1]; left = min( min( min(0.0f,u1), u2 ), u3); right = max( max( max(0.0f,u1), u2 ), u3); top = min( min( min(0.0f,v1), v2 ), v3); down = max( max( max(0.0f,v1), v2 ), v3); // create dst image dst.create(int(abs(right-left)), int(abs(down-top)), src.type()); CV_Assert( dst.channels() == src.channels() ); int channels = dst.channels(); int i,j; uchar* p; uchar* q; for( i = 0; i < dst.rows; ++i) { p = dst.ptr<uchar>(i); for ( j = 0; j < dst.cols; ++j) { // rotation int x = (j+left)*TransMat[0][0] - (i+top)*TransMat[0][1] ; // NOTE: adverse rotation here!!! int y = -(j+left)*TransMat[1][0] + (i+top)*TransMat[1][1] ; if( (x >= 0) && (x < src.cols) && (y >= 0) && (y < src.rows) ) { q = src.ptr<uchar>(y); switch(channels) { case 1: { p[j] = q[x]; break; } case 3: { p[3*j] = q[3*x] ; p[3*j+1] = q[3*x+1]; p[3*j+2] = q[3*x+2]; break; } } } } } }