写点什么

Python OpenCV 之图像乘除与像素的逻辑运算,图像处理取经之旅第 17 天

发布于: 2021 年 04 月 02 日
Python OpenCV 之图像乘除与像素的逻辑运算,图像处理取经之旅第 17 天

今天的学习的内容是:通过 Python OpenCV 对图像实现乘除操作,涉及函数为 cv2.multiplycv2.divide。后面又补充了一些像素的逻辑运算,以及一个综合案例

cv2.multiply

该函数的语法格式如下:


cv2.multiply(src1, src2, dst=None, scale=None, dtype=None)
复制代码


参数说明:src1:第一张图像 src2:第二张图像 dst:可选参数,目标图像,需要提前分配空间,可省略 mask:掩膜 scale:缩放比,常量,即在 src1*src2 的基础上再乘 scaledtype:输出图像数组的深度,默认等于-1


测试下面的代码,尝试之后,发现乘法很容易就全黑或者全白,毕竟两个数字相乘知乎,很容易超过 255。


import cv2 as cv
def multiply_demo(src1, src2): ret = cv.multiply(src1, src2) cv.imshow("multiply_demo", ret) cv.waitKey(0)
if __name__ == "__main__": src1 = cv.imread("./18_3.jpeg") src2 = cv.imread("./18_4.jpg") multiply_demo(src1, src2)
复制代码



如果 cv2.multiply 函数的第二个图像为一个标量,那运行结果是针对单一通道进行叠加。


import cv2 as cv
from matplotlib import pyplot as plt
def multiply_demo(src1, src2): ret = cv.multiply(src1, 1.5)
plt.subplot(121), plt.imshow(src1), plt.title('src1') plt.subplot(122), plt.imshow(ret), plt.title('ret') plt.show()
if __name__ == "__main__": src1 = cv.imread("./18_3.jpeg") src2 = cv.imread("./18_4.jpg") multiply_demo(cv.cvtColor(src1,cv.COLOR_BGR2RGB), cv.cvtColor(src2,cv.COLOR_BGR2RGB))
复制代码


运行效果截图:


cv2.divide

该函数的语法格式为:


divide(src1, src2, dst=None, scale=None, dtype=None)
复制代码


本部分与相乘基本一致,图像相除最后很容易得到一个全黑的图。


具体可以自行尝试。

像素的逻辑运算

像素的逻辑运算涉及与、或、非、异或等基本运算(要进行逻辑运算,两张图片的形状(shape)必须一样)


对应函数的格式如下

cv2.bitwise_and(src1, src2,mask)

作用:对二进制数据进行“与”操作,即对图像(灰度图像或彩色图像均可)每个像素值进行二进制“与”操作,1&1=1,1&0=0,0&1=0,0&0=0,这个里面的掩膜非常有用,我们细说一下。


在彻底学习演膜之前,需要接触一个新的概念,又要学习新东西啦。


而且在接下来的几篇博客,都要围绕演膜与 ROI 展开,因为在学习的时候,发现这部分知识很重要。


ROI(感兴趣区域,英文全称叫做 Region Of Internet)


下面我们实现找到 ROI,并且移动 ROI,代码如下:


下述代码测试图片,使用的是:![Python OpenCV 之图像乘除与像素的逻辑运算,图像处理取经之旅第 17 天](https://img-blog.csdnimg.cn/20210116200546156.jpeg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hpaGVsbA==,size_16,color_FFFFFF,t_70#pic_center =500x)我们要获取的是蕾姆的犄角


import cv2 as cv
path = r"1919.jpeg"
# 读取图片image = cv.imread(path)# 输出图片形状# 注意输出的元组(rows,cols,dtype)print(image.shape)# cv.imshow("image", image)# 捕捉犄角区域horn = image[60:100, 180:240]# cv.imshow("horn", horn)# 框选犄角区域# image = cv.rectangle(image, (180, 55), (240, 105), (0, 0, 255), thickness=2)# print(horn.shape)# 拷贝一个犄角# image[60:100, 120:180] = image[60:100, 180:240]# 只要形状大小相同就可以移动 ROI 到另一部分# image[100:140, 220:280] = horn# 犄角转换成灰度图horn = cv.cvtColor(horn, cv.COLOR_BGR2GRAY)# 灰度图在转换成BGR图back_horn = cv.cvtColor(horn, cv.COLOR_GRAY2BGR)# image[250:370, 250:350] = back_hornimage[60:100, 180:240] = back_horn
cv.imshow("Region Of Interest(ROI)", horn)cv.imshow("horn", image)
cv.waitKey()cv.destroyAllWindows()
复制代码


上述代码,你可以在学习过程中自行解开查阅。重点部分都已经写在注释里面了。


获取到犄角图之后,我们在对其进行二值化操作,具体代码如下


import cv2 as cv
path = r"1919.jpeg"
# 读取图片image = cv.imread(path)# 输出图片形状# 注意输出的元组(rows,cols,dtype)print(image.shape)# cv.imshow("image", image)# 捕捉犄角区域horn = image[60:100, 180:240]
# 犄角转换成灰度图gray_horn = cv.cvtColor(horn, cv.COLOR_BGR2GRAY)
# 获取到了犄角的二值化图像thresh, mask = cv.threshold(gray_horn, 160, 255, cv.THRESH_BINARY)
# 获取 mask 的反色图像mask_inv = cv.bitwise_not(mask)# cv.imshow("mask", mask)

# 打开一个彩色糖果图片colors = cv.imread(r"colors.jpg")# 选中一块与 mask 相同大小的 ROIrows, cols = mask.shape[:2]pie_colors = colors[10:10+rows, 20:20+cols]print(pie_colors.shape)print(mask.shape)cv.imshow("pie_colors", pie_colors)

# 选出犄角部分img1_bg = cv.bitwise_and(horn, pie_colors, mask=mask)# cv.imshow("img1_bg", img1_bg)img2_fg = cv.bitwise_and(horn, horn, mask=mask_inv)# cv.imshow("img2_fg", img2_fg)# 两个犄角合并在一起add_img = image.copy() # 对原图像进行拷贝dst = cv.addWeighted(img1_bg, 0.3, img2_fg, 1, 0)# cv.imshow("dst", dst)add_img[60:100, 180:240] = dst# image[60:100, 180:240] = back_horn
cv.imshow("origin", image)cv.imshow("new", add_img)
cv.waitKey()cv.destroyAllWindows()
复制代码


上面的代码,理解起来有写难度,本阶段先尝试理解即可(橡皮擦在写的时候,也晕掉了,总感觉缺少一些知识,没有吃透)


用到了以前学习的二值化操作,用到了灰度图,也用到了图像叠加。


也有可能是因为案例选择的不好,最后更换犄角之后的图片很难看,如下图所示。


看起来,缺少一部分融合的效果。后面知识比较全面之后,可能对这些理解会更加深入。![Python OpenCV 之图像乘除与像素的逻辑运算,图像处理取经之旅第 17 天](https://img-blog.csdnimg.cn/20210116204741541.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hpaGVsbA==,size_16,color_FFFFFF,t_70#pic_center =600x)效果虽然丑爆了,但是终究是能操作指定区域了。


上述代码也用到了下面的逻辑运算,先理解含义,后面逐步展开内容。

cv2.bitwise_or(src1, src2,mask)

作用:对不同通道相同位置的二进制值进行"或"运算(对应位置只要有一个为 1,结果就为 1)。

cv2.bitwise_not()

作用:按位取反

cv2.bitwise_xor(src1,src2,dst,mask)

作用:输出两个图像的异或 dst = src1 ^ src2


测试代码如下:


import cv2import numpy as npfrom matplotlib import pyplot as plt
src1 = cv2.imread('18_1.jpg')src2 = cv2.imread('18_2.jpg')d_and = cv2.bitwise_and(src1, src2)d_or = cv2.bitwise_or(src1, src2)d_not = cv2.bitwise_not(src1)d_xor = cv2.bitwise_xor(src1, src2)
title = ['src1', 'src2', 'and', 'or', 'not', 'xor']images = [src1, src2, d_and, d_or, d_not, d_xor]for i in range(6): plt.subplot(2, 3, i+1) plt.imshow(cv2.cvtColor( images[i], cv2.COLOR_BGR2RGB), 'gray'), plt.title(title[i])plt.show()
复制代码


代码运行之后的效果如图:


![Python OpenCV 之图像乘除与像素的逻辑运算,图像处理取经之旅第 17 天](https://img-blog.csdnimg.cn/20210116154646209.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hpaGVsbA==,size_16,color_FFFFFF,t_70#pic_center =600x)下篇博客,将使用之前的内容,加上像素的逻辑运算完成一个【扣章效果】。


学习完今天的效果之后,发现对以前学过的地方有遗漏,后面几篇博客,基于已经学习的知识,好好夯实几天吧。

OpenCV 尾声

1 个小时又过去了,对 Python OpenCV 相关的知识点,你掌握了吗?


空闲之余,可以订阅橡皮擦的爬虫百例课程学习爬虫知识。


想学 Python 爬虫,可以订阅橡皮擦专栏哦~ 🈲🈲🈲🈲 点击发现惊喜 🈲🈲🈲🈲




博主 ID:梦想橡皮擦,希望大家<font color="red">点赞</font>、<font color="red">评论</font>、<font color="red">收藏</font>。

发布于: 2021 年 04 月 02 日阅读数: 10
用户头像

爬虫 100 例作者,蓝桥签约作者,博客专家 2021.02.06 加入

6 年产品经理+教学经验,3 年互联网项目管理经验; 互联网资深爱好者; 沉迷各种技术无法自拔,导致年龄被困在 25 岁; CSDN 爬虫 100 例作者。 个人公众号“梦想橡皮擦”。

评论

发布
暂无评论
Python OpenCV 之图像乘除与像素的逻辑运算,图像处理取经之旅第 17 天