在图片不被裁剪时opencv绕图片中任意点旋转任意角度

opencv绕图片中任意角度旋转任意角度

  最近在做项目需要把把图片绕图片中任意点旋转任意角度,考虑到自己旋转需要编写插值算法,所以想到了用opencv,但是网上都是围绕图片中点旋转任意角度的,都是向下面这样写的:

绕图片中心旋转图片不裁剪

#include"opencv.hpp" #include<iostream> using namespace std; using namespace cv; int main() { 	Mat src = imread("timg.jpg"); 	Mat des,m; 	Point2f center = Point(src.cols / 2, src.rows / 2); 	double angle = 50,scale=0.5; 	int w = src.cols, h = src.rows; 	int bound_w = (h * fabs(sin(angle * CV_PI / 180)) + w * fabs(cos(angle * CV_PI / 180))) * scale; 	int bound_h = (h * fabs(cos(angle * CV_PI / 180)) + w * fabs(sin(angle * CV_PI / 180))) * scale; 	m = getRotationMatrix2D(center, angle, scale); 	m.at<double>(0, 2) += (bound_w - src.cols) / 2; 	m.at<double>(1, 2) += (bound_h - src.rows) / 2; 	 	warpAffine(src,des,m,Size2i(bound_h,bound_w)); 	imshow("image",des); 	waitKey(); 	return 0;

旋转之后的效果: 

在图片不被裁剪时opencv绕图片中任意点旋转任意角度

但是遇到绕任意点旋转时,会产生问题,用这种方式还是会存在裁剪,如果要理解绕任意点旋转,需要先理解函数getRotationMatrix2D,这个函数处理过程如下面矩阵表示所示:

在图片不被裁剪时opencv绕图片中任意点旋转任意角度

具体实现代码如下:

    Mat src = imread("/home/sss/1111.jpg", IMREAD_GRAYSCALE);     Mat des, m; //旋转的任意角度     double angle = 45;     int w = src.cols, h = src.rows;     Point2f rorate_center; //旋转的任意中心     rorate_center.x = w;     rorate_center.y = h; //重新计算旋转后的宽和高     int bound_w = ceil(h * fabs(sin(angle * CV_PI / 180.0)) + w * fabs(cos(angle * CV_PI / 180.0)));     int bound_h = ceil(h * fabs(cos(angle * CV_PI / 180.0)) + w * fabs(sin(angle * CV_PI / 180.0)));     m = getRotationMatrix2D(rorate_center, angle, 1.0);  //通过eigen计算旋转矩阵     Eigen::Matrix3d T1;     T1 << 1, 0, -rorate_center.x,             0, 1, -rorate_center.y,             0, 0, 1;     Eigen::Matrix3d T2;     T2 <<   1, 0, rorate_center.x,             0, 1, rorate_center.y,             0, 0, 1;     Eigen::Matrix3d rorate;     rorate << cos(angle * CV_PI / 180.0), sin(angle * CV_PI / 180.0), 0,             -sin(angle * CV_PI / 180.0), cos(angle * CV_PI / 180.0), 0,             0, 0, 1;     Eigen::Matrix3d T = T2 * rorate * T1; //计算原来矩阵的四个顶点经过变换后的顶点     Eigen::Matrix<double,3, 1> left_top_p, right_top_p, right_bottom_p, left_botoom_p;     left_top_p << 0, 0, 1;     right_top_p << w, 0, 1;     right_bottom_p << w, h, 1;     left_botoom_p << 0, h , 1;     left_top_p = T * left_top_p;     right_top_p = T * right_top_p;     right_bottom_p = T * right_bottom_p;     left_botoom_p = T * left_botoom_p;  //找到经过变换过定位的最大最小值     double min_x = 10000, min_y = 10000;     //min_x     if(left_top_p[0] < min_x){         min_x = left_top_p[0];     }     if(right_top_p[0] < min_x){         min_x = right_top_p[0];     }     if(right_bottom_p[0] < min_x)     {         min_x = right_bottom_p[0];     }     if(left_botoom_p[0] < min_x){         min_x = left_botoom_p[0];     }      //min_y     if(left_top_p[1] < min_y){         min_y = left_top_p[1];     }     if(right_top_p[1] < min_y){         min_y = right_top_p[1];     }     if(right_bottom_p[1] < min_y)     {         min_y = right_bottom_p[1];     }     if(left_botoom_p[1] < min_y){         min_y = left_botoom_p[1];     }      double max_x = -1000, max_y = -1000;     //max_x     if(left_top_p[0] > max_x){         max_x = left_top_p[0];     }     if(right_top_p[0] > max_x){         max_x = right_top_p[0];     }     if(right_bottom_p[0] > max_x)     {         max_x = right_bottom_p[0];     }     if(left_botoom_p[0] > max_x){         max_x = left_botoom_p[0];     }      //max_y     if(left_top_p[1] > max_y){         max_y = left_top_p[1];     }     if(right_top_p[1] > max_y){         max_y = right_top_p[1];     }     if(right_bottom_p[1] > max_y)     {         max_y = right_bottom_p[1];     }     if(left_botoom_p[1] > max_y){         max_y = left_botoom_p[1];     }      //将偏置添加到矩阵中     m.at<double>(0, 2) += -min_x;     m.at<double>(1, 2) += -min_y;  //变换,最后不会存在裁剪     warpAffine(src, des , m , Size2i(bound_w , bound_h),                INTER_LINEAR, 0, Scalar(100, 100, 100));     imwrite("/home/sss/222.jpg", des);     return 0;

经过变换过的图片不会存在裁剪:

在图片不被裁剪时opencv绕图片中任意点旋转任意角度

 

 

 

发表评论

相关文章