网上有很多opencv图像旋转的方法,但都不是很全面。本文通过特殊情况特殊处理的方法,实现90°,180°及270°旋转后图像无空白,及任意角度的旋转。
下面是源码:
1 #define ISFLOAT_EQUAL_ZERO(x) ((x) > -0.000001f && (x) < 0.000001f) 2 3 static cv::Mat generateHomography(float angle) 4 { 5 // angle - rotation around Oz in degrees 6 float angleRadian = static_cast<float>(angle * CV_PI / 180); 7 cv::Mat H = cv::Mat::eye(3, 3, CV_32FC1); 8 H.at<float>(0,0) = H.at<float>(1,1) = std::cos(angleRadian); 9 H.at<float>(0,1) = -std::sin(angleRadian); 10 H.at<float>(1,0) = std::sin(angleRadian); 11 12 return H; 13 } 14 15 static void RotateAjust(cv::Mat& img, float angle) 16 { 17 // a = a +/- 2kpi 18 int k = abs(angle / 360); 19 if(angle > 0){ 20 angle -= k*360; 21 }else if(angle < 0){ 22 angle += k*360; 23 } 24 25 if(ISFLOAT_EQUAL_ZERO(angle)){ 26 return; 27 } 28 29 // 特殊处理 30 if(90 == angle){ 31 cv::Mat temp; 32 cv::transpose(img, temp); 33 cv::flip(temp, img, 0); 34 return; 35 } else if(180 == angle){ 36 cv::flip(img, img, -1); 37 return; 38 } else if(270 == angle){ 39 cv::Mat temp; 40 cv::transpose(img, temp); 41 cv::flip(temp, img, 1); 42 return; 43 } 44 45 int width = img.cols; 46 int height = img.rows; 47 48 // angle - rotation around Oz in degrees 49 float diag = std::sqrt(static_cast<float>(width * width + height * height)); 50 cv::Mat LUShift = cv::Mat::eye(3, 3, CV_32FC1); // left up 51 LUShift.at<float>(0,2) = static_cast<float>(-width * 0.5f); 52 LUShift.at<float>(1,2) = static_cast<float>(-height * 0.5f); 53 cv::Mat RDShift = cv::Mat::eye(3, 3, CV_32FC1); // right down 54 RDShift.at<float>(0,2) = diag * 0.5f; 55 RDShift.at<float>(1,2) = diag * 0.5f; 56 cv::Size sz(cvRound(diag), cvRound(diag)); 57 58 cv::Mat dst; 59 cv::Mat H = RDShift * generateHomography(angle) * LUShift; 60 cv::warpPerspective(img, dst, H, sz); 61 img = dst; 62 }
参考文件:
【1】OpenCV2.4.13 sourcesmodules onfree est est_rotation_and_scale_invariance.cpp
【2】http://www.tuicool.com/articles/emIr2u
【3】http://blog.csdn.net/moses1213/article/details/48790801