如果你想对图像进行校准,那么透视变换是非常有效的变换手段。透视变换的定义为将图像投影到一个新的视平面,通常也被称之为投影映射。
在介绍opencv的透视变换函数之前,我们举例来讲解该算法的原理:
直观的来看,透视变换的作用就是将左侧图像的坐标点
[[50,0],[150,0],[0,200],[200,200]]
转化为新的坐标
[[0,0],[200,0],[0,200],[200,200]]
通过计算我们知道,转换矩阵如下:
我们来验证一下,采用左上角的点(50,0)带入公式,如下:
接着我们将列向量的前两维度除以第三维执行归一化:
所以我们知道原图左上角点执行透视变换后的映射关系:
核心代码
#include
#include
using namespace std;
using namespace cv;
struct userdata {
Mat im;
vector<Point2f> points;
};
void mouseHandle(int event, int x, int y, int flags,void* ptr)
{
if (event == EVENT_LBUTTONDOWN)
{
userdata *data = (userdata*)ptr;
circle(data->im, Point(x, y), 3, Scalar(0, 0, 255), 3, CV_AA);
imshow("dst", data->im);
if (data->points.size() < 4)
{
data->points.push_back(Point2f(x, y));
}
}
}
int main()
{
Mat Image = imread("hai.png");
imshow("Image", Image);
vector<Point2f> obj;
obj.push_back(Point2f(0, 0));
obj.push_back(Point2f(Image.cols, 0));
obj.push_back(Point2f(Image.cols, Image.rows));
obj.push_back(Point2f(0, Image.rows));
Mat Image2 = imread("background.jpg");
imshow("Image2", Image2);
Mat dst = Image2.clone();
userdata data;
data.im = dst;
imshow("dst", dst);
setMouseCallback("dst", mouseHandle, &data);
waitKey(0);
//将需要替换的图透视变换到大图进行变换
Mat H = findHomography(obj, data.points, CV_RANSAC);
warpPerspective(Image, dst, H, dst.size());
imshow("result", dst);
Point pts[4];
for (int i = 0; i < 4; i++)
{
pts[i] = data.points[i];
}
//进行填充(0,0,0)
fillConvexPoly(Image2, pts, 4, Scalar(0), CV_AA);
imshow("....", Image2);
//进行或操作
Image2 += dst;
imshow("finally", Image2);
waitKey(0);
}
效果