逻辑运算是一种非常重要的运算方式,图像处理过程中经常要按照位进行逻辑运算,本节介绍 OpenC'V 中的按位逻辑运算,简称位运算
在 OpenCV内,常见的位运算函数如表 31 所示
序号 | 函数名 | 基本含义 |
---|---|---|
1 | cv2.bitwise_and() | 按位与 |
2 | cv2.bitwise_or() | 按位或 |
3 | cv2.bitwise_xor() | 按位异或 |
4 | cv2.bitwise_not() | 按位取反 |
3.3.1 按位与运算
在与运算中,当参与与运算的两个逻辑值都是直时,结果才为真。其逻辑关系可以类比图 34 所示的串联电路,只有当两个开关都闭合时,灯才会亮
表 32 对与运算算子的不同情况进行了说明,表中使用“and”表示与运算
与运算
序号 | 算子1 | 算子2 | 结果 | 规则 |
---|---|---|---|---|
1 | 0 | 0 | 0 | and(0,0)=0 |
2 | 0 | 1 | 0 | and(0,1)=0 |
3 | 1 | 0 | 0 | and(1,0)=0 |
4 | 1 | 1 | 1 | and(1,1)=1 |
按位与运算是指将数值转换为二进制值后,在对应的位置上进行与运算。例如,表 3-3层示了两个数值进行按位与运算的示例
按位与运算
序号 | 数值 | 十进制值 | 二进制值 |
---|---|---|---|
1 | 数值 1 | 198 | 1100 0110 |
2 | 数值 2 | 219 | 1101 1011 |
3 | 按位与运算结果 | 194 | 1100 0010 |
在 opencv 中,可以使用 cv2.bitwise_and(a,b) 函数来实现按位与运算,其语法格式为:
dst = cv2.bitwise_and(src1,src2[,mask]])
dst 表示与输入值具有同样大小的 ararry输出值
src1表示第一个 ararry 或 scalar类型的输入值
src2 表示第二个ararry 或 scalar 类型的输入值
mask 表示可选操作掩码,8 位单通道 ararry
按位与操作有如下特点
将任何数值N 与数值0 进行按位与操作,都会得到数值0
将任何数值N(这里仅考虑8 位值)与数值 255(8 位二进制数是1111 1111)进行按位与操作,都会得到数值N 本身
可以通过表 34 观察数值N(表中是 219)与特殊值0和 255 进行按位与运算的结果
根据上述特点,可以构造一幅掩模图像M,掩模图像M 中只有两种值:一种是数值0 一种是数值 255 将该掩模图像M 与幅灰度图像G 进行按位与操作,在得到的结果图像R中
与掩模图像M 中的数值 255 对应位置上的值,来源于灰度图像G
与掩模图像M 中的数值0 对应位置上的值为零(黑色)
第 13 章将从另外一个角度对上述情况进行说明,以帮助大家更好地理解掩模及处理方式
【例 3.7】使用数组演示与掩模图像的按位与运算
根据题目要求,编写代码如
import cv2
import numpy as np
a=np.random.randint(0,255,(5,5),dtype=np.uint8)
b=np.zeros((5,5),dtype=np.uint8)
b[0:3,0:3]=255
b[4,4]=255
c=cv2.bitwise_and(a,b)
print("a=\n",a)
print("b=\n",b)
print("c=\n",c)
a=
[[111 159 2 209 5]
[ 41 209 100 66 105]
[ 90 10 59 125 213]
[ 52 71 145 64 171]
[124 74 67 77 113]]
b=
[[255 255 255 0 0]
[255 255 255 0 0]
[255 255 255 0 0]
[ 0 0 0 0 0]
[ 0 0 0 0 255]]
c=
[[111 159 2 0 0]
[ 41 209 100 0 0]
[ 90 10 59 0 0]
[ 0 0 0 0 0]
[ 0 0 0 0 113]]
从程序可以看出,数组c 米源于数组a 与数组b 的按位与操作,运算结果显示,对于 数组c 内的值,与数组b 中数值 255 对应位置上的值来源于数组 a:与数组b 中数值0 对应位置上的值为0
【例 3.8】构造一个掩模图像,使用按位与运算保留图像中被掩模指定的部分在本例中,我们构造一个掩模图像,保留图像 lena 的头部
根据目要求,编写代码如下:
import cv2
import numpy as np
a=cv2.imread("C:\\Users\\Administrator\\Desktop\\opencv\\lena.bmp",0)
b=np.zeros(a.shape,dtype=np.uint8)
b[100:400,200:400]=255
b[100:500,100:200]=255
c=cv2.bitwise_and(a,b)
cv2.imshow("a",a)
cv2.imshow("b",b)
cv2.imshow("c",c)
cv2.waitKey()
cv2.destroyAllWindows()
运行上述程序,输出结果如图 3.5 所示,左图是原始图像 lena,中间的图是掩模图像,右图是按位与结果图像,可以看到,被掩模指定的头部图像被保留在了运算结果中
除了需要对灰度图像进行掩模处理,还经常需要针对 BGR 糢式的彩色图像使用掩模提取指定部分。由于按位与操作要求参与运算的数据有相同的通道,所以无法直接将彩色图像与道的掩模图像进行按位与操作。一般情况下,可以通过将掩模图像转换为 BGR 模式的彩在像,让彩色图像与掩模图像进行按位与操作,实现掩模运算。
【例 3.9】构造一个掩模图像,使用按位与操作保留图像内被掩模所指定的部分。
根据题目要求,编写代码如下
import cv2
import numpy as np
a=cv2.imread("C:\\Users\\Administrator\\Desktop\\opencv\\lena.bmp",1)
b=np.zeros(a.shape,dtype=np.uint8)
b[100:400,200:400]=255
b[100:500,100:200]=255
c=cv2.bitwise_and(a,b)
print("a.shape=",a.shape)
print("b.shape=",b.shape)
cv2.imshow("a",a)
cv2.imshow("b",b)
cv2.imshow("c",c)
cv2.waitKey()
cv2.destroyAllWindows()
运行上述程序,输出结果如图 36 所示,其中左图是原始图像,中间的图是掩模图像,右图是原始图像和掩模图像按位与后提取的图像。由于本书为黑白印刷,所以为了更好地观察行效果,请大家亲自上机运行程序
输出:
a.shape= (512, 512, 3)
b.shape= (512, 512, 3)
3.3.2 按位或运算
或运算的规则是,当参与或运算的两个逻辑值中有一个为真时,结果就为真,其逻辑关系可以类比为如图的并联电路,两个开关中只要有任何一个闭合时,灯就会亮
序号 | 算子1 | 算子2 | 结果 | 规则 |
---|---|---|---|---|
1 | 0 | 0 | 0 | or(0,0)=0 |
2 | 0 | 1 | 0 | or(0,1)=1 |
3 | 1 | 0 | 0 | or(1,0)=1 |
4 | 1 | 1 | 1 | or(1,1)=1 |
按位或运算是指将数值转换为二进制值后,在对应的位置上进行或运算。例如,表 3.6展 示了两个数值边行按位或运算的示例
序号 | 数值 | 十进制值 | 二进制值 |
---|---|---|---|
1 | 数值 1 | 198 | 1100 0110 |
2 | 数值 2 | 219 | 1101 1011 |
3 | 按位与运算结果 | 223 | 1101 1111 |
在 OpenCV中,可以使用 cv2.bitwise_or(a,b) 函数来实现按位或运算,其语法格式为
dst = cv2.bitwise_or(src1,src2[,mask]])
式中
dst 表示与输入值具有同样大小的 arrary输出值
src1表示第一个 ararry 或 scalar类型的输入值
src2 表示第二个ararry 或 scalar 类型的输入值
mask 表示可选操作掩码,8 位单通道 arrary值
3.3.3 按位非运算
非运算是取反操作,满足如下逻辑
1 当运算数为真时,结果为假
2 当算数为为假时,结果为真
表 3.7 对参与运算算子的不同情况进行了说明,表中使用“not”表示非运算
序号 | 算子 | 结果 | 规则 |
---|---|---|---|
1 | 0 | 1 | not(0)=1 |
2 | 1 | 0 | not(1)=0 |
按位非运算是指将数值转换为二进制值后,在对应的位置上进行非运算,例如,3-8 示了按位非运算的示例
序号 | 说明 | 十进制值 | 二进制值 |
---|---|---|---|
1 | 原始值 | 198 | 1100 0110 |
2 | 按位非运算结果 | 57 | 0011 1001 |
在 OpenCV中,可以使用函数 cv2.bitwise_not 来实现按位取反操作,其语法格式为
dst = cv2.bitwise_not(src[,mask]])
式中
dst 表示与输入值具有同样大小的 arrary输出值
src表示第一个 ararry 或 scalar类型的输入值
mask 表示可选操作掩码,8 位单通道 arrary值
3.3.4 按位异或运算
异或运算也叫半加运算,其运算法则与不带进位的二进制加法类似,其英文为"exclusive OR" 因此其函数常表示为 xor
表 3-9 对参与异或运算的算子的不同悟况进行了说明,其中“xor”表示异或运算
序号 | 算子1 | 算子2 | 结果 | 规则 |
---|---|---|---|---|
1 | 0 | 0 | 0 | xor(0,0)=0 |
2 | 0 | 1 | 1 | xor(0,1)=1 |
3 | 1 | 0 | 1 | xor(1,0)=1 |
4 | 1 | 1 | 0 | xor(1,1)=0 |
按位异或运算是指将数值转换为二进制值后,在对应的位置进行异或运算,
展示了两个数值进行按位异或运算的示例
序号 | 数值 | 十进制值 | 二进制值 |
---|---|---|---|
1 | 数值 1 | 198 | 1100 0110 |
2 | 数值 2 | 219 | 1101 1011 |
3 | 按位异或运算结果 | 29 | 0001 1101 |
在 OpenCV中,可以使用函数 cv2.bitwise_xor 来实现按位异或操作,其语法格式为
dst = cv2.bitwise_xor(src1,src2[,mask]])
式中
dst 表示与输入值具有同样大小的 arrary输出值
src1表示第一个 ararry 或 scalar类型的输入值
src2 表示第二个ararry 或 scalar 类型的输入值
mask 表示可选操作掩码,8 位单通道 arrary值