当前位置:网站首页>【OpenCV】-仿射变换
【OpenCV】-仿射变换
2022-08-05 10:26:00 【我菜就爱学】
1、认识仿射变换
仿射变换(Affine Map)又称仿射映射,是指在几何中,一个向量空间进行一次线性变换并接上一个平移,变换为另一个向量空间的过程。保持二维图形之间的相对位置保持不变,平行线依然是平行线,且直线上的点的位置顺序不变。
一个任意的仿射变换都可以表示为乘以一个矩阵接着再加上一个向量的形式。三种常见的变换形式:
- 旋转:ratation(线性变换)
- 平移:translation(向量加)
- 缩放:scale(线性变换)
通常使用2 x 3的矩阵来表示仿射变换:


2、仿射变换的求法
说明:仿射变换表示的就是两幅图片之间的一种联系,关于这种联系的信息大致可以分为以下两种场景:
- 已知X和T,而且已知它们是有联系的,接下来的跟着就是求出矩阵M。
- 已知M和X,想要求得T。只要应用算式T=M*X即可。

如上,点1、2、3(在Image 1中形成一个三角形)与Image 2中的三个点是一一映射的关系,且它们仍然形成三角形,但形状已经和之前的不一样的,可以通过这样的两组三点求出仿射变换,然后把这种变换应用到图像中去。
3、进行仿射变换:warpAffine()函数
warpAffine()函数的作用依据下面的公式对图像做仿射变换:
d s t ( x , y ) = s r c ( M 11 X + M 12 Y + M 13 , M 21 X + M 22 Y + M 23 ) dst(x,y)=src(M11X+M12Y+M13,M21X+M22Y+M23) dst(x,y)=src(M11X+M12Y+M13,M21X+M22Y+M23)
void warpAffine(InputArray src,OutputArray dst,InputArray M,Size dsize,int flags=INTER_LINEAR,intborderMOde=BODER_CONSTANT,const Scalar& borderValue=Scalar())
第一个参数:输入图像
第二个参数:输出图像,函数调用后的运算结果存在这里,需要和源图片有一样的尺寸和类型
第三个参数:2 x 3的变换矩阵,求得的仿射变换
第四个参数:表示输出图像的尺寸
第五个参数:插值方法的标识符。默认值是线性插值法(INTER_LINEAR)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oCWwUOWK-1659625193572)(F:\学习记录\opencv\截图\image-20220804143908462.png)]](/img/57/f80d9eefa929f435a11f2135492f1b.png)
第六个参数:边界像素模式
第七个参数:在恒定的边界情况下取值,默认值Scalar(),即0
4、计算二维旋转变换矩阵:getRotationMatrix2D()函数
说明:getRotationMatrix2D()函数用于计算二维旋转变换矩阵。变换会将旋转中心映射到它自身
Mat getRotationMatrix2D(Point2f center,double angle,double scale)
- 第一个参数:表示源图像的旋转中心
- 第二个参数:旋转角度。角度为正值表示向逆时针旋转(坐标原点是左上角)
- 第三个参数:缩放系统
5、示例程序:
#include<opencv2/opencv.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<iostream>
using namespace std;
using namespace cv;
#define WINDOW_NAME1 "【原始图窗口】"
#define WINDOW_NAME2 "【经过Warp后的窗口】"
#define WINDOW_NAME3 "【经过Warp和Rotate后的窗口】"
int main()
{
system("color 2F");
//参数准备
Point2f srcTriangle[3];
Point2f dstTriangle[3];
Mat rotMat(2, 3, CV_32FC1);
Mat warpMat(2, 3, CV_32FC1);
Mat srcImage, dstImage_warp, dstImage_warp_rotate;
//加载源图像
srcImage = imread("E:\\Pec\\lan.jpg",1);
//设置目标图像的大小和类型与源图像一致
dstImage_warp = Mat::zeros(srcImage.rows, srcImage.cols, srcImage.type());
//设置源图像和目标图像上的三组点以计算仿射变换
//srcTriangle[0] = Point2f(0, 0); //Point2f表示Point类的两个数据x,y为float类型;vector 表示存放四维int
//srcTriangle[1] = Point2f(static_cast<float>(srcImage.cols - 1), 0);
//srcTriangle[2] = Point2f(0, static_cast<float>(srcImage.rows - 1));
//dstTriangle[0] = Point2f(static_cast<float>(srcImage.cols*0.0), static_cast<float>(srcImage.rows*0.33));
//dstTriangle[1] = Point2f(static_cast<float>(srcImage.cols*0.65), static_cast<float>(srcImage.rows*0.35));
//dstTriangle[2] = Point2f(static_cast<float>(srcImage.cols*0.15), static_cast<float>(srcImage.rows*0.6));
//获取变换矩阵,指定三个点
srcTriangle[0] = Point2f(50, 50);
srcTriangle[1] = Point2f(200, 50);
srcTriangle[2] = Point2f(50, 200);
dstTriangle[0] = Point2f(100, 100);
dstTriangle[1] = Point2f(200, 50);
dstTriangle[2] = Point2f(100, 250);
//求仿射变换,得到一个2x3的矩阵
warpMat = getAffineTransform(srcTriangle, dstTriangle);
//对源图像应用刚刚的求得的仿射变换
warpAffine(srcImage, dstImage_warp, warpMat, dstImage_warp.size());
//对图像进行缩放后再旋转
//计算图像中点顺时针旋转50°缩放因子为0.6的旋转矩阵
Point center = Point(dstImage_warp.cols / 2, dstImage_warp.rows / 2);
double angle = -30.0;
double scale = 0.8;
//通过上面的旋转细节信息求出旋转矩阵
rotMat = getRotationMatrix2D(center, angle, scale);
//旋转已经缩放后的图像
warpAffine(dstImage_warp, dstImage_warp_rotate, rotMat, dstImage_warp.size());
imshow(WINDOW_NAME1, srcImage);
imshow(WINDOW_NAME2, dstImage_warp);
imshow(WINDOW_NAME3, dstImage_warp_rotate);
waitKey(0);
return 0;
}

边栏推荐
- [Strong Net Cup 2022] WP-UM
- 【Office】Microsoft Office下载地址合集(微软官方原版离线安装下载)
- The fuse: OAuth 2.0 four authorized login methods must read
- Chapter 5: Multithreaded Communication—wait and notify
- How to choose coins and determine the corresponding strategy research
- 第五章:多线程通信—wait和notify
- Introduction to SD NAND Flash!
- 19.3 restart the Oracle environment
- RT-Thread记录(一、RT-Thread 版本、RT-Thread Studio开发环境 及 配合CubeMX开发快速上手)
- Still looking for a network backup resources?Hurry up to collect the following network backup resource search artifact it is worth collecting!
猜你喜欢

This notebook of concurrent programming knowledge points strongly recommended by Ali will be a breakthrough for you to get an offer from a big factory

PCB布局必知必会:教你正确地布设运算放大器的电路板

012年通过修补_sss_提高扩散模型效率

How can project cost control help project success?

SQL Outer Join Intersection, Union, Difference Query

首次去中心化抢劫?近2亿美元损失:跨链桥Nomad 被攻击事件分析

Still looking for a network backup resources?Hurry up to collect the following network backup resource search artifact it is worth collecting!

产品太多了,如何实现一次登录多产品互通?

我们的Web3创业项目,黄了

three objects are arranged in a spherical shape around the circumference
随机推荐
RT - Thread record (a, RT, RT Thread version - Thread Studio development environment and cooperate CubeMX quick-and-dirty)
Confessing in the era of digital transformation: Mai Cong Software allows enterprises to use data in the easiest way
three.js调试工具dat.gui使用
The JVM collection that Alibaba's top architects have summarized for many years, where can't I check it!
How does the official account operate and maintain?Public account operation and maintenance professional team
第五章:redis持久化,包括rdb和aof两种方式[通俗易懂]
FPGA: Basic Getting Started Button Controlling LED Lights
Offensive World-PWN-new_easypwn
数分面试(一)----与业务相关
JS introduction to reverse the recycling business network of learning, simple encryption mobile phone number
[Unity] [UGUI] [Display text on the screen]
2022华数杯数学建模A题环形振荡器的优化设计思路思路代码分享
【Unity】【UGUI】【在屏幕上显示文本】
导火索:OAuth 2.0四种授权登录方式必读
linux下oracle常见操作以及日常积累知识点(函数、定时任务)
项目成本控制如何帮助项目成功?
[强网杯2022]WP-UM
The fuse: OAuth 2.0 four authorized login methods must read
PCB layout must know: teach you to correctly lay out the circuit board of the op amp
用KUSTO查询语句(KQL)在Azure Data Explorer Database上查询LOG实战