OpenCV案例(四): 投射矫正
仿射变换是二维坐标间的线性变换, 故而变换后的图像仍然具有原图的一些性质,包括“平直性”以及“平行性”,常用于图像翻转(Flip)、旋转(Rotations)、平移(Translations)、缩放(Scale operations)等,
透视变换(Perspective Transformation),又称投影映射(Projective Mapping)、投射变换等,是三维空间上的非线性变换,可看作是仿射变换的更一般形式,简单讲即通过一个3x3的变换矩阵将原图投影到一个新的视平面(Viewing Plane),在视觉上的直观表现就是产生或消除了远近感。落实到OpenCV,图像的透视变换由以下函数完成(该函数是针对图像的包装,其本质调用getPerspectiveTransform获得投射矩阵,并使用warpPerspective进行投射变换:
投射原理:待更.....
使用方法:使用鼠标分别获得左上,右上,左下和右下四个点的坐标,即可进行投射变换。
代码:
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/opencv.hpp>
#include <math.h>
#include <iostream>
using namespace std;
using namespace cv;
vector<Point> vec;
void on_mouse(int EVENT, int x, int y, int flags, void* userdata)
{
Mat mouse_click = *(Mat*)userdata;
Point p(x, y);
switch (EVENT)
{
case EVENT_LBUTTONDOWN:
{
vec.push_back(p); //读取点击坐标
cout << "X = " << x << " , Y = " << y << endl;
circle(mouse_click, p, 2, Scalar(255), 3);
}
break;
default:break;
}
}
int main()
{
namedWindow("【display】");
Mat grayimg, BinaryImg, morhImage;
Mat img = imread("../img/55.png");
setMouseCallback("【display】", on_mouse, &img);
vector<Point2f> src_corners(4);
vector<Point2f> dest_corners(4);
while (1)
{
if (vec.size() == 4) //获取变换图像的四个点坐标
{
src_corners[0] = vec[0];
src_corners[1] = vec[1];
src_corners[2] = vec[2];
src_corners[3] = vec[3];
dest_corners[0] = vec[0];
dest_corners[1] = Point(vec[3].x,vec[0].y); //1,3坐标当作变换后的对称坐标点
dest_corners[2] = Point(vec[0].x, vec[3].y);
dest_corners[3] = vec[3];
// 获取透视变换矩阵
Mat resultImage;
Mat warpmatrix = getPerspectiveTransform(src_corners, dest_corners); //计算投射矩阵
warpPerspective(img, resultImage, warpmatrix, resultImage.size(), INTER_LINEAR);//投射变换
imshow("投射变换", resultImage);
break;
}
imshow("【display】", img);
waitKey(40);
}
waitKey(0);
}
结果: