当前位置:网站首页>【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;
}
边栏推荐
- Login function and logout function (St. Regis Takeaway)
- 数据中台建设(十):数据安全管理
- 牛刀小试基本语法,Go lang1.18入门精炼教程,由白丁入鸿儒,go lang基本语法和变量的使用EP02
- Development common manual link sharing
- 浅析WSGI协议
- 第四章:activiti流程中,变量的传递和获取流程变量 ,设置和获取多个流程变量,设置和获取局部流程变量「建议收藏」
- 第八章:activiti多用户任务分配
- The JVM collection that Alibaba's top architects have summarized for many years, where can't I check it!
- 第五章:activiti流程分流判断,判断走不同的任务节点
- 告白数字化转型时代:麦聪软件以最简单的方式让企业把数据用起来
猜你喜欢
three.js调试工具dat.gui使用
RT - Thread record (a, RT, RT Thread version - Thread Studio development environment and cooperate CubeMX quick-and-dirty)
上位机开发C#语言:模拟STC串口助手接收单片机发送数据
入门 Polkadot 平行链开发,看这一篇就够了
DFINITY 基金会创始人谈熊市沉浮,DeFi 项目该何去何从
2022华数杯数学建模A题环形振荡器的优化设计思路思路代码分享
阿里全新推出:微服务突击手册,把所有操作都写出来了PDF
Still looking for a network backup resources?Hurry up to collect the following network backup resource search artifact it is worth collecting!
E-sports, convenience, efficiency, security, key words for OriginOS functions
STM32+ULN2003 drives 28BYJ4 stepper motor (forward and reverse according to the number of turns)
随机推荐
STM32+ULN2003 drives 28BYJ4 stepper motor (forward and reverse according to the number of turns)
Still looking for a network backup resources?Hurry up to collect the following network backup resource search artifact it is worth collecting!
上位机开发C#语言:模拟STC串口助手接收单片机发送数据
[强网杯2022]WP-UM
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
企业的数字化转型到底是否可以买来?
High-quality DeFi application building guide to help developers enjoy DeFi Summer
What is SPL?
Header file search rules when compiling with GCC
Score interview (1)----related to business
七夕来袭!还要做CDH数据迁移怎么办?来看看DistCp
深入理解 Istio 流量管理的超时时间设置
你最隐秘的性格在哪?
第五章:redis持久化,包括rdb和aof两种方式[通俗易懂]
60行从零开始自己动手写FutureTask是什么体验?
导火索:OAuth 2.0四种授权登录方式必读
开发常用手册链接分享
QSS 选择器
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?