当前位置:网站首页>【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)
第六个参数:边界像素模式
第七个参数:在恒定的边界情况下取值,默认值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;
}
边栏推荐
- 012年通过修补_sss_提高扩散模型效率
- 机器学习-基础知识 - Precision, Recall, Sensitivity, Specificity, Accuracy, FNR, FPR, TPR, TNR, F1 Score, Bal
- 【综合类型第 35 篇】程序员的七夕浪漫时刻
- First Decentralized Heist?Loss of nearly 200 million US dollars: analysis of the attack on the cross-chain bridge Nomad
- three物体围绕一周呈球形排列
- three.js debugging tool dat.gui use
- The query that the user's test score is greater than the average score of a single subject
- Chapter 4: In the activiti process, variable transmission and acquisition process variables, setting and acquiring multiple process variables, setting and acquiring local process variables "recommende
- SQL Outer Join Intersection, Union, Difference Query
- The century-old Nordic luxury home appliance brand ASKO smart wine cabinet in the three-temperature area presents the Chinese Valentine’s Day, and tastes the love of the delicacy
猜你喜欢
Introduction to SD NAND Flash!
一文道清什么是SPL
SQL Outer Join Intersection, Union, Difference Query
产品太多了,如何实现一次登录多产品互通?
华为轻量级神经网络架构GhostNet再升级,GPU上大显身手的G-GhostNet(IJCV22)
SQL外连接之交集、并集、差集查询
Meteorological data processing example - matlab string cutting matching and R language date matching (data splicing)
linux下oracle常见操作以及日常积累知识点(函数、定时任务)
three.js调试工具dat.gui使用
【MindSpore易点通机器人-01】你也许见过很多知识问答机器人,但这个有点不一样
随机推荐
第五章:多线程通信—wait和notify
第六章:activiti流程分流判断之排它网关和并行网关
攻防世界-PWN-new_easypwn
使用工具类把对象中的null值转换为空字符串(集合也可以使用)
Confessing in the era of digital transformation: Mai Cong Software allows enterprises to use data in the easiest way
STM32+ULN2003 drives 28BYJ4 stepper motor (forward and reverse according to the number of turns)
开发常用手册链接分享
three.js debugging tool dat.gui use
如何测试一下现场的备机失败,转发主机的场景?
Login function and logout function (St. Regis Takeaway)
js劫持数组push方法
电竞、便捷、高效、安全,盘点OriginOS功能的关键词
Introduction to SD NAND Flash!
PCB layout must know: teach you to correctly lay out the circuit board of the op amp
How to choose coins and determine the corresponding strategy research
告白数字化转型时代:麦聪软件以最简单的方式让企业把数据用起来
牛刀小试基本语法,Go lang1.18入门精炼教程,由白丁入鸿儒,go lang基本语法和变量的使用EP02
力扣(LeetCode)216. 组合总和 III(2022.08.04)
Opencv图像缩放和平移
Brief Analysis of WSGI Protocol