OpenCV : 投影变换
程序员文章站
2023-12-25 17:44:15
...
投影变换
物体在三维空间发生了旋转,叫做投影变换.由于可能出现阴影或遮挡,所以变换后较难复原.如果物体时平面的,就可以通过投影变换物体三维变换进行模型化,这叫做专用的二维投影变换.
矩阵表示:
求投影矩阵
- getPerspectiveTransform(src, dst)
- src : 原坐标
- dst : 变换后的坐标
- 返回结果为:3x3的投影矩阵,数据类型为CV_64F
计算投影矩阵
#include<iostream>
#include<opencv2/core.hpp>
#include<opencv2/highgui.hpp>
#include<opencv2/imgproc.hpp>
using namespace cv;
using namespace std;
int main()
{
//原坐标
Point2f src[] = { Point2f(0, 0), Point2f(20, 0), Point2f(0, 20), Point2f(20, 20) };
//投影后的坐标
Point2f dst[] = { Point2f(10, 20),Point2f(20, 2), Point2f(50, 70), Point2f(25, 7) };
Mat P =getPerspectiveTransform(src, dst);
cout << P << endl;
return 0;
}
#include<iostream>
#include<opencv2/core.hpp>
#include<opencv2/highgui.hpp>
#include<opencv2/imgproc.hpp>
using namespace cv;
using namespace std;
int main()
{
//原坐标
Mat src = (Mat_<float>(4, 2) << 0, 0, 20, 0, 0, 20, 20, 20);
//投影后的坐标
Mat dst = (Mat_<float>(4, 2) << 10, 2, 20, 2, 5, 7, 25, 7);
Mat P =getPerspectiveTransform(src, dst);
cout << P << endl;
return 0;
}
图像的投影变换
- warpPerspective(Mat src, Mat dst, Mat P, Size dsize)
- src : 原图
- dst : 输出图片
- P : 投影矩阵
- dsize : 输出图像大小
- circle(Mat img, Point center, int radius, const Scalar & color, int thickness=1, int lineType=8, int shift=0)
- img : 图像矩阵(2d)
- center : 圆心坐标
- radius : 半径长度
- color : 颜色
- thickness : 线的粗细
- lineType : 线的类型
- OpenCV中其他类似的方法还有:rectangle, ellipse, line(矩形,椭圆,线段)
#include<iostream>
#include<opencv2/core.hpp>
#include<opencv2/highgui.hpp>
#include<opencv2/imgproc.hpp>
using namespace cv;
using namespace std;
int main()
{
Mat img = imread("./People/5g.jpg", 1);
Mat src = (Mat_<float>(4, 2)<< 0, 0, 1000, 0, 0, 1000, 1000, 1000);
Mat dst = (Mat_<float>(4, 2) << 0, 0, 1000, 0, 300, 1000, 600, 1000);
Mat P = getPerspectiveTransform(src, dst);
Mat O;
cout << "rows : " << img.rows << endl;
cout << "cols : " << img.cols << endl;
warpPerspective(img, O, P, img.size());
imshow("PerspectiveTransform", O);
waitKey(0);
return 0;
}
原图
投影后
通过鼠标点击事件,进行图像投影
#include<iostream>
#include<opencv2/core.hpp>
#include<opencv2/highgui.hpp>
#include<opencv2/imgproc.hpp>
using namespace cv;
using namespace std;
Mat I_img; // 输入图片
Mat P_img; // 投影后的图片
Point2f src_point[4]; // 原坐标
Point2f dst_point[4]; // 投影后的坐标
int i = 0, j = 0; // 记录点击次数
Point2f point_i, point_p;
// 同鼠标事件获得原图中坐标
void mouse_I(int event, int x, int y, int flags, void* param)
{
switch (event)
{
case CV_EVENT_LBUTTONDOWN:
point_i = Point2f(x, y);
break;
case CV_EVENT_LBUTTONUP:
src_point[i] = point_i;
circle(I_img, src_point[i], 7, Scalar(0), 3); //画出点击的坐标
i += 1;
break;
default:
break;
}
}
// 在画布上选择投影后的坐标
void mouse_pI(int event, int x, int y, int flags, void* param)
{
switch (event)
{
case CV_EVENT_LBUTTONDOWN:
point_p = Point2f(x, y);
break;
case CV_EVENT_LBUTTONUP:
dst_point[j] = point_p;
circle(P_img, dst_point[j], 7, Scalar(0), 3);
j += 1;
break;
default:
break;
}
}
int main()
{
I_img = imread("./People/5.jpg", CV_LOAD_IMAGE_GRAYSCALE);
if (!I_img.data)
return -1;
P_img = 255 * Mat::ones(I_img.size(), CV_8UC1);
namedWindow("Original Image");
setMouseCallback("Original Image", mouse_I, NULL);
namedWindow("Output Image");
setMouseCallback("Output Image", mouse_pI, NULL);
imshow("Original Image", I_img);
imshow("Output Image", P_img);
while (!(i == 4 && j == 4))
{
imshow("Original Image", I_img);
imshow("Output Image", P_img);
if (waitKey(50) == 'q')
break;
}
imshow("Original Image", I_img);
imshow("Output Image", P_img);
// 撤销鼠标事件
setMouseCallback("Original Image", NULL, NULL);
setMouseCallback("Output Image", NULL, NULL);
// 计算投影矩阵
Mat P = getPerspectiveTransform(src_point, dst_point);
// 投影变换
Mat R;
warpPerspective(I_img, R, P, I_img.size());
imshow("Persepctive Result", R);
waitKey(0);
return 0;
}