您的原始样本很可能不够“干净”。
看起来黑色的R 通道的值接近于零,但不是零。
当cv2.bitwise_and 或cv2.bitwise_or 与mask 一起使用时,掩码中所有不等于0 的值都被视为“真”(当掩码!= 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 而不是+1:image = 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:
如您所见,image 和 R 看起来相同,但 masked 结果完全不同。
建议的解决方案:
- 您可能会找到更好的输入图像。
- 您可以将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: