参考教程 https://blog.csdn.net/liuphahaha/article/details/50719275

什么是Homography 
在图1中有两张书的平面图,两张图分别有四个相对位置相同的点,Homography就是一个变换(3*3矩阵),将一张图中的点映射到另一张图中对应的点

如何得到一个Homography

要得到两张图片的H,就必须至少知道4个相同对应位置的点,opencv中可以利用findHomography正确得到

  1. //pts_src和pts_dst是源图像和目标图像中的点矢量。它们是vector <Point2f>类型。我们需要至少4个对应点。
  2.  
  3. Mat h = findHomography(pts_src, pts_dst);
  4.  
  5. //计算出的单应性可用于将源图像扭曲到目标。 im_src和im_dst属于Mat类型。大小是im_dst的大小(宽度,高度)。
  6.  
  7. warpPerspective(im_src, im_dst, h, size);

 OpenCV C++ Homography的一个简单例子: 

  1. #include "opencv2/opencv.hpp"
  2.  
  3. using namespace cv;
  4. using namespace std;
  5.  
  6. int main( int argc, char** argv)
  7. {
  8. // Read source image.
  9. Mat im_src = imread("book2.jpg");
  10. // Four corners of the book in source image
  11. vector<Point2f> pts_src;
  12. pts_src.push_back(Point2f(141, 131));
  13. pts_src.push_back(Point2f(480, 159));
  14. pts_src.push_back(Point2f(493, 630));
  15. pts_src.push_back(Point2f(64, 601));
  16.  
  17. // Read destination image.
  18. Mat im_dst = imread("book1.jpg");
  19. // Four corners of the book in destination image.
  20. vector<Point2f> pts_dst;
  21. pts_dst.push_back(Point2f(318, 256));
  22. pts_dst.push_back(Point2f(534, 372));
  23. pts_dst.push_back(Point2f(316, 670));
  24. pts_dst.push_back(Point2f(73, 473));
  25.  
  26. // Calculate Homography
  27. Mat h = findHomography(pts_src, pts_dst);
  28.  
  29. // Output image
  30. Mat im_out;
  31. // Warp source image to destination based on homography
  32. warpPerspective(im_src, im_out, h, im_dst.size());
  33.  
  34. // Display images
  35. imshow("Source Image", im_src);
  36. imshow("Destination Image", im_dst);
  37. imshow("Warped Source Image", im_out);
  38.  
  39. waitKey(0);
  40. }

  

Homography应用:图像矫正
假设你有一张如下所示的图片

你想点击图中书的四个顶点,然后得到正放的书:

该如何做? 
利用Homography可以做到这点。 
1.首先获取书本四个顶点的坐标 pts_src 
2.然后我们需要知道书本的宽高比,此书的宽高比是3/4,所以可使输出图像的size 为300*400,就可设其四个点的坐标为(0,0),(299,0),(299,399),(0,399)保存在pts_dst中 
3.通过pts_src和pts_dst 获取homography 
4.对原图应用homography 得到输出

  1. #include <opencv2/opencv.hpp>
  2.  
  3. using namespace cv;
  4. using namespace std;
  5.  
  6. struct userdata{
  7. Mat im;
  8. vector<Point2f> points;
  9. };
  10.  
  11. void mouseHandler(int event, int x, int y, int flags, void* data_ptr)
  12. {
  13. if ( event == EVENT_LBUTTONDOWN )
  14. {
  15. userdata *data = ((userdata *) data_ptr);
  16. circle(data->im, Point(x,y),3,Scalar(0,0,255), 5, CV_AA);
  17. imshow("Image", data->im);
  18. if (data->points.size() < 4)
  19. {
  20. data->points.push_back(Point2f(x,y));
  21. }
  22. }
  23.  
  24. }
  25.  
  26. void main()
  27. {
  28.  
  29. // Read source image.
  30. Mat im_src = imread("book1.jpg");
  31.  
  32. // Destination image. The aspect ratio of the book is 3/4
  33. Size size(300,400);
  34. Mat im_dst = Mat::zeros(size,CV_8UC3);
  35.  
  36. // Create a vector of destination points.
  37. vector<Point2f> pts_dst;
  38.  
  39. pts_dst.push_back(Point2f(0,0));
  40. pts_dst.push_back(Point2f(size.width - 1, 0));
  41. pts_dst.push_back(Point2f(size.width - 1, size.height -1));
  42. pts_dst.push_back(Point2f(0, size.height - 1 ));
  43.  
  44. // Set data for mouse event
  45. Mat im_temp = im_src.clone();
  46. userdata data;
  47. data.im = im_temp;
  48.  
  49. cout << "Click on the four corners of the book -- top left first and" << endl
  50. << "bottom left last -- and then hit ENTER" << endl;
  51.  
  52. // Show image and wait for 4 clicks.
  53. imshow("Image", im_temp);
  54. // Set the callback function for any mouse event
  55. setMouseCallback("Image", mouseHandler, &data);
  56. waitKey(0);
  57.  
  58. // Calculate the homography
  59. Mat h = findHomography(data.points, pts_dst);
  60.  
  61. // Warp source image to destination
  62. warpPerspective(im_src, im_dst, h, size);
  63.  
  64. // Show image
  65. imshow("Image", im_dst);
  66. waitKey(0);
  67.  
  68. }

  

Homography应用:虚拟广告牌

在足球或者棒球体育直播中,经常可以看到球场旁边有虚拟广告,并且还会根据地区,国家的不同播放不同的广告,这是如何做到的? 
看完此篇博客,你应该就能知道如何实现了。原理跟前一个差不多,这里直接上代码

  1. #include <opencv2/opencv.hpp>
  2.  
  3. using namespace cv;
  4. using namespace std;
  5.  
  6. struct userdata{
  7. Mat im;
  8. vector<Point2f> points;
  9. };
  10.  
  11. void mouseHandler(int event, int x, int y, int flags, void* data_ptr)
  12. {
  13. if ( event == EVENT_LBUTTONDOWN )
  14. {
  15. userdata *data = ((userdata *) data_ptr);
  16. circle(data->im, Point(x,y),3,Scalar(0,255,255), 5, CV_AA);
  17. imshow("Image", data->im);
  18. if (data->points.size() < 4)
  19. {
  20. data->points.push_back(Point2f(x,y));
  21. }
  22. }
  23.  
  24. }
  25.  
  26. int main( int argc, char** argv)
  27. {
  28.  
  29. // Read in the image.
  30. Mat im_src = imread("first-image.jpg");
  31. Size size = im_src.size();
  32.  
  33. // Create a vector of points.
  34. vector<Point2f> pts_src;
  35. pts_src.push_back(Point2f(0,0));
  36. pts_src.push_back(Point2f(size.width - 1, 0));
  37. pts_src.push_back(Point2f(size.width - 1, size.height -1));
  38. pts_src.push_back(Point2f(0, size.height - 1 ));
  39.  
  40. // Destination image
  41. Mat im_dst = imread("times-square.jpg");
  42.  
  43. // Set data for mouse handler
  44. Mat im_temp = im_dst.clone();
  45. userdata data;
  46. data.im = im_temp;
  47.  
  48. //show the image
  49. imshow("Image", im_temp);
  50.  
  51. cout << "Click on four corners of a billboard and then press ENTER" << endl;
  52. //set the callback function for any mouse event
  53. setMouseCallback("Image", mouseHandler, &data);
  54. waitKey(0);
  55.  
  56. // Calculate Homography between source and destination points
  57. Mat h = findHomography(pts_src, data.points);
  58.  
  59. // Warp source image
  60. warpPerspective(im_src, im_temp, h, im_temp.size());
  61.  
  62. // Extract four points from mouse data
  63. Point pts_dst[4];
  64. for( int i = 0; i < 4; i++)
  65. {
  66. pts_dst[i] = data.points[i];
  67. }
  68.  
  69. // Black out polygonal area in destination image.
  70. fillConvexPoly(im_dst, pts_dst, 4, Scalar(0), CV_AA);
  71.  
  72. // Add warped source image to destination image.
  73. im_dst = im_dst + im_temp;
  74.  
  75. // Display image.
  76. imshow("Image", im_dst);
  77. waitKey(0);
  78.  
  79. return 0;
  80. }

  

结果

开源项目(7)Opencv日常之Homography的更多相关文章

  1. C#.NET开源项目、机器学习、Power BI

    [总目录]本博客博文总目录-实时更新   阅读目录 1.开源Math.NET基础数学类库使用系列 2.C#操作Excel组件Spire.XLS文章目录 3.彩票数据资料库文章 4.数据挖掘与机器学习相 ...

  2. 转:基于开源项目OpenCV的人脸识别Demo版整理(不仅可以识别人脸,还可以识别眼睛鼻子嘴等)【模式识别中的翘楚】

    文章来自于:http://blog.renren.com/share/246648717/8171467499 基于开源项目OpenCV的人脸识别Demo版整理(不仅可以识别人脸,还可以识别眼睛鼻子嘴 ...

  3. .Net 开源项目资源大全

    伯乐在线已在 GitHub 上发起「DotNet 资源大全中文版」的整理.欢迎扩散.欢迎加入. https://github.com/jobbole/awesome-dotnet-cn (注:下面用 ...

  4. Github上关于iOS的各种开源项目集合(强烈建议大家收藏,查看,总有一款你需要)

    下拉刷新 EGOTableViewPullRefresh - 最早的下拉刷新控件. SVPullToRefresh - 下拉刷新控件. MJRefresh - 仅需一行代码就可以为UITableVie ...

  5. GitHub上史上最全的Android开源项目分类汇总 (转)

    GitHub上史上最全的Android开源项目分类汇总 标签: github android 开源 | 发表时间:2014-11-23 23:00 | 作者:u013149325 分享到: 出处:ht ...

  6. iOS及Mac开源项目和学习资料【超级全面】

    UI 下拉刷新 EGOTableViewPullRefresh – 最早的下拉刷新控件. SVPullToRefresh – 下拉刷新控件. MJRefresh – 仅需一行代码就可以为UITable ...

  7. iOS开发--iOS及Mac开源项目和学习资料

    文/零距离仰望星空(简书作者)原文链接:http://www.jianshu.com/p/f6cdbc8192ba著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”. 原文出处:codecl ...

  8. iOS、mac开源项目及库汇总

    原文地址:http://blog.csdn.net/qq_26359763/article/details/51076499    iOS每日一记------------之 中级完美大整理 iOS.m ...

  9. iOS、mac开源项目及库(感谢原作者的分享)

    目录 模糊效果 富文本 表相关 HUD与Toast 其他UI 其他动画 网络测试 网络聊天 Model 数据库 PDF 摄像照相视频音频处理 消息相关 消息推送服务器端 版本新API的Demo 测试及 ...

随机推荐

  1. golang面对对象

  2. LaTeX 小试牛刀

    跟大家分享一下正式第一次使用 LaTex 的经验,之前数学建模的时候一直想用,但没有找到合适的软件.前段时间,实验室老师让我帮忙套个 IEEE ACCESS 的模板. 尝试过 TexPad,的确 UI ...

  3. C#简单构架之EF进行读写分离+多数据库Mysql/SqlServer

    http://www.php361.com/index.php?c=index&a=view&id=3857 不建议用,太重的框架EF,仅仅参考一下别人的思路就好. [导读]最近因为项 ...

  4. 整理:WPF中Binding的几种写法

    原文:整理:WPF中Binding的几种写法 目的:整理WPF中Bind的写法 <!--绑定到DataContext--> <Button Content="{Bindin ...

  5. MethodInvoker委托,跨线程访问

    Invoke(new MethodInvoker(delegate { textBox1.Enabled = true; })); 上面是简单缩写,也可以写成 private void btnOK_C ...

  6. Google Chrome 浏览器JS无法更新解决办法

    JS无法更新原因: 浏览器为了加载快,默认是按照自定规则更新缓存,非实时更新. 我们在开发的时候,JS变动很快,需要即时让浏览器加载最新文件,也就是禁用浏览器缓存 (1)使用F12进入开发者模式,找到 ...

  7. jwt认证生成后的token如何传回后端并解析的详解

    jwt认证生成后的token后端解析 一.首先前端发送token token所在的位置headers {'authorization':token的值',Content-Type':applicati ...

  8. python基础06--文件操作

    1.1 文件操作 1.只读(r,rb)     rb以bytes方式读文件 只写(w,wb) 追加(a,ab) r+ 读写 w+ 写读 a+  追加写读 以什么编码方式储存的文件,就用什么编码方式打开 ...

  9. 【开发笔记】-MySQL数据库5.7+版本,编码格式设置

    原因 昨天不小心把数据库搞崩了,重装了5.7.27版本得mysql数据库,在安装过程中并没有设置数据库默认编码格式等操作.在把项目启动后,jpa自动创建表结构,会把数据库,表,字段的编码自动设置为IS ...

  10. vue与webpack开发环境搭建:从无到有

    一个vue从无到有的搭建过程. 一.不论是webpack还是vue,最初的第一步就是安装node.js.它是基石. 从官网下载你需要的安装包:官网下载链接:http://nodejs.cn/downl ...