图像运算有很多种,包括 加法、减法、乘法、除法、位运算、平方根、对数、绝对值等;
加减乘除等 需保持 图像 shape 和 dtype 一致,或者第二个图像是个标量值;
dst = cv.add(src1, src2[, dst[, mask[, dtype]]]) dst = cv2.subtract(src1, src2, dst, mask, dtype) dst = cv2.multiply(src1, src2, dst, scale, dtype) dst = scale * src1 * src2 dst = cv2.divide(src1, src2, dst, scale, dtype) dst = scale * src1 / src2
注意 OpenCV运算 和 Numpy运算 之间有区别:OpenCV运算是饱和运算,而Numpy运算是模运算;
OpenCV功能将提供更好的结果,最好坚持使用OpenCV功能。
图像加法
以加法为例解释 饱和运算 和 模运算
## opencv VS numpy # def add(src1, src2, dst=None, mask=None, dtype=None): x = np.uint8([10]) y = np.uint8([250]) z1 = x + y # 250 + 10 = 260 % 256 = 4 8位无符号整型,最大 256 z2 = cv.add(x, y) # 250 + 10 = 260 => 255 print(z1, z2) # [4] [[255]]
第二个数为 标量值 示例
# 加 标量值 xx = np.random.randint(0, 100, size=(2, 2), dtype=np.uint8) print(xx) # [[ 8 22] # [28 11]] yy = 10 zz = cv.add(xx, yy) print(zz) # [[18 32] # [38 21]]
图像融合
图像融合 的本质也是 图像加法,只是 赋予了图像 不同的权重;它给人一种混合或透明的感觉
计算公式:dst=α⋅img1+β⋅img2+γ
# def addWeighted(src1, alpha, src2, beta, gamma, dst=None, dtype=None): img11 = cv.imread('imgs/2.png')[:300, :350] img22 = cv.imread('imgs/3.png')[:300, :350] # img11 img22 shape 一致 print(img11.shape, img11.dtype, img22.shape, img22.dtype) img33 = cv.addWeighted(img11, 0.3, img22, 0.7, 0) cv.imshow('t', img33) cv.waitKey(0)
效果图
图像减法 与 差分
图像差分 其实 就是 两张图 做差,图像的减法通常用于查找图像的差异;
subtract(src1, src2, dst=None, mask=None, dtype=None)
src1:作为被减数的图像数组或一个标量
src2:作为减数的图像数组或一个标量
dst:可选参数,输出结果保存的变量,默认值为None,如果为非None,输出图像保存到dst对应实参中,其大小和通道数与输入图像相同,图像的深度(即图像像素的位数)由dtype参数或输入图像确
mask:图像掩膜,可选参数,为8位单通道的灰度图像,用于指定要更改的输出图像数组的元素,即输出图像像素只有mask对应位置元素不为0的部分才输出,否则该位置像素的所有通道分量都设置为0
dtype:可选参数,输出图像数组的深度,即图像单个像素值的位数(如RGB用三个字节表示,则为24位)。
返回值:相减的结果图像
示例
img1 = np.random.randint(100, 256, size=(5, 5), dtype=np.uint8) img2 = np.random.randint(0, 20, size=(5, 5), dtype=np.uint8) dst1 = cv.subtract(img1, img2) print('jianfa', dst1) dst2 = cv.absdiff(img1, img2) print('chafen', dst2) print((dst1 - dst2).sum()) # 0
一般都选用 opencv 的用法,而不用 numpy 计算,区别请看
https://blog.csdn.net/LaoYuanPython/article/details/109020778
图像乘法
不太常用,也没看懂怎么算的
x = np.random.randint(0, 10, size=(3, 3), dtype=np.uint8) y = np.random.choice([0, 255], size=(3, 3)).astype(np.uint8) z1 = cv.multiply(x, y) z2 = cv.multiply(x, x) print(x) # [[ 8 150 28] # [139 24 219] # [208 171 67]] print(y) # [[255 255 255] # [ 0 0 0] # [ 0 0 255]] print(z1) # [[255 255 255] # [ 0 0 0] # [ 0 0 255]] print(z2) # [[64 0 9] # [49 9 49] # [49 81 49]]
位运算
这个比较常用,也比较复杂
基础函数
先简单了解几个函数,在 位运算 中 会用到 【更详细的功能 后续 会 专门讲解】
固定阈值二值化
def threshold(src, thresh, maxval, type, dst=None)
src: 输入图,只能输入单通道图像,通常来说为灰度图
thresh: 阈值
maxval: 当像素值超过了阈值(或者小于阈值,根据type来决定),所赋予的值
type:二值化操作的类型,包含以下5种类型: cv2.THRESH_BINARY; cv2.THRESH_BINARY_INV; cv2.THRESH_TRUNC; cv2.THRESH_TOZERO;cv2.THRESH_TOZERO_INV
dst: 输出图
上下阈值二值化
def inRange(src, lowerb, upperb, dst=None)
介于 low 和 up 之间 为 255,否则为 0
示例
xx = np.random.randint(0, 255, size=(5, 5), dtype=np.uint8) print(xx) # [[ 8 150 28 139 24] # [219 208 171 67 55] # [ 67 71 103 223 123] # [105 87 47 173 108] # [ 79 0 193 134 176]] ## def threshold(src, thresh, maxval, type, dst=None): # 小于 thresh 为 0,大于 thresh 为 maxval yy, zz = cv.threshold(xx, 100, 200, cv.THRESH_BINARY) print(zz) # [[ 0 200 0 200 0] # [200 200 200 0 0] # [ 0 0 200 200 200] # [200 0 0 200 200] # [ 0 0 200 200 200]] ## def inRange(src, lowerb, upperb, dst=None): # 介于 low 和 up 之间 为 255,否则为 0 ss = cv.inRange(xx, 100, 150) print(xx) # [[ 8 150 28 139 24] # [219 208 171 67 55] # [ 67 71 103 223 123] # [105 87 47 173 108] # [ 79 0 193 134 176]] print(ss) # [[ 0 255 0 255 0] # [ 0 0 0 0 0] # [ 0 0 255 0 255] # [255 0 0 0 255] # [ 0 0 0 255 0]]
掩膜 mask
掩膜的概念来源于PCB制版的过程,在半导体制造中,许多芯片工艺步骤采用光刻技术,用于这些步骤的图形“底片”称为掩膜(也称作“掩模”),
其作用是:在硅片上 选定的区域 用一个 不透明的图形模板 遮盖,继而下面的 腐蚀或扩散 将只影响 选定的区域以外 的区域。
图像掩膜与其类似,用选定的 图形、图像或物体 对 待处理的 图像 进行遮挡,来控制图像处理的区域或者处理过程
数字图像处理中,掩膜多为 二维矩阵,也可为 多值图像,图像掩膜主要用于:
1. 提取感兴趣区域ROI:掩膜图像 与 待处理图像 相乘,感兴趣区内图像值保持不变,其余置0
2. 屏蔽作用:用掩膜对图像上某些区域进行屏蔽,使其不参与处理,或者仅对屏蔽区域进行处理
3. 结构特征提取:用相似性计算或者图像匹配方法 检测和提取 图像中与 掩膜 相似的 结构特征
4. 特殊形状图像的制作
位运算函数
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
示例
## def bitwise_and(src1, src2, dst=None, mask=None): x = np.uint8([[0, 0], [255, 255]]) print(x) # [[ 0 0] # [255 255]] y = np.uint8([[0, 255], [0, 255]]) print(y) # [[ 0 255] # [ 0 255]] print(cv.bitwise_not(x)) # 取反, 0变成255, 255变成0 # [[255 255] # [ 0 0]] print(cv.bitwise_and(x, x)) # # [[ 0 0] # [255 255]] print(cv.bitwise_and(x, y)) # 且 # [[ 0 0] # [ 0 255]] print(cv.bitwise_or(x, x)) # [[ 0 0] # [255 255]] print(cv.bitwise_or(x, y)) # 或 # [[ 0 255] # [255 255]] print(cv.bitwise_xor(x, x)) # [[0 0] # [0 0]] print(cv.bitwise_xor(x, y)) # 异或,不同为255,相同为0 # [[ 0 255] # [255 0]]
掩膜-位运算-实例
以郁金香图片为例,原图大小为1024×768,先压缩一下,利用opencv的inRange()函数,制作掩模,再用bitwise_and()函数,提取感兴趣区域
# set blue thresh lower_yellow = np.array([11, 43, 46]) upper_yellow = np.array([25, 255, 255]) frame = cv.imread("imgs/mask2.png") # 读取图像 cv.imshow("who", frame) # compress cp = cv.resize(frame, (300, 300), interpolation=cv.INTER_AREA) cv.imwrite("tulips_1.jpg", cp) # change to hsv model hsv = cv.cvtColor(cp, cv.COLOR_BGR2HSV) # get mask mask = cv.inRange(hsv, lower_yellow, upper_yellow) # 获取黄色 ROI, inRange 介于 low 和 up 之间 为 1 cv.imshow('Mask', mask) # detect blue res = cv.bitwise_and(cp, cp, mask=mask) # 只对 mask 进行计算,这里就是 提取 mask 区域,其他区域置0 cv.imshow('Result', res) cv.waitKey(0) cv.destroyAllWindows()
效果图
参考资料:
https://blog.csdn.net/sinat_21258931/article/details/61418681 python-opencv函数总结之(一)threshold、adaptiveThreshold、Otsu 二值化
https://blog.csdn.net/qq_42444944/article/details/91988092 python-opencv中的cv2.inRange函数
https://blog.csdn.net/weixin_26882891/article/details/113009845 python图像相乘运算_opencv-python-学习笔记六(图像的基本运算)
https://blog.csdn.net/youandme520/article/details/107844995 bitwise_and、bitwise_not等图像基本运算及掩膜
https://blog.csdn.net/weixin_41115751/article/details/84568029 python_opencv图像算术运算(cv2.bitwise_and(),cv2.bitwise_not())按位运算
https://blog.csdn.net/zhouzongzong/article/details/93028651 【OpenCV + Python】之bitwise_and、bitwise_not,bitwise_xor等图像基本运算(opencv位操作)