赞
踩
透视变换是3D转换,透视变换的本质是将图像投影到一个新的视平面;
据此,我们可以使用透视变化来实现鸟瞰图和图形贴图的效果;
实现前:
实现效果:
- Mat image=imread("road.jpg");
- imshow("image",image);
- Mat result=Mat::zeros(500,600,CV_8UC1);
- //存储转换后的图像坐标 按顺时针 左上、右上、右下、左下(可自己定顺序)
- vector<Point2f> obj;
- obj.push_back(Point2f(0,0));
- obj.push_back(Point2f(600,0));
- obj.push_back(Point2f(600,500));
- obj.push_back(Point2f(0,500));
在原图中点击四个点获取四个坐标,顺序与上述1中设置的坐标对应,如果1中是顺时针,按选择坐标时也应该按顺时针操作,并且按照左上、右上、右下、左下顺序;
- //2.在原图窗口里做鼠标操作,通过鼠标回调函数,获取原图四个坐标
- struct imagedata data;
- data.img=image;//将原图传入
- setMouseCallback("image",mouseHundle,&data);//鼠标回调函数
- waitKey(0);//键盘输入 向下执行
- //点击按键之后结束鼠标操作,得到原图四个坐标和转换后的坐标
- //用到的结构体和鼠标处理函数
- struct imagedata
- {
- Mat img;
- vector<Point2f>points;
- //该points是test1原图需要做转换的坐标
- //在test2中是原图转换后的坐标
- };
-
- void mouseHundle(int event,int x,int y,int flag,void *arg)
- {
- struct imagedata* ind=(struct imagedata *)arg;
- if(event==EVENT_LBUTTONDOWN)//鼠标左键按下
- {
- //画圆
- circle(ind->img,Point(x,y),3,Scalar(0,0,255),3,CV_AA);
- imshow("image",ind->img);//test1鸟瞰图显示原图带圆点
- //imshow("dst",ind->img);//test2贴图显示city图带圆点
- if(ind->points.size()<4)
- {
- ind->points.push_back(Point2f(x,y));//转换的坐标只需要收集四个
- }
- }
- }

Mat res=findHomography(data.points,obj,CV_RANSAC);
将原图转变为效果图进行显示
- warpPerspective(image,result,res,result.size());
- imshow("result",result);
- waitKey(0);
city图实现前:
贴图实现后:
左边大屏幕更改
贴图与鸟瞰图有些不同,鸟瞰图是将一张原图,通过选择四个点转换成鸟瞰图;
转换后的坐标固定的,转换前的4个坐标由鼠标选择;
而贴图的话,是将原图通过选择的点进行转换,再贴到city图中;
转换前的坐标固定的,就是普通的图片,转换后的坐标由鼠标选择;
- Mat image1=imread("1.jpg");//原图
- Mat image2=imread("city.jpg");//city图
- Mat dst=image2.clone();//克隆一份城市图
- //1.准备原图要贴上去的图,即1.jpg
- //Mat result=Mat::zeros(image1.rows,image1.cols,CV_8UC1);
- //存储转换前的图像坐标
- vector<Point2f> obj;
- obj.push_back(Point2f(0,0));
- obj.push_back(Point2f(image1.cols,0));
- obj.push_back(Point2f(image1.cols,image1.rows));
- obj.push_back(Point2f(0,image1.rows));
-
- imshow("dst",image2);
- struct imagedata data;
- data.img=dst;//将city图传入
- setMouseCallback("dst",mouseHundle,&data);//鼠标回调函数
- waitKey(0);
- //点击按键之后结束鼠标操作,得到原图四个坐标和转换后的坐标
- Mat res=findHomography(obj,data.points,CV_RANSAC);
- warpPerspective(image1,dst,res,dst.size());
- imshow("image1",dst);
做到这一步,将原图变成这样子
最后通过image2+=dst把图片贴到city图上,这样就完成了
- Point pts[4];
- for(int i=0;i<4;i++)
- {
- pts[i]=data.points[i];
- }
- //在city图中选择的位置填充成黑色,防止两图颜色冲突
- fillConvexPoly(image2,pts,4,Scalar(0),CV_AA);
-
- image2+=dst;//把图片贴到city图上
- imshow("final",image2);
- waitKey(0);
完整源码
- #include <iostream>
- #include <opencv2/opencv.hpp>
- using namespace std;
- using namespace cv;
-
- struct imagedata
- {
- Mat img;
- vector<Point2f>points;
- //该points是test1原图需要做转换的坐标
- //在test2中是原图转换后的坐标
- };
-
- void mouseHundle(int event,int x,int y,int flag,void *arg)
- {
- struct imagedata* ind=(struct imagedata *)arg;
- if(event==EVENT_LBUTTONDOWN)//鼠标左键按下
- {
- //画圆
- circle(ind->img,Point(x,y),3,Scalar(0,0,255),3,CV_AA);
- //imshow("image",ind->img);//test1显示原图带圆点
- imshow("dst",ind->img);//test2显示city图带圆点
- if(ind->points.size()<4)
- {
- ind->points.push_back(Point2f(x,y));//转换的坐标只需要收集四个
- }
- }
- }
-
- void test1()
- {
- Mat image=imread("road.jpg");
- imshow("image",image);
-
- //1.准备空的mat对象 用于保存转换后的图
- Mat result=Mat::zeros(500,600,CV_8UC1);
- //存储转换后的图像坐标 按顺时针 左上、右上、右下、做下(可自己定顺序)
- vector<Point2f> obj;
- obj.push_back(Point2f(0,0));
- obj.push_back(Point2f(600,0));
- obj.push_back(Point2f(600,500));
- obj.push_back(Point2f(0,500));
-
- //2.在原图窗口里做鼠标操作,通过鼠标回调函数,获取原图四个坐标
- struct imagedata data;
- data.img=image;//将原图传入
- setMouseCallback("image",mouseHundle,&data);//鼠标回调函数
- waitKey(0);
- //点击按键之后结束鼠标操作,得到原图四个坐标和转换后的坐标
- //3.开始计算坐标映射矩阵
- Mat res=findHomography(data.points,obj,CV_RANSAC);
-
- //4.透视转换
- warpPerspective(image,result,res,result.size());
- imshow("result",result);
- waitKey(0);
- }
- void test2()
- {
- Mat image1=imread("1.jpg");
- Mat image2=imread("city.jpg");
- Mat dst=image2.clone();//克隆一份城市图
-
- //1.准备原图要贴上去的图,即1.jpg
- //Mat result=Mat::zeros(image1.rows,image1.cols,CV_8UC1);
- //存储转换前的图像坐标
- vector<Point2f> obj;
- obj.push_back(Point2f(0,0));
- obj.push_back(Point2f(image1.cols,0));
- obj.push_back(Point2f(image1.cols,image1.rows));
- obj.push_back(Point2f(0,image1.rows));
-
- imshow("dst",image2);
-
- //2.在city窗口里做鼠标操作,通过鼠标回调函数,获取需要四个坐标
- struct imagedata data;
- data.img=dst;//将city图传入
- setMouseCallback("dst",mouseHundle,&data);//鼠标回调函数
- waitKey(0);
- //点击按键之后结束鼠标操作,得到原图四个坐标和转换后的坐标
- //3.开始计算坐标映射矩阵
- Mat res=findHomography(obj,data.points,CV_RANSAC);
-
- //4.透视转换
- warpPerspective(image1,dst,res,dst.size());
- imshow("image1",dst);
-
- Point pts[4];
- for(int i=0;i<4;i++)
- {
- pts[i]=data.points[i];
- }
- //在city图中选择的位置填充成黑色,防止两图颜色冲突
- fillConvexPoly(image2,pts,4,Scalar(0),CV_AA);
-
- image2+=dst;//把图片贴到city图上
- imshow("final",image2);
- waitKey(0);
- }
-
- int main()
- {
- //test1();
- test2();
- return 0;
- }

感谢观看!!!!
以上就是全部内容,如果对您有帮助,欢迎点赞评论,或者发现有哪里写错的,欢迎指正!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。