直线检测练习:hough线变换

  • 1.hough线变换概述
  • 2.hough线变换原理
  • 3. API介绍
    • 3.1 opencv版
      • 3.1.1 HoughLines API介绍(SHT、MSHT)
      • 3.1.1 HoughLinesP API介绍(PPHT)
    • 3.2 MATLAB版
  • --------------------------------END-----------------------------------

1.hough线变换概述

在计算机视觉与图像分析领域,直线(段)检测一直是热门的研究问题,作为一种底层图像特征,是检测图像高层特征或分析图像内容的基础。直线段包含更丰富的信息,如直线段角度、中心点等,当然也有很多方面的应用,比如:图像修复、消失点检测、图像匹配、遥感图像分析、三维重建和道路检测等。
本篇主要浅显介绍一下霍夫线变换,霍夫变换于1962 年由PaulHough 首次提出,后于 1972 年由 Richard Duda & Peter Hart 推广使用 ,经典霍夫变换常用来检测图像中的直线 ,当然也可以检测圆和椭圆,其原理都是:运用两个坐标空间之间的变换将在一个空间中具有相同形状的曲线或直线映射到另 一个坐标空间的一个点上形成峰值,从而把检测任意形状的问题转化为统计峰值问题 。这种方法的 一 个突出优点是分割结果的稳定性,即对数据的不完全或噪声不是非常敏感,只需边缘检测简单处理便可以进行检测。
OpenCV 中的霍夫线变换有如下三种:
· 标准霍夫变换 ( StandardHough Transform, SHT ) ,由 HoughLines函数 调用。
· 多尺度霍夫变换(Multi-ScaleHough Transform , MSHT ) ,由HoughLines函数调用 。
· 累计概率霍夫变换(ProgressiveProbabilistic Hough Transform, PPHT ),由HoughLinesP 函数调用

2.hough线变换原理

(1)一条直线在图像三维空间可由两个变量表示,有以下两种情况。如图所示:

①在直角坐标系 :可由参数斜率和截距( k , b ) 表示 :
y=kx+b\text{y}=\text{kx}+\text{b}\, y=kx+b
②在极坐标系 :可由参数极径和极角(r,θ)表示:

y=(−cos⁡θsin⁡θ)x+(rsin⁡θ)\text{y}=\left( -\frac{\cos \boldsymbol{\theta }}{\sin \boldsymbol{\theta }} \right) \boldsymbol{x}+\left( \frac{\boldsymbol{r}}{\sin \boldsymbol{\theta }} \right) y=(−sinθcosθ​)x+(sinθr​)

可以利用下面的式子相互推导:

化简可以得到:

对于边缘检测图像的某一个点(x0,y0)\left( \text{x}_0,\text{y}_0 \right)(x0​,y0​) 来说,可以将通过这个点的 一族直线统一定义为:

也就是说每一个(rθ,θ)\left( \boldsymbol{r}_{\boldsymbol{\theta }},\boldsymbol{\theta } \right)(rθ​,θ)就确定一条过(x0,y0)\left( \text{x}_0,\text{y}_0 \right)(x0​,y0​)的直线。
(2)如果选定一个边缘像素点,我们在极坐标对极径极角平面绘出所有通过它的直线,对应参数绘制到坐标图上就是一条正弦曲线 ,如图:

(3) 把很多个边缘像素点参数曲线绘制到同一个坐标图上,相互之间就会产生很多交点,每一个交点(rθ,θ)\left( \boldsymbol{r}_{\boldsymbol{\theta }},\boldsymbol{\theta } \right)(rθ​,θ)就表示一条直线,相交的正弦曲线数目就表示共线的边缘像素点的数目,如图三条曲线相交一点:

这三条曲线在平面相交于点( 0.925 ,9 . 6 ) ,也就是说原图中这三点共线,这条线可由交点坐标推算出来。
(4)hough可以找出大量的线,但有些是没用的,可以设置一些阈值来过滤掉一部分。

3. API介绍

3.1 opencv版

OpenCV 支持三种不同的霍夫线变换 ,分别是 : 标准霍夫变换(Standard Hough Transform,SHT ) 、多尺度霍夫变换(Multi-Scale Hough Transform, MSHT )和累计概率霍夫变换( Progressive Probabilistic Hough Transform, PPHT ) 。
MSHT 是SHT算法 的一个改进 ,它在一定的范围内进行霍夫变换,计算单独线段的方向以及范围 ,从而减少计算量 ,缩短计算时间 。之所以称 PPHT 为 "概率"的 ,是因为并不将累加器平面内的所有可能的点累加 ,而只是累加其中的一部分,该想法是如果峰值如果足够高 ,只用 一 小部分时间去 寻找它就够了 。 按照猜想,可以实质性地减少计算时间 。使用时就会发现PPHT更好一点。

3.1.1 HoughLines API介绍(SHT、MSHT)

cv::HoughLines(

InputArray src, // 输入图像,必须8-bit的灰度图像

OutputArray lines, // 输出的极坐标来表示直线

double rho, // 生成极坐标时候的像素扫描步长

double theta, //生成极坐标时候的角度步长,一般取值CV_PI/180

int threshold, // 阈值,只有获得足够交点的极坐标点才被看成是直线

double srn=0;// 是否应用多尺度的霍夫变换,如果不是设置0表示经典霍夫变换

double stn=0;//是否应用多尺度的霍夫变换,如果不是设置0表示经典霍夫变换

double min_theta=0; // 表示角度扫描范围 0 ~180之间, 默认即可

double max_theta=CV_PI)

代码如下:


#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
using namespace std;int main(){Mat srcImage = imread("text2.jpg");  Mat midImage, dstImage;Canny(srcImage, midImage, 50, 200, 3);//进行一此canny边缘检测cvtColor(midImage, dstImage, COLOR_GRAY2BGR);//转化边缘检测后的图为灰度图 vector<Vec2f> lines;//定义一个矢量结构lines用于存放得到的线段矢量集合HoughLines(midImage, lines, 1, CV_PI / 180, 150, 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(dstImage, pt1, pt2, Scalar(55, 100, 195), 1, LINE_AA);
}imshow("边缘检测后的图", midImage);imshow("效果图", dstImage);waitKey(0);return 0;
}

输入一间教室的图像:

得到输出图像为:

如果图像的边缘复杂的话,SHT,MSHT就比较难调教了:

3.1.1 HoughLinesP API介绍(PPHT)

cv::HoughLinesP( InputArray src, // 输入图像,必须8-bit的灰度图像
OutputArraylines, // 输出的极坐标来表示直线,每一条线由具有 4 个元素的矢量 (x_ l ,y_ l , x_2, y_2 ) 表示,其中 (x_l ,y_l)和 (x_2 ,y_2) 是是每个检测到的钱段的结束点 。
double rho, // 生成极坐标时候的像素扫描步长
double theta,//生成极坐标时候的角度步长,一般取值CV_PI/180
int threshold, // 阈值,只有获得足够交点的极坐标点才被看成是直线
double minLineLength=0;// 最小直线长度
double maxLineGap=0;// 最大间隔,即允许将同 一行点与点之间连接起来的最大的距离)

上代码:

#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
using namespace std;int main() {Mat src, gsrc, dst;src = imread("test1.jpg");cvtColor(src, gsrc, COLOR_BGR2GRAY);namedWindow("边缘图像", WINDOW_AUTOSIZE);Mat esrc;//hough变换之前最好进行一次中值滤波blur(gsrc, gsrc, Size(3, 3), Point(-1, -1), BORDER_DEFAULT);Canny(gsrc, esrc, 150, 200, 3, false);cvtColor(gsrc, dst, COLOR_GRAY2BGR);//esrc = ~esrc;vector<Vec4f>plines;HoughLinesP(esrc, plines, 1, CV_PI / 180.0, 10, 100, 10);Scalar color = Scalar(0, 0, 255);for (size_t i = 0; i < plines.size(); i++) {Vec4f hline = plines[i];line(dst, Point(hline[0], hline[1]), Point(hline[2], hline[3]), color, 3, LINE_AA);}//size_t 相当于intimshow("边缘图像", esrc);imshow("直线检测", dst);waitKey(0);return 0;
}

如下图,这结果明显比SHT好很多:

3.2 MATLAB版

分为三步
(1)对二值边缘图像直接hough变换:

[H,theta,rho]=hough(q);%霍夫变换
figure,imshow(H);

如图,其参数曲线太多,肉眼已无法辨别交点:

(2)利用houghpeaks做峰值检测:
hough变换的优点就是把rho、theta参数空间细分为了所谓的累加器单元,首先要找到包含最大值的多个hough变换单元,可以设置需要的峰值数目上限。

P  = houghpeaks(H,6);
figure,imshow(H,[],'XData',theta,'YData',rho,'InitialMagnification','fit');
xlabel('\theta'), ylabel('\rho');
axis on, axis normal, hold on;
plot(theta(P(:,2)),rho(P(:,1)),'s','color','white');

可以看到图中标记出了6个峰值:

(3)利用houghlines来来做线检测:
识别出一组候选峰值后,找出与这些峰值相关的线段以及它们的起始和结束位置:

lines = houghlines(q,theta,rho,P,'FillGap',4,'MinLength',15);
figure, imshow(x), hold on
% max_len = 0;
for k = 1:length(lines)xy = [lines(k).point1; lines(k).point2];plot(xy(:,1),xy(:,2),'LineWidth',2,'Color','green');

结果如下:


总的来说,SHT、PPHT都是使用图像边缘点对参数空间投票,PPHT还随机选取边缘点加速计算时间,算法简单易实现,但是只适用于干扰较少的场景,对于密集边缘很容易错误检测,漏检直线段或是端点检测错误。

--------------------------------END-----------------------------------

注:opencv学习可以参考大佬@浅墨_毛星云

直线检测练习:hough线变换相关推荐

  1. 直线检测之Hough变换(霍夫变换)

    霍夫变换,英文名称Hough Transform,作用是用来检测图像中的直线或者圆等几何图形的. 给定一张图像中的n个点,假设我们希望找到这些点中一个位于直线上的点集,一种可行的解决方法是,先找到所有 ...

  2. python 霍夫直线变换_霍夫线变换

    目录:一.引入极坐标 二.霍夫线变换实现原理 三.图像中的霍夫线变换 四.概率霍夫变换 五.Python 例子 六.参考 Hough线变换是一种用于检测直线的变换.它最大的优点是,即使是虚线(dash ...

  3. 直线检测——Radon变换/霍夫变换/基于快速傅里叶变换的直线检测

    1. 直线检测 1.1. Radon直线检测原理 基于Radon变换的直线检测的目的就是检测根据角度变化时出现的"局部峰值",即可以确定直线的方向,同时,峰值大小能够确定直线上点的 ...

  4. Python+OpenCV:Hough直线检测(Hough Line Transform)

    Python+OpenCV:Hough直线检测(Hough Line Transform) 理论 A line can be represented as  or in a parametric fo ...

  5. 霍夫变换直线检测理解

    一步一步来: 1.在白纸上画出一个直角坐标系,任意给出一个点: 2.那么,对于点(x0,y0),经过这个点的直线必定满足y0=k*x0+b,其中k是直线的斜率,b是直线的截距: 3.上式可以化成b=y ...

  6. opencv 霍夫线变换

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

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

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

  8. QT+opencv学习笔记(5)——霍夫直线检测、圆检测及椭圆检测

    开发环境为:win10+QT5.8+opencv3.2 Hough变换是图像处理中从图像中识别几何形状的基本方法之一,应用很广泛.最基本的Hough变换是从黑白图像中检测直线,还可以经过改进检测圆.椭 ...

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

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

最新文章

  1. Streaming K-Means、Fuzzy C-means、Canopy
  2. jquery插件treetable使用
  3. 使用keepalived实现双机热备
  4. ssm实训报告心得_Java开发学习心得(一):SSM环境搭建
  5. XXX管理平台系统——项目风险
  6. BZOJ 3564: [SHOI2014]信号增幅仪(随机增量法)
  7. 学hadoop需要什么基础
  8. 这么好的视频不看吗?深度学习和线代,微积分
  9. GDB 调试 ---转 比较全的东东
  10. Burp Suite 实战指南
  11. IDEA中运行maven多模块项目,提示程序包xxxx不存在
  12. Imagemagick转换图片成ico
  13. android studio 使用第三方模拟器连接方法,如MUMU模拟器
  14. 光纤交换机 序列号_IBM B系列光纤交换机B24默认激活和license以及如何导入license...
  15. 导致请求失败 设备硬件出现致命错误_硬盘提示无法访问设备硬件出现致命错误,导致请求失败,里面的数据如何找到...
  16. fastadmin相关操作(生成CRUD,生成菜单,关闭验证码,调试模式,开启表格用户查看权限)
  17. SDL(Simple DirectMedia Layer)
  18. ELK日志分析平台的搭建
  19. 服务器不支持 tls 重新协商修正,OpenSSL安全重新协商失败
  20. css3 抽奖实现炸弹爆炸效果 卡片翻转效果 雪花效果

热门文章

  1. 用图片文字提取大师提取图片上面的文字
  2. 显著性检测—基于上下文内容感知方法
  3. MATLAB 编程风格指南
  4. csrf验证问题 -- 不同域名下Iframe嵌套Cookie失效导致csrf验证失败
  5. 单片机原理及应用笔记
  6. c++设计一个模拟网上购书的结账系统
  7. PHP做文件下载功能
  8. AT89C51-红绿灯源码
  9. 基数排序(radix sort)
  10. ACwing ACwing ACwing