OpenCV多色阈值

时间:2014-02-18 03:00:02

标签: python opencv numpy

我正在尝试在opencv cv2图像上进行多色阈值处理。我试图解决的问题如下:

  • R,G,B每个都有一个“有效”列表
  • 如果像素的R,G,B都被视为有效,则制作像素(0,0,0),否则制作(255,255,255)

例如

  • [221,180,50]在R频道中被视为有效
  • [23,18,2]在G频道中被视为有效
  • [84,22,48]在B频道中被视为有效

然后,如果像素具有以下任何值(RGB顺序)

  • (221,23,84)
  • (221,23,22)
  • (221,23,48)
  • (221,18,84)
  • (221,18,22)
  • (221,18,48)
  • ...
  • (50,2,48)

它将转换为(0,0,0),否则(255,255,255)

目前,我正在使用嵌套for循环:

for x in range(width):
    for y in range(height):
        imcv[y, x] = threshold(imcv[y, x])

其中threshold函数执行上述逻辑。请注意,虽然我就地执行了此操作,但不需要进行就地转换。

我目前使用的方法有效,但非常慢。我相信在OpenCV / Numpy中必须有一个更好的方法。我对这两个框架都很陌生,无法弄清楚如何。

我研究了OpenCV阈值处理功能,看来它们只能在单通道灰度图像上工作,而且范围也需要连续范围。我需要的是在离散值上对所有3个通道进行阈值处理。我想有一个自定义函数需要传入,但我无法在他们的文档中找到合适的API。

我也查找了可以使用的numpy API,例如ufunc。看来我无法实现我在这里使用它,或者我没有看到如何。

感谢任何帮助。

编辑:

感谢AbidRahmanK和HYRY,两种解决方案在性能上都取得了超过x1500的改进。

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     1    1.576    1.576    1.576    1.576 test.py:48(preprocess_cv2_image)
     1    0.000    0.000    0.001    0.001 test.py:79(preprocess_cv2_image3)
     1    0.000    0.000    0.001    0.001 test.py:66(preprocess_cv2_image2)

2 个答案:

答案 0 :(得分:2)

请试试这个:

z1 = np.dstack([np.in1d(img[...,0],B),np.in1d(img[...,1],G),np.in1d(img[...,2],R)]).reshape(img.shape)
q = np.all(z1,axis=2)
out = np.uint8(q)*255
如果该元素在b中,则

np.in1d(a,b)为您提供与True相同长度的布尔数组,否则为False。它只是Python中in方法的矢量化对应物。或者简而言之:

  

np.in1d(a,b)< ==> [对于我来说,如果我在其他地方,则为真假)

您对所有通道执行此操作,即检查第一个通道中B中的有效值,第二个带G,第三个带R。

然后使用np.dstack将它们沿z方向堆叠。为什么z方向?因为我们想要 BGR-BGR-BGR ... 格式。

但请记住,这是一维数组,因此我们使用X.reshape(img.shape)方法将其重塑为原始图像形状。

所以现在你有一个布尔掩码,如果有效则为True,否则为False。

这一切都在第一行代码中。

现在您想要查看有效的BGR组合。如果所有B,G,R分量都为True,则组合有效。所以你在z方向上应用np.all()。再次得到一个布尔掩码q

q将是一个布尔掩码,有效颜色为True,其他为False。

所以你转换为整数数据类型,True - > 1和假 - > 0

然后将它乘以255.如果您想要倒置图像,可以使用np.bitwise_not

答案 1 :(得分:1)

你可以为R,G,B制作三个布尔数组,如果该值对R有效,那么R[value]为True,那么你可以使用Rm[img[:, :, 2]] & Gm[img[:, :, 1]] & Bm[img[:, :, 0]]得到结果:

import numpy as np

img = np.random.randint(0, 256, (2000, 2000, 3))

def make_mask(idx):
    b = np.zeros(256, np.bool)
    b[idx] = True
    return b

R = [221, 180, 50]
G = [23, 18, 2]
B = [84, 22, 48]


Rm, Gm, Bm = [make_mask(v) for v in [R, G, B]]
a = Rm[img[:, :, 2]] & Gm[img[:, :, 1]] & Bm[img[:, :, 0]]

最后,要获得结果图像:

v = np.array([[255,255,255], [0,0,0]], np.uint8)
v[a.astype(np.uint8)]