首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何从底部填充图像,直到使用OpenCV检测到边缘为止?

如何从底部填充图像,直到使用OpenCV检测到边缘为止?
EN

Stack Overflow用户
提问于 2017-07-17 04:23:19
回答 2查看 2K关注 0票数 2

我的目标是能够使用链接 3复制这个OpenCV显示的避障方法,看起来他们提供的软件只适用于OpenCV。我认为使用OpenCV进行复制是可能的。我目前在第二步使用Canny边缘检测。我不知道我可以使用什么函数来创建第3步,在这个步骤3中,图像是从底部填充的,直到检测到边缘。如有任何参考资料,将不胜感激。谢谢。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-07-17 08:08:38

方法0

这是标准的,基于循环的方法来完成这一点。这个想法是从每一列的底部开始,把每个像素都涂成白色,直到一个白色像素被击中。这就是小猪在下面的建议。

代码语言:javascript
复制
h, w = edges.shape[:2]
filled_from_bottom = np.zeros((h, w))
for col in range(w):
    for row in reversed(range(h)):
        if edges[row][col] < 255: filled_from_bottom[row][col] = 255
        else: break

方法1

现在,这个方法使用了一些numpy技巧来加速操作。

首先,对于每一列,在边缘图像中有一个非零值的地方,查找最大行索引。

代码语言:javascript
复制
h, w = img.shape[:2]
row_inds = np.indices((h, w))[0] # gives row indices in shape of img
row_inds_at_edges = row_inds.copy()
row_inds_at_edges[edges==0] = 0 # only get indices at edges, 0 elsewhere
max_row_inds = np.amax(row_inds_at_edges, axis=0) # find the max row ind over each col

然后,您可以创建一个布尔数组,其中每个大于或等于最大索引的索引都是True

代码语言:javascript
复制
inds_after_edges = row_inds >= max_row_inds

然后,您只需在布尔数组给出的新索引处填充一个新的空白图像就可以了。

代码语言:javascript
复制
filled_from_bottom = np.zeros((h, w))
filled_from_bottom[inds_after_edges] = 255

方法2

这种方法的内存效率略高,速度效率略高一些。这是与方法1相同的基本前提。

首先,对于每一列,查找与每列中的最大值相对应的行索引(即边缘图像中的白色颜色)。注意,函数np.argmax将返回数组中最大值的第一个实例,而我们希望得到最后一个实例:

在最大值多次出现的情况下,返回对应于第一次出现的索引。

因此,一个简单的方法是垂直翻转数组,但这给了我们倒转数组的索引。我认为在看到它之后,仅仅解释一下一条龙就更直观了:

代码语言:javascript
复制
h, w = img.shape[:2]
max_row_inds = h - np.argmax(edges[::-1], axis=0)

切片[::-1]从上到下反转边缘(也可以使用np.flipud)。然后,由于数组是翻转的,np.argmax从末尾给出索引,所以h - np.argmax将索引赋给正确的定向数组。np.argmax(..., axis=0)的意思是,我们取每列的最大值。

现在,我们可以像前面一样创建布尔数组:

代码语言:javascript
复制
row_inds = np.indices((h, w))[0]
inds_after_edges = row_inds >= max_row_inds

这个方法比较好的原因是我们没有创建数组的副本,而是删除了许多值的数组赋值。

速度试验

第一种方法是最简单的,但在Python中是最慢的。Python循环非常慢,而numpy操作通常是用基于C或Fortran的方法实现的,因此它们非常快速。我用以下代码测试了这种差异:

代码语言:javascript
复制
import timeit
times = range(1000)

start_time = timeit.default_timer()
A = [method0(edges) for t in times]
print("method0: ", timeit.default_timer() - start_time)

start_time = timeit.default_timer()
B = [method1(edges) for t in times]
print("method1: ", timeit.default_timer() - start_time)

start_time = timeit.default_timer()
C = [method2(edges) for t in times]
print("method2: ", timeit.default_timer() - start_time)

所以每种方法都运行了1000次。结果:

代码语言:javascript
复制
method0: 62.79985192901222
method1: 0.9703722179983743
method2: 0.7760374149947893

我们看到,最终的方法是最快的,就像预期的那样;只是比method1快一点,但并不疯狂。然而,基于循环的方法之间的差别是巨大的。

输出

票数 2
EN

Stack Overflow用户

发布于 2017-07-17 07:58:28

这是从图像的底部开始,然后逐个像素进行垂直处理,填充每个空白的黑色像素,直到看到一个非黑色像素为止。然后,填充停止垂直列,并继续进行下一列。

为此,您不需要任何花哨的OpenCV函数。这可以通过简单地使用几个循环来实现。

您可以就地执行此操作,也可以使用单独的输出映像,使用零进行初始化。

您所要做的就是从底部开始对图像的列进行迭代。如果像素的值为零,则将输出像素设置为255,一旦碰到不是零的像素,则将其余像素设置为0(或将其保留为0)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45135950

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档