为啥OpenCV for Python的cv2.HoughLines的返回值需要用索引来访问?

Posted

技术标签:

【中文标题】为啥OpenCV for Python的cv2.HoughLines的返回值需要用索引来访问?【英文标题】:Why is the returned value of cv2.HoughLines of OpenCV for Python need to be accessed with index?为什么OpenCV for Python的cv2.HoughLines的返回值需要用索引来访问? 【发布时间】:2016-04-29 00:32:11 【问题描述】:

我希望我写的问题标题是正确的,因为我不知道如何准确地解释它。考虑下面的代码:

lines = cv2.HoughLines(edges,1,np.pi/180,200)
for rho,theta in lines[0]:
    a = np.cos(theta)
    b = np.sin(theta)
    x0 = a*rho
    y0 = b*rho
    x1 = int(x0 + 1000*(-b))
    y1 = int(y0 + 1000*(a))
    x2 = int(x0 - 1000*(-b))
    y2 = int(y0 - 1000*(a))

    cv2.line(img,(x1,y1),(x2,y2),(0,0,255),2)

为什么一定要写成for rho,theta in lines[0]:?通过这种代码,我只能获得一行。我试图删除lines 中的索引,但我得到了ValueError: need more than 1 value to unpack。我试图打印返回的值,它看起来像这样:

[[[ 287.            1.97222209]]

[[ 885.            1.20427716]]

[[ 881.            1.22173047]]]

我已经解决了这个问题,我让代码看起来像这样:

lines = cv2.HoughLines(edges,1,np.pi/180,200)
for i in range(10):
    for rho,theta in lines[i]:

我想知道,到底发生了什么?还是我在这里做错了什么?

【问题讨论】:

如果 tthe docs 说要使用 lines[0],那么这可能是正确的。 python 库是通往 C++ 核心的桥梁,因此索引可能与此有关。 【参考方案1】:

我认为应该是这样的:

for line in lines:
    rho, theta = line[0]
    ...

这样你循环遍历lines数组中的所有值,每个值都是一个line,由rhotheta组成。

如果他们将其构造成这样当然会更好

[ [r0,t0], [r1,t1], ... ,[rn,tn] ]

但相反,他们通过使用额外的嵌套来混淆

[ [[r0,t0]], [[r1,t1]], ... ,[[rn,tn]] ]

表格。

line in lines: 循环通过给出[[ri,ti]] 术语,然后您可以通过line[0] 将其转换为[ri,ti],然后将其传递给rhotheta

【讨论】:

这是正确答案。也许 OpenCV 改变了这个功能。无论哪种方式,文档都已过时或完全错误。很奇怪。【参考方案2】:

这个问题和这个答案是指这个基于opencv 3.0.0 的tutorial。在 openCV 3.2.0 中,houghlines 返回的嵌套列表是一个 nX1X2 数组(其中 n 是行数),访问 rho 和 theta 的正确方法可以在 tutorial 中找到。

所以.. 根据第一个教程: “Lines”是一个多维 1XnX2 数组(ndarray),其中 n 是检测到的行数。

第一个数组只包含一个元素,lines[0](nX2 数组),它是你的行列表(你只需要遍历它)。

在第二级,您有行[0][0]、行[0][1]、...、行[0][n]。 (这是你的台词)

最后,在第 3 级,您有 lines[0][n][0] 和 lines[0][n][1] ,它们是每行的 rho 和 theta 值。您的解决方案将不起作用,因为没有 lines[1] 数组!

您可以将其添加到您的代码中并查看它打印的内容。

print lines.shape
print lines[0].shape
print lines[0][0].shape

【讨论】:

这是一个nX1X2 数组。您的代码分别为我打印 (14, 1, 2)(1, 2)(2,)(其中 14 是可变的,即 n)。 嗯,其实你说对了一部分。最初的问题和我的回答都参考了这个基于 opencv 3.0.0 的tutorial。从文档中可以看出,数组确实是 1XnX2,这也解释了为什么使用lines[0] 来访问示例中的行。从那时起,呈现 houghlines 输出的嵌套列表已更改,访问它们的正确方法可以在 tutorial 中找到。 同意。我对您的回答投了反对票,因为鉴于 OP 有不同的版本,它没有回答这个问题。现在改为点赞,感谢您的修改!【参考方案3】:
for line in lines:
    rho, theta = line[0]
    a = np.cos(theta)
    b = np.sin(theta)

这适用于 Python2.7 (Anaconda) 和 OpenCV3.1.0。 OpenCV (1XnX2) 提供的在线文档中的示例与其在 HoughLines 函数 (nX1X2) 中实际返回的示例之间似乎存在不匹配。

【讨论】:

【参考方案4】:

通过写入line[0],您可以访问数组的第一个元素。在这种情况下,第一个元素是另一个包含行参数 rho 和 theta 的数组。这就是cv2.HoughLines 函数返回结果的方式。

因此,如果您想遍历 rho 和 theta 的每个组合(即图像中找到的每一行),您可以编写

for [rho, theta] in lines[0]:
    print rho
    print theta

【讨论】:

【参考方案5】:

这对我有用

for l in lines:
    rho = l[0][0]
    theta = l[0][1]
    a = np.cos(theta)

【讨论】:

虽然此代码可能会回答问题,但提供有关此代码为何和/或如何回答问题的额外上下文可提高其长期价值。【参考方案6】:
lines=cv2.HoughLines(canny,1,numpy.pi/180,120)
for i in lines:
    # print(i)
    rho=i[0][0]
    theta=i[0][1]
    a=numpy.cos(theta)
    b=numpy.sin(theta)
    x0=a*rho
    y0=b*rho
    x1=int(x0+1000*(-b))
    y1=int(y0+1000*(a))
    x2=int(x0-1000*(-b))
    y2=int(y0-1000*(a))
    cv2.line(img,(x1,y1),(x2,y2),(0,255,0),1)
cv2.imshow('ss',img)

【讨论】:

【参考方案7】:
img = cv2.Canny(img,50,150)
lines = cv2.HoughLines(img,1,np.pi/180,50)
for k in range(lines.shape[0]):
    for rho,theta in lines[k]:
            a = np.cos(theta)
            b = np.sin(theta)
            x0 = a*rho
            y0 = b*rho
            P=2*max(img.shape)
            x1 = int(x0 + P*(-b))
            y1 = int(y0 + P*(a))
            x2 = int(x0 - P*(-b))
            y2 = int(y0 - P*(a))
            cv2.line(img,(x1,y1),(x2,y2),(0,255,0),5)

【讨论】:

以上是关于为啥OpenCV for Python的cv2.HoughLines的返回值需要用索引来访问?的主要内容,如果未能解决你的问题,请参考以下文章

Python and OpenCV - 为啥用 OpenCV 处理的裁剪图像仍然可以影响原始图像?

为啥 OpenCV 的 MSER 的 Python 实现和 Java 实现会产生不同的输出?

人脸识别为啥用python开发

为啥在 OpenCV Python 中按位发送错误?

opencv-python:为啥检测到不正确的边界框(几个边界框)?

opencv中加载掩膜为啥是灰度图