【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实现图像按位与运算的技巧。