为什么我不能使用 cv2.split 结果作为我的 cv2.bitwise_and 的掩码?

Why I could not use cv2.split result as masking for my cv2.bitwise_and?

我想知道为什么这不起作用?我尝试通过将 OpenCV 徽标拆分为 R、G 和 B 来进行简单操作,然后我尝试使用按位和将红色蒙版应用于原始图像,但为什么我没有只得到图像的红色部分?我做错了什么?谢谢。

代码在这里:

您要执行的操作需要 cv2.bitwise_and() method, not the cv2.bitwise_or() 方法。

尝试:

masked = cv2.bitwise_and(image, image, mask=R)
cv2.imshow('mask', masked)

参考:OpenCV - Apply mask to a color image

很可能是您的原始样本“不够干净”。
看起来黑色的 R 通道的值接近于零,但 不是 零。

cv2.bitwise_andcv2.bitwise_ormask 一起使用时,掩码中所有不等于零的值都被视为“真”(当掩码 != 0 , 值类似于 255).


仔细检查您发布的图片会发现黑色像素的值实际上是 1 而不是 0:


我从 here 下载了一个“干净”的 OpenCV 徽标,它按预期工作:

import cv2
import numpy as np

image = cv2.imread('OpenCV_Logo.png')

B, G, R = cv2.split(image)

# Using bitwise_or and bitwise_and gives the same result.
masked = cv2.bitwise_or(image, image, mask=R)  

cv2.imshow('Red', R)
cv2.imshow('masked', masked)
cv2.waitKey()
cv2.destroyAllWindows()

OpenCV_Logo:

R:

masked:

如您所见,边缘周围有残留物,因为边缘不是“纯”零。


重现您的问题很简单:
我们可以将 1 添加到 image.
的所有元素 为了避免溢出,我使用 cv2.add 而不是 +1image = cv2.add(image, np.ones_like(image).

代码示例:

import cv2
import numpy as np

image = cv2.imread('OpenCV_Logo.png')

image = cv2.add(image, np.ones_like(image))

B, G, R = cv2.split(image)

masked = cv2.bitwise_or(image, image, mask=R)

cv2.imshow('image', image)
cv2.imshow('Red', R)
cv2.imshow('masked', masked)
cv2.waitKey()
cv2.destroyAllWindows()

结果:

image:

R:

masked:

如你所见imageR看起来一样,但masked结果完全不同。


建议的解决方案:

  1. 您可能会找到更好的输入图像。
  2. 您可以将 cv2.threshold 应用到 R 以将所有低值设置为零。

cv2.threshold 应用阈值,结果是二值图像 - 所有值都是零或 255。

使用示例cv2.threshold

import cv2
import numpy as np

image = cv2.imread('OpenCV_Logo.png')

image = cv2.add(image, np.ones_like(image))  # Modify the image for the example.

B, G, R = cv2.split(image)

# cv2.THRESH_OTSU finds the threshold automatically, you may use manual threshold instead.
R = cv2.threshold(R, 0, 255, cv2.THRESH_OTSU)[1]

masked = cv2.bitwise_or(image, image, mask=R)

cv2.imshow('image', image)
cv2.imshow('Red', R)
cv2.imshow('masked', masked)
cv2.waitKey()
cv2.destroyAllWindows()

结果:

masked: