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;

旋转之后的效果:

但是遇到绕任意点旋转时,会产生问题,用这种方式还是会存在裁剪,如果要理解绕任意点旋转,需要先理解函数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;

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

在图片不被裁剪时opencv绕图片中任意点旋转任意角度的更多相关文章

  1. C#图片处理示例(裁剪,缩放,清晰度,水印)

    C#图片处理示例(裁剪,缩放,清晰度,水印) 吴剑 2011-02-20 原创文章,转载必需注明出处:http://www.cnblogs.com/wu-jian/ 前言 需求源自项目中的一些应用,比 ...

  2. Uploadify & jQuery.imgAreaSelect 插件实现图片上传裁剪

    在网站中需要一个图片上传裁剪的功能,借鉴这篇文章 Ajax+PHP+jQuery图片截图上传 的指点,找到了jquery.imgAreaSelect这个不错插件,能对图片进行自定义区域选择并给出坐标, ...

  3. php裁剪图片(支持定点裁剪)

    /** * 图片裁剪函数,支持指定定点裁剪和方位裁剪两种裁剪模式 * @param <string> $src_file 原图片路径 * @param <int> $new_w ...

  4. PictureCutting图片批量裁切(裁剪)工具

    PictureCutting图片批量裁切(裁剪)工具 写这个工具的原因是因为在获取一个软件的皮肤包中的图片的时候需要进行批量的裁切工作,而有没有找到在linux下简单好用的工具,干脆就用QT写了一个. ...

  5. 图片上传裁剪zyupload

    图片上传控件用的是zyupload控件,使用过程中遇到了一些问题,特别记录下来 上图是目前的使用效果,这个控件我是用js代码动态添加出来的 HTML代码: <div class="wi ...

  6. OkHttp框架从入门到放弃,解析图片使用Picasso裁剪,二次封装OkHttpUtils,Post提交表单数据

    OkHttp框架从入门到放弃,解析图片使用Picasso裁剪,二次封装OkHttpUtils,Post提交表单数据 我们这片博文就来聊聊这个反响很不错的OkHttp了,标题是我恶搞的,本篇将着重详细的 ...

  7. 当图片加载失败时更换图片, Firefox onerror 报错

    当图片加载失败时更换图片. <!DOCTYPE html> <meta charset="UTF-8"> <img src="http:// ...

  8. Android 4.4从图库选择图片,获取图片路径并裁剪

    转至 http://blog.csdn.net/tempersitu/article/details/20557383 最近在做一个从图库选择图片或拍照,然后裁剪的功能.本来是没问题的,一直在用 In ...

  9. 批量改变图片的尺寸大小 python opencv

    我目标文件夹下有一大批图片,我要把它转变为指定尺寸大小的图片,用pthon和opencv实现的. 以上为原图片. import cv2 import os # 按指定图像大小调整尺寸 def resi ...

随机推荐

  1. 控制台字体怎么改为console?

    windows控制台窗口在中文版下没有console字体,如果要使用console的话就必须先将窗口转换为英文版. 1.win+R进入运行窗口,然后cmd进入命令窗口 2.在命令行窗口输入 chcp ...

  2. 翟佳:高可用、强一致、低延迟——BookKeeper的存储实现

    分享嘉宾:翟佳 StreamNative 联合创始人 编辑整理:张晓伟 美团点评 出品平台:DataFunTalk 导读:多数读者们了解BookKeeper是通过Pulsar,实际上BookKeepe ...

  3. Windows环境中Hadoop配置

    我们之前已经在Windows中安装好了Hadoop,并且配置了环境变量.如果要在本地上运行的,还需要这两个文件,可以去找一下,放到Hadoop的bin目录下面.这样我们写好的mr程序就可以直接在Win ...

  4. 使用Django2.0.4集成钉钉第三方扫码登录

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_124 钉钉作为阿里旗下的一款免费移动通讯软件,受众群体越来越多,这里我们使用Django来集成一下钉钉的三方账号登录,首先注册钉钉 ...

  5. 技术分享 | MySQL数据误删除的总结

    欢迎来到 GreatSQL社区分享的MySQL技术文章,如有疑问或想学习的内容,可以在下方评论区留言,看到后会进行解答 内容提要 用delete语句 使用drop.truncate删除表以及drop删 ...

  6. Word 段前分页是什么?怎么设置?

    描述 这两个标题在第一个标题的页中,且两个标题都没有独立分页.要让每一个标题独立分页,需要对标题的格式进行修改. 段前分页指的是标题与标题之间不在同一个页中,每一个标题都在独立的页中. 设置段前分页 ...

  7. 我开源了一个Go学习仓库|笔记预览

    前言 大半个月前我参与了字节后端面试,未通过第四面,面试总结写在了这篇文章: https://juejin.cn/post/7132712873351970823 在此文的末尾,我写到为了全面回顾Go ...

  8. rcu使用遇到问题汇总

    1.3.10内核,在项目中遇到一种情况,我们根据sk指针hash到一个cpu上,然后访问该cpu对应分配的一个数据区. 然后系统会偶尔crash掉,crash掉有两种情况,一种是cred的rcu回收时 ...

  9. 使用Python的selenium库制作脚本,支持后台运行

    本文介绍如何使用Python的selenium库制作脚本.概念:       Selenium是一个用于测试网站的自动化测试工具,支持各种浏览器包括Chrome.Firefox.Safari等主流界面 ...

  10. kubernetes之镜像拉取策略ImagePullSecrets;

    1.容器镜像是什么? 1.容器镜像(Container Image)是最终运行的软件: 2.容器镜像(最初为Docker镜像,现在叫OCI镜像更合适)是将软件打包的形式.但是容器镜像还可以携带额外的设 ...