在圖片不被裁剪時opencv繞圖片中任意點旋轉任意角度

opencv繞圖片中任意角度旋轉任意角度
??最近在做項目需要把把圖片繞圖片中任意點旋轉任意角度,考慮到自己旋轉需要編寫插值算法,所以想到了用opencv,但是網上都是圍繞圖片中點旋轉任意角度的,都是向下面這樣寫的:
繞圖片中心旋轉圖片不裁剪
#include"opencv.hpp"#include<iostream>using namespace std;using namespace cv;int main() { Mat src = https://www.huyubaike.com/biancheng/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 = https://www.huyubaike.com/biancheng/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_xif(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_yif(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_xif(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_yif(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繞圖片中任意點旋轉任意角度

文章插圖
【在圖片不被裁剪時opencv繞圖片中任意點旋轉任意角度】

    推薦閱讀