我的编程空间,编程开发者的网络收藏夹
学习永远不晚

OpenCV实现绕图片中任意角度旋转任意角度

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

OpenCV实现绕图片中任意角度旋转任意角度

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

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

#include"opencv.hpp"
#include<iostream>
using namespace std;
using namespace cv;
int main() {
	Mat class="lazy" data-src = imread("timg.jpg");
	Mat des,m;
	Point2f center = Point(class="lazy" data-src.cols / 2, class="lazy" data-src.rows / 2);
	double angle = 50,scale=0.5;
	int w = class="lazy" data-src.cols, h = class="lazy" data-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 - class="lazy" data-src.cols) / 2;
	m.at<double>(1, 2) += (bound_h - class="lazy" data-src.rows) / 2;
	
	warpAffine(class="lazy" data-src,des,m,Size2i(bound_h,bound_w));
	imshow("image",des);
	waitKey();
	return 0;

旋转之后的效果: 

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

具体实现代码如下:

    Mat class="lazy" data-src = imread("/home/sss/1111.jpg", IMREAD_GRAYSCALE);
    Mat des, m;
//旋转的任意角度
    double angle = 45;
    int w = class="lazy" data-src.cols, h = class="lazy" data-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(class="lazy" data-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图片旋转内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

OpenCV实现绕图片中任意角度旋转任意角度

下载Word文档到电脑,方便收藏和打印~

下载Word文档

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录