小言_互联网的博客

在OpenCV里实现二值图的逻辑运算

563人阅读  评论(0)

在前面学习了阈值分割,这样得到的图像往往是二值图,有了二值图之后就可以利用二值图之间进行逻辑运算,在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
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场