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

Har*_*uja 4 python opencv bit-manipulation

在openCV中使用时,我并不完全理解"bitwise_and"运算符的作用.我也想知道它的参数.

man*_*ver 28

一般用法是您想要获取由另一个图像定义的图像的子集,通常称为"掩码".

因此,假设您想要"抓住"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
Run Code Online (Sandbox Code Playgroud)

您可以使用Python生成上面的图像:

import numpy as np

mask = np.zeros(shape=(8,8), dtype=bool)
mask[0:4,0:4] = True
Run Code Online (Sandbox Code Playgroud)

然后假设你有一个像这样的图像:

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
Run Code Online (Sandbox Code Playgroud)

具体来说,想象一下上面的图像是美国国旗的简化表示:左上角的星星,其他地方的星星.假设您想要形成上面的图像.您可以使用掩码,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
Run Code Online (Sandbox Code Playgroud)

现在你有一个星星的形象:

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
Run Code Online (Sandbox Code Playgroud)

和酒吧的形象:

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
Run Code Online (Sandbox Code Playgroud)

并且你想以特定的方式组合它们,形成旗帜,左上象限中的星星和其他地方的条形.

imageStarsCropped = cv2.bitwise_and(imageStars, mask)
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

你看到它是如何形成的吗?该bitwise_and回报率1在每个像素地方imageStars1mask1; 否则,它返回0.

现在让我们来imageBarsCropped.首先,让我们颠倒面具:

maskReversed = cv2.bitwise_not(mask)
Run Code Online (Sandbox Code Playgroud)

bitwise_not把它变成1's 0'和0's 1' 变成's'.它"翻转了一下". 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
Run Code Online (Sandbox Code Playgroud)

现在,我们将用maskReversed"抓住" imageBars我们想要的部分.

imageBarsCropped = cv2.bitwise_and(imageBars, maskReversed)
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

现在,让我们将两个"裁剪"的图像组合起来形成旗帜!

imageFlag = cv2.bitwise_or(imageStarsCropped, imageBarsCropped)
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

你明白为什么吗? bitwise_or返回1imageStarsCropped[r,c]==1OR imageBarsCropped[r,c]==1.

好吧,我希望这有助于您理解OpenCV中的按位操作.这些属性与使用二进制数的按位运算一一对应,计算机可以进行算术运算.

  • 如果不仅有 0 和 1,还有 0、1 和 2 值,那么会发生什么也很高兴。结果可能不是那么明显:) (11认同)

min*_*ins 9

运营商做什么的?

bitwise_andbitwise_orbitwise_xor对取自两个数组src1nd 的元素执行按位运算src2bitwise_not类似。按位表示布尔运算是在值的每一位之间逐位完成的。

掩模参数是什么?

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

面膜如何使用?

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

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

openCV 按位与和按位或

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()
Run Code Online (Sandbox Code Playgroud)

代码可能还可以改进。


Sta*_*dis -2

按位与

\n
\n

计算两个数组或一个数组和一个标量的每个元素的按位合。

\n

参数:

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

这是在网上找到的示例:\n http://docs.opencv.org/trunk/d0/d86/tutorial_py_image_arithmetics.html

\n

  • 这是该函数的文档。 (11认同)