Python将图像像素掩码从一组值中移除

3

给定一个带标签的图像(像素值对应其标签),以及接受的标签列表,我正在尝试创建一个“掩码”图像,如果像素的标签被接受,则其值为255,否则为0

我知道这是一种缓慢的方法,因为它以Python速度迭代图像(但它很好地演示了这个想法):

mask = numpy.zeros(labels.shape[:2], dtype = "uint8")

for i in xrange(mask.shape[0]):
    for j in xrange(mask.shape[1]):
        if labels[i][j] in accepted:
            mask[i][j] = 255

我知道使用python切片和掩码会更快,但我不知道如何组合一个复杂的条件。当我逐个遮罩像这样接受标签的像素时,我仍然可以获得巨大的加速。

for value in accepted:
    mask[labels == value] = 255

我能用一行代码实现我想要的吗?我的python知识比较生疏(也就是说:最近几年几乎没有接触过python),虽然我试图借鉴其他例子来构造代码,但是下面这段代码是我得到的最接近结果:

mask[(labels in accepted).all()] = 255

在这种情况下,我遇到了以下错误:ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all() 我查看了类似的SO问题(例如这里这里等),但它们似乎都涵盖了值来自范围或低于/高于阈值(<10)的情况,或者要更改的图像切片是连续的。
任何有关如何检查“值是否在接受的值之间”的建议都将非常有用。
2个回答

4

同时,我找到了一个速度可接受的解决方案来回答自己的问题:

mask = numpy.zeros(labels.shape[:2], dtype = "uint8")
mask[numpy.in1d(labels, accepted).reshape(mask.shape)] = 255

首先使用numpy.in1dlabels数组中获取布尔数组,并检查哪些元素在accepted中存在(Python关键字"in"的逐个函数)。

由于即使可以应用于2D数组(它只是展开数组),似乎这必然返回一个1D数组,因此我接下来使用reshape()使布尔数组的维度对应于mask的维度。

最后,我使用该布尔数组索引所需的mask元素,并将其设置为所需值。


@rayryeng 老实说,我自己已经解决了这个问题,其实并不需要让你的解决方案正常运行。但是现在更多的是出于专业好奇心和喜欢解决问题的习惯,我只是想知道为什么我不能重现你的例子,只是为了能够重现它 :D - penelope
这个效果真是惊人 - 从使用一个for循环72小时到使用numpy的in1d只需40秒就完成了我的工作。谢谢! - Kevin M

1
将bool_obj中为True的像素位置提取出来,存放在一个列表中。其中x和y分别是这个像素在二维数组中的行和列索引值,img[x,y,:]则指代图片中这个位置的像素RGB值。最后将列表转换成一个numpy数组list_pixels。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接