透视变换
想更具体了解透视变换原理,请去主页看,此处不具体介绍
目录
仿射变换和透视变幻的区别
仿射变换和透视变换是计算机视觉中常用的图像变换技术。它们之间的主要区别在于变换时是否保持了平行线和直线的性质。
-
仿射变换: 仿射变换是一种线性变换,它保持了直线的性质,包括平行线的关系和直线的比例关系。仿射变换可以进行平移、旋转、缩放和剪切等操作。在仿射变换中,平行线在变换前后仍然保持平行。
应用场合:仿射变换常用于图像校正、图像拼接、图像配准和特征提取等领域。例如,通过仿射变换可以将倾斜的图像校正为正常的姿态,或者将多个图像拼接成全景图像。
-
透视变换: 透视变换是一种非线性变换,它能够改变图像中物体之间的角度关系。透视变换可以将一个平面上的图像映射到另一个平面上,使得远离观察者的物体看起来较小,而靠近观察者的物体看起来较大。透视变换会改变的平行线关系,直线变换后可能是直线、曲线或者折线,具体取决于变换的参数和场景的几何结构。
当透视变换应用于一个平面上的图像时,平行线可能会在变换后相交,从而形成一条曲线。这是因为透视变换会考虑到观察者的视角和远近的效果,导致平行线在远离观察者的方向上会逐渐收敛。
应用场合:透视变换常用于图像校正、三维重建和虚拟现实等领域。例如,在计算机图形学中,透视变换可以将三维场景投影到二维屏幕上,实现逼真的三维效果。
透视变换
1.含义与定义
透视变换又称为四点变换,和仿射变换一样,通常需要得到透视变换矩阵getPerspectiveTransform()
,然后才能通过warpPerspective()
对图像进行透视变换。
之所以称为四点变换,是因为我们得需要通过变换前后的四个点的对应关系才能求得变换矩阵M(3*3矩阵),为什么是四个点,因为变换矩阵有8个未知数(通常令a33=1)而一个点可以提供两个方程:
而透视变换矩阵各个部分所代表的意义如下所示:
其中:a33令其为1,注意:与仿射变换不同,注意其表示平移的参数位置!!
2.密集透变化与稀疏透视变换
2.1密集透视变换(warpPerspective())
密集透视变换是指将一个图像中的每个像素点都通过透视变换映射到另一个图像中,从而实现两个图像之间的对应关系。这种变换方法可以创建一个完整的透视变换图像,其输出图像的每个像素都与输入图像的某个像素对应。一般情况下密集透视变换warpPerspective函数常与函数getPerspectiveTransform一起使用实现对图像的透视校正。
2.2稀疏透视变换
指仅对图像中特定的点或选定的特征点进行透视变换,并将它们映射到另一个图像中的对应点。这种方法通常用于处理具有大量特征点或兴趣点的场景,可以在图像匹配、目标跟踪等应用中起到加速计算的作用。稀疏透视变换perspectiveTransform经常与findhomography一起使用。
源码
1.获取透视变换矩阵
//方式一
Mat cv::getPerspectiveTransform( InputArray src,
InputArray dst,
int solveMethod = DECOMP_LU
)
//方式二
Mat cv::getPerspectiveTransform ( const Point2f src[],
const Point2f dst[],
int solveMethod = DECOMP_LU
)
方式一与方式二不同的是一个输入的是Mat类图像,一个输入的是数组,而其数组内的数据类型是浮点对
Enumerator | |
---|---|
DECOMP_LU | 最佳主轴元素的高斯消元法 |
DECOMP_SVD | 奇异值分解法 |
DECOMP_EIG | 特征值分解法 |
DECOMP_CHOLESKY | Cholesky 分解法 |
DECOMP_QR | QR 分解法 |
DECOMP_NORMAL | 使用正规方程公式,可以与其他的标志一起使用 |
2.透视变换
void cv::warpPerspective ( InputArray src,
OutputArray dst,
InputArray M,
Size dsize,
int flags = INTER_LINEAR,
int borderMode = BORDER_CONSTANT,
const Scalar & borderValue = Scalar()
)
-
src:输入图像矩阵
-
dst:输出图像
-
M:透视矩阵
-
dsize:输出图像尺寸
-
flags:插值方法标志
-
borderMode:像素边界外推方法
-
borderValue:填充边界值
实操
#include<opencv2/opencv.hpp>
#include<iostream>
#include<vector>
using namespace std;
using namespace cv;
int main()
{
Mat img = imread("D://桌面//opencv学习笔记//toushi1.jpg");
if (img.empty())
{
cout << "读取失败!" << endl;
return -1;
}
Point2f src1[4];
Point2f src2[4];
src1[0] = Point2f(46, 507);//左上角坐标,行列值和坐标值正好相反
src1[1] = Point2f(684, 16);//右上
src1[2] = Point2f(640,1198);//左下
src1[3] = Point2f(1247,544);//右下
src2[0] = Point2f(0, 0);//与上面一一对应
src2[1] = Point2f(1279,0);
src2[2] = Point2f(0,1279);
src2[3] = Point2f(1279, 1279);
Mat M,dst;
;
M = getPerspectiveTransform(src1, src2);
warpPerspective(img, dst, M, Size(1280,1280),INTER_LINEAR);
imshow("dst", dst);
waitKey(1);
return 0;
}
实验结果:
注意:本实验用的ImageWatch插件查看四个角点坐标值