在前面学习了阈值分割,这样得到的图像往往是二值图,有了二值图之后就可以利用二值图之间进行逻辑运算,在OpenCV里提供了bitwise_and、bitwise_or、bitwise_xor、bitwise_not这四个按位操作函数。
bitwise_and是对二进制数据进行“与”操作,即对图像(灰度图像或彩色图像均可)每个像素值进行二进制“与”操作,1&1=1,1&0=0,0&1=0,0&0=0。
bitwise_or是对二进制数据进行“或”操作,即对图像(灰度图像或彩色图像均可)每个像素值进行二进制“或”操作,1|1=1,1|0=0,0|1=0,0|0=0。
bitwise_xor是对二进制数据进行“异或”操作,即对图像(灰度图像或彩色图像均可)每个像素值进行二进制“异或”操作,1^1=0,1^0=1,0^1=1,0^0=0。
bitwise_not是对二进制数据进行“非”操作,即对图像(灰度图像或彩色图像均可)每个像素值进行二进制“非”操作,~1=0,~0=1。
先来看bitwise_and函数的定义,理解了它,其它函数与它是一样的。
dst=cv.bitwise_and(src1, src2[, dst[, mask]])
其中参数:
src1 输入数组1
src2 输入数组2
dst 输出运算后的数组
mask 可选参数,8位单通道数组,指定那些元素可以改变。
用下面的例子来熟悉图像的逻辑运算:
#python 3.7.4,opencv4.1
#蔡军生 https://blog.csdn.net/caimouse/article/details/51749579
#
import cv2
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
#方形图
rectangle = np.zeros((300,300),dtype="uint8")
cv2.rectangle(rectangle,(25,25),(275,275),255,-1)
#圆形图
circle = np.zeros((300,300),dtype="uint8")
cv2.circle(circle,(150,150),150,255,-1)
#图像逻辑运算
bitwiseAnd = cv2.bitwise_and(rectangle,circle)
bitwiseOr = cv2.bitwise_or(rectangle,circle)
bitwiseXor = cv2.bitwise_xor(rectangle,circle)
bitwiseNot = cv2.bitwise_not(rectangle)
titles = ['方形图', '圆形图', 'bitwise_and', 'bitwise_or','bitwise_xor','bitwise_not']
images = [rectangle, circle, bitwiseAnd, bitwiseOr, bitwiseXor, bitwiseNot]
for i in range(6):
plt.subplot(2, 3, i + 1), plt.imshow(images[i], 'gray')
plt.title(titles[i], fontsize=8)
plt.xticks([]), plt.yticks([])
plt.show()
cv2.waitKey(0)
cv2.destroyAllWindows()
结果输出如下:
在这里对方形图和圆形图进行逻辑运算。在bitwise_and中可以看到下面的关系:
黑色 + 任何颜色 = 黑色
白色 + 任何颜色 = 任何颜色
下面就来使用bitwise_and函数来做一些比较特别的内容。最近发现在微信里头像添加国旗的活动,那么我们也来做一下这个事情,虽然还可以使用其它的方法实现,但这里采用上面学习过的知识来实现它。比如把下图:
贴在下面这个图上面:
从上面可以看到国旗图片是一个非规则的边缘,因此可以采用图像的逻辑操作函数来实现,下面一步一步地实现这个过程,首先要用下面的代码实现图片加载:
#图片的路径
imgname1 = "szimg.png"
imgflag = "redflag.png"
#读取图片
image = cv2.imread(imgname1, cv2.IMREAD_COLOR)
imgflag = cv2.imread(imgflag, cv2.IMREAD_COLOR)
接着要选择国旗贴在图片上的位置,由于微信头像是贴在右下角,这里也来选择贴在右下角:
#图片的高度和宽度
h,w = image.shape[:2]
print('imagesize={}-{}'.format(w,h))
#显示原图
cv2.imshow("Image",image)
cv2.imshow("flag",imgflag)
#
rows,cols,channels = imgflag.shape
roi = image[h-rows:h, w-cols:w ]
cv2.imshow("roi", roi)
接着下来要创建两张掩膜(mask),在这里采用前面阈值分割的方法来实现,当然你也可采用别的方法:
flaggray = cv2.cvtColor(imgflag,cv2.COLOR_BGR2GRAY)
cv2.imshow('flaggray',flaggray)
ret, mask = cv2.threshold(flaggray, 230, 255, cv2.THRESH_BINARY_INV)
mask_inv = cv2.bitwise_not(mask)
cv2.imshow("mask", mask)
cv2.imshow("mask_inv",mask_inv)
创建成功之后,掩膜mask和mask_inv显示出来如下:
有了掩膜之后,就可以把贴图的背景处理出来:
img_bg = cv2.bitwise_and(roi,roi,mask = mask_inv)
cv2.imshow("img_bg", img_bg)
在这里roi使用mask_inv掩膜,所以白色地方保留原图的颜色,但黑色地方全部变成黑色了,如下图:
接着下来使得掩膜mask来创建国旗的前景图案,因为与白色相与的结果保持原样:
flag_fg = cv2.bitwise_and(imgflag,imgflag,mask = mask)
cv2.imshow("flag_fg", flag_fg)
结果显示如下:
接着下来把图像的背景和前景合屏到一起,就完成不规则图像的贴图:
out_img = cv2.add(img_bg,flag_fg)
cv2.imshow("out_img", out_img)
image[h-rows:h, w-cols:w] = out_img
cv2.imshow("out", image)
结果显示如下:
到这里就实现前面的目标了。
https://blog.csdn.net/caimouse/article/details/51749579
整个例子的源码如下:
#python 3.7.4,opencv4.1
#蔡军生 https://blog.csdn.net/caimouse/article/details/51749579
#
import cv2
import numpy as np
#图片的路径
imgname1 = "szimg.png"
imgflag = "redflag.png"
#读取图片
image = cv2.imread(imgname1, cv2.IMREAD_COLOR)
imgflag = cv2.imread(imgflag, cv2.IMREAD_COLOR)
#图片的高度和宽度
h,w = image.shape[:2]
print('imagesize={}-{}'.format(w,h))
#显示原图
cv2.imshow("Image",image)
cv2.imshow("flag",imgflag)
#
rows,cols,channels = imgflag.shape
roi = image[h-rows:h, w-cols:w ]
cv2.imshow("roi", roi)
flaggray = cv2.cvtColor(imgflag,cv2.COLOR_BGR2GRAY)
cv2.imshow('flaggray',flaggray)
ret, mask = cv2.threshold(flaggray, 230, 255, cv2.THRESH_BINARY_INV)
mask_inv = cv2.bitwise_not(mask)
cv2.imshow("mask", mask)
cv2.imshow("mask_inv",mask_inv)
img_bg = cv2.bitwise_and(roi,roi,mask = mask_inv)
cv2.imshow("img_bg", img_bg)
flag_fg = cv2.bitwise_and(imgflag,imgflag,mask = mask)
cv2.imshow("flag_fg", flag_fg)
out_img = cv2.add(img_bg,flag_fg)
cv2.imshow("out_img", out_img)
image[h-rows:h, w-cols:w] = out_img
cv2.imshow("out", image)
cv2.waitKey(0)
cv2.destroyAllWindows()
转载:https://blog.csdn.net/caimouse/article/details/101700438