霍夫线变换

  1. 霍夫线变换是一种用来寻找直线的方法.
  2. 是用霍夫线变换之前, 首先要对图像进行边缘检测的处理,也即霍夫线变换的直接输入只能是边缘二值图像.

它是如何实现的?

  1. 众所周知, 一条直线在图像二维空间可由两个变量表示. 例如:

    1. 在 笛卡尔坐标系: 可由参数:  斜率和截距表示.
    2. 在 极坐标系: 可由参数:  极径和极角表示

    对于霍夫变换, 我们将用 极坐标系 来表示直线. 因此, 直线的表达式可为:

    化简得: 

  2. 一般来说对于点 , 我们可以将通过这个点的一族直线统一定义为:

    这就意味着每一对  代表一条通过点  的直线.

  3. 如果对于一个给定点  我们在极坐标对极径极角平面绘出所有通过它的直线, 将得到一条正弦曲线. 例如, 对于给定点  and 我们可以绘出下图 (在平面  - ):

    只绘出满足下列条件的点  and .

  4. 我们可以对图像中所有的点进行上述操作. 如果两个不同点进行上述操作后得到的曲线在平面  -  相交, 这就意味着它们通过同一条直线. 例如, 接上面的例子我们继续对点:  和点  绘图, 得到下图:

    这三条曲线在  -  平面相交于点 , 坐标表示的是参数对 () 或者是说点 , 点  和点  组成的平面内的的直线.

  5. 那么以上的材料要说明什么呢? 这意味着一般来说, 一条直线能够通过在平面  -  寻找交于一点的曲线数量来 检测. 越多曲线交于一点也就意味着这个交点表示的直线由更多的点组成. 一般来说我们可以通过设置直线上点的 阈值 来定义多少条曲线交于一点我们才认为 检测 到了一条直线.

  6. 这就是霍夫线变换要做的. 它追踪图像中每个点对应曲线间的交点. 如果交于一点的曲线的数量超过了 阈值, 那么可以认为这个交点所代表的参数对  在原图像中为一条直线.

标准霍夫线变换和统计概率霍夫线变换

OpenCV实现了以下两种霍夫线变换:

  1. 标准霍夫线变换
  • 原理在上面的部分已经说明了. 它能给我们提供一组参数对  的集合来表示检测到的直线
  • 在OpenCV 中通过函数 HoughLines 来实现
  1. 统计概率霍夫线变换
  • 这是执行起来效率更高的霍夫线变换. 它输出检测到的直线的端点 
  • 在OpenCV 中它通过函数 HoughLinesP 来实现

代码

  1. 这个程序是用来做什么的?

    • 加载一幅图片
    • 对图片进行 标准霍夫线变换 或是 统计概率霍夫线变换.
    • 分别在两个窗口显示原图像和绘出检测到直线的图像.
  2. 我们将要说明的例程能从 这里 下载。 一个更高级的版本 (能同时演示标准霍夫线变换和统计概率霍夫线变换并带有活动条来改变变换的阈值) 能从 这里 下载。
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"#include <iostream>using namespace cv;
using namespace std;void help()
{cout << "\nThis program demonstrates line finding with the Hough transform.\n""Usage:\n""./houghlines <image_name>, Default is pic1.jpg\n" << endl;
}int main(int argc, char** argv)
{const char* filename = argc >= 2 ? argv[1] : "pic1.jpg";Mat src = imread(filename, 0);if(src.empty()){help();cout << "can not open " << filename << endl;return -1;}Mat dst, cdst;Canny(src, dst, 50, 200, 3);cvtColor(dst, cdst, CV_GRAY2BGR);#if 0
  vector<Vec2f> lines;
  HoughLines(dst, lines, 1, CV_PI/180, 100, 0, 0 );  for( size_t i = 0; i < lines.size(); i++ )
  {     float rho = lines[i][0], theta = lines[i][1];
     Point pt1, pt2;
     double a = cos(theta), b = sin(theta);
     double x0 = a*rho, y0 = b*rho;
     pt1.x = cvRound(x0 + 1000*(-b));
     pt1.y = cvRound(y0 + 1000*(a));
     pt2.x = cvRound(x0 - 1000*(-b));
     pt2.y = cvRound(y0 - 1000*(a));
     line( cdst, pt1, pt2, Scalar(0,0,255), 3, CV_AA);
  }
 #else
  vector<Vec4i> lines;
  HoughLinesP(dst, lines, 1, CV_PI/180, 50, 50, 10 );
  for( size_t i = 0; i < lines.size(); i++ )
  {    Vec4i l = lines[i];
    line( cdst, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0,0,255), 3, CV_AA);
  }
 #endifimshow("source", src);imshow("detected lines", cdst);waitKey();return 0;
}

代码说明

  1. 加载图片

    Mat src = imread(filename, 0);
    if(src.empty())
    {help();cout << "can not open " << filename << endl;return -1;
    }
    

  2. 用Canny算子对图像进行边缘检测

    Canny(src, dst, 50, 200, 3);
    

    现在我们将要执行霍夫线变换. 我们将会说明怎样使用OpenCV的函数做到这一点:

  3. 标准霍夫线变换

    1. 首先, 你要执行变换:

      vector<Vec2f> lines;
      HoughLines(dst, lines, 1, CV_PI/180, 100, 0, 0 );
      

      带有以下自变量:

      • dst: 边缘检测的输出图像. 它应该是个灰度图 (但事实上是个二值化图)
      • lines: 储存着检测到的直线的参数对  的容器 * rho : 参数极径  以像素值为单位的分辨率. 我们使用 1 像素.
      • theta: 参数极角  以弧度为单位的分辨率. 我们使用 1度 (即CV_PI/180)
      • threshold: 要”检测” 一条直线所需最少的的曲线交点
      • srn and stn: 参数默认为0. 查缺OpenCV参考文献来获取更多信息.
    2. 通过画出检测到的直线来显示结果.

      for( size_t i = 0; i < lines.size(); i++ )
      {float rho = lines[i][0], theta = lines[i][1];Point pt1, pt2;double a = cos(theta), b = sin(theta);double x0 = a*rho, y0 = b*rho;pt1.x = cvRound(x0 + 1000*(-b));pt1.y = cvRound(y0 + 1000*(a));pt2.x = cvRound(x0 - 1000*(-b));pt2.y = cvRound(y0 - 1000*(a));line( cdst, pt1, pt2, Scalar(0,0,255), 3, CV_AA);
      }
      

  4. 统计概率霍夫线变换

    1. 首先, 你要执行变换:

      vector<Vec4i> lines;
      HoughLinesP(dst, lines, 1, CV_PI/180, 50, 50, 10 );
      

      带有以下自变量:

      • dst: 边缘检测的输出图像. 它应该是个灰度图 (但事实上是个二值化图) * lines: 储存着检测到的直线的参数对  的容器
      • rho : 参数极径  以像素值为单位的分辨率. 我们使用 1 像素.
      • theta: 参数极角  以弧度为单位的分辨率. 我们使用 1度 (即CV_PI/180)
      • threshold: 要”检测” 一条直线所需最少的的曲线交点 * minLinLength: 能组成一条直线的最少点的数量. 点数量不足的直线将被抛弃.
      • maxLineGap: 能被认为在一条直线上的亮点的最大距离.
    2. 通过画出检测到的直线来显示结果.

      for( size_t i = 0; i < lines.size(); i++ )
      {Vec4i l = lines[i];line( cdst, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0,0,255), 3, CV_AA);
      }
      

  5. 显示原始图像和检测到的直线:

    imshow("source", src);
    imshow("detected lines", cdst);
    

  6. 等待用户按键推出程序

    waitKey();
    

结果¶

Note

得到的结果使用的是在上面 代码 部分提到的更高级版代码. 霍夫线变换的代码没有改变, 唯一不同的是在GUI的部分加入了活动条可动态改变阈值.输入图像为:

通过执行统计概率霍夫线变换我们能得到下面的结果:

当你使用滑动条来改变 阈值 的时候会观察到检测到线的数目的改变. 这是因为: 如果你设置了一个更大的阈值, 能检测到的线的数目将更少 (你需要更多的点来表示一条能检测到的直线).

opencv 霍夫线变换相关推荐

  1. OpenCV 霍夫线变换Hough Line Transform

    OpenCV 霍夫线变换Hough Line Transform 霍夫线变换Hough Line Transform 目标 理论 霍夫线变换 它是如何工作的? 标准概率霍夫线变换 这个程序做什么? 代 ...

  2. Python OpenCV -- 霍夫线变换(十二)

    霍夫线变换 1. 霍夫线变换是一种用来寻找直线的方法. 2. 是用霍夫线变换之前, 首先要对图像进行边缘检测的处理,也即霍夫线变换的直接输入只能是边缘二值图像. 实现: 1.  一条直线在图像二维空间 ...

  3. OpenCV中的霍夫线变换、概率霍夫线变换

    OpenCV中的霍夫线变换.概率霍夫线变换 1. 效果图 2. 原理 2.1 什么是霍夫变换? 2.2 什么是概率霍夫变换? 3. 源码 3.1 霍夫变换 3.2 概率霍夫变换 参考 这篇博客将介绍P ...

  4. OpenCV霍夫变换:霍夫线变换,霍夫圆变换合辑

    本篇文章中,我们一起探讨了OpenCV中霍夫变换相关的知识点,以及了解了OpenCV中实现霍夫线变换的HoughLines.HoughLinesP函数的使用方法,实现霍夫圆变换的HoughCircle ...

  5. OpenCV之imgproc 模块. 图像处理(3)霍夫线变换 霍夫圆变换 Remapping 重映射 仿射变换

    霍夫线变换 目标 在这个部分您将学习到: 使用OpenCV的以下函数 HoughLines 和 HoughLinesP 来检测图像中的直线. 原理 Note 以下原理的说明来自书籍 学习OpenCV  ...

  6. 【OpenCV新手教程之十四】OpenCV霍夫变换:霍夫线变换,霍夫圆变换合辑

    本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/26977557 作者:毛星云(浅墨) ...

  7. 花老湿学习OpenCV:霍夫线变换与直线检测

    引言: 霍夫变换(Hough Transform)是图像处理中的一种特征提取技术,它通过一种投票算法检测具有特定形状的物体.该过程在一个参数空间中通过计算累计结果的局部最大值得到一个符合该特定形状的集 ...

  8. 【OpenCV入门教程之十四】OpenCV霍夫变换:霍夫线变换,霍夫圆变换合辑

    本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/26977557 作者:毛星云(浅墨) ...

  9. OpenCV3学习(6.2)——霍夫(Hough)变换:霍夫线变换HoughLine,霍夫圆变换HoughCircles

    霍夫变换是图像处理中从图像中识别几何形状的基本方法之一,应用很广泛,也有很多改进算法.主要用来从图像中分离出具有某种相同特征的几何形状(如,直线,圆等).最基本的霍夫变换是从黑白图像中检测直线(线段) ...

最新文章

  1. Apache Struts2(S2-045)漏洞反思总结
  2. js获取当前日期_vue项目中获取前后N天日期
  3. Hazelcast入门指南第3部分
  4. Python——使用Flask框架封装接口
  5. Winform文件下载之WebClient
  6. 一般来讲,大公司都有自己的决策团队
  7. B/S WEB端条码打印系统 斑马条码打印解决方案
  8. 学术第一步:搞清楚SCI、EI、ISTP和中文核心期刊的区别
  9. 单片机编程软件很简单(12),Keil单片机编程软件配置操作
  10. 布线工程-认识光纤和光缆
  11. word排版学习笔记
  12. 阅兵方阵(蓝桥杯2018真题)
  13. 学生个人html静态网页制作 基于HTML+CSS+JavaScript+jquery仿苏宁易购官网商城模板
  14. 四、数据仓库--ORACLE数据库卸数实现
  15. RFC868--时间协议客户机与服务器的实现
  16. 16进制颜色值与百分比颜色值的换算关系
  17. Burg法求解AR(p)模型参数及MATLAB实现
  18. 翻遍“微信小程序”的所有知乎问答,我们整理了大家最关注几个话题
  19. [转载]Deep Neural Networks are Easily Fooled: High Confidence Predictions for Unrecognizable Images
  20. oracle update exsits,Oracle 11g 递归+ exists执行计划的改变

热门文章

  1. 高通8xxx平台双MIC设置
  2. 关于Android Service真正的完全详解,你需要知道的一切
  3. 用shell写了一个自动编译代码的脚本
  4. Mongodb分布式集群搭建
  5. 对话框Flags的设置值
  6. HTML解析原理概括(转载)
  7. 30分钟带你熟练性能优化的那点儿事儿(案例说明)
  8. Spring context:component-scan代替context:annotation-config
  9. Linux下MySQL链接被防火墙阻止
  10. CentOS 7核心安装及基本配置