【P38 6】OpenCV Python——图片的运算(算术运算、逻辑运算)加法add、subtract减法、乘法multiply、除法divide
- 1 加法运算
- 1.1 加法运算示例add
- 1.2 cv2.add() 和直接相加 对比
- 2 减法
- 3 乘法multiply,除法divide
- 3.1 乘法运算(亮度增强)
- 3.2. 基础除法运算 (需添加常量防除零)
- 3.3. 标准化除法改进 (更可视化的结果)
- 3.4. 通道加权乘法(矩阵元素级)
- 3.5 除法再探究
1 加法运算
1.1 加法运算示例add
import cv2
import numpy as npdog=cv2.imread('dog.jpeg')h=dog.shape[0]//2#//取整除法
w=dog.shape[1]//2#尺寸太大了,不便展示
dog = cv2.resize(dog, (w,h), interpolation = cv2.INTER_CUBIC)
#dog=dog.resize((200,200))#不知为啥,这个resize是错的,运行一闪而过
print(dog.shape)
cv2.imshow("dog",dog)img=np.full((h,w,3),50,np.uint8)#生成每个像素的RGB值都是(50,50,50)的灰色图像
result=cv2.add(dog,img)#直接相加,效果不好
dog2=dog+img#显示
cv2.imshow("img",img)
cv2.imshow("result",result)
cv2.imshow("dog2",dog2)#直接相加,效果不好key=cv2.waitKey(0)
add函数相加(饱和运算):效果(左)
直接相加(模运算),效果不好(右)
1.2 cv2.add() 和直接相加 对比
在OpenCV中,cv2.add() 和直接相加 (+) 是两种不同的图像像素值相加方式,主要区别在于数值处理机制:
1 cv2.add() 函数:
- 饱和运算(Saturation Arithmetic):
- 计算结果超过255时自动截断为255;
- 例:200 + 100 = 255;
- 保证结果始终在0-255范围内;
- 适合图像混合/叠加操作;
2 直接相加 (+): - 模运算(Modulo Arithmetic):
- 计算结果超过255时会取模(256取余);
- 例:200 + 100 = 300 % 256 = 44;
- 产生非预期的颜色循环效果;
- 通常需要手动处理溢出(如 np.clip(dog+img, 0, 255));
2 减法
img=np.full((h,w,3),50,np.uint8)
add_img=cv2.add(dog,img)#加
subtract_img=cv2.subtract(dog,img)#减#显示
cv2.imshow("img",img)
cv2.imshow("add_img",add_img)
cv2.imshow("subtract_img",subtract_img)
原图
左加,右减;
结论:
加运算,图片更亮;
减运算,图片更暗;
完整代码
import cv2
import numpy as npdog=cv2.imread('dog.jpeg')h=dog.shape[0]//2#//取整除法
w=dog.shape[1]//2#尺寸太大了,不便展示
dog = cv2.resize(dog, (w,h), interpolation = cv2.INTER_CUBIC)
#dog=dog.resize((200,200))#不知为啥,这个resize是错的,运行一闪而过
print(dog.shape)
cv2.imshow("dog",dog)img=np.full((h,w,3),50,np.uint8)
add_img=cv2.add(dog,img)#加
subtract_img=cv2.subtract(dog,img)#减#显示
cv2.imshow("img",img)
cv2.imshow("add_img",add_img)
cv2.imshow("subtract_img",subtract_img)key=cv2.waitKey(0)
3 乘法multiply,除法divide
import cv2
import numpy as npdog=cv2.imread('dog.jpeg')h=dog.shape[0]//2#//取整除法
w=dog.shape[1]//2#尺寸太大了,不便展示
dog = cv2.resize(dog, (w,h), interpolation = cv2.INTER_CUBIC)
#dog=dog.resize((200,200))#不知为啥,这个resize是错的,运行一闪而过
print(dog.shape)
cv2.imshow("dog",dog)img=np.full((h,w,3),50,np.uint8)#生成每个像素的RGB值都是(50,50,50)的灰色图像#乘法运算(亮度增强效果)
mult_img = cv2.multiply(dog, 1.5) # 1.5倍亮度提升
cv2.imshow("Multiplication", mult_img)# 除法运算(需添加微小常量防除零)
divide51_img = cv2.divide(dog, img + 1) # 避免除数为0
cv2.imshow("Division/51", divide51_img)#标准化除法(更可视化的结果)
normalized_div = cv2.divide(dog, img + 1, scale=100) # 缩放结果
cv2.imshow("Normalized Division", normalized_div)#加权乘法(矩阵元素级)
matrix_mult = cv2.multiply(dog, np.array([0.8, 1.2, 0.9], dtype=np.float32))
cv2.imshow("Channel Weighted Multiply", matrix_mult)key=cv2.waitKey(0)
下面是对上面代码关键部分的解释
3.1 乘法运算(亮度增强)
mult_img = cv2.multiply(dog, 1.5) # 1.5倍亮度提升
- 原理: 对每个像素的BGR通道值执行标量乘法
- 运算规则:
- 采用饱和运算:结果 = min(原始值 × 1.5, 255);
- 例如:原像素值100 → 100×1.5=150(正常显示);
- 原像素值200 → 200×1.5=300 → 截断为255;
- 效果: 整体亮度提升,高光区域可能出现过曝;
3.2. 基础除法运算 (需添加常量防除零)
divide_img = cv2.divide(dog, img + 1) # img是50的灰度图
- 运算过程:
- 除数:
img + 1 = 51
(所有像素值); - 计算公式: 结果 = dog / 51;
- 典型计算: 原像素值100 → 100/51≈1.96 → 转换为uint8后=1(几乎全黑);
- 除数:
- 全黑原因:
- 原始图像像素值范围(0-255)除以51后结果范围(0-5);
- 转换为uint8类型时,小于1的值显示为0(纯黑);
3.3. 标准化除法改进 (更可视化的结果)
将除法的结果 再乘以 scale 倍率。
normalized_div = cv2.divide(dog, img + 1, scale=100)
改进原理:
- scale参数作为乘数:结果 =
100 × (dog/51)
- 使输出值范围扩大到0-500,但:
- 仍会被截断到255(uint8限制)
- 实际效果:100/51×100≈196(可见灰度)
3.4. 通道加权乘法(矩阵元素级)
通道加权乘法: 每个通道乘以不同的系数;
matrix_mult = cv2.multiply(dog, [0.8,1.2,0.9])
特殊效果:
- B通道×0.8(削弱蓝色)
- G通道×1.2(增强绿色)
- R通道×0.9(轻微削弱红色)
应用场景: 色彩平衡调整;
3.5 除法再探究
下面两种代码,都是每个通道除以5的意思,结果一样
divide_45_img = cv2.divide(dog, img - 45)
cv2.imshow("Division-45", divide_45_img)
divide5_img = cv2.divide(dog, 5)
cv2.imshow("Division/5", divide5_img)