如何在MATLAB中使用Hough变换进行线条检测

516 阅读7分钟

在MATLAB中使用Hough变换进行线条检测

Hough变换是一种在图像中分离出特定形状的算法。这些所需的特征应该以一个给定的参数形式来指定。这种算法被广泛用于检测规则的曲线。这些曲线是诸如直线、曲线、椭圆等。然而,Hough变换的一般应用不可能达到简单的分析特征描述。例如,线条检测是一个重要的特征,它有助于分析两个物体。它可以给出两个物体之间更重要的关系。

本教程将研究我们如何在Matlab中使用hough变换。此外,我们将了解线条检测的重要性以及如何使用Matlab代码进行线条检测。

前提条件

要学习本教程,你需要:

  • 安装[MATLAB]。
  • 对[MATLAB]基础知识的正确理解。

标准哈夫变换

我们可以用这个变换来测量一条线的长度。例如,假设需要检测图像中的一条线,它可以做到这一点。

Straight line

线条的一般表达式是y=mx+c。这意味着你可以把一条线映射成一个坐标对,m, c 。然而,垂直线有一个问题,因为斜率值是无界的。在这种情况下,Hough变换使用不同的参数表示。参数是θ和ρ。这里, θ 是轴和连接该最接近点的原点线之间的角度。ρ对应于从原点到直线上最近的点的距离。

Expression using rho, and theta

从概念上讲,Hough变换是将X和Y的图像坐标映射到参数坐标θ,ρ。

使用hough变换来检测一条线

假设一幅图像由一条线组成,如下图所示。

Your line

一条线是由多个点组成的。同样地,多条线也可以通过同一个点。我们在Hough变换平面上将多条线可视化,参数 θ 在x轴上,rhorho在y轴上。图像上的每一个点都被转换为正弦波。正弦波是一个正弦波形状的信号。

Image in the hough transform plane

它是有意义的,因为许多线可能会通过图像平面上的一个特定点。它在Hough平面上转化为一个正弦波。如果这些线中有两条或更多的线在图像平面上重合形成一条线,它们将在hough变换平面上相交。

Conciding lines

请注意,相交的正弦波的数量决定了一条线的强度。这就是Hough变换的工作原理。

在Matlab中使用hough变换提取线段

假设你有一个带线的图像,你想提取线段;算法是。

  1. 使用hough函数创建一个hough变换矩阵。
  2. 找到Hough变换矩阵函数中的峰值。这些峰值对应于参数平面中的交点。每个峰都是一条检测到的线。
  3. 使用Hough变换函数将峰值映射回图像平面。然后你再提取线段。

现在,我们用一个简单的图像来实现上述算法。我们有两个二进制图像,如下图所示。

Binary images

这些图像是二进制的,因为Hough变换函数在二进制图像上工作。注意,可以在Matlab中绘制这两幅图像。我们将首先绘制这两幅图像并提取线段。我们首先绘制带有两个点的图像,并从中提取线段,然后再去绘制第二个图像。

为了绘制带有两个点的图像,我们将执行下面的代码。

close all
clear
clc
%% 1. Image with two dots
a = zeros(50);
a(20,20) = 1; a(40,10) = 1;
figure;
subplot(2,2,1)
imshow(a)
title('Image with 2 dots')

Close all 用来关闭所有打开的数字, ,并清除命令窗口。然后我们用 ,制作一个尺寸为50x50的零点矩阵。 和 是放置点的位置。 创建一个图形窗口。然后我们使用 来查看输出。最后,使用 函数,我们为我们的输出创建一个子图。 创建一个 轴,该图被放置在位置 。clc zero(50) a(20, 20) a(40, 10) Figure imshow() subplot() subplot(m,n,p) MxN p

我们使用hough() 函数来计算hough矩阵。这个函数将二进制图像作为输入。这个函数给出了三个输出,即变换矩阵(H)、θ(T)和rho(R)。之后,我们使用实用函数houghMatViz() ,将输出结果可视化,如下图所示。

[H, T, R] = hough(a);
subplot(2, 2, 2)
houghMatViz(H, T, R)

让我们看一下这个实用函数的内容。记住,这个函数应该在一个不同的脚本中,然后我们再调用它。

function houghMatViz(H,T,R)
Hgray = mat2gray(H); % Converting hough matrix(H) into grayscale image.
Hgray = imadjust(Hgray); % Enhancing the brightness

imshow(Hgray,'XData',T,'YData',R);
hold on

axis on % turning on the axis.
axis normal 
colormap(hot);title('Hough Transform'); % Giving colormap to the image.

xlabel('\theta')  % add x-y labels
ylabel('\rho');

这个实用函数使用mat2gray() 函数将hough矩阵转换为灰度图像。然后,使用imadjust()function. Finally, this function takes the grayscale image as the argument. Theimshow()function displays the output depending on theXDataand theYData`调整灰度图像的亮度。

当我们执行这段代码时,我们得到两个正弦波,对应于图像中的两个点,如下图所示。

Two sinusoids corresponding to the two points

我们使用houghpeaks() 函数来寻找峰值。使用这个函数,你可以提供需要返回的峰值数量作为输出。如果你没有提供的话,输出将是最高的峰。

hPeaks = houghpeaks(H);

因为我们没有指定峰的数量,所以输出的是最大的峰。要看到这一点,在命令窗口中执行hpeaks 。我们可以在H 矩阵中找到峰值出现的位置。它是通过索引theta(T)、Rho(R)数组和像素位置来完成的,并绘制输出结果,如下所示。

x = T(hPeaks(:,2));  %indexing the theta(T) array
y = R(hPeaks(:,1));  %Indexing the rho(R) array

plot(x,y,'gs')

输出结果是。

Peak

绿色方块是峰值位置。峰值位置是穿过两个图像点的线。现在,我们将把同样的逻辑应用于第二幅图像。这里唯一的区别是,我们提取线段来重新绘制检测到的线条。让我们首先绘制线段。

b = eye(150);
subplot(2,2,3)
imshow(b)
title('Image with a line')

在这里,我们使用函数eye() ,给出一个MxN矩阵,其中主对角线上有1,其他部分有0。当我们使用这个函数时,我们得到如下图所示的图。

Plot of line

在图像中,有许多正弦波。这些正弦波中的每一个都对应于一条线上的一个点。最后一步是将峰值映射回图像平面并提取线段。这可以用houghlines() 函数来完成。这个函数将原始图像作为图像参考的输入,一个T、R值的数组,以及必须被标记回图像平面的峰值作为参数。

hlines = houghlines(b, T, R, hPeaks);

使用这些hline 值,我们可以在原始图像上重新绘制检测到的线条。这有助于我们看到检测是否成功。要做到这一点,我们使用下面的代码。

xy = [hlines.point1; hlines.point2];
figure;
imshow(b)
hold on
plot(xy(:,1), xy(:,2), 'g--', 'Linewidth', 5)
title('Detected line')

这里,我们使用hlines 结构来创建两个点,即hlines.point1hlines.point2 。在原始图像上,我们用不同的线型(-)、颜色(g)和线宽(5)来绘制这些点。它给出了下面的图。

Reconstruction

我们在图中看到的是原始线,虚线代表检测到的线。现在使用这种方法,我们可以从图像中提取线条。

总结

Hough变换形成了一种算法,使得检测图像中的线条变得容易。同时,这种算法也可以用来检测视频中的线条。这是因为视频是视频帧的组合。视频帧是一个部分的图像部分。这意味着我们可以用图像来训练算法,然后在视频中实现它。这使得它在机器人领域广泛适用。