我正在使用python和opencv在this paper中实现组件标记算法。它需要逐个像素地检查输入图像并执行所谓的轮廓跟踪子程序以将标签分配给二进制图像的斑点。
我设法让它运行,但似乎很慢。分析代码表明,访问像素的for循环似乎是瓶颈。 256px * 256px图像大约需要200ms。这大致是我的所作所为:
for i in image.height:
for j in image.width:
p = image[i, j]
pa = image[i - 1, j]
pb = image[i + 1, j]
# etc...
其中“image”是二进制opencv图像。
我想知道是否有更快的方法,以便它也可用于视频应用程序。对于相同的问题大小,我的目标是40-50ms的运行时间,达到20-25fps。 10-15fps也可能是可接受的(运行时间为66-100ms)。
非常感谢任何提示,我能做的事情。
答案 0 :(得分:1)
Python的最新OpenCV绑定返回了numpy数据类型,这意味着您可以使用完整的numpy库。在numpy(带索引)上循环2D数组通常使用ndenumerate
来完成,这应该提供至少一点加速(因为它是针对N-D阵列优化的单个循环)。您可以查看numpy vectorize
,这会产生更多的加速,但如果您需要数组的索引,那么ndenumerate
就是您所需要的。
除此之外,你最好的选择可能是在C中编写瓶颈操作。
<强>更新强>
如果它会有所帮助,我相信scipy.ndimage.label
正是您正在尝试做的事情,甚至可能使用相同的算法。
答案 1 :(得分:1)
我看到很多帖子都说缺乏OpenCV标签。
正如@ malloc47所说,scipy.ndimage.label
会起作用。我已经习惯了,但是当我在寻找图像中最大的斑点时,我对它的表现并不满意。我没有特别需要标签,因此我最终使用cv2.findContours
和cv2.contourArea
来隔离最大的标签:
# The [0] is because I didn't care about the hierarchy, which is the second
# return value of cv2.findContours.
contours = cv2.findContours(numpy_array,
mode=cv2.RETR_EXTERNAL,
method=cv2.CHAIN_APPROX_SIMPLE
)[0]
areas = [cv2.contourArea(ctr) for ctr in contours]
max_contour = [contours[areas.index(max(areas))]]
对于非常相似的结果,这对我来说比scipy.ndimage.label
快得多。正如我所说,这不是一个标签,但可以使用轮廓查找器给出相当好的标签。