【问题标题】:How to get an object bounding box given pixel label in python?如何在python中获取给定像素标签的对象边界框?
【发布时间】:2016-12-19 03:35:10
【问题描述】:

假设我有一个图像的场景解析图,这个场景解析图中的每个像素都表示这个像素属于哪个对象。现在我想获取每个对象的边界框,如何在 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 计算体重和身高。

还有其他更有效的方法吗?谢谢。

【问题讨论】:

  • 请向我们展示您的尝试。
  • 已添加。@JulienBernu
  • 您需要做的事情听起来与图形 flood filling 非常相似,因此您可以使用算法作为起点(双关语)。

标签: python image-processing


【解决方案1】:

使用 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] 是最后一个元素,因此是最右边的非空列。然后根据是否包含边框,差异给出宽度,给出或取 1。 高度类似的东西,但在另一个轴上。

【讨论】:

  • 我不知道,可能是numpy 的强制使用,因为它完全可以使用python。但是 OP 没有向我们展示任何代码,所以我怀疑他没有编写任何代码。一些高级代表不喜欢在没有先编写代码的情况下为 OP 编写代码。
  • OP 要求效率,因此禁止使用 numpy 先验并因此而投票对我来说似乎很愚蠢。如果这是我不是通灵者的第二个原因,那么我希望被告知而不是被期望读懂他们的想法...... +我已经看到很多类似的问题由高级代表自己回答......
  • 感谢您的回答,我不知道为什么这被否决了,但这正是我所需要的。
  • @Julien Bernu:在某些企业系统上,numpy 不可用,也无法安装。我怀疑否决票与此有关。我认为您没有充分解释您的解决方案。好吧,有些人有代表花费对工作答案进行投票的方式,这对他们有好处。我更喜欢评论并询问它是如何工作的。 +1(但我想要一些解释作为回报:))
  • @Jean-FrançoisFabre 是的,要求额外澄清从来没有杀死任何人......你去;)
【解决方案2】:

如果要处理图片,可以使用 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,你可以得到更多的测量值:质心、面积...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-01-05
    • 2016-06-10
    • 1970-01-01
    • 2018-05-26
    • 2019-09-18
    • 2021-12-13
    • 2019-05-11
    • 1970-01-01
    相关资源
    最近更新 更多