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


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

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

    绕图片中心旋转图片不裁剪
    #include"opencv.hpp"
    #include
    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;

    旋转之后的效果: 

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

    具体实现代码如下:

        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;

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

     

     

     

  • 相关阅读:
    从零自制docker-14-【实现 mydocker commit 打包容器成镜像】
    C/C++---------------LeetCode第349.两个数组的交集
    SRS5.0-报错: srt serve error code=6006
    unity3d-Animation&&Animator接口(基本使用)
    Spring Boot启动流程分析及原理
    数据结构之美:如何优化内存和性能
    【考研数学】线性代数第五章 —— 特征值和特征向量(3,矩阵对角化理论)
    建站系列(六)--- 后端开发语言
    2022年6月的PMP考试,大家考的怎么样?
    JavaCV人脸识别三部曲之二:训练
  • 原文地址:https://www.cnblogs.com/RobustFresher/p/16739300.html