【问题标题】:Opencv python HoughLinesP strange resultsOpencv python HoughLinesP 奇怪的结果
【发布时间】:2016-07-26 22:28:32
【问题描述】:

我正在尝试获得与this HoughLinesP 过滤器教程中相同的结果。我像这样拍摄了相同的图像和相同的阈值:

import cv2
from line import Line
import numpy as np

img = cv2.imread('building.jpg',1)
cannied = cv2.Canny(img, 50, 200, 3)
lines = cv2.HoughLinesP(cannied, 1, np.pi / 180, 80, 30, 10)


for leftx, boty, rightx, topy in lines[0]:
    line = Line((leftx, boty), (rightx,topy))
    line.draw(img, (255, 255, 0), 2)

cv2.imwrite('lines.png',img)
cv2.imwrite('canniedHouse.png',cannied)
cv2.waitKey(0)
cv2.destroyAllWindows()

Line 类是一个自定义类,它不做任何有趣的事情,只是计算一些东西并且可以画线。 然后我得到这两张图片:

如您所见,我在图像中间只看到了一条小线。

不知道出了什么问题。我错过了什么?

谢谢。

【问题讨论】:

    标签: python opencv houghlinesp


    【解决方案1】:

    注意:由于您链接了 OpenCV 2.4.x 的教程,我最初假设您也使用 OpenCV 2.4.11 编写了代码。事实证明,您实际上使用的是 OpenCV 3.x。请记住,2.x 和 3.x 之间的 API 有细微的变化。


    你打错了HoughLinesP

    根据文档,Python函数的签名是:

    cv2.HoughLinesP(image, rho, theta, threshold[, lines[, minLineLength[, maxLineGap]]]) → lines
    

    如果我们在您的调用中标记参数,我们会得到以下信息:

    lines = cv2.HoughLinesP(cannied, rho=1, theta=np.pi / 180
        , threshold=80, lines=30, minLineLength=10)
    

    但是,正确移植到 Python 的 C++ 代码将是

    lines = cv2.HoughLinesP(cannied, rho=1, theta=np.pi / 180
        , threshold=80, minLineLength=30, maxLineGap=10)
    


    Canny类似的情况

    cv2.Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradient]]]) → edges
    

    再次,让我们标记参数:

    cannied = cv2.Canny(img, threshold1=50, threshold2=200, edges=3)
    

    但应该是:

    cannied = cv2.Canny(img, threshold1=50, threshold2=200, apertureSize=3)
    

    但这对输出没有影响,因为光圈大小的默认值为 3。


    最后,正如我们用Vasanthnamatoj 确定的,cv2.HoughLinesP 生成的输出格式有所不同:

    • 在 2.4 中看起来像 [[[x1, y1, x2, y2], [...], ..., [...]]]
    • 在 3.x 中看起来像 [[[x1, y1, x2, y2]], [[...]], ..., [[...]]]

    我添加了一个简短的get_lines 函数,用于在两个版本中将线条转换为一致的布局 ([[x1, y1, x2, y2], [...], ..., [...]])。


    适用于两个 OpenCV 版本的完整脚本:

    import cv2
    import numpy as np
    
    
    def get_lines(lines_in):
        if cv2.__version__ < '3.0':
            return lines_in[0]
        return [l[0] for l in lines]
    
    
    img = cv2.imread('building.jpg')
    img_gray = gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    
    cannied = cv2.Canny(img_gray, threshold1=50, threshold2=200, apertureSize=3)
    lines = cv2.HoughLinesP(cannied, rho=1, theta=np.pi / 180, threshold=80, minLineLength=30, maxLineGap=10)
    
    for line in get_lines(lines):
        leftx, boty, rightx, topy = line
        cv2.line(img, (leftx, boty), (rightx,topy), (255, 255, 0), 2)
    
    cv2.imwrite('lines.png',img)
    cv2.imwrite('canniedHouse.png',cannied)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

    【讨论】:

      【解决方案2】:

      正如 Dan 的回答所提到的,Canny 和 HoughLinesP 中没有正确指定参数。

      修改代码:

      import cv2
      from line import Line
      import numpy as np
      
      img = cv2.imread('building.jpg',1)
      cannied = cv2.Canny(img, 50, 200, apertureSize=3)
      lines = cv2.HoughLinesP(cannied, 1, np.pi / 180, 80, minLineLength=30, maxLineGap=10)
      
      for leftx, boty, rightx, topy in lines[0]:
          line = Line((leftx, boty), (rightx,topy))
          line.draw(img, (255, 255, 0), 2)
      
      cv2.imwrite('lines.png',img)
      cv2.imwrite('canniedHouse.png',cannied)
      cv2.waitKey(0)
      cv2.destroyAllWindows()
      

      输出:

      如果您使用的是 OpenCV-3+,请改用此 for 循环,因为 HoughLinesP 返回不同的输出格式[[[x1, y1, x2, y2]], [[...]]...[[...]]]

      for l in lines:  #Modified to loop across all the lines
          leftx, boty, rightx, topy = l[0] #assign each line's values to variables
          line = Line((leftx, boty), (rightx,topy))
          line.draw(img, (255, 255, 0), 2)
      

      【讨论】:

      • 这可能是特定于版本的。当我查看 OpenCV 2.4.11 中的 lines 时,我发现它采用以下格式:[[[x1,y1,x2,y2],[....]]]。这使得 Anton 的代码正确。
      • 是的。我认为你是对的。 2.4.11 有不同的格式。我会更新我的答案。
      【解决方案3】:

      您的代码中的问题是返回的行是如何排列的。 这段代码对我有用:

      import cv2
      import numpy as np
      
      img = cv2.imread('building.jpg',1)
      cannied = cv2.Canny(img, 50, 200, 3)
      lines = cv2.HoughLinesP(cannied, 1, np.pi / 180, 80, 30, 10)
      
      for line in lines:
          leftx, boty, rightx, topy = line[0]
          cv2.line(img, (leftx, boty), (rightx,topy), (255, 255, 0), 2)
      
      cv2.imwrite('lines.png',img)
      cv2.imwrite('canniedHouse.png',cannied)
      cv2.imshow('', img)
      cv2.waitKey(0)
      cv2.destroyAllWindows()
      

      为了让代码在我的机器上运行,我还做了一些其他的小改动。

      我认为您需要更改一些参数才能获得与文档中完全相同的结果。

      【讨论】:

      • 由于您的代码与 Vasanth 的代码几乎相同,因此它包含的问题与我在 cmets 中指出的相同。
      • 不知道这个,谢谢指出!看起来 OP 在版本 3 上也这样做了。
      • 关于 OP 的 OpenCV 版本的要点。我的视野有点狭隘,因为我把注意力集中在了错误的参数上。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-12
      • 1970-01-01
      • 1970-01-01
      • 2020-07-13
      • 2016-01-22
      • 1970-01-01
      相关资源
      最近更新 更多