bitwise_and运算符在openCV中究竟做了什么?

时间:2017-06-02 16:31:55

标签: python opencv bit-manipulation

我并不完全明白" bitwise_and"运算符在openCV中使用时执行。 我也想知道它的参数。

6 个答案:

答案 0 :(得分:14)

一般用法是您要获取另一幅图像定义的图像子集,通常称为“蒙版”。

因此,假设您要“抓取” 8x8图像的左上象限。您可以形成一个看起来像这样的面具:

1 1 1 1 0 0 0 0
1 1 1 1 0 0 0 0
1 1 1 1 0 0 0 0
1 1 1 1 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0

您可以使用以下命令使用Python生成以上图像:

import numpy as np

mask = np.zeros(shape=(8,8), dtype=bool)
mask[0:4,0:4] = True

然后假设您有一个类似的图像:

1 0 1 0 1 1 1 1
0 1 0 1 0 0 0 0
1 0 1 0 1 1 1 1
0 1 0 1 0 0 0 0
1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0

为具体起见,请想象上图是美国国旗的简化表示:左上方的星星,其他地方均为条形。假设您要形成上面的图像。您可以使用遮罩以及bitwise_and和bitwise_or来帮助您。

imageStars = np.ones(shape=(8,8), dtype=bool)
for r, row in enumerate(imageStars):
    for c, col in enumerate(row):
        if r % 2 != c % 2: # even row, odd column, or odd row, even column
            imageStars[r,c] = False

imageBars = np.zeros(shape=(8,8), dtype=bool)
for r, row in enumerate(imageStars):
    if r % 2 == 0:
        imageBars[r,:] = True

现在您有了星星的图像:

1 0 1 0 1 0 1 0
0 1 0 1 0 1 0 1    
1 0 1 0 1 0 1 0
0 1 0 1 0 1 0 1    
1 0 1 0 1 0 1 0
0 1 0 1 0 1 0 1    
1 0 1 0 1 0 1 0
0 1 0 1 0 1 0 1

还有条形图:

1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0

您想以一种特殊的方式将它们组合起来以形成标志,左上象限中的星星和其他地方的条形。

imageStarsCropped = cv2.bitwise_and(imageStars, mask)

imageStarsCropped如下所示:

1 0 1 0 0 0 0 0
0 1 0 1 0 0 0 0    
1 0 1 0 0 0 0 0
0 1 0 1 0 0 0 0  
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0

您看到它是如何形成的吗? bitwise_and1imageStars并且1mask的每个像素处返回1;否则,它返回0

现在让我们得到imageBarsCropped。首先,让我们扭转面具:

maskReversed = cv2.bitwise_not(mask)

bitwise_not1变成0,而0变成1。它“翻转位”。 maskReversed如下所示:

0 0 0 0 1 1 1 1
0 0 0 0 1 1 1 1
0 0 0 0 1 1 1 1
0 0 0 0 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1

现在,我们将使用maskReversed来“抓住”我们想要的imageBars的一部分。

imageBarsCropped = cv2.bitwise_and(imageBars, maskReversed)

imageBarsCropped如下所示:

0 0 0 0 1 1 1 1
0 0 0 0 0 0 0 0
0 0 0 0 1 1 1 1
0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0

现在,让我们将两个“裁剪的”图像组合起来以形成标记!

imageFlag = cv2.bitwise_or(imageStarsCropped, imageBarsCropped)

imageFlag如下所示:

1 0 1 0 1 1 1 1
0 1 0 1 0 0 0 0
1 0 1 0 1 1 1 1
0 1 0 1 0 0 0 0
1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0

您知道为什么吗?每当bitwise_or1时,imageStarsCropped[r,c]==1返回imageBarsCropped[r,c]==1

好吧,我希望这可以帮助您了解OpenCV中的按位操作。这些属性与计算机执行算术运算的二进制数字按位运算一一对应。

答案 1 :(得分:1)

@mannyglover给出的带有美国国旗示例的答案是一个很好的答案!我还要快速添加一下,对于实际图像,任何大于0的像素值都将转换为“ true”(在@mannyglover的示例中为1),而“ 0”(斜度黑色)将为“ false”。

这意味着在执行bitwise_and之后,遮罩的任何黑色间距像素都会将原始图像中的相应像素变为黑色。 (因为0等于0)

以下是在OpenCV中完成的示例:

原始图片:stack.jpg

遮罩:mask.jpg

应用result = cv2.bitwise_and(stack, stack, mask=mask)后:result.jpg

答案 2 :(得分:1)

操作员做什么?

bitwise_andbitwise_orbitwise_xor 对取自两个数组 src1src2 的元素执行按位运算。 bitwise_not 类似。按位表示布尔运算在值的每一位之间进行,每一位。

掩码参数是什么?

它实际上不是布尔掩码(并且布尔数组将被拒绝)。它是一个 uint8 数组类型,其中检查值是否为 0。 “掩码”与图像具有相同的 x,y 形状,但其元素是标量,即对于 uint8 的 100 x 50 x 3 图像,掩码必须是 uint8 的 100 x 50 数组。

口罩是怎么用的?

此掩码确定是否将对位置 x,y 处的像素对执行操作。如果掩码中 x,y 位置的元素为 0,则不执行任何操作,结果数组中的像素为 0,0,0(黑色)。如果位置 x,y 处的掩码元素不为空,则按位运算确定结果数组中的值。

假设我们要提取圆内的像素并使其他像素变为白色。这可以使用具有互补掩码的按位运算来完成:

openCV bitwise_and and bitwise_or

import numpy as np
import cv2
import matplotlib.pyplot as plt

images = 'images/'

# Read image 330 x 379 x 3 uint8
img = cv2.imread(images + 'sample.jpg')

# Reorder channels as display is done with pyplot
img[:,:,[0,1,2]] = img[:,:,[2,1,0]]

# Create white image, 3 channels 330 x 379 x 3 uint8
w_3c = np.full_like(img, fill_value=(255,255,255))

# Define disk elements
center = (img.shape[1]//2, img.shape[0]//2)
radius = int(min(center) * .9)

# Create white disk, 3 channels 330 x 379 x 3 uint8
# and single channel 330 x 379 uint8
d_3c = np.zeros_like (img[:,:], dtype='uint8')
cv2.circle(d_3c, center, radius, [255]*3, thickness=cv2.FILLED)
d_1c = d_3c[:,:,0]

# Extract pixels disk using white disk single channel
masked = cv2.bitwise_and(img, w_3c, mask=d_1c)

# Add white background
d_3c_i = ~d_3c
final = cv2.bitwise_or(img, d_3c_i)

# Prepare to plot
to_plot = [[(img,'img'),
            (w_3c,'w_3c')],
           [(d_3c,'d_3c'),
            (d_1c,'d_1c'),
            (d_3c_i,'d_3c_i')],
           [(masked,'img & w_3c mask d_1c'),
            (final,'img | d_3c_i)')]]
r = len(to_plot)
c = max([len(l) for l in to_plot])

# Show everthing
fig,ax = plt.subplots(r,c, tight_layout=True)
for i in range(r):
    for j in range(c):
        axij = ax[i,j]
        if j < len(to_plot[i]):
            dims = to_plot[i][j][0].ndim
            if dims <= 3:
                axij.imshow(to_plot[i][j][0], cmap='gray')
            else:
                axij.imshow(to_plot[i][j][0])
            axij.set_title(to_plot[i][j][1])
            axij.set_xticks([])
            axij.set_yticks([])
        else:
            axij.set_axis_off()

plt.ioff()
plt.show()

代码可能可以改进。

答案 3 :(得分:1)

致正在寻找有关 bitwise_or 的简单解释的人

假设我们要编写 cv2.bitwise_or,我们必须:

  1. 仅在掩码非零的位置执行 src1 数组与 src2 数组的按位或运算

因此假设掩码是 100x100 形状,只有 mak1 = 1,其他都是 0。此外,src1 是 600x600x3 数组,所有值都为 255,而 src2 与 src1 相同。

所以在我们的 cv2.bitwise_or 操作之后,我们得到一个形状为 600x600x3 的输出数组,输出1 = 255(因为这是我们对 src1 和 src2 进行位或运算的唯一地方)和其余的输出数组的位置将为 0。

答案 4 :(得分:0)

仅是对以上答案的详细说明-不是完整的答案。在现实生活中,图像数组的值将介于0到255之间,而不仅仅是0和1。 bitwise_or在这种情况下要做的是将两个图像中的每个对应数字转换成其二进制形式,然后执行 and 或其他操作。

示例:

考虑两个值233和180。这些数字中的bitwise_or得出253(使用cv2.bitwise_or(np.array([233]), np.array([180]))。233和180的二进制等效项是11101001和10110100。执行bitwise_or得出我们是11111101,与253相同。此数字是通过对233和180的二进制等效项中的每个数字进行(可以验证)来获得的。

bin(233) #0b in the output just means it is a binary number
0b11101001

bin(180)
0b10110100

bin(253)
0b11111101

cv2.bitwise_or(np.array([233]), np.array([180]))
array([[253]], dtype=int32)
通过对数字的位进行逻辑运算,

,而不是and xor 的作用与类似。

答案 5 :(得分:-3)

<强> bitwise_and

计算两个数组或数组和标量的每元素逐位连接。

参数:

  • src1 - 第一个输入数组或标量。
  • src2 - 第二个输入数组或标量。
  • src - 单输入数组。
  • value - 标量值。
  • dst - 与输入数组具有相同大小和类型的输出数组。
  • mask - 可选操作掩码,8位单通道数组,指定要更改的输出数组的元素。

以下是网络上的示例: http://docs.opencv.org/trunk/d0/d86/tutorial_py_image_arithmetics.html