图像运算有很多种,包括 加法、减法、乘法、除法、位运算、平方根、对数、绝对值等;

加减乘除等 需保持 图像 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位操作)