计算机视觉基础:图像处理Task 02 几何变换
文章目录
- 理论分析
- 1.坐标系转换
- 2.变换形式
- 反向映射
- 插值
- 函数实现(C++)
- 平移
- 旋转
理论分析
对于旋转和偏移,就需要3步(3次变换):
1.将输入原图图像坐标转换为笛卡尔坐标系;
2.进行旋转计算。旋转矩阵前面已经给出了;
3.将旋转后的图像的笛卡尔坐标转回图像坐标。
1.坐标系转换
对于缩放、平移可以以图像坐标原点(图像左上角为原点)为中心变换,这不用坐标系变换,直接按照一般形式计算即可。而对于旋转和偏移,一般是以图像中心为原点,那么这就涉及坐标系转换了。图像坐标的原点在图像左上角,水平向右为 X 轴,垂直向下为 Y 轴。数学课本中常见的坐标系是以图像中心为原点,水平向右为 X 轴,垂直向上为 Y 轴,称为笛卡尔坐标系。
在图像中我们的坐标系通常是AB和AC方向的,原点为A,而笛卡尔直角坐标系是DE和DF方向的,原点为D。令图像表示为M×N的矩阵,对于点A而言,两坐标系中的坐标分别是(0,0)和(-N/2,M/2),则图像某像素点(x’,y’)转换为笛卡尔坐标(x,y)转换关系为,x为列,y为行:
逆变换为:
2.变换形式
在数据图像处理中图像变换采取变换矩阵的方式,即仿射变换,仿射变换形式如下:
式中的T就是变换矩阵,其中 (v,w)为原坐标,(x,y) 为变换后的坐标,不同的变换对应不同的矩阵,一些常见的变换矩阵及作用如下表:
于是,根据前面说的3个步骤(3次变换),旋转(顺时针旋转)的变换形式就为,3次变换就有3个矩阵:
反向映射
前向映射就是根据原图用变换公式直接算出输出图像相应像素的空间位置,那么这会导致一个问题:可能会有多个像素坐标映射到输出图像的同一位置,也可能输出图像的某些位置完全没有相应的输入图像像素与它匹配,也就是没有被映射到,造成有规律的空洞(黑色的蜂窝状)。更好的一种方式是采用 反向映射(Inverse Mapping):扫描输出图像的位置(x,y),通过 Image (为T的逆矩阵)计算输入图像对应的位置 (v,w),通过插值方法决定输出图像该位置的灰度值。
插值
采用反向映射后,需通过插值方法决定输出图像该位置的值,因此需要选择插值算法。通常有最近邻插值、双线性插值,双三次插值等,OpencV默认采用双线性插值,我们也就采用双线性插值。
函数实现(C++)
平移
平移需要函数warpAffine
void boxFilter( InputArray src, OutputArray dst, int ddepth,Size ksize, Point anchor = Point(-1,-1),bool normalize = true,int borderType = BORDER_DEFAULT );
第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。
第二个参数,OutputArray类型的dst,函数调用后的运算结果存在这里,需和源图片有一样的尺寸和类型。
第三个参数,InputArray类型的M,2×3的变换矩阵。
第四个参数,Size类型的dsize,表示输出图像的尺寸。
第五个参数,int类型的flags,插值方法的标识符。此参数有默认值INTER_LINEAR(线性插值),可选的插值方式如下: INTER_NEAREST - 最近邻插值 INTER_LINEAR - 线性插值(默认值) INTER_AREA - 区域插值 INTER_CUBIC –三次样条插值 INTER_LANCZOS4 -Lanczos插值 CV_WARP_FILL_OUTLIERS - 填充所有输出图像的象素。如果部分象素落在输入图像的边界外,那么它们的值设定为 fillval. CV_WARP_INVERSE_MAP –表示M为输出图像到输入图像的反变换,即 。因此可以直接用来做象素插值。否则, warpAffine函数从M矩阵得到反变换。
第六个参数,int类型的borderMode,边界像素模式,默认值为BORDER_CONSTANT。
第七个参数,const Scalar&类型的borderValue,在恒定的边界情况下取的值,默认值为Scalar(),即0。
cv::Mat src = cv::imread("lenna.jpg");cv::Mat dst;cv::Size dst_sz = src.size();//定义平移矩阵cv::Mat t_mat =cv::Mat::zeros(2, 3, CV_32FC1);t_mat.at<float>(0, 0) = 1;t_mat.at<float>(0, 2) = 20; //水平平移量t_mat.at<float>(1, 1) = 1;t_mat.at<float>(1, 2) = 10; //竖直平移量//根据平移矩阵进行仿射变换cv::warpAffine(src, dst, t_mat, dst_sz);//显示平移效果cv::imshow("image", src);cv::imshow("result", dst);cv::waitKey(0);return 0;
旋转
旋转需要函数getRotationMatrix2D
Mat getRotationMatrix2D(Point2f center, double angle, double scale)
第一个参数,Point2f类型的center,表示源图像的旋转中心。
第二个参数,double类型的angle,旋转角度。角度为正值表示向逆时针旋转(坐标原点是左上角)。
第三个参数,double类型的scale,缩放系数
cv::Mat src = cv::imread("lenna.jpg");cv::Mat dst;//旋转角度double angle = 45;cv::Size src_sz = src.size();cv::Size dst_sz(src_sz.height, src_sz.width);int len = std::max(src.cols, src.rows);//指定旋转中心(图像中点)cv::Point2f center(len / 2., len / 2.);//获取旋转矩阵(2x3矩阵)cv::Mat rot_mat = cv::getRotationMatrix2D(center, angle, 1.0);//根据旋转矩阵进行仿射变换cv::warpAffine(src, dst, rot_mat, dst_sz);//显示旋转效果cv::imshow("image", src);cv::imshow("result", dst);cv::waitKey(0);return 0;
计算机视觉基础:图像处理Task 02 几何变换相关推荐
- 计算机视觉基础---图像处理(几何变换)cpp+python
2.1 简介 该部分将对基本的几何变换进行学习,几何变换的原理大多都是相似,只是变换矩阵不同,因此,我们以最常用的平移和旋转为例进行学习.在深度学习领域,我们常用平移.旋转.镜像等操作进行数据增广:在 ...
- 计算机视觉基础-图像处理-几何变换
本文来源于Datawhale组队学习的教材手册,供大家参考阅读. https://github.com/datawhalechina/team-learning/blob/master/%E8%AE% ...
- 计算机视觉基础-图像处理(图像滤波)cpp+python
4.1 简介 图像的实质是一种二维信号,滤波是信号处理中的一个重要概念.在图像处理中,滤波是一种非常常见的技术,它们的原理非常简单,但是其思想却十分值得借鉴,滤波是很多图像算法的前置步骤或基础,掌握图 ...
- Datawhale 计算机视觉基础-图像处理(上)-Task01 OpenCV框架与图像插值算法
简介 在图像处理中,平移变换.旋转变换以及放缩变换是一些基础且常用的操作.这些几何变换并不改变图象的象素值,只是在图象平面上进行象素的重新排列.在一幅输入图象 [ u , v ] [u,v] [u,v ...
- 计算机视觉基础-图像处理(边缘检测)cpp+python
6.1 简介 6.1.1 什么是边缘? 边缘是图像强度函数快速变化的地方 6.1.2 如何检测边缘? 为了检测边缘,我们需要检测图像中的不连续性,可以使用导数来检测不连续性. 如上图所示,上图的第一幅 ...
- 计算机视觉基础-图像处理(图像分割/二值化)cpp+python
5.1 简介 该部分的学习内容是对经典的阈值分割算法进行回顾,图像阈值化分割是一种传统的最常用的图像分割方法,因其实现简单.计算量小.性能较稳定而成为图像分割中最基本和应用最广泛的分割技术.它特别适用 ...
- 计算机视觉基础——图像处理(彩色空间互转)cpp+python
3.1 简介 图像彩色空间互转在图像处理中应用非常广泛,而且很多算法只对灰度图有效:另外,相比RGB,其他颜色空间(比如HSV.HSI)更具可分离性和可操作性,所以很多图像算法需要将图像从RGB转为其 ...
- 计算机视觉基础-图像处理 Task06 边缘检测
文章目录 Sobel算子 Canny边缘检测 1.高斯滤波 2.计算梯度强度和方向 3.非极大值抑制 4.用双阈值算法检测和连接边缘 函数实现 Sobel算子 Canny算法 Sobel算子 我们可以 ...
- 计算机视觉基础-图像处理 Task05 图像分割/二值化
文章目录 OSTU二值化 自适应阈值 函数实现 OSTU二值化 自适应阈值 图像阈值化分割是一种传统的最常用的图像分割方法,因其实现简单.计算量小.性能较稳定而成为图像分割中最基本和应用最广泛的分割技 ...
最新文章
- sci face 补全
- 新方向!DeepMind提出人工生命框架,促进智能生物体的出现
- 饶毅:中国脑计划是我见过的最差科学经费管理,中国猴计划应该缓行
- POJ - 1236 Network of Schools
- 降低数据中心功耗的 4 大方法
- Effective C++ 阅读笔记(一)透彻了解inline以及降低编译依存关系
- 西安工程大学计算机科学学院刘宝宝,计算机科学学院召开研究生国家奖学金答辩会...
- 数学建模-2.优劣解距离法Topisis模型
- java widget_自己的AppWidget一个简单教程 - 开发 - Android - JavaEye群组
- Eclipse中如何让Java类与Servlet产生关联【实现处理请求内容】
- 巧用Ajax的beforeSend 提高用户体验
- 不会优化数据库,早晚被优化!
- 数电educoder的verilog参考答案
- 库卡机器人bco运动_库卡工业机器人编程运动教程
- 在Node.js中了解Hello World
- ctf GetFlag
- mysql 12点_MySQL 查询昨天中午12点到今天中午12点的数据
- Microsoft Azure 建立虚拟机
- 云原生可观测性平台-云监控
- SCU 4437 Carries 想法题