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

边栏推荐
- three objects are arranged in a spherical shape around the circumference
- PHP operation mangoDb
- SQL外连接之交集、并集、差集查询
- 机器学习-基础知识 - Precision, Recall, Sensitivity, Specificity, Accuracy, FNR, FPR, TPR, TNR, F1 Score, Bal
- What are the standards for electrical engineering
- 2022华数杯数学建模思路分析交流
- 基于MindSpore高效完成图像分割,实现Dice!
- STM32+ULN2003驱动28BYJ4步进电机(根据圈数正转、反转)
- Confessing in the era of digital transformation: Mai Cong Software allows enterprises to use data in the easiest way
- 第六章:activiti流程分流判断之排它网关和并行网关
猜你喜欢

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

FPGA:开发环境Vivado的使用

字节一面:TCP 和 UDP 可以使用同一个端口吗?

Common operations of oracle under linux and daily accumulation of knowledge points (functions, timed tasks)

Getting started with Polkadot parachain development, this article is enough

Ali's new launch: Microservices Assault Manual, all operations are written out in PDF

Use KUSTO query statement (KQL) to query LOG on Azure Data Explorer Database

PCB layout must know: teach you to correctly lay out the circuit board of the op amp

What is SPL?

项目成本控制如何帮助项目成功?
随机推荐
【MindSpore Easy-Diantong Robot-01】You may have seen many knowledge quiz robots, but this one is a bit different
The JVM collection that Alibaba's top architects have summarized for many years, where can't I check it!
2022 Huashu Cup Mathematical Modeling Ideas Analysis and Exchange
Getting started with Polkadot parachain development, this article is enough
第五章:多线程通信—wait和notify
60行从零开始自己动手写FutureTask是什么体验?
uniapp connect ibeacon
电竞、便捷、高效、安全,盘点OriginOS功能的关键词
Oracle 19.3 restart 环境
LeetCode 216. Combined Sum III (2022.08.04)
SQL Outer Join Intersection, Union, Difference Query
数分面试(一)----与业务相关
What are the standards for electrical engineering
一文道清什么是SPL
Still looking for a network backup resources?Hurry up to collect the following network backup resource search artifact it is worth collecting!
[Office] Collection of Microsoft Office download addresses (offline installation and download of Microsoft's official original version)
SD NAND Flash简介!
Opencv算术操作
第五章:activiti流程分流判断,判断走不同的任务节点
NowCoderTOP35-40——持续更新ing