Bootstrap

python学opencv|读取图像(四十三)使用cv2.bitwise_and()函数实现图像按位与运算

【1】引言

前序已经对图像叠加进行了一些探索:

python学opencv|读取图像(四十)掩模:三通道图像的局部覆盖-CSDN博客

python学opencv|读取图像(四十一 )使用cv2.add()函数实现各个像素点BGR叠加-CSDN博客

python学opencv|读取图像(四十二)使用cv2.add()函数实现多图像叠加-CSDN博客

这些叠加的本质上都是通过叠加各个像素点上的BGR值实现的。

有时候需要仿照数学上的做法,对像素点上的值做与运算,这时候就要使用cv2.bitwise_and()函数。

【2】官网教程

点击下方链接,直达官网教程:OpenCV: Operations on arrays

官网对cv2.bitwise_and()函数的说明为:

图1

具体的,参数意义为:

void cv::bitwise_and     (     InputArray     src1,     #第一个图像
        InputArray     src2,                                        #第二个图像
        OutputArray     dst,                                       #输出图像
        InputArray     mask = noArray() )                  #掩模,单通道数据,可选参数

按位与运算要求数据的大小一致,对于三通道图像,会逐个通道进行按位与运算。

【3】代码测试

【3.1】灰度图像

首先对灰度图像进行按位与运算,先引入必要的模块和初始图像:

import cv2 as cv # 引入CV模块
import numpy as np #引入numpy模块

# 读取图片-直接转化灰度图
src = cv.imread('srcp.png',0) #读取图像
dst=src#输出图像

然后定义了第二个图像,是一个黑色画布加灰白色掩模矩阵的图像,定义按位与运算:

# 定义图像
image = np.zeros(src.shape, np.uint8)  # 定义一个竖直和水平像素与初始图像等大的全0矩阵
print('像素大小为',src.shape)
image[100:200, :] = 200  # 第一个通道值
image[:,100:350 ] = 200  # 第二个通道值
#image[:, :, 200:300] = 255  # 第三个通道值
img=cv.bitwise_and(src,image) #与运算

然后显示和保存图像:

#显示BGR值
print("dst像素数为[150,150]位置处的BGR=", dst[150,150])  # 获取像素数为[100,100]位置处的BGR
print("img像素数为[150,150]位置处的BGR=", img[150,150])  # 获取像素数为[100,100]位置处的BGR


#合并图像
himg=np.hstack((src,img))
# 显示和保存定义的图像
cv.imshow('display-and-src-2', dst)  # 显示图像
cv.imshow('display-and-2', img)  # 显示图像
cv.imwrite('display-and-2.png', img)  # 保存图像
cv.imshow('display-and-image-2', image)  # 显示图像
cv.imwrite('display-and-image-2.png', image)  # 保存图像
cv.imshow('display-and-himg-2', himg)  # 显示图像
cv.imwrite('display-and-himg-2.png', himg)  # 保存图像
cv.waitKey()  # 图像不关闭
cv.destroyAllWindows()  # 释放所有窗口

代码运行相关的图像为:

图2 初始图像

图3 按位与运算后的图像-灰度图像

图4 掩模-二维矩阵

图5 初始图像和按位与运算后的图像对比-灰度图像

  由图2至图5可见,经过按位与运算后,只在掩模区域显示了图像,并且图像的清晰度发生了变化,进一步读取到的特定点BGR值为:

图6 特定点BGR值

由图6显示BGR值,结合掩模定义代码,可知在按位与运算过程中,显示出来的图像BGR值统一为掩模值200。

# 定义图像
image = np.zeros(src.shape, np.uint8)  # 定义一个竖直和水平像素与初始图像等大的全0矩阵
print('像素大小为',src.shape)
image[100:200, :] = 200  # 第一个通道值
image[:,100:350 ] = 200  # 第二个通道值

此时的完整代码为:

import cv2 as cv # 引入CV模块
import numpy as np #引入numpy模块

# 读取图片-直接转化灰度图
src = cv.imread('srcp.png',0) #读取图像
dst=src#输出图像

# 定义图像
image = np.zeros(src.shape, np.uint8)  # 定义一个竖直和水平像素与初始图像等大的全0矩阵
print('像素大小为',src.shape)
image[100:200, :] = 200  # 第一个通道值
image[:,100:350 ] = 200  # 第二个通道值
#image[:, :, 200:300] = 255  # 第三个通道值
img=cv.bitwise_and(src,image) #与运算

#显示BGR值
print("dst像素数为[150,150]位置处的BGR=", dst[150,150])  # 获取像素数为[100,100]位置处的BGR
print("img像素数为[150,150]位置处的BGR=", img[150,150])  # 获取像素数为[100,100]位置处的BGR


#合并图像
himg=np.hstack((src,img))
# 显示和保存定义的图像
cv.imshow('display-and-src-2', dst)  # 显示图像
cv.imshow('display-and-2', img)  # 显示图像
cv.imwrite('display-and-2.png', img)  # 保存图像
cv.imshow('display-and-image-2', image)  # 显示图像
cv.imwrite('display-and-image-2.png', image)  # 保存图像
cv.imshow('display-and-himg-2', himg)  # 显示图像
cv.imwrite('display-and-himg-2.png', himg)  # 保存图像
cv.waitKey()  # 图像不关闭
cv.destroyAllWindows()  # 释放所有窗口

【3.2】彩色图像

之后进行彩色图像的零值和反零值处理,首先需要改一行代码,将src = cv.imread('srcp.png',0)改为:

src = cv.imread('srcp.png') #读取图像

然后定义掩模矩阵为三维矩阵:

# 定义图像
image = np.zeros(src.shape, np.uint8)  # 定义一个竖直和水平像素与初始图像等大的全0矩阵
print('像素大小为',src.shape)
image[100:200, :, :] = 200  # 第一个通道值
image[:,100:350,: ] = 200  # 第二个通道值

直接输出完整代码:

import cv2 as cv # 引入CV模块
import numpy as np #引入numpy模块

# 读取图片-直接转化灰度图
src = cv.imread('srcp.png') #读取图像
dst=src#输出图像

# 定义图像
image = np.zeros(src.shape, np.uint8)  # 定义一个竖直和水平像素与初始图像等大的全0矩阵
print('像素大小为',src.shape)
image[100:200, :, :] = 200  # 第一个通道值
image[:,100:350,: ] = 200  # 第二个通道值
#image[:, :, 200:300] = 255  # 第三个通道值
img=cv.bitwise_and(src,image) #与运算

#显示BGR值
print("dst像素数为[150,150]位置处的BGR=", dst[150,150])  # 获取像素数为[100,100]位置处的BGR
print("img像素数为[150,150]位置处的BGR=", img[150,150])  # 获取像素数为[100,100]位置处的BGR

#合并图像
himg=np.hstack((src,img))
# 显示和保存定义的图像
cv.imshow('display-and-src', dst)  # 显示图像
cv.imshow('display-and', img)  # 显示图像
cv.imwrite('display-and.png', img)  # 保存图像
cv.imshow('display-and-image', image)  # 显示图像
cv.imwrite('display-and-image.png', image)  # 保存图像
cv.imshow('display-and-himg', himg)  # 显示图像
cv.imwrite('display-and-himg.png', himg)  # 保存图像
cv.waitKey()  # 图像不关闭
cv.destroyAllWindows()  # 释放所有窗口

代码运行的相关图像为:

图7 按位与运算后的图像-彩色图像

图8 掩模-三维矩阵

 图9 初始图像和按位与运算后的图像对比-彩色图像

进一步探索第二个图像掩模BGR值带来的BGR值变化,读取到的特定像素点BGR值为:

图10  特定点BGR值

由图10显示BGR值,结合掩模定义代码,可知在按位与运算过程中,显示出来的图像BGR值只在R通道统一为200。 

【4】代码测试

实际上上述图像在做按位与运算的时候,没有加入掩模,上述提记的掩模是指第二个图像自身所带的掩模。

【4.1】第二个图像掩模值修改

然后做一个测试,将第二个图像的掩模值改为255:

灰度图像的修改值为:

# 定义图像
image = np.zeros(src.shape, np.uint8)  # 定义一个竖直和水平像素与初始图像等大的全0矩阵
print('像素大小为',src.shape)
image[100:200, :] = 200  # 第一个通道值
image[:,100:350 ] = 255  # 第二个通道值

运行后获得的BGR值为:

图11  特定点BGR值-灰度图像

此时的图像对比效果为:

 图12  初始图像和按位与运算后的图像对比-灰度图像

图12所展示的图像表明,在image[:,100:350 ] = 255 ,也就是第二个通道值确定的区域,图像的BGR值和原图像其实是一致的。

图13 变化对比-灰度图像

彩色图像的修改值为:

# 定义图像
image = np.zeros(src.shape, np.uint8)  # 定义一个竖直和水平像素与初始图像等大的全0矩阵
print('像素大小为',src.shape)
image[100:200, :, :] = 200  # 第一个通道值
image[:,100:350,: ] = 255  # 第二个通道值

运行后获得的BGR值为:

 图14  特定点BGR值-彩色图像 

此时的图像对比效果为:

  图15  初始图像和按位与运算后的图像对比-彩色图像

图15所展示的图像表明,在image[:,100:350,: ] = 255 ,也就是第二个通道值确定的区域,图像的BGR值和原图像其实是一致的。

图16  变化对比-彩色图像

这种变化效果,本质上有一种截断的可能:当高于第二个图像给定的掩模值后,图像BGR值会被截断到掩模值,其余就保持原值。

【4.2】第二个图像掩模值扩大

然后继续利用彩色图像的通道数为3,扩大第二个图像的掩模矩阵定义范围:

# 定义图像
image = np.zeros(src.shape, np.uint8)  # 定义一个竖直和水平像素与初始图像等大的全0矩阵
print('像素大小为',src.shape)
image[100:200, :, :] = 55  # 第一个通道值
image[:,100:350,: ] = 155  # 第二个通道值
image[:, :, 200:300] = 255  # 第三个通道值

此时代码运行后,获得的相关图像为:

 图17  初始图像和按位与运算后的图像对比-彩色图像

 图18 掩模-三维矩阵扩展

图19 按位与运算后的图像-彩色图像 

图18和图19是对图17的解释,图18 的颜色深深浅,自然也会影响到图19 的颜色深浅。

此时获得的特定点BGR值为:

图20 特定点BGR值-彩色图像 

 【5】总结

掌握了python+opencv实现图像按位与运算的技巧。

;