霍夫线变换的原理

  • 一条直线在图像二维空间可由两个变量表示,有以下两种情况:

① 在笛卡尔坐标系中:可由参数斜率和截距(k,b)表示。

② 在极坐标系中:可由参数极经和极角(r,θ)表示。

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

化简便可得到:

  • 对于(x0,y0),我们可以将通过这一点的所有直线统一定义为:

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

  • 对于一个给定点   ,我们可以在直角坐标系中,绘出所有通过它的直线(θ 为 x 轴,r 为 y 轴)。最终我们将得到一条正弦曲线。

注意:只绘出满足下列条件的点   and  

  • 我们可以对图像中所有的点进行上述操作.。如果两个不同点进行上述操作后得到的曲线在平面  -  相交, 这就意味着它们有一个公共的(θ,rθ),即过一条公共的直线。下图中,若曲线每点权重均为 1 ,则交点处权重为 3。

  • 越多曲线交于一点,也就意味着这个交点表示的直线由更多的点组成,权重和越大。我们可以设置一个阈值,来决定多少条曲线交于一点(权重多大)我们才认为检测到了一条直线。

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

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

  1. 标准霍夫变换(StandardHough Transform,SHT)

    • 原理在上面的部分已经说明了. 它能给我们提供一组参数对(ρ,θ)的集合来表示检测到的直线。
    • 在 OpenCV 中通过函数 HoughLines 来实现。
  2. 多尺度霍夫变换(Multi-ScaleHough Transform,MSHT)
    • 和标准霍夫变换类似。
  3. 累计概率霍夫变换(ProgressiveProbabilistic Hough Transform,PPHT),由HoughLinesP函数调用。
    • 这是执行起来效率更高的霍夫线变换. 它输出检测到的直线的端点 
    • 在 OpenCV 中它通过函数 HoughLinesP 来实现。
标准 & 多尺度 霍夫线变换:HoughLines 函数

void HoughLines(InputArray image, OutputArray lines, double rho, double theta, int threshold, double srn = 0, double stn = 0);

  • image,输入图像,即源图像。需要为 8 位的单通道二值图像。
  • lines,存放直线的矢量信息的数组。每条直线由具有 2 个元素的矢量(ρ,Θ)表示,其中,ρ 是离坐标原点(0,0)也就是图像左上角的距离,Θ 是弧度线条旋转角度(0 表示垂直直线,∏/2 表示水平直线,注意,不是 0 度和 90 度)                                                          
  • rho,以像素为单位的距离精度。另一种表述是平面  -  中 r 轴的单位长度。
  • theta,以弧度为单位的角度精度。另一种表示是平面  -  中 θ 轴的单位长度。
  • threshold,权重累加平面的阈值参数。大于阈值 threshold 的线段才可以被确认为直线。
  • srn,默认值为 0。多尺度霍夫线变换才会用到的参数。对于多尺度霍夫线变换,平面  -  中 r 轴的单位长度 = rho / srn。
  • stn,默认值为 0。也是多尺度霍夫线变换才会用到的参数。对于多尺度霍夫线变换,平面  -  中 θ 轴的单位长度 = theta / stn。如果 srn、stn 同时为 0,就表示使用经典霍夫变换,否则两个参数都应该为正数。

 

代码示例:

#include<opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
int hough_value = ;
Mat src, canny_img;
void hough_change(int, void*) {
vector<Vec2f>lines;
HoughLines(canny_img, lines, , CV_PI / 180.0, hough_value);
RNG rngs = { };
Mat show = src.clone();
for (int i = ; i < lines.size(); i++) {
float rho = lines[i][], theta = lines[i][]; double sin_theta = sin(theta), cos_theta = cos(theta);
double x = rho * cos_theta, y = rho * sin_theta; //以垂点为基础,将直线延长
Point pt1, pt2;
pt1.x = cvRound(x + * (-sin_theta));
pt1.y = cvRound(y + * (cos_theta));
pt2.x = cvRound(x - * (-sin_theta));
pt2.y = cvRound(y - * (cos_theta)); Scalar colors = Scalar(rngs.uniform(, ), rngs.uniform(, ), rngs.uniform(, ));
line(show, pt1, pt2, colors, );
}
imshow("show", show);
}
int main() {
src = imread("C:/Users/齐明洋/Desktop/1.jpg");
GaussianBlur(src, src, Size(, ), , );
imshow("src", src); Canny(src, canny_img, , , );
imshow("canny_img", canny_img); namedWindow("show");
createTrackbar("threshold", "show", &hough_value, , hough_change);
hough_change(, ); waitKey();
}

效果演示:

累计概率霍夫变换:HoughLinesP 函数

void HoughLinesP(InputArray image, OutputArray lines, double rho, double theta, int threshold, double minLineLength = 0, double maxLineGap= 0);

  • lines,存放直线信息矢量的数组。每条直线由具有 4 个元素的矢量(x_1,y_1,x_2,y_2)表示,其中,(x_1,y_1)和(x_2,y_2)是每条检测到的直线的两端端点。
  • minLineLength ,默认值为 0。最短线段的长度,比这个设定参数短的线段就不能被显现出来。
  • maxLineGap,默认值为 0。允许将同一行点与点之间连接起来的最大距离。
  • 其余参数,类比 HoughLines 函数的参数。

代码示例:

#include<opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
int hough_value = ;
Mat src, canny_img;
void hough_change(int, void*) {
vector<Vec4f>lines;
HoughLinesP(canny_img, lines, , CV_PI / , hough_value, , );
RNG rngs = { };
Mat show = src.clone();
for (int i = ; i < lines.size(); i++) {
Point pt1, pt2;
pt1.x = lines[i][];
pt1.y = lines[i][];
pt2.x = lines[i][];
pt2.y = lines[i][]; Scalar colors = Scalar(rngs.uniform(, ), rngs.uniform(, ), rngs.uniform(, ));
line(show, pt1, pt2, colors, );
}
imshow("show", show);
}
int main() {
src = imread("C:/Users/齐明洋/Desktop/1.jpg");
GaussianBlur(src, src, Size(, ), , );
imshow("src", src); Canny(src, canny_img, , , );
imshow("canny_img", canny_img); namedWindow("show");
createTrackbar("threshold", "show", &hough_value, , hough_change);
hough_change(, ); waitKey();
}

效果演示:

借鉴博客:https://www.cnblogs.com/xmu-rcs-jty/p/7531814.html

http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/imgproc/imgtrans/hough_lines/hough_lines.html

opencv —— HoughLines、HoughLinesP 霍夫线变换原理(标准霍夫线变换、多尺度霍夫线变换、累积概率霍夫线变换)及直线检测的更多相关文章

  1. opencv:霍夫直线检测

    #include <opencv2/opencv.hpp> #include <iostream> using namespace cv; using namespace st ...

  2. Hough变换原理

    Hough变换原理 一.简单介绍 Hough变换是图像处理中从图像中识别几何形状的基本方法之一.Hough变换的基本原理在于利用点与线的对偶性,将原始图像空间的给定的曲线通过曲线表达形式变为参数空间的 ...

  3. Python+OpenCV图像处理(十四)—— 直线检测

    简介: 1.霍夫变换(Hough Transform) 霍夫变换是图像处理中从图像中识别几何形状的基本方法之一,应用很广泛,也有很多改进算法.主要用来从图像中分离出具有某种相同特征的几何形状(如,直线 ...

  4. 【python+opencv】直线检测+圆检测

     Python+OpenCV图像处理—— 直线检测 直线检测理论知识: 1.霍夫变换(Hough Transform) 霍夫变换是图像处理中从图像中识别几何形状的基本方法之一,应用很广泛,也有很多改进 ...

  5. opencv直线检测在c#、Android和ios下的实现方法

    opencv直线检测在c#.Android和ios下的实现方法 本文为作者原创,未经允许,不得转载 :原文由作者发表在博客园:http://www.cnblogs.com/panxiaochun/p/ ...

  6. opencv学习笔记霍夫变换——直线检测

    参考大佬博文:blog.csdn.net/jia20003/article/details/7724530 lps-683.iteye.com/blog/2254368 openCV里有两个函数(比较 ...

  7. Win8 Metro(C#)数字图像处理--2.38Hough变换直线检测

    原文:Win8 Metro(C#)数字图像处理--2.38Hough变换直线检测  [函数名称] Hough 变换直线检测         HoughLineDetect(WriteableBit ...

  8. Android开发中的OpenCV霍夫直线检测(Imgproc.HoughLines()&Imgproc.HoughLinesP())

    本文为作者原创,转载请注明出处(http://www.cnblogs.com/mar-q/)by 负赑屃   //2017-04-21更新: 很多网友希望能得到源码,由于在公司做的,所以不太方便传出来 ...

  9. 霍夫直线检测 opencv

    本次实验是检测图像中的直线,用到了HoughLines()和HoughLinesP()函数,其中HoughLinesP()称为累计概率霍夫变换,实验结果显示累计概率霍夫变换要比标准霍夫变换的效果好.具 ...

随机推荐

  1. spring源码系列(二):IOC接口设计分析

    这里主要对springIOC接口体系进行简单的概述和分析,具体每个接口详细分析在下面目录: 参考内容: <Spring技术内幕:深入解析 Spring架构与设计原理> 和 <Spri ...

  2. 创建一个圆类Circle的对象,分别设置圆的半径计算并分别显示圆半径、圆面积、圆周长。

    编写一个圆类Circle,该类拥有: ①一个成员变量 Radius(私有,浮点型): // 存放圆的半径: ②两个构造方法 Circle( ) // 将半径设为0 Circle(double r ) ...

  3. 在Navicat新建用户

    1.Ctrl+Q,进入查询,创建表空间. 输入create tablespace test datafile 'D:\Oracle\test.ora' size 1000m; 这里的test为表空间名 ...

  4. 全卷积网络FCN

    全卷积网络FCN fcn是深度学习用于图像分割的鼻祖.后续的很多网络结构都是在此基础上演进而来. 图像分割即像素级别的分类. 语义分割的基本框架: 前端fcn(以及在此基础上的segnet,decon ...

  5. 剑指offer刷题笔记

    删除链表中重复的结点:较难 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针. 例如,链表1->2->3->3->4->4- ...

  6. (六)mybatis拦截器

    首先拦截器可以拦截mybatis四大核心对象:StatementHandler,ParameterHandler,ResultSetHandler,Executor,具体拦截时根据需求拦截一部分方法 ...

  7. git命令清单 摘自 阮老师

    常用 Git 命令清单   作者: 阮一峰 日期: 2015年12月 9日 我每天使用 Git ,但是很多命令记不住. 一般来说,日常使用只要记住下图6个命令,就可以了.但是熟练使用,恐怕要记住60- ...

  8. 2 深入分析 Java IO的工作机制(二)

    2.5 I/O调优 下面总结一些磁盘I/O和网络I/O的常用优化技巧. 2.5.1 磁盘I/O优化 1. 性能检测 应用程序通常都需要访问磁盘来读取数据,而磁盘I/O通常都很耗时,要判断I/O是否是一 ...

  9. 对MYSQL注入相关内容及部分Trick的归类小结

    前言 最近在给学校的社团成员进行web安全方面的培训,由于在mysql注入这一块知识点挺杂的,入门容易,精通较难,网上相对比较全的资料也比较少,大多都是一个比较散的知识点,所以我打算将我在学习过程中遇 ...

  10. javascript获取一个字符串的长度(包含中文)

    /* getStrLen(str):获取一个字符串的长度(包含中文) */ function getStrLen(str){ let len = 0, i, c; for (i = 0; i < ...