【图像处理知识】Hough变换

参考: 

1. https://www.zybuluo.com/lutingting/note/554459 

2. 《数字图像处理的MATLAB实现(第二版)》, Rafael C. Gonzalez

3. MATLAB帮助文档

 

Hough变换于1962年由Paul Hough提出,是一种使用表决方式的参数估计技术,其原理是利用图像空间和Hough参数空间的线-点对偶性,把图像空间中的检测问题转换到参数空间中进行。

下面参考https://www.zybuluo.com/lutingting/note/554459 

1. 极坐标系

极坐标系(polar coordinates)是指在平面内由极点O、极轴L、极径r组成的坐标系。如下图展示了一个极坐标系,图中两个红点是要利用极坐标表示的两个点,黑点是极坐标系的极点。

2. 极坐标系和直角坐标系的关系

在直角坐标系下,点P的坐标表示为

在极坐标系下,点M的坐标表示为

可以根据下图对极坐标和直角坐标进行相互之间的转换

注:本图中的r与上图中的ρ是同样的表述

3. 极坐标系和直角坐标系中的直线

在极坐标系中,应该如何表示直线方程呢?如上图所示,有一直线L,点P是直线L上的任意一点,其对应的直角坐标为(x,y),该点的极坐标为(r,φ),该直线到原点O的距离为ρ。

首先,由图可知:ρ = r * cos( θ - φ ),然后根据三角函数的关系对该式展开,可得:

ρ = r * cos( θ - φ )  = r * cosθcosφ + r * sinθsinφ

又根据点P的直角坐标(x,y)和极坐标(r,φ)之间的关系:x=r*cosφ, y=r*sinφ,代入到上式中,可以得到ρ=xcosθ+ysinθ

所以直线L的极坐标方程就是ρ=xcosθ+ysinθ。

上式中(x,y)是直线L上的任意一点。也就是说,给出极坐标系中的一个点(ρ,θ),可以唯一确定直角坐标系中的一条直线其中ρ表示直角坐标系下直线到原点O的距离,θ表示直角坐标系下直线和原点间的垂线与x轴正向的夹角。或者说,直角坐标系中的直线在极坐标系下表示为一个点。这即是极坐标系和直角坐标系的点-线对偶性。

4. 利用Hough变换检测直线

下面的例子形象地展示了如何利用Hough变换进行直线检测。记住上面的结论:直角坐标系中的一条直线对应于极坐标系下的一个点。这里的直角坐标系对应于原始图像空间,极坐标系对应于参数空间(也叫Hough空间)。

· 给定一幅图像,如下所示,图像中有一条直线

· 首先进行边缘检测,找出边缘点,如下图所示,红色的点表示边缘点

· 对于任何一个边缘点,找到所有可能经过该点的直线,这些直线都各自对应着参数空间中的一个点,而该边缘点的无穷多条直线对应于参数空间中的点将形成一条参数空间中的曲线。如下左边两图所示,原始图像空间中绿色的直线在参数空间中对应的点是(r2,θ2),原始图像空间中蓝色的直线在参数空间中对应的点是(r1,θ1)。如下右边两图所示,找出经过该边缘点的所有直线,列出各直线在参数空间中的点,这些点可以连接成一条曲线。

       

· 曲线如下图所示,最终我们可以用这条曲线来表示所有可能经过第1个边缘点的直线

· 重复上述过程,画出所有边缘点的曲线,每个边缘点都对应着参数空间中的一条曲线。那么,参数空间中所有这些曲线的交点一定是原始图像空间中所有边缘点的共同直线。或者说某个交点经过的曲线最多(此处涉及到表决,如何判断这个交点经过的曲线最多),那么这个交点很有可能表示原始图像中的直线。得到这个交点的坐标(ρ,θ)之后,根据方程ρ=xcosθ+ysinθ,可以计算出直角坐标系下的直线,然后在原始图像中标出直线,达到检测直线的目的。

 

下面参考《数字图像处理的MATLAB实现(第二版)》

如上图所示。图a说明了参数ρ和θ的几何解释。水平线的θ=0,ρ等于正的x截距;相似的,垂直线θ=90°,ρ等于正的y截距。或者θ=-90°,ρ等于负的y截距。

图b中的两条曲线分别表示通过图a中两个特定点(xi, yi)和(xj, yj)的一簇直线。交叉点对应于通过(xi, yi)和(xj, yj)的直线。

Hough变换在计算上的诱人之处是把ρθ空间再细分为所谓的累加单元。正如上图c中说明的那样,其中的(ρmin, ρmax)和(θmin, θmax)是预期的参数值范围。一般来说,值的最大范围是-90°≤θ≤90°和-D≤ρ≤D,其中D是图像中两个角之间的最远距离。

图c中,在坐标(i,j)的单元位置,累加器的值是A(i,j),对应于参数空间坐标(ρi,θj)的小正方形。最初,这些单元位置均为0。然后,对于原始图像空间中的每个非背景点(xk,yk)(图a中),我们令θ等于在θ轴上允许的细分值,并通过公式ρ=xk*cosθ+yk*sinθ解出相应的ρ值。然后,得到的ρ值四舍五入为最接近的ρ轴上允许的单元值。相应的累加器单元增加一个增量。在这个过程的最后,累加单元A(i,j)中的值Q表示参数空间中的点(ρi, θj)有Q条曲线经过,对应到原始图像空间中,也就是有Q个点是在一条相同的直线上的。ρθ平面上,细分的数目决定了这些点共线的精确度。累加器数组在工具箱中叫做Hough变换矩阵,简称Hough变换。

与Hough变换有关的工具箱函数

图像处理工具箱中提供了3个与Hough变换相关的函数。函数hough()实现了前面讨论的概念;函数houghpeaks()寻找Hough变换的峰值(累加单元的高计数);函数houghlines()以来自其他两个函数的结果为基础在原始图像中提取线段。

1. 函数hough()

默认语法是: [ H, theta, rho ] = hough(f) 

完整语法是: [ H , theta, rho ] = hough(f, 'ThetaRes', val1, 'RhoRes', val2)

其中,H是Hough变换矩阵,theta(单位是度数)和rho是θ和ρ向量,在这些值上产生Hough变换。输入f是二值图像,val1是0到90的标量,指定了沿θ轴Hough变换的间距(默认是1),val2是0到hypot(size(f,1), size(f,2))之间的实标量,其中函数hypot()表示平方和的平方根,指定了沿ρ轴Hough变换的间隔(默认是1)。

举例:hough变换的说明,在这个例子中,我们用简单的合成图像来说明hough函数的机理。

% 创建合成图像
f = zeros(101, 101); 
f(1, 1) = 1; 
f(101, 1) = 1; 
f(1, 101) = 1; 
f(101, 101) = 1; 
f(51, 51) = 1;

% 显示合成图像
figure; 
subplot(121), imshow(f); 

% 采用默认值进行hough变换,并显示hough变换的结果
H = hough(f); 
subplot(122), imshow(H, []);

 

接下来,我们调用带有三个参数的hough函数。然后把向量theta和rho作为附加输入参量传递给函数imshow(),从而控制水平轴和垂直轴的标度。我们还要把 'InitialMagnification' 选项传递给带有值 'fit' 的imshow函数,因此整个图像将被强迫在图形窗口中进行装配。axis函数被用来打开轴标记,并使其显示填充图的矩形框。最后,xlabel和ylabel函数用希腊字母LaTeX字体符号在轴上标值。

 

% 创建合成图像
f = zeros(101, 101); 
f(1, 1) = 1; 
f(101, 1) = 1; 
f(1, 101) = 1; 
f(101, 101) = 1; 
f(51, 51) = 1;

% 显示合成图像
figure; 
subplot(121), imshow(f); 

% 采用完整语法形式调用hough函数
[ H, theta, rho ] = hough(f, 'ThetaRes', 1, 'RhoRes', 1); 
subplot(122), imshow(H, [], 'XData', theta, 'YData', rho, 'InitialMagnification', 'fit'); 
axis on;
axis normal; 
xlabel('\theta'); % 加上\后x坐标轴显示θ,否则显示theta
ylabel('\rho');

 

接下来分析一下上图,左图为原始图像空间,有5个目标点,右图为参数空间,有5条对应的曲线。三条曲线(直线可视为曲线)在±45°处的有交点,说明在原始图像空间中在±45°处各有3个点共线。两条曲线在(ρ,θ)=(0,-90)、(-101,-90)、(0,0)、(101,90)、(0,90)处有交点,说明原始图像空间中有4组位于垂直线和水平线上的共线点。

 

2. 函数houghpeaks()

线检测和线连接用的Hough变换,第一步是用高的计数寻找累加单元(工具箱中把高的计数单元作为峰值)。

函数作用:确定Hough变换中的峰值(identify peaks in hough transform)

语法形式

peaks = houghpeaks(H, numpeaks)    或者    peaks = houghpeaks(..., Name, Value, ...)

描述

peaks = houghpeaks(H, numpeaks) locates peaks in the Hough transform matrix, H, generated by the hough function. 参数 numpeaks 指定了需要确定的峰值个数。函数返回 peaks,它是一个包含峰值点行坐标和列坐标的矩阵(从后面示例代码中可知,这个矩阵是一个两列矩阵,第一列保存的是ρ,第二列保存的是θ)。peaks = houghpeaks(..., Name, Value, ...) locates peaks in the Hough transform matrix, 这里使用命名的参数控制各项操作。

MATLAB帮助文档中的示例:(为了更直观地显示处理效果,代码有改动)

locate and display peaks in hough transform of rotated image ( 定位并显示旋转图像的hough变换中的峰值点 )

close all; clear all; clc; 

% Read image into workspace
I = imread('circuit.tif'); 
figure; 
subplot(121), imshow(I); 

% Create binary image
BW = edge(imrotate(I, 50, 'crop'), 'canny');
subplot(122), imshow(BW); 

% Create hough transform of image
[H, theta, rho] = hough(BW);
figure, imshow(H, [], 'InitialMagnification', 'fit'); 
axis normal;

% Find peaks in the hough transform of the image and plot them
P = houghpeaks(H, 3); 
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', 'red'); 

 

  

 

在图像中找出了3个峰值点,均用红色矩形框标记出来了。

3. 函数houghlines()

函数作用

根据Hough变换提取线段(extract line segments based on hough transform)

语法形式

lines=houghlines(BW, theta, rho, peaks)  

lines=houghlines(..., Name, Value, ...)

描述

lines=houghlines(BW, theta, rho, peaks)提取图像BW中对应于Hough变换下特定峰点的线段(extract line segments in the image BW associated with particular bins in a Hough transform)。(这里把bin理解为hough变换中的峰点,不知道确不确切)。theta和rho是由函数hough()返回的向量。peaks是函数houghpeaks()返回的用于寻找线段的矩阵,该矩阵包含了Hough变换下特定峰点的行坐标和列坐标。返回值lines是一个结构数组,它的长度等于寻找到的线段的数量。

lines=houghlines(..., Name, Value, ...)提取图像BW中的线段,这里命名的参数会影响函数的操作。(额,翻译过来就是这个样子)。

MATLAB帮助文档中的示例:(稍有改动)

Find line segments and Highlight longest segment(寻找线段并使最长的线段高亮)

close all; clear all; clc; 

% Read image into workspace
I = imread('circuit.tif'); 
figure; 
subplot(131), imshow(I); 

% Rotate the image
rotI = imrotate(I, 33, 'crop'); 
subplot(132), imshow(rotI); 

% Create a binary image
BW = edge(rotI, 'canny'); 
subplot(133), imshow(BW); 

% Create the hough transform using the binary image 
[H, T, R] = hough(BW); 
figure, imshow(H, [], 'XData', T, 'YData', R, 'InitialMagnification', 'fit'); 
xlabel('\theta'), ylabel('\rho'); 
axis on, axis normal, hold on;
colormap(gca, hot);

% Find peaks in the hough transform of the image
P = houghpeaks(H, 5); 
x = T(P(:,2));
y = R(P(:,1)); 
plot(x, y, 's', 'color', 'blue'); 

% Find lines and plot them
lines = houghlines(BW, T, R, P, 'FillGap', 5, 'MinLength', 7); 
figure, imshow(rotI), hold on; 
max_len = 0; 
for k = 1 : length(lines)  % here length(lines)=12
   xy = [lines(k).point1; lines(k).point2]; 
   plot(xy(:, 1), xy(:, 2), 'LineWidth', 2, 'Color', 'green');
   
   % Plot beginnings and ends of lines
   plot(xy(1,1), xy(1,2), 'x', 'LineWidth', 2, 'Color', 'yellow');
   plot(xy(2,1), xy(2,2), 'x', 'LineWidth', 2, 'Color', 'red'); 
   
   % Determine the endpoints of the longest line segment
   len = norm(lines(k).point1 - lines(k).point2); % distance between point1 and point2
   if ( len > max_len )
      max_len = len; 
      xy_long = xy; 
   end
end

% Highlinght the longest line segment by coloring it cyan
plot(xy_long(:, 1), xy_long(:, 2), 'LineWidth', 2, 'Color', 'cyan'); 


 

   

 

 

版权声明:本文为qq_15971883原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_15971883/article/details/80583364

智能推荐

java乐观锁和悲观锁最底层的实现

1. CAS实现的乐观锁 CAS(Compare And Swap 比较并且替换)是乐观锁的一种实现方式,是一种轻量级锁,JUC 中很多工具类的实现就是基于 CAS 的,也可以理解为自旋锁 JUC是指import java.util.concurrent下面的包, 比如:import java.util.concurrent.atomic.AtomicInteger; 最终实现是汇编指令:lock...

Python 中各种imread函数的区别与联系

  原博客:https://blog.csdn.net/renelian1572/article/details/78761278 最近一直在用python做图像处理相关的东西,被各种imread函数搞得很头疼,因此今天决定将这些imread总结一下,以免以后因此犯些愚蠢的错误。如果你正好也对此感到困惑可以看下这篇总结。当然,要了解具体的细节,还是应该 read the fuc...

用栈判断一个字符串是否平衡

注: (1)本文定义:左符号:‘(’、‘[’、‘{’…… 右符号:‘)’、‘]’、‘}’……. (2)所谓的字符串的符号平衡,是指字符串中的左符号与右符号对应且相等,如字符串中的如‘(&r...

JAVA环境变量配置

位置 计算机->属性->高级系统设置->环境变量 方式一 用户变量新建path 系统变量新建classpath 方式二 系统变量 新建JAVA_HOME,值为JDK路径 编辑path,前加 方式三 用户变量新建JAVA_HOME 此路径含lib、bin、jre等文件夹。后运行tomcat,eclipse等需此变量,故最好设。 用户变量编辑Path,前加 系统可在任何路径识别jav...

常用的伪类选择器

CSS选择器众多 CSS选择器及权重计算 最常用的莫过于类选择器,其它的相对用的就不会那么多了,当然属性选择器和为类选择器用的也会比较多,这里我们就常用的伪类选择器来讲一讲。 什么是伪类选择器? CSS伪类是用来添加一些选择器的特殊效果。 常用的为类选择器 状态伪类 我们中最常见的为类选择器就是a标签(链接)上的为类选择器。 当我们使用它们的时候,需要遵循一定的顺序问题,否则将可能出现bug 注意...

猜你喜欢

ButterKnife的使用介绍及原理探究(六)

前面分析了ButterKnife的源码,了解其实现原理,那么就将原理运用于实践吧。 github地址:       点击打开链接 一、自定义注解 这里为了便于理解,只提供BindView注解。 二、添加注解处理器 添加ViewInjectProcessor注解处理器,看代码, 这里分别实现了init、getSupportedAnnotationTypes、g...

1.写一个程序,提示输入两个字符串,然后进行比较,输出较小的字符串。考试复习题库1|要求:只能使用单字符比较操作。

1.写一个程序,提示输入两个字符串,然后进行比较,输出较小的字符串。 要求只能使用单字符比较操作。 参考代码: 实验结果截图:...

小demo:slideDown()实现二级菜单栏下拉效果

效果如下,鼠标经过显示隐藏的二级菜单栏 但是这样的时候会存在一个问题,就是鼠标快速不停移入移出会导致二级菜单栏闪屏现象,一般需要使用stop()来清除事件  ...

基于docker环境的mysql主从复制

1、安装docker 可以参考之前的博客,之前写过了~ 2、拉取mysql镜像 3、创建mysql01和mysql02实例 主: 从: 4、进入容器修改配置 1)修改主数据库配置 进入主数据库容器 切换到 etc/mysql/目录下 查看可以看到my.cnf文件,使用vim编辑器打开,但是需要提前安装 安装vim命令: 安装成功后,修改my.cnf文件 新增配置后的my.cnf: binlog 日...

机器学习算法之决策树

原文:http://www.jianshu.com/p/6eecdeee5012 决策树是一种简单高效并且具有强解释性的模型,广泛应用于数据分析领域。其本质是一颗由多个判断节点组成的树,如: 决策树 在使用模型进行预测时,根据输入参数依次在各个判断节点进行判断游走,最后到叶子节点即为预测结果。 如何构造决策树 决策树算法的核心是通过对数据的学习,选定判断节点,构造一颗合适的决策树。 假设我们从用户...