OpenCV图像旋转
图像旋转是指图像按照某个位置转动一定角度的过程,旋转中图像仍保持这原始尺寸。图像旋转后图像的水平对称轴、垂直对称轴及中心坐标原点都可能会发生变换,因此需要对图像旋转中的坐标进行相应转换。
如下图:

假设图像逆时针旋转\(\theta\),则根据坐标转换可得旋转转换为:
x' = r\cos(\alpha - \theta)\\
y' = r\sin(\alpha - \theta)\tag{1}
\end{cases}\]
而
\sin\alpha = \frac{y}{\sqrt{x^2 + y^2}},
\cos\alpha = \frac{x}{\sqrt{x^2 + y^2}}\]
带入(1)可得:
x' = x\cos\theta + y\sin\theta\\
y' = -x\sin\theta + y\cos\theta
\end{cases}\]
即如下:
x'&y'& 1
\end{bmatrix} \
=
\begin{bmatrix}
x &y &1
\end{bmatrix} \
\begin{bmatrix}
\cos\theta & -\sin\theta & 0 \\
\sin\theta & \cos\theta &0 \\
0 & 0 & 1\tag{2}
\end{bmatrix}\]
而旋转后的图片的灰度值等于原图中相应位置的灰度值如下:
\]
同时我们要修正原点的位置,因为图像中的坐标原点在图像的左上角,经过旋转后图像的大小会有所变化,原点也需要修正。实现代码如下:
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
#include <string>
#include <cmath>
using namespace cv;
Mat imgRotate(Mat matSrc, float angle, bool direction)
{
float theta = angle * CV_PI / 180.0;
int nRowsSrc = matSrc.rows;
int nColsSrc = matSrc.cols;
// 如果是顺时针旋转
if (!direction)
theta = 2 * CV_PI - theta;
// 全部以逆时针旋转来计算
// 逆时针旋转矩阵
float matRotate[3][3]{
{std::cos(theta), -std::sin(theta), 0},
{std::sin(theta), std::cos(theta), 0 },
{0, 0, 1}
};
float pt[3][2]{
{ 0, nRowsSrc },
{nColsSrc, nRowsSrc},
{nColsSrc, 0}
};
for (int i = 0; i < 3; i++)
{
float x = pt[i][0] * matRotate[0][0] + pt[i][1] * matRotate[1][0];
float y = pt[i][0] * matRotate[0][1] + pt[i][1] * matRotate[1][1];
pt[i][0] = x;
pt[i][1] = y;
}
// 计算出旋转后图像的极值点和尺寸
float fMin_x = min(min(min(pt[0][0], pt[1][0]), pt[2][0]), (float)0.0);
float fMin_y = min(min(min(pt[0][1], pt[1][1]), pt[2][1]), (float)0.0);
float fMax_x = max(max(max(pt[0][0], pt[1][0]), pt[2][0]), (float)0.0);
float fMax_y = max(max(max(pt[0][1], pt[1][1]), pt[2][1]), (float)0.0);
int nRows = cvRound(fMax_y - fMin_y + 0.5) + 1;
int nCols = cvRound(fMax_x - fMin_x + 0.5) + 1;
int nMin_x = cvRound(fMin_x + 0.5);
int nMin_y = cvRound(fMin_y + 0.5);
// 拷贝输出图像
Mat matRet(nRows, nCols, matSrc.type(), Scalar(0));
for (int j = 0; j < nRows; j++)
{
for (int i = 0; i < nCols; i++)
{
// 计算出输出图像在原图像中的对应点的坐标,然后复制该坐标的灰度值
// 因为是逆时针转换,所以这里映射到原图像的时候可以看成是,输出图像
// 到顺时针旋转到原图像的,而顺时针旋转矩阵刚好是逆时针旋转矩阵的转置
// 同时还要考虑到要把旋转后的图像的左上角移动到坐标原点。
int x = (i + nMin_x) * matRotate[0][0] + (j + nMin_y) * matRotate[0][1];
int y = (i + nMin_x) * matRotate[1][0] + (j + nMin_y) * matRotate[1][1];
if (x >= 0 && x < nColsSrc && y >= 0 && y < nRowsSrc)
{
matRet.at<Vec3b>(j, i) = matSrc.at<Vec3b>(y, x);
}
}
}
return matRet;
}
测试代码:
int main()
{
std::string strPath = "D:\\MyDocuments\\My Pictures\\OpenCV\\";
Mat matSrc = imread(strPath + "panda.jpg");
if (matSrc.empty())
return 1;
float angle = 30;
Mat matRet = imgRotate(matSrc, angle, true);
imshow("src", matSrc);
imshow("rotate", matRet);
// 保存图像
imwrite(strPath + "rotate_panda.jpg", matRet);
waitKey();
return 0;
}

OpenCV图像旋转的更多相关文章
- OpenCV:OpenCV图像旋转的代码
OpenCV图像旋转的代码 cv::transpose( bfM, bfM ) 前提:使用两个矩阵Mat型进行下标操作是不行的,耗费的时间太长了.直接使用两个指针对拷贝才是王道.不知道和OpenCV比 ...
- opencv 图像旋转
理论 http://www.cnblogs.com/wangguchangqing/p/4045150.html 翻开任意一本图像处理的书,都会讲到图像的几何变换,这里面包括:仿射变换(affine ...
- OpenCV 图像旋转实现
1 旋转矩形 首先建议阅读图像旋转算法原理-旋转矩阵,这篇博客可以让你很好地理解图像中的每一个点是如何进行旋转操作的.其中涉及到了图像原点与笛卡尔坐标原点之间的相互转换以及点旋转的一些公式推导. 这里 ...
- OpenCL + OpenCV 图像旋转
▶ 使用 OpenCV 从文件读取彩色的 png 图像,旋转一定角度以后写回文件 ● 代码,核函数 // rotate.cl //__constant sampler_t sampler = CLK_ ...
- opencv 图像仿射变换 计算仿射变换后对应特征点的新坐标 图像旋转、缩放、平移
常常需要最图像进行仿射变换,仿射变换后,我们可能需要将原来图像中的特征点坐标进行重新计算,获得原来图像中例如眼睛瞳孔坐标的新的位置,用于在新得到图像中继续利用瞳孔位置坐标. 仿射变换在:http:// ...
- [opencv] 图像几何变换:旋转,缩放,斜切
几何变换 几何变换可以看成图像中物体(或像素)空间位置改变,或者说是像素的移动. 几何运算需要空间变换和灰度级差值两个步骤的算法,像素通过变换映射到新的坐标位置,新的位置可能是在几个像素之间,即不一定 ...
- 基于c++和opencv底层的图像旋转
图像旋转:本质上是对旋转后的图片中的每个像素计算在原图的位置. 在opencv包里有自带的旋转函数,当你知道倾斜角度theta时: 用getRotationMatrix2D可得2X3的旋转变换矩阵 M ...
- OpenCV计算机视觉学习(11)——图像空间几何变换(图像缩放,图像旋转,图像翻转,图像平移,仿射变换,镜像变换)
如果需要处理的原图及代码,请移步小编的GitHub地址 传送门:请点击我 如果点击有误:https://github.com/LeBron-Jian/ComputerVisionPractice 图像 ...
- 【OpenCV学习笔记】之六 手写图像旋转函数---万丈高楼平地起
话说,平凡之处显真格,这一点也没错! 比如,对旋转图像进行双线性插值,很简单吧? 可,对我,折腾了大半天,也没有达到预期效果! 尤其是三个误区让我抓瞎好久: 1,坐标旋转公式. 这东西,要用 ...
随机推荐
- wmware虚拟化的启动问题
2019-05-09,14点14 vmware出现VMware提示:已将该虚拟机配置为使用 64 位客户机操作系统.但是,无法执行 64 位操作.解决方案 进入bios里面intel 虚拟化技术 先设 ...
- CSS3 -- column 实现瀑布流布局
本例使用 CSS column 实现瀑布流布局 关键点,column-count: 元素内容将被划分的最佳列数 关键点,break-inside: 避免在元素内部插入分页符 html div.g-co ...
- 19-SQLServer定期自动导入数据的dtsx部署
一.注意点 1.登录Integration Service必须使用windows用户,并且只能在本地服务器登录. 2.SQLServer2000以前,叫dts,全程Data Transformatio ...
- 题解 【NOIP2003】神经网络
[NOIP2003]神经网络 Description 问题背景: 人工神经网络( Artificial Neural Network )是一种新兴的具有自我学习能力的计算系统,在模式识别.函数逼近及贷 ...
- ila核数据输出
在Tcl Console中输入以下命令(其中dataxxxx表示文件名,hw_ila_2则为ila窗口名): write_hw_ila_data -csv_file -force dataxxxx [ ...
- 019_linuxC++之_函数模板引入
(一)首先我们来看非模板程序,函数只是输入不一样的变量就需要构件很多个不一样的函数,那么这样很麻烦,则引入函数模板 int& max(int& a, int& b) { ret ...
- 我带旅游ERP管理系统开发的经历
前言 不怎么会写博文的我也不知道怎么写,但是有冲动让我去记录下我做项目的经历. 项目背景 某旅行社需要一款内部业务管理系统,找了一家外包来开发但最终不是她们想要的,上线的时候很多问题,首先酒店和票务资 ...
- [CCC 2016] 生命中的圆
题面 有这么一类题,它让你求一个0/1环经过T轮周围异或过程之后的样子. 周围异或即 a[i][k] = a[i-1][k-1] ^ a[i-1][k+1] ,其中第一维表示轮数,第二维表示位置. 千 ...
- art-template自定义函数
自定义函数 // 百分比计算 template.defaults.imports.percentage = function (num1, num2) { var res; if(!num1 & ...
- oracle面试题1
1.题目要求 已知关系模式:S (SNO,SNAME)学生关系.SNO 为学号,SNAME 为姓名C (CNO,CNAME,CTEACHER)课程关系.CNO 为课程号,CNAME 为课程名,CTEA ...