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】灰度图像

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

python 复制代码
import cv2 as cv # 引入CV模块
import numpy as np #引入numpy模块

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

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

python 复制代码
# 定义图像
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) #与运算

然后显示和保存图像:

python 复制代码
#显示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  # 第二个通道值

此时的完整代码为:

python 复制代码
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  # 第二个通道值

直接输出完整代码:

python 复制代码
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实现图像按位与运算的技巧。

相关推荐
明月看潮生1 分钟前
青少年编程与数学 02-019 Rust 编程基础 01课题、环境准备
开发语言·青少年编程·rust·编程与数学
VBA63378 分钟前
VBA高级应用30例应用4:利用屏蔽事件来阻止自动运行事件
开发语言
Pop–17 分钟前
Vue3 el-tree:全选时只返回父节点,半选只返回勾选中的节点(省-市区-县-镇-乡-村-街道)
开发语言·javascript·vue.js
虚!!!看代码32 分钟前
【JVM-GC调优】
java·开发语言·jvm
yuanyxh34 分钟前
commonmark.js 源码阅读(一) - Block Parser
开发语言·前端·javascript
Nina_71737 分钟前
Day 15 训练
python
小白的代码日记1 小时前
java-反射精讲
java·开发语言
进取星辰1 小时前
22、城堡防御工事——React 19 错误边界与监控
开发语言·前端·javascript
zxctsclrjjjcph1 小时前
【递归、搜索和回溯】递归、搜索和回溯介绍及递归类算法例题
开发语言·c++·算法·力扣
charlie1145141911 小时前
编译日志:关于编译opencv带有ffmpeg视频解码支持的若干办法
opencv·ffmpeg·音视频·imx6ull·移植教程