Python 如何使用numpy为图像中所有相对白色的部分创建遮罩?

Python 如何使用numpy为图像中所有相对白色的部分创建遮罩?,python,numpy,opencv,Python,Numpy,Opencv,假设我有两个白色图像(RGB 800x600图像),在一些未知位置“脏”,我想创建一个最终的组合图像,其中包含两个图像的所有脏部分 只需将图像添加到一起,就可以减少每个斑点的“脏度”,因为我将像素值减半,然后再添加它们(以保持在0->255 rgb范围内),当有两个以上的图像时,这一点会被放大 我想做的是为3通道图像中所有相对白色的像素创建一个遮罩,我已经看到,如果所有RGB值彼此在10-15范围内,则一个像素相对白色。如何使用numpy创建此遮罩 我想做的事情的伪代码: img = cv2.i

假设我有两个白色图像(RGB 800x600图像),在一些未知位置“脏”,我想创建一个最终的组合图像,其中包含两个图像的所有脏部分

只需将图像添加到一起,就可以减少每个斑点的“脏度”,因为我将像素值减半,然后再添加它们(以保持在0->255 rgb范围内),当有两个以上的图像时,这一点会被放大

我想做的是为3通道图像中所有相对白色的像素创建一个遮罩,我已经看到,如果所有RGB值彼此在10-15范围内,则一个像素相对白色。如何使用numpy创建此遮罩

我想做的事情的伪代码:

img = cv2.imread(img) #BGR image
mask = np.where( BGR within 10 of each other)
然后我可以使用第一幅图像,在第二幅图像未被遮罩的地方替换像素,保持“脏度级别”相对脏。(我知道第二张图片的肮脏程度会取代第一张,但没关系)

编辑: 人们要求图像,所以我创建了一些示例图像,白色不会总是像这些示例中那样完全是白色的,这就是为什么我需要使用“在10 BGR范围内”的图像

图1

图2

图3(综合起来,忽略图2与此处黄色斑点的差异,它们应该是相同的)

您要求的是颜色之间的距离小于10的像素

在这里,翻译成numpy

img = cv2.imread(img) #  assuming rgb image in naming
r = img[:, :, 0]
g = img[:, :, 1]
b = img[:, :, 2]
rg_close = np.abs(r - g) < 10
gb_close = np.abs(g - b) < 10
br_close = np.abs(b - r) < 10

all_close = np.logical_and(np.logical_and(rg_close, gb_close), br_close)
img=cv2.imread(img)#在命名中使用rgb图像
r=img[:,:,0]
g=img[:,:,1]
b=img[:,:,2]
rg_close=np.abs(r-g)<10
gb_close=np.abs(g-b)<10
br_close=np.abs(b-r)<10
all_close=np.logical_and(np.logical_and(rg_close,gb_close),br_close)
然而,我相信这不是你真正想要的

我想你想要的是分割背景的面具

这实际上更简单,假设背景是完全白色的:

img = cv2.imread(img)
background_mask = 245 * 3 < img[: ,: ,0] + img[: ,: ,1] + img[: ,: ,2]
img=cv2.imread(img)
背景=245*3

请注意,这段代码需要阈值游戏,并且只显示了一个概念。

我建议您转换并寻找饱和(彩色)像素,如下所示:

import cv2

# Load background and foreground images
bg = cv2.imread('A.jpg')
fg = cv2.imread('B.jpg')

# Convert to HSV colourspace and extract just the Saturation
Sat = cv2.cvtColor(fg, cv2.COLOR_BGR2HSV)[..., 1]

# Find best (Otsu) threshold to divide black from white, and apply it
_ , mask = cv2.threshold(Sat,0,1,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

# At each pixel, choose foreground where mask is set and background elsewhere
res = np.where(mask[...,np.newaxis], fg, bg)

# Save the result
cv2.imwrite('result.png', res)


请注意,如果它拾取的彩色像素太多或太少,则可以对其进行修改。如果吸得太少,你可能会放大面膜,如果吸得太多,你可能会腐蚀面膜。你也可以在蒙版之前使图像模糊一点,这可能不是一个坏主意,因为这是一个带有压缩伪影的“讨厌的”JPEG。如果您只想让某些颜色通过,或者只想让某些亮度或混合,您可以更改饱和度测试,使其更具临床意义和针对性。

如果您只对白色感兴趣,为什么不对图像进行灰度缩放?请分享一张有代表性的图像,希望也能分享一张“清理”版本的图像,这样我们就可以看到你想做什么了。@MarkSetchell我添加了一些图像以澄清我并没有完全按照你的描述,但我认为你想把第二张图像中的黄色像素复制到第一张(背景)图像上。如果这是正确的,我建议您使用
cvtColor(…cv2.COLOR\u BGR2HSV)
将第二张图像转换为HSV,并找到饱和度较高的像素,即彩色像素,然后将它们复制到背景图像上。如果您的“splodge”将颜色从黄色更改为蓝色或橙色等,这仍然有效。白色并不总是像示例图像中那样白色。想象一下白色上的阴影,你仍然可以用眼睛看到它是白色的,rgb像素值仍然在,但有时不接近245*3甚至200*3。这可能值得一试,只是没有时间去尝试:/@Joram在这种情况下,你可以尝试一个简单的边缘检测器,然后用它来遮罩。我希望边缘像素不是背景。最简单的边缘检测是(对于灰度图像):
vertical=img[1:,:]-img[:1,:]
horizontal=img[:,1:]-img[:,:1]
边缘=垂直+水平
轮廓=边缘>阈值
。使用偏移量(+-1,没有计算出来),你会得到一个非常清晰的轮廓。然后可以根据颜色使用种子填充算法。还有一个想法……你也可以试着用canny找到边缘,然后用从最白的像素生长出来的种子填充来创建一个面具。谢谢你的答案!这也是一个不错的解决方案。我肯定会对HSV感到更舒服