当前位置:   article > 正文

【OpenCV】透视变换应用——实现鸟瞰图与贴图_opencv 鸟瞰图

opencv 鸟瞰图

透视变换是3D转换,透视变换的本质是将图像投影到一个新的视平面;

据此,我们可以使用透视变化来实现鸟瞰图和图形贴图的效果;

一、鸟瞰图

实现前:

 实现效果:

 

1.准备一个空的mat对象 用于保存转换后的图

  1. Mat image=imread("road.jpg");
  2. imshow("image",image);
  3. Mat result=Mat::zeros(500,600,CV_8UC1);
  4. //存储转换后的图像坐标 按顺时针 左上、右上、右下、左下(可自己定顺序)
  5. vector<Point2f> obj;
  6. obj.push_back(Point2f(0,0));
  7. obj.push_back(Point2f(600,0));
  8. obj.push_back(Point2f(600,500));
  9. obj.push_back(Point2f(0,500));

2.在原图窗口里做鼠标操作,通过setMouseCallback鼠标回调函数,获取原图四个坐标

在原图中点击四个点获取四个坐标,顺序与上述1中设置的坐标对应,如果1中是顺时针,按选择坐标时也应该按顺时针操作,并且按照左上、右上、右下、左下顺序;

  1. //2.在原图窗口里做鼠标操作,通过鼠标回调函数,获取原图四个坐标
  2. struct imagedata data;
  3. data.img=image;//将原图传入
  4. setMouseCallback("image",mouseHundle,&data);//鼠标回调函数
  5. waitKey(0);//键盘输入 向下执行
  6. //点击按键之后结束鼠标操作,得到原图四个坐标和转换后的坐标
  1. //用到的结构体和鼠标处理函数
  2. struct imagedata
  3. {
  4. Mat img;
  5. vector<Point2f>points;
  6. //该points是test1原图需要做转换的坐标
  7. //test2中是原图转换后的坐标
  8. };
  9. void mouseHundle(int event,int x,int y,int flag,void *arg)
  10. {
  11. struct imagedata* ind=(struct imagedata *)arg;
  12. if(event==EVENT_LBUTTONDOWN)//鼠标左键按下
  13. {
  14. //画圆
  15. circle(ind->img,Point(x,y),3,Scalar(0,0,255),3,CV_AA);
  16. imshow("image",ind->img);//test1鸟瞰图显示原图带圆点
  17. //imshow("dst",ind->img);//test2贴图显示city图带圆点
  18. if(ind->points.size()<4)
  19. {
  20. ind->points.push_back(Point2f(x,y));//转换的坐标只需要收集四个
  21. }
  22. }
  23. }

3.开始计算坐标映射矩阵

Mat res=findHomography(data.points,obj,CV_RANSAC);

4.进行透视转换

将原图转变为效果图进行显示

  1. warpPerspective(image,result,res,result.size());
  2. imshow("result",result);
  3. waitKey(0);

二、贴图

city图实现前: 

 贴图实现后:

左边大屏幕更改

 贴图与鸟瞰图有些不同,鸟瞰图是将一张原图,通过选择四个点转换成鸟瞰图;

转换后的坐标固定的,转换前的4个坐标由鼠标选择;

而贴图的话,是将原图通过选择的点进行转换,再贴到city图中;

转换前的坐标固定的,就是普通的图片,转换后的坐标由鼠标选择;

1.准备原图要贴上去的图,即1.jpg

  1. Mat image1=imread("1.jpg");//原图
  2. Mat image2=imread("city.jpg");//city图
  3. Mat dst=image2.clone();//克隆一份城市图
  4. //1.准备原图要贴上去的图,即1.jpg
  5. //Mat result=Mat::zeros(image1.rows,image1.cols,CV_8UC1);
  6. //存储转换前的图像坐标
  7. vector<Point2f> obj;
  8. obj.push_back(Point2f(0,0));
  9. obj.push_back(Point2f(image1.cols,0));
  10. obj.push_back(Point2f(image1.cols,image1.rows));
  11. obj.push_back(Point2f(0,image1.rows));
  12. imshow("dst",image2);

2.在city窗口里做鼠标操作,通过鼠标回调函数,获取转换后的四个坐标

  1. struct imagedata data;
  2. data.img=dst;//将city图传入
  3. setMouseCallback("dst",mouseHundle,&data);//鼠标回调函数
  4. waitKey(0);

 3.开始计算坐标映射矩阵

  1. //点击按键之后结束鼠标操作,得到原图四个坐标和转换后的坐标
  2. Mat res=findHomography(obj,data.points,CV_RANSAC);

 4.透视转换

  1. warpPerspective(image1,dst,res,dst.size());
  2. imshow("image1",dst);

 做到这一步,将原图变成这样子

 

5. 获取四个坐标,将city图中选择的位置填充成黑色,防止两个图片颜色冲突

最后通过image2+=dst把图片贴到city图上,这样就完成了

  1. Point pts[4];
  2. for(int i=0;i<4;i++)
  3. {
  4. pts[i]=data.points[i];
  5. }
  6. //在city图中选择的位置填充成黑色,防止两图颜色冲突
  7. fillConvexPoly(image2,pts,4,Scalar(0),CV_AA);
  8. image2+=dst;//把图片贴到city图上
  9. imshow("final",image2);
  10. waitKey(0);

 完整源码

  1. #include <iostream>
  2. #include <opencv2/opencv.hpp>
  3. using namespace std;
  4. using namespace cv;
  5. struct imagedata
  6. {
  7. Mat img;
  8. vector<Point2f>points;
  9. //该points是test1原图需要做转换的坐标
  10. //test2中是原图转换后的坐标
  11. };
  12. void mouseHundle(int event,int x,int y,int flag,void *arg)
  13. {
  14. struct imagedata* ind=(struct imagedata *)arg;
  15. if(event==EVENT_LBUTTONDOWN)//鼠标左键按下
  16. {
  17. //画圆
  18. circle(ind->img,Point(x,y),3,Scalar(0,0,255),3,CV_AA);
  19. //imshow("image",ind->img);//test1显示原图带圆点
  20. imshow("dst",ind->img);//test2显示city图带圆点
  21. if(ind->points.size()<4)
  22. {
  23. ind->points.push_back(Point2f(x,y));//转换的坐标只需要收集四个
  24. }
  25. }
  26. }
  27. void test1()
  28. {
  29. Mat image=imread("road.jpg");
  30. imshow("image",image);
  31. //1.准备空的mat对象 用于保存转换后的图
  32. Mat result=Mat::zeros(500,600,CV_8UC1);
  33. //存储转换后的图像坐标 按顺时针 左上、右上、右下、做下(可自己定顺序)
  34. vector<Point2f> obj;
  35. obj.push_back(Point2f(0,0));
  36. obj.push_back(Point2f(600,0));
  37. obj.push_back(Point2f(600,500));
  38. obj.push_back(Point2f(0,500));
  39. //2.在原图窗口里做鼠标操作,通过鼠标回调函数,获取原图四个坐标
  40. struct imagedata data;
  41. data.img=image;//将原图传入
  42. setMouseCallback("image",mouseHundle,&data);//鼠标回调函数
  43. waitKey(0);
  44. //点击按键之后结束鼠标操作,得到原图四个坐标和转换后的坐标
  45. //3.开始计算坐标映射矩阵
  46. Mat res=findHomography(data.points,obj,CV_RANSAC);
  47. //4.透视转换
  48. warpPerspective(image,result,res,result.size());
  49. imshow("result",result);
  50. waitKey(0);
  51. }
  52. void test2()
  53. {
  54. Mat image1=imread("1.jpg");
  55. Mat image2=imread("city.jpg");
  56. Mat dst=image2.clone();//克隆一份城市图
  57. //1.准备原图要贴上去的图,即1.jpg
  58. //Mat result=Mat::zeros(image1.rows,image1.cols,CV_8UC1);
  59. //存储转换前的图像坐标
  60. vector<Point2f> obj;
  61. obj.push_back(Point2f(0,0));
  62. obj.push_back(Point2f(image1.cols,0));
  63. obj.push_back(Point2f(image1.cols,image1.rows));
  64. obj.push_back(Point2f(0,image1.rows));
  65. imshow("dst",image2);
  66. //2.在city窗口里做鼠标操作,通过鼠标回调函数,获取需要四个坐标
  67. struct imagedata data;
  68. data.img=dst;//将city图传入
  69. setMouseCallback("dst",mouseHundle,&data);//鼠标回调函数
  70. waitKey(0);
  71. //点击按键之后结束鼠标操作,得到原图四个坐标和转换后的坐标
  72. //3.开始计算坐标映射矩阵
  73. Mat res=findHomography(obj,data.points,CV_RANSAC);
  74. //4.透视转换
  75. warpPerspective(image1,dst,res,dst.size());
  76. imshow("image1",dst);
  77. Point pts[4];
  78. for(int i=0;i<4;i++)
  79. {
  80. pts[i]=data.points[i];
  81. }
  82. //在city图中选择的位置填充成黑色,防止两图颜色冲突
  83. fillConvexPoly(image2,pts,4,Scalar(0),CV_AA);
  84. image2+=dst;//把图片贴到city图上
  85. imshow("final",image2);
  86. waitKey(0);
  87. }
  88. int main()
  89. {
  90. //test1();
  91. test2();
  92. return 0;
  93. }

感谢观看!!!!

以上就是全部内容,如果对您有帮助,欢迎点赞评论,或者发现有哪里写错的,欢迎指正!

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/869657
推荐阅读
相关标签
  

闽ICP备14008679号