OpenCV實現(xiàn)繞圖片中任意角度旋轉(zhuǎn)任意角度
最近在做項目需要把把圖片繞圖片中任意點旋轉(zhuǎn)任意角度,考慮到自己旋轉(zhuǎn)需要編寫插值算法,所以想到了用opencv,但是網(wǎng)上都是圍繞圖片中點旋轉(zhuǎn)任意角度的,都是向下面這樣寫的:
繞圖片中心旋轉(zhuǎn)圖片不裁剪
#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;
旋轉(zhuǎn)之后的效果:
但是遇到繞任意點旋轉(zhuǎn)時,會產(chǎn)生問題,用這種方式還是會存在裁剪,如果要理解繞任意點旋轉(zhuǎn),需要先理解函數(shù)getRotationMatrix2D,這個函數(shù)處理過程如下面矩陣表示所示:
具體實現(xiàn)代碼如下:
Mat src = imread("/home/sss/1111.jpg", IMREAD_GRAYSCALE); Mat des, m; //旋轉(zhuǎn)的任意角度 double angle = 45; int w = src.cols, h = src.rows; Point2f rorate_center; //旋轉(zhuǎn)的任意中心 rorate_center.x = w; rorate_center.y = h; //重新計算旋轉(zhuǎn)后的寬和高 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計算旋轉(zhuǎn)矩陣 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; //計算原來矩陣的四個頂點經(jīng)過變換后的頂點 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; //找到經(jīng)過變換過定位的最大最小值 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;
經(jīng)過變換過的圖片不會存在裁剪:
到此這篇關(guān)于OpenCV實現(xiàn)繞圖片中任意角度旋轉(zhuǎn)任意角度的文章就介紹到這了,更多相關(guān)OpenCV圖片旋轉(zhuǎn)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
關(guān)于C++中的static關(guān)鍵字的總結(jié)
C++的static有兩種用法:面向過程程序設(shè)計中的static和面向?qū)ο蟪绦蛟O(shè)計中的static。前者應(yīng)用于普通變量和函數(shù),不涉及類;后者主要說明static在類中的作用2013-09-09VSCode插件開發(fā)全攻略之打包、發(fā)布、升級的詳細教程
這篇文章主要介紹了VSCode插件開發(fā)全攻略之打包、發(fā)布、升級的教程,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-05-05