OpenCV - 将蒙版应用于彩色图像

Posted

技术标签:

【中文标题】OpenCV - 将蒙版应用于彩色图像【英文标题】:OpenCV - Apply mask to a color image 【发布时间】:2012-05-15 04:51:46 【问题描述】:

如何在最新的 python 绑定 (cv2) 中将蒙版应用于彩色图像?在之前的 python 绑定中,最简单的方法是使用cv.Copy 例如

cv.Copy(dst, src, mask)

但是这个函数在 cv2 绑定中不可用。有没有不使用样板代码的解决方法?

【问题讨论】:

你想做什么。?由于它支持 numpy,因此您可以使用 numpy 函数。 我正在对原始图像进行 HSV 颜色空间的过滤 【参考方案1】:

这里,如果你已经有了蒙版图片,你可以使用cv2.bitwise_and函数。

检查以下代码:

img = cv2.imread('lena.jpg')
mask = cv2.imread('mask.png',0)
res = cv2.bitwise_and(img,img,mask = mask)

lena 图像和矩形遮罩的输出如下。

【讨论】:

我正在尝试做类似的事情。口罩应该是黑色还是白色?很抱歉这个基本问题,我是opencv的新手。谢谢 是的,你是对的,掩码应该是黑白单通道。无论您要处理图像中的哪个区域,蒙版中的那些区域都应该是白色的,其他所有区域都是黑色的。而且你问这个问题也不必抱歉,每个人刚开始学习都是新手,我也是。 非常感谢阿比德!我今晚回家时会试试看。我必须将图像拆分为几个区域(并将此过程重复为多个图像)。问候! 我可以做到 =),现在我需要摆脱黑色区域...知道如何做到这一点吗? 您可以选择对图像进行切片。 roi = img[y:y+h,x:x+w] 其中 x,y 是区域的左上角,h,w 是区域的高度和宽度。【参考方案2】:

好吧,如果您希望背景不是纯黑色,这里有一个解决方案。我们只需要将遮罩反转并应用到相同大小的背景图像中,然后将背景和前景结合起来。这个解决方案的优点是背景可以是任何东西(甚至是其他图像)。

这个例子是从Hough Circle Transform修改而来的。第一张图是 OpenCV 标志,第二张是原始蒙版,第三张是背景+前景组合。

# http://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_houghcircles/py_houghcircles.html
import cv2
import numpy as np

# load the image
img = cv2.imread('E:\\FOTOS\\opencv\\opencv_logo.png')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# detect circles
gray = cv2.medianBlur(cv2.cvtColor(img, cv2.COLOR_RGB2GRAY), 5)
circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1, 20, param1=50, param2=50, minRadius=0, maxRadius=0)
circles = np.uint16(np.around(circles))

# draw mask
mask = np.full((img.shape[0], img.shape[1]), 0, dtype=np.uint8)  # mask is only 
for i in circles[0, :]:
    cv2.circle(mask, (i[0], i[1]), i[2], (255, 255, 255), -1)

# get first masked value (foreground)
fg = cv2.bitwise_or(img, img, mask=mask)

# get second masked value (background) mask must be inverted
mask = cv2.bitwise_not(mask)
background = np.full(img.shape, 255, dtype=np.uint8)
bk = cv2.bitwise_or(background, background, mask=mask)

# combine foreground+background
final = cv2.bitwise_or(fg, bk)

注意:最好使用 opencv 方法,因为它们已经过优化。

【讨论】:

【参考方案3】:
import cv2 as cv

im_color = cv.imread("lena.png", cv.IMREAD_COLOR)
im_gray = cv.cvtColor(im_color, cv.COLOR_BGR2GRAY)

此时你有一个彩色和一个灰色的图像。我们在这里处理8-bituint8 图像。这意味着图像可以具有[0, 255] 范围内的像素值,并且值必须是整数。

让我们做一个二元阈值操作。它创建一个黑白蒙版图像。黑色区域的值为0,白色区域的值为255

_, mask = cv.threshold(im_gray, thresh=180, maxval=255, type=cv.THRESH_BINARY)
im_thresh_gray = cv.bitwise_and(im_gray, mask)

可以在左下方看到面具。右边的图像是在灰度图像和蒙版之间应用bitwise_and 操作的结果。发生的情况是,掩码的像素值为零(黑色)的空间位置在结果图像中变为像素值为零。蒙版像素值为 255(白色)的位置,生成的图像保留其原始灰度值。

要将此蒙版应用于我们的原始彩色图像,我们需要将蒙版转换为 3 通道图像,因为原始彩色图像是 3 通道图像。

mask3 = cv.cvtColor(mask, cv.COLOR_GRAY2BGR)  # 3 channel mask

然后,我们可以使用相同的bitwise_and 函数将这个 3 通道蒙版应用于我们的彩色图像。

im_thresh_color = cv.bitwise_and(im_color, mask3)

代码中的mask3是左下图,im_thresh_color是右图。

您可以绘制结果并亲自查看。

cv.imshow("original image", im_color)
cv.imshow("binary mask", mask)
cv.imshow("3 channel mask", mask3)
cv.imshow("im_thresh_gray", im_thresh_gray)
cv.imshow("im_thresh_color", im_thresh_color)
cv.waitKey(0)

原图是lenacolor.png,我发现here。

【讨论】:

【参考方案4】:

所描述的其他方法假定使用二进制掩码。如果您想使用实值单通道灰度图像作为遮罩(例如来自 alpha 通道),您可以将其扩展为三个通道,然后将其用于插值:

assert len(mask.shape) == 2 and issubclass(mask.dtype.type, np.floating)
assert len(foreground_rgb.shape) == 3
assert len(background_rgb.shape) == 3

alpha3 = np.stack([mask]*3, axis=2)
blended = alpha3 * foreground_rgb + (1. - alpha3) * background_rgb

请注意,mask 需要在0..1 范围内才能使操作成功。还假设1.0编码只保留前景,而0.0表示只保留背景。

如果面具的形状可能是(h, w, 1),这会有所帮助:

alpha3 = np.squeeze(np.stack([np.atleast_3d(mask)]*3, axis=2))

这里np.atleast_3d(mask) 使掩码(h, w, 1) 如果它是(h, w)np.squeeze(...) 将结果从(h, w, 3, 1) 重塑为(h, w, 3)

【讨论】:

感谢您的插图。如何使用二进制掩码将 rgb 像素更改为特定值?例如rgb_image[bin_msk] = [41,34,128]。我的图像是 3000px x 3000px【参考方案5】:

Abid Rahman K 给出的答案并不完全正确。我也试过了,发现很有帮助,但卡住了。

这就是我使用给定蒙版复制图像的方式。

x, y = np.where(mask!=0)
pts = zip(x, y)
# Assuming dst and src are of same sizes
for pt in pts:
   dst[pt] = src[pt]

这有点慢,但给出了正确的结果。

编辑:

Python 方式。

idx = (mask!=0)
dst[idx] = src[idx]

【讨论】:

当 cv2 中的“bitwise_and”方法按要求 100% 工作时,无需在此处重新发明***。不仅如此,它的作用也非常明显。

以上是关于OpenCV - 将蒙版应用于彩色图像的主要内容,如果未能解决你的问题,请参考以下文章

使用 OpenCV 进行天空分析的图像 [关闭]

OpenCV 将我自己的滤镜应用于彩色图像

将条件应用于opencv图像

将蒙版阵列 2d 应用到 3d

Opencv - 蒙版图像导致黑色图像

Opencv检测边界和ROI掩码