【问题标题】:Explanation about hough_line_peaks after using hough_line使用 hough_line 后关于 hough_line_peaks 的说明
【发布时间】:2019-05-23 22:15:38
【问题描述】:

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

这是检测图像中线条角度的代码的 sn-p:

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]

【问题讨论】:

  • 没有人会回答这个问题,因为它不是MWE。首先,如果这些是对实际 opencv 函数的调用,Hough 变换签名将如下所示:h, theta, d = HoughLines(image, rho=1, theta=1, threshold=1) 但这里发生的 hough_line 让我觉得这是对其他函数的调用,而不是对 cv2 的调用。与hough_line_peaks 相同。 zip(*...) 构造也很可疑,为什么要解压缩然后再次使用 zip 重新打包。如果你给我们一些东西,我们可以试试 - 也许
  • 我使用的 hough_line 和 hough_line_peaks 来自 scikit-image API 而不是 openCV。
  • 就像我说的,没有进口或标签是不可能的。

标签: python hough-transform


【解决方案1】:

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

  • 使用hough_lines 检测图像上的所有线条。
    • 这将返回累加器值、角度、弧度和与原点的距离,假设霍夫空间中有 1000 个峰值,它标识为线。
  • 仅选择所有检测到的行中最突出的行
    • 距离原点至少 9 个“分辨率”步距另一个相似峰的峰
    • theta 坐标与另一个相似的峰相距至少 10 角“分辨率”的那些峰
    • 在整个霍夫空间中累加器计数大于 max_count/2 的那些
    • 这个选择让我们假设原始 1000 行中的 200 行更有可能实际上是图像中的行。
    • 这实际上是对所有返回的hough_lines 的过滤器,它选择最有可能是行的那些。因此,您还可以返回累加器值、角度、弧度和与原点的距离。
  • 然后你将所有从hough_line_peaks返回的角度复制到一个名为a的新list
  • 然后使用另一个 for 循环遍历 a 并创建一个名为 angle 的新列表,在其中存储从 a 转换为 degrees 的值

如您所见,可能还有改进的余地。首先,不需要复制整个角度列表。其次,你实际上做了更多的伤害,因为现在你不能使用 numpy 给你的向量化操作。从 hough_line_peaks 返回的数组是一个 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)) 应该总是值得怀疑的,因为* 被称为“解包”操作符。因此,给定一个元组、列表或任何其他可迭代的(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=1a 的水平切片,因此(1+2)/2=1.5(3+4)/2=3.5。这同样适用于任何更大维度的元素矩阵,其中包含更多维度的附录。因此,对于 2D 矩阵,它的垂直+水平对于 3D 它将是垂直+水平+深度。所以轴 2 对“深度”求和。

为什么这是必要的,hough_lines 只能处理强度数据。它不理解颜色。但在彩色图像中,每个像素实际上是 3 个数字(r, b, g),代表红色、蓝色和绿色通道强度。这些强度的混合最终会在显示器上产生颜色。因此mean(axis=2) 行指示 numpy 获取表示图像的 3D 矩阵并返回给您一个 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 |  .   .
    |  .    .
    |  .     .
    | 

【讨论】:

  • 谢谢队友,真的很有帮助,真的很感激:)
  • 你知道image = np.mean(image,axis=2) 是做什么的吗?我读到它根据轴计算平均值,但它在算法中有什么好处?
  • @DanielK 编辑了我的答案。
猜你喜欢
  • 2019-09-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-29
  • 2019-05-06
相关资源
最近更新 更多