为啥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
,由rho
和theta
组成。
如果他们将其构造成这样当然会更好
[ [r0,t0], [r1,t1], ... ,[rn,tn] ]
但相反,他们通过使用额外的嵌套来混淆
[ [[r0,t0]], [[r1,t1]], ... ,[[rn,tn]] ]
表格。
line in lines:
循环通过给出[[ri,ti]]
术语,然后您可以通过line[0]
将其转换为[ri,ti]
,然后将其传递给rho
和theta
。
【讨论】:
这是正确答案。也许 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 实现会产生不同的输出?