使用hough_line后关于hough_line_peaks的解释

Explanation about hough_line_peaks after using hough_line

谁能解释一下为什么在使用 h,theta,d = hough_line(image) 检测图像中的角度后,我们是否必须使用此 for 循环 for _, a, d in zip(*hough_line_peaks(h, theta, d)): angle.append(a) #angle is a list 将角度添加到列表中? 由于 hough_line(image) 会将角度存储在 theta 变量中,为什么我们不能使用它来检索角度并将它们添加到列表中?

这是检测图像中线条角度的代码片段:

image = imread(file_name)  
image = np.mean(image, axis=2)  

h, theta, d = hough_line(image)  

angle = []  

for _, a, d in zip(*hough_line_peaks(h, theta, d)):
        angle.append(a)  

angle = [a * 180 / np.pi for a in angle]

所以这里发生的事情如下:

  • 使用 hough_lines 检测图像上的所有线条。
    • 这个 returns 累加器值、角度(以弧度为单位)和与原点的距离,假设 Hough space 中的 1000 个峰被识别为线。
  • select 只检测所有检测到的线中最突出的线
    • 与原点的距离至少为 9 "resolution" 步的那些峰与另一个相似的峰
    • theta 坐标与另一个相似的峰 "resolution" 步距至少 10 角的那些峰
    • 整个Hough中累加器计数大于max_count/2的space
    • 这个选择可以说是原始 1000 行中的 200 行更有可能是图像中的实际行。
    • 这实际上是对所有 returned hough_lines 的筛选器,它会挑选出最有可能是行的内容。因此,您还可以获得累加器值、角度(以弧度为单位)以及与原点的距离。
  • 然后你将从 hough_line_peaks 得到的所有角度复制到一个名为 a
  • 的新 list
  • 然后您使用另一个 for 循环遍历 a 并创建一个名为 angle 的新列表,您在其中存储从 a 转换为 degrees[ 的值=76=]

如您所见,可能还有改进的余地。首先,无需复制整个角度列表。其次,你实际上造成了更多的伤害,因为现在你不能使用 numpy 给你的矢量化操作。从 hough_line_peaks 编辑的数组 return 是一个 numpy ndarray,你可以直接将其相乘。

import skimage

image = skimage.io.imread(file_name)  
image = np.mean(image, axis=2)  

h, theta, d = skimage.transform.hough_line(image)
bestH, bestTheta, bestD = skimage.transform.hough_line_peaks(h, theta, d)
angle = bestTheta * (180/np.pi)

应该会得到相同的结果,而且可能会更快一些。整行 zip(*hough_line_peaks(h, theta, d)) 应该始终值得怀疑,因为 * 被称为 "unpacking" 运算符。因此,给定一个元组、列表或任何其他可迭代对象 (a, b, c),解包运算符将可迭代对象 *(a, b, c) --> a, b, c 解包,然后再次压缩它们只是将它们再次打包 *(a, b, c) --> a, b, c --> (a, b, c)。这些结构应该总是有点可疑。 for 循环 for _, a, b in... 中的下划线只是将该值作为无名丢弃。最后的 [ a for a in...] 构造称为列表推导式,它的工作方式与 for 循环完全相同,但只是语法糖,可在可能的情况下使内容更具可读性。

编辑

回答评论中的额外问题。让我们说:

>> import numpy as np
>>> a = np.array([[1, 2], [3, 4]])
>>> a
array([[1, 2],
       [3, 4]])

>>> a.mean(axis=0)
array([2., 3.])

>>> a.mean(axis=1)
array([1.5, 3.5])

所以轴 0 上的 mean 正在做 (1+3)/2=2(2+4)/2=3 - 因此有效 axis=0 是跨越 a 的垂直切片。 axis=1 是横跨 a 的水平切片,因此 (1+2)/2=1.5(3+4)/2=3.5。对于具有附录的任何更大维度的元素矩阵也是如此,您只有更多维度。所以对于 2D 矩阵,它的垂直+水平对于 3D 它将是垂直+水平+深度。所以轴 2 在 "depth" 上求和。

为什么这是必要的,因为 hough_lines 只能处理强度数据。它不理解颜色。但在彩色图像中,每个像素实际上是 3 个数字 (r, b, g),代表红色、蓝色和绿色通道强度。这些强度的混合最终会在显示器上产生颜色。因此,mean(axis=2) 行指示 numpy 获取表示图像的 3D 矩阵,并向您 return 提供 2D 矩阵,其中每个像素强度值已被 3 种颜色强度值的平均值所取代。

所以彩色图像:

index      1           2     ....
     ___________________________________
  1  | [1, 2, 3]  [4, 5, 6] ...
  2  | [7, 8, 9] .          ...
  .  |     .       .
  .  |     .         .
  .  |     .           .

变成灰度图:

index  1  2
    ______________________________
  1 |  2  5 ...
  2 |  8  . ...
  3 |  .   .
    |  .    .
    |  .     .
    |