1。制作单通道图像
如果您需要一个图像具有单个通道,则使用一个通道而不是三个通道来生成它。所以而不是:
output = numpy.zeros(img.shape) # (height, width, 3)
output[~mask] = (255, 255, 255)
写:
output = numpy.zeros(img.shape[:2]) # just (height, width)
output[~mask] = 255
或者,如果您加载了多通道图像并且只想选择一个通道进行处理,请对其进行切片:
img = img[...,0] # red channel
但是如果您正在进行特征检测等进一步处理,则无需在此处保存输出图像或重新加载它。你可以继续使用mask。
2。寻找连续区域
您可以使用scipy.ndimage.measurements.label 查找图像的连续区域。默认情况下,这只会找到正交连接的区域;如果您也想要对角连接的区域,则传递适当的 structure 参数:
labels, n = scipy.ndimage.measurements.label(mask, numpy.ones((3, 3)))
结果是labels(与mask 形状相同的数组,包含标记mask 的连续区域的不同整数)和n(找到的区域数)。然后调用scipy.ndimage.measurements.find_objects 获取边界框:
>>> bboxes = scipy.ndimage.measurements.find_objects(labels)
>>> bboxes[0]
(slice(0, 2, None), slice(19, 23, None))
因此,在 x = 19–23 和 y = 0–2 处发现了这个物体(它是沿着图像顶部边缘的黑色小条)。您可以通过使用这对切片对原始图像进行索引来获取包含对象的子图像。这是对象 #3 中最上面的矩形:
>>> bboxes[3]
(slice(33, 60, None), slice(10, 86, None))
>>> img[bboxes[3]]
array([[255, 255, 0, ..., 0, 255, 255],
[255, 0, 0, ..., 0, 0, 255],
[ 0, 0, 255, ..., 0, 0, 255],
...,
[ 0, 0, 0, ..., 0, 0, 255],
[255, 0, 0, ..., 0, 255, 255],
[255, 255, 255, ..., 255, 255, 255]], dtype=uint8)
(其他矩形是对象 #4、#5 和 #8。)这是一种可视化它们的方法:
boxed = numpy.dstack((img,) * 3)
for y, x in bboxes:
if y.stop - y.start == 27: # is this the right criterion?
boxed[(y.start, y.stop-1), x] = (0, 255, 0)
boxed[y, (x.start, x.stop-1)] = (0, 255, 0)
imsave('boxed.png', boxed)