在 res = cv2.bitwise_and(img,img,mask = mask) 中解释参数的含义

30

我正在尝试提取输入图像中的蓝色。为此,我使用命令创建了一个蓝色HSV颜色边界和阈值HSV图像。

mask_img = cv2.inRange(hsv, lower_blue, upper_blue)

接下来,我使用了按位与来处理输入图像和阈值图像。具体实现如下:

res = cv2.bitwise_and(img, img, mask = mask_img)

在这里,img是输入图像。我从OpenCV中得到了这段代码。但我不明白为什么在bitwise_and中使用了三个参数,每个参数实际上代表什么?为什么要在src1和src2中使用相同的图像?

此外,mask关键字在这里的用途是什么?请帮助我找出答案。


这个答案,针对一个类似的问题,更好地解释了原因。 - Dhruv
7个回答

14

14

这背后的基本概念是黑色的价值,在OPEN_CV中,它的价值为0。所以黑色+任何颜色=任何颜色,因为黑色的价值是0。

现在假设我们有两个图像,一个名为img1,另一个名为img2。img2包含一个标志,我们想把它放在img1上。我们创建threshold,然后创建img2的maskmask_inv,还创建img1的roi。 现在我们需要做两件事来将img2的标志添加到img1上。我们使用mask_inv帮助创建roi的背景,并将mask_inv分为两个区域,一个是黑色,一个是白色,在白色区域中,我们将放置img1部分,并保留黑色不变-

img1_bg = cv2.bitwise_and(roi,roi,mask = mask_inv)

在你的问题中,你直接使用了创建的img标签的遮罩。

res = cv2.bitwise_and(img,img,mask = mask_img)

在img2中,我们需要将logo创建为ROI的前景。

img2_fg = cv2.bitwise_and(img2,img2,mask = mask)

在这里,我们使用了掩膜层,img2的标志部分填充在掩膜的白色部分。当我们将两者合并时,就会得到一个完美的组合ROI。

要获取完整的描述和理解,请访问:OPEN CV CODE FILES AND FULL DESCRIPTION


13

每个参数实际上是什么意思?

res = cv2.bitwise_and(img, img, mask=mask_img)

src1:第一幅图像(合并的第一个对象)

src2:第二幅图像(合并的第二个对象)

mask:被理解为合并规则。如果图像区域(经过灰度化和掩膜处理后)呈黑色(取值为0),则不进行合并操作(即不将第一幅图像相应区域与第二幅图像相应区域合并),反之,则进行合并操作。在您的代码中,所引用的图像是“mask_img”。

在我的情况下,当它使白色+任何颜色=任何颜色时,我的代码是正确的。

import cv2
import numpy as np

# Load two images
img1 = cv2.imread('bongSung.jpg')
img2 = cv2.imread('opencv.jpg')

# I want to put logo on top-left corner, so I create a ROI 
rows, cols, channels = img2.shape
roi = img1[0:rows, 0:cols]

# NOw we need to create a mask of the logo, mask is conversion to grayscale of an image
img2gray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY) 
ret, mask = cv2.threshold(img2gray, 220, 255, cv2.THRESH_BINARY_INV)
cv2.imshow('mask', mask)

mask_inv = cv2.bitwise_not(mask)
#cv2.imshow("mask_inv", mask_inv)

#When using bitwise_and() in opencv with python then white + anycolor = anycolor; black + anycolor = black 
img1_bg = cv2.bitwise_and(roi,roi,mask = mask_inv)
#cv2.imshow("img1_bg", img1_bg)

cv2.imshow("img2", img2)

img2_fg = cv2.bitwise_and(img2,img2,mask = mask)
cv2.imshow('img2_fg', img2_fg)

dst = cv2.add(img1_bg,img2_fg)

img1[0:rows, 0:cols] = dst

#cv2.imshow("Image", img1)
cv2.waitKey(0)

cv2.destroyAllWindows()

7
从上面的答案中,我们可以了解到bitwise_and()函数参数的定义,但它们都没有回答另一个问题:为什么在src1和src2中使用相同的图像?
这个问题可能是由于OpenCV文档中功能定义过于简化而导致的,对于一些人来说可能会产生歧义。在文档中,bitwise_and()被定义为dst(I)=sur1(I) ^ sur2(I),如果mask(I) != 0,其中^表示'and'运算符。
从这个定义中,我一开始无法理解当mask(I)为0时如何处理dst(I)。
通过测试结果,我认为应该给出更清晰的函数定义:
当mask(I) != 0时,dst(I)=sur1(I) ^ sur2(I);否则,dst(I)保留其原始值,dst数组的所有元素默认值为0。
现在我们知道,使用相同的图像作为sur1和sur2,它只会保留mask(I) != 0区域内的原始图像部分,其他区域显示dst图像的部分(作为mask形状)。
此外,在其他位运算操作中,定义应与上述相同,并且需要添加dst数组的otherwise条件和默认值描述。

0

以下链接清晰地解释了位运算及每个参数的意义。 http://opencvexamples.blogspot.com/2013/10/bitwise-and-or-xor-and-not.html

void bitwise_and(InputArray src1, InputArray src2, OutputArray dst, InputArray mask=noArray())

计算两个数组或一个数组和一个标量的逐元素按位与运算。 参数: src1 - 第一个输入数组或标量。

src2 - 第二个输入数组或标量。

src - 单个输入数组。

value - 标量值。

dst - 输出数组,其大小和类型与输入数组相同。 mask - 可选操作掩码,8位单通道数组,指定要更改的输出数组元素。


0

按位与 ( InputArray src1, InputArray src2, OutputArray dst, InputArray mask = noArray() )

src1 第一个输入数组或标量。

src2 第二个输入数组或标量。

dst 输出数组,其大小和类型与输入数组相同。

mask 可选操作掩码,8位单通道数组,指定要更改的输出数组的元素。

如果mask(I)≠0,则dst(I)=src1(I)∧src2(I)

mask操作dst

计算两个数组(dst = src1 & src2)的按位合取。计算两个数组或一个数组和标量的逐元素按位合取。


0
关于两次使用img,我的猜测是我们不太在意img[i]和img[i]是什么,因为它只是二进制的img[i]。重要的是,正如Mohammed Awney所提到的,当掩模为0时,我们使img[i]变为0,否则我们保持像素不变。这是一种根据我们的掩模将img中的特定像素变黑的方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接