版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/dcrmg/article/details/52475777
透视变换通过投影的方式,把当前图像映射到另外一个平面,就像电影院里的交代放映机,如果幕布或者胶带其中任意一个与放映机发出的光纤不是垂直90度角的,那么投影到幕布上的图像就会发生畸变。这种畸变就是透视畸变的一种。
透视变换对畸变图像的校正需要取得畸变图像的一组4个点的坐标,和目标图像的一组4个点的坐标,通过两组坐标点可以计算出透视变换的变换矩阵,之后对整个原始图像执行变换矩阵的变换,就可以实现图像校正。
以下一幅图像中的书由于拍摄时摄像头视角的原因,导致一定程度的畸变:
可以看到距离摄像头越近的点,看起来越大,越远的点看起来越小。对这幅图像透视校正的目的就是要纠正这种形变,得到书的正视角矩形图像,校正效果相当于是从书的正上方视角拍摄的。
例程用Opencv中的warpPerspective方法实现:
-
#include "core/core.hpp"
-
#include "highgui/highgui.hpp"
-
#include "imgproc/imgproc.hpp"
-
-
using
namespace cv;
-
-
void onMouse(int event,int x,int y,int flags,void *utsc);
-
Point2f srcTri[
4],dstTri[
4];
-
int clickTimes=
0;
//在图像上单击次数
-
Mat image;
-
Mat imageWarp;
-
int main(int argc,char *argv[])
-
{
-
image=imread(argv[
1]);
-
imshow(
"Source Image",image);
-
setMouseCallback(
"Source Image",onMouse);
-
waitKey();
-
return
0;
-
}
-
-
void onMouse(int event,int x,int y,int flags,void *utsc)
-
{
-
if(event==CV_EVENT_LBUTTONUP)
//响应鼠标左键抬起事件
-
{
-
circle(image,Point(x,y),
2.5,Scalar(
0,
0,
255),
2.5);
//标记选中点
-
imshow(
"Source Image",image);
-
srcTri[clickTimes].x=x;
-
srcTri[clickTimes].y=y;
-
clickTimes++;
-
}
-
if(clickTimes==
4)
-
{
-
dstTri[
0].x=
0;
-
dstTri[
0].y=
0;
-
dstTri[
1].x=image.rows
-1;
-
dstTri[
1].y=
0;
-
dstTri[
2].x=
0;
-
dstTri[
2].y=image.cols
-161;
-
dstTri[
3].x=image.rows
-1;
-
dstTri[
3].y=image.cols
-161;
-
Mat transform=Mat::zeros(
3,
3,CV_32FC1);
//透视变换矩阵
-
transform=getPerspectiveTransform(srcTri,dstTri);
//获取透视变换矩阵
-
warpPerspective(image,imageWarp,transform,Size(image.rows,image.cols
-160));
//透视变换
-
imshow(
"After WarpPerspecttive",imageWarp);
-
}
-
}
通过鼠标左键单击原始图像书的4个角点,透射到另外一个视平面的4个矩形的角点上,实现畸变校正。
每次点击在原图上画出红色的原点标示出点位:
透视校正效果:
由于拍摄视角倾斜角度比较大,并且转换后的图像有高度方向上的拉伸,所以图像对比度有所下降。