背景知识
OpenCV的例程warpPerspective是用来矫正畸变图像,warpPerspective函数原型为:
CV_EXPORTS_W void 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 :表示插值方法的组合,线性插值或者最近邻插值;如设置了可选项WARP_INVERSE_MAP(变形插值映射),则会使得转换矩阵M为逆变形
borderMode :像素外推方法
borderValue :边界为常量时使用的值,默认为0
=======
除了正式使用的warpPerspective函数以外,还有一个重要的函数---getPerspectiveTransform,获得透视转换矩阵。只有在得到了转换矩阵之后,才可以使用warpPerspective进行转换,且getPerspectiveTransform的值为warpPerspective函数的第三个参数。(说的有点啰嗦了,待会上代码就明白多了)。
getPerspectiveTransform函数原型为:
CV_EXPORTS Mat getPerspectiveTransform( const Point2f src[], const Point2f dst[] );
各个参数含义:
src:输入的原图的四个角点坐标
dst:输出的四个角点坐标,输出图片应是去掉多余的像素,所以四个角点的坐标依次为(0,0),(row,0),(0,col),(row, col);row为输出图像的行数,col为其列数。
========
此代码是在参考原博文https://blog.csdn.net/dcrmg/article/details/52475777的基础上改的,此处手动@-牧野-
代码如下:
#include "core/core.hpp" #include "highgui/highgui.hpp" #include "imgproc/imgproc.hpp" #include <math.h> 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; } float distance(Point2f a, Point2f b) { float y = a.y - b.y; float x = a.x - b.x; return sqrt(pow(x, 2) + pow(y, 2)); } 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) { float disRow = distance(srcTri[0], srcTri[1]); float disCol = distance(srcTri[0], srcTri[2]); dstTri[0].x = 0; dstTri[0].y = 0; dstTri[1].x = disRow; dstTri[1].y = 0; dstTri[2].x = 0; dstTri[2].y = disCol; dstTri[3].x = disRow; dstTri[3].y = disCol; Mat transform = Mat::zeros(3, 3, CV_32FC1); //透视变换矩阵 transform = getPerspectiveTransform(srcTri, dstTri); //获取透视变换矩阵 warpPerspective(image, imageWarp, transform, Size(disRow, disCol)); //透视变换 imshow("After WarpPerspecttive", imageWarp); } }
可以看到,我只是加了一个距离公式算出输出图像的行和列;这样的话使用getPerspectiveTransform函数时会得到较准确的矩阵,也就不必在warpPerspective时自己算出应该减去多少了。
ps:今天属于清明节的第二天假期,在实验室放着音乐,写着第二篇博客,开心。加油吧!