当前位置:网站首页>【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;
}

边栏推荐
猜你喜欢

Confessing in the era of digital transformation: Mai Cong Software allows enterprises to use data in the easiest way

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

创建一个 Dapp,为什么要选择波卡?

上位机开发C#语言:模拟STC串口助手接收单片机发送数据

项目成本控制如何帮助项目成功?

告白数字化转型时代:麦聪软件以最简单的方式让企业把数据用起来

Our Web3 Entrepreneurship Project, Yellow

The host computer develops C# language: simulates the STC serial port assistant to receive the data sent by the microcontroller

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

linux下oracle常见操作以及日常积累知识点(函数、定时任务)
随机推荐
PHP 操作mangoDb
PCB layout must know: teach you to correctly lay out the circuit board of the op amp
PCB布局必知必会:教你正确地布设运算放大器的电路板
[强网杯2022]WP-UM
百年北欧奢华家电品牌ASKO智能三温区酒柜臻献七夕,共品珍馐爱意
Voice-based social software development - making the most of its value
FPGA: Use of the development environment Vivado
The founder of the DFINITY Foundation talks about the ups and downs of the bear market, and where should DeFi projects go?
Huawei's lightweight neural network architecture GhostNet has been upgraded again, and G-GhostNet (IJCV22) has shown its talents on the GPU
SMB + SMB2: Accessing shares return an error after prolonged idle period
RT-Thread记录(一、RT-Thread 版本、RT-Thread Studio开发环境 及 配合CubeMX开发快速上手)
数据可视化(一)
第七章,activiti个人任务分配,动态指定和监听器指定任务委派人「建议收藏」
气象数据数据处理实例——matlab字符串切割匹配与R语言日期匹配(数据拼接)
Use KUSTO query statement (KQL) to query LOG on Azure Data Explorer Database
2022 Huashu Cup Mathematical Modeling Ideas Analysis and Exchange
静态链接和动态链接
单片机:温度控制DS18B20
用KUSTO查询语句(KQL)在Azure Data Explorer Database上查询LOG实战
Confessing in the era of digital transformation: Mai Cong Software allows enterprises to use data in the easiest way