1、灰度图由0~255表示,0为黑,255为白,从位操作的角度出发,纯黑色为0,不是纯黑色为1,所以在一些纯白色,或者纯黑色背景里,可以转为灰度图,利用阈值将非背景色的内容抠出来作为模板,再与原图做位操作,进行抠图。
(1)Cv2.bitwise_not(图片文件),将图片里像素值按位反向。
(2)Cv2.bitwise_and (目标文件,源文件,mask),将图片里的像素值按位与
(3)Cv2.add(目标文件,源文件),将图片里的像素值按位加
(4)Cv2.bitwise_xor (目标文件,源文件,mask),将图片里的像素值按位异或
2、函数参数含义(举例一个,其余类似):
CV_EXPORTS_W void bitwise_and(InputArray src1, InputArray src2,
OutputArray dst, InputArray mask = noArray());
参数一:第一个输入数组或标量。
参数二:第二个输入数组或一个标量。
参数三:输出与输入具有相同大小和类型的数组。
参数四:操作掩码;8位单通道数组,用于指定要更改的输出数组的元素。
功能:sr1与sr2相与取较小值为结果,相或取较大值为结果,两个数组的每个元素按位进行与操作(&)。
这几个函数计算一般都是以0和1作为计算标准,在图像计算种函数会把两个值中较小的那一个当成“0”,较大的那一个当成“1”,来进行逻辑操作
3、计算中参数提到mask,下面介绍下mask作用:
图像掩膜用选定的图像、图形或物体,对处理的图像(全部或局部)进行遮挡,来控制图像处理的区域或处理过程。
数字图像处理中,掩模为二维矩阵数组,有时也用多值图像,图像掩模主要用于:
①提取感兴趣区,用预先制作的感兴趣区掩模与待处理图像相乘,得到感兴趣区图像,感兴趣区内图像值保持不变,而区外图像值都为0。
②屏蔽作用,用掩模对图像上某些区域作屏蔽,使其不参加处理或不参加处理参数的计算,或仅对屏蔽区作处理或统计。
③结构特征提取,用相似性变量或图像匹配方法检测和提取图像中与掩模相似的结构特征。
④特殊形状图像的制作。
在所有图像基本运算的操作函数中,凡是带有掩膜(mask)的处理函数,其掩膜都参与运算(输入图像运算完之后再与掩膜图像或矩阵运算)。
如果一个给定的像素的值大于零,那么这个像素会被打开,如果它的值为零,它就会被关闭。按位功能在这些二进制条件下运行。
- AND:当且仅当两个像素都大于零时,按位AND才为真,相与取较大值为结果
- OR:如果两个像素中的任何一个大于零,则按位“或”为真,相或取较小值为结果
- XOR 异或功能:当且仅当两个像素转化为二进制进行异或计算
- NOT 取反:倒置图像中的“开”和“关”像素。
下面看一些实例:
import cv2
import numpy as np
#加载图像
img1 = cv2.imread('C:/Users/Desktop/1.JPG')
img2 = cv2.imread('C:/Users/Desktop/opencv.jpg')
#I want to put logo on top-left corner, So I create a ROI
rows,cols,channels = img2.shape
print(img2.shape)
print(img1.shape)
roi = img1[0:rows, 0:cols ]
#Now create a mask of logo and create its inverse mask also
img2gray = cv2.cvtColor(img2,cv2.COLOR_BGR2GRAY)
#cv2.imshow("img2gray",img2gray)
ret, mask = cv2.threshold(img2gray, 175, 255, cv2.THRESH_BINARY)
cv2.imshow("mask",mask)
mask_inv = cv2.bitwise_not(mask)
#cv2.imshow("mask_inv",mask_inv)
#Now black-out the area of logo in ROI
#取 roi 中与 mask 中不为零的值对应的像素的值,其他值为 0
#注意这里必须有 mask=mask 或者 mask=mask_inv, 其中的 mask= 不能忽略
img1_bg = cv2.bitwise_and(roi,roi,mask = mask)
cv2.imshow("img1_bg",img1_bg)
#取 roi 中与 mask_inv 中不为零的值对应的像素的值,其他值为 0。
#Take only region of logo from logo image.
img2_fg = cv2.bitwise_and(img2,img2,mask = mask_inv)
cv2.imshow("img2_fg",img2_fg)
#Put logo in ROI and modify the main image
dst = cv2.add(img1_bg,img2_fg)
cv2.imshow("dst ",dst )
img1[0:rows, 0:cols ] = dst
#cv2.imshow('res',img1)
cv2.waitKey(0)
cv2.destroyAllWindows()
img1_bg = cv2.bitwise_and(roi,roi,mask = mask)其中mask作为蒙版,与ROI进行计算,黑色部分不计算,剩下mask白色部分与ROI与计算,取较小的值,生成img1_bg
img2_fg = cv2.bitwise_and(img2,img2,mask = mask_inv) #黑色部分不参与计算,mask_inv白色部分与img2非白色部分相与,取较小值,生成img2_fg。
dst = cv2.add(img1_bg,img2_fg) # img1_bg与img2_fg 两者相加,生成最终想要的图dst。
产生上图结果的代码如下:
import cv2
import numpy as np
#加载图像
img1 = cv2.imread('C:/Users/Desktop/1.JPG')
img2 = cv2.imread('C:/Users/Desktop/opencv.jpg')
img3 = cv2.imread('C:/Users/Desktop/3.JPG')
#I want to put logo on top-left corner, So I create a ROI
rows,cols,channels = img2.shape
print(img2.shape)
print(img1.shape)
roi = img1[0:rows, 0:cols ]
roi2 = img3[0:rows, 0:cols ]
cv2.imshow("roi",roi)
cv2.imshow("roi2",roi2)
#Now create a mask of logo and create its inverse mask also
img2gray = cv2.cvtColor(img2,cv2.COLOR_BGR2GRAY)
#cv2.imshow("img2gray",img2gray)
ret, mask = cv2.threshold(img2gray, 175, 255, cv2.THRESH_BINARY)
cv2.imshow("mask",mask)
mask_inv = cv2.bitwise_not(mask)
#cv2.imshow("mask_inv",mask_inv)
#Now black-out the area of logo in ROI
#取 roi 中与 mask 中不为零的值对应的像素的值,其他值为 0
#注意这里必须有 mask=mask 或者 mask=mask_inv, 其中的 mask= 不能忽略
img1_bg = cv2.bitwise_and(roi,roi2,mask = mask)
cv2.imshow("img1_bg",img1_bg)
若把bitwise_and改为bitwise_or,则结果如下图:
img1_bg = cv2.bitwise_or(roi,roi2,mask = mask)
结果验证:
print(roi.item(100,100,2))
print(roi2.item(100,100,2))
print(img1_bg.item(100,100,2))
打印结果,当使用bitwise_or时,取较大的值:
打印结果,当使用bitwise_and时,取较小的值:
打印结果,当使用bitwise_xor时,取值是将216(11011000)与8(10000)转化为二进制进行异或计算得到:
异或理解:
import numpy as np
import cv2
#画矩形
Rectangle = np.zeros((300,300),dtype="uint8")
cv2.rectangle(Rectangle,(25,25),(275,275),255,-1)
cv2.imshow("Rectangle",Rectangle)
cv2.waitKey(0)
#画圆形
Circle = np.zeros((300,300),dtype="uint8")
cv2.circle(Circle,(150,150),150,255,-1)
cv2.imshow("Circle",Circle)
cv2.waitKey(0)
#图像的异或
bitwiseXor = cv2.bitwise_xor(Rectangle,Circle)
cv2.imshow("XOR",bitwiseXor)
cv2.waitKey(0)
下面这个还是很容易理解的: