2016-08-12 98 views
1

假设我有一个场景解析映射的图像,这个场景解析映射中的每个像素指示这个像素属于哪个对象。现在我想要获得每个对象的边界框,我该如何在python中实现它? 对于一个具体例子,说我有一个场景分析图是这样的:如何获得在python中给定像素标签的对象边界框?

0 0 0 0 0 0 0 
0 1 1 0 0 0 0 
1 1 1 1 0 0 0 
0 0 1 1 1 0 0 
0 0 1 1 1 0 0 
0 0 0 0 0 0 0 
0 0 0 0 0 0 0 

所以边框是:

0 0 0 0 0 0 0 
1 1 1 1 1 0 0 
1 0 0 0 1 0 0 
1 0 0 0 1 0 0 
1 1 1 1 1 0 0 
0 0 0 0 0 0 0 
0 0 0 0 0 0 0 

其实,在我的任务,只知道这个宽度和高度对象就够了。

一个基本的想法是在场景解析图中从上,下,左,右方向搜索四条边。但是图像中可能存在很多小物体,这种方式并不具有时间效率。

第二种方法是计算所有非零元素的坐标并找出最大/最小x/y。然后使用这些x和y来计算重量和高度。

有没有其他更有效的方法来做到这一点?谢谢。

+0

请SH把你的尝试交给我们。 – Julien

+0

加入@ @ JulienBernu – Demonedge

+0

你需要做的事听起来非常类似于图形[洪水填充](https://en.wikipedia.org/wiki/Flood_fill),所以你可以使用算法来做它的起点点(双关语意)。 – martineau

回答

3

如果你正在处理图像,你可以使用scipy的ndimage库。

如果只有一个对象的图像中,你可以得到scipy.ndimage.measurements.find_objects测量(http://docs.scipy.org/doc/scipy-0.16.1/reference/generated/scipy.ndimage.measurements.find_objects.html):

import numpy as np 
from scipy import ndimage 
a = np.array([[0, 0, 0, 0, 0, 0, 0], 
       [0, 1, 1, 0, 0, 0, 0], 
       [1, 1, 1, 1, 0, 0, 0], 
       [0, 0, 1, 1, 1, 0, 0], 
       [0, 0, 1, 1, 1, 0, 0], 
       [0, 0, 0, 0, 0, 0, 0], 
       [0, 0, 0, 0, 0, 0, 0]]) 

# Find the location of all objects 
objs = ndimage.find_objects(a) 

# Get the height and width 
height = int(objs[0][0].stop - objs[0][0].start) 
width = int(objs[0][1].stop - objs[0][1].start) 

如果在图像中许多对象,你首先必须标记每个对象,然后得到的测量:

import numpy as np 
from scipy import ndimage 
a = np.array([[0, 0, 0, 0, 0, 0, 0], 
       [0, 1, 1, 0, 0, 0, 0], 
       [1, 1, 1, 1, 0, 0, 0], 
       [0, 0, 1, 1, 1, 0, 0], 
       [0, 0, 1, 1, 1, 0, 0], 
       [0, 0, 0, 0, 0, 0, 0], 
       [0, 0, 1, 1, 1, 0, 0]]) # Second object here 
# Label objects 
labeled_image, num_features = ndimage.label(a) 
# Find the location of all objects 
objs = ndimage.find_objects(labeled_image) 
# Get the height and width 
measurements = [] 
for ob in objs: 
    measurements.append((int(ob[0].stop - ob[0].start), int(ob[1].stop - ob[1].start))) 

如果检查ndimage.measurements,你可以得到更多的测量:质量,区域的中心......

+0

这真的很酷!谢谢! – Demonedge

2

使用numpy的:更

import numpy as np 

ind = np.nonzero(arr.any(axis=0))[0] # indices of non empty columns 
width = ind[-1] - ind[0] + 1 
ind = np.nonzero(arr.any(axis=1))[0] # indices of non empty rows 
height = ind[-1] - ind[0] + 1 

说明一下:

arr.any(axis=0)给出了一个布尔数组,告诉您如果列是空的(False)否(True)。 np.nonzero(arr.any(axis=0))[0]然后从该数组中提取非零(即True)索引。 ind[0]是该数组的第一个元素,因此最左列非空列和ind[-1]是最后一个元素,因此是最右侧非空列。然后差异给出宽度,取决于是否包含边框。 高度相似的东西,但在另一个轴上。

+0

为什么downvote? – Julien

+0

我不知道,也许强制使用'numpy',因为它完全可以用python来实现。但OP没有向我们显示任何代码,所以我怀疑他没有编写任何代码。一些高级代表人员在编写代码时没有先写代码就皱眉头。 –

+0

OP要求效率,所以禁止使用numpy先验和downvoting出于这个原因似乎对我来说是愚蠢的。如果这是我不是一个精神病患者的第二个原因,所以我希望被告知而不是被期望读懂他们的想法......+我已经看到很多类似的问题由hi-rep人自己回答... – Julien

相关问题