一、图像的加法与减法运算

图像的加法和减法运算均基于像素点的逐点计算,在图像处理中属于基础操作,其核心用途分别为信息融合与差异提取。

1. 图像加法运算

图像加法运算指对两幅或多幅图像对应位置的像素值进行求和,进而生成一幅新图像。

核心用途

  • 图像融合:将不同来源的图像信息进行叠加,例如将红外图像与可见光图像相加,可同时保留两种图像的特征。
  • 降噪处理:对同一场景拍摄的多幅含噪声图像取平均(加法运算后除以图像数量),能够有效降低随机噪声。
  • 亮度调整:将图像与一个固定的亮度值矩阵相加,可整体提升图像的亮度。

关键规则

  • 参与加法运算的图像尺寸必须完全一致,否则无法实现逐点对应计算。
  • 像素值相加后可能会超出图像的灰度级范围(如8位图像的像素值范围为0-255),因此需要进行截断(超出255则设为255)或归一化处理,以避免因像素值溢出而导致图像失真。

2. 图像减法运算

图像减法运算指用一幅图像对应位置的像素值减去另一幅图像对应位置的像素值,生成的新图像能够突出两者之间的差异。

核心用途

  • 运动检测:在同一背景下,用不同时刻拍摄的两幅图像相减,差值不为零的区域即为运动目标(如在监控中检测行人、车辆等)。
  • 去除固定背景:在医学影像(如X光片)或工业检测中,通过减去固定的背景图像,可突出前景的病变区域或缺陷。
  • 图像对比:对比处理前后的图像(如降噪、增强前后的图像),通过减法运算能够直观地显示处理效果的差异。

关键规则

  • 与加法运算类似,参与减法运算的图像尺寸必须一致,且通常要求是针对同一场景、使用同一设备拍摄的图像。
  • 减法运算后可能会出现负的像素值,需要对其进行处理(如取绝对值,或把负数值设为0),以确保运算结果符合图像的灰度级范围。
# 图像的减法和加法运算
import cv2
import numpy as np

lh = cv2.imread('10.jpg')

# 图像的加法运算即矩阵的加法运算,因此参与加法运算的两张图像必须尺寸相等
cv2.imshow('lh', lh)

print(lh.shape)

img = np.ones((942, 720, 3), np.uint8) * 50

result = cv2.add(lh, img)  # 图像变亮
cv2.imshow('result', result)

result_1 = cv2.subtract(lh, img)  # 图像变暗
cv2.imshow('result_1', result_1)
cv2.waitKey(0)

输出结果如下:
在这里插入图片描述

二、图像融合

图像融合(Image Fusion)是将多源图像(如不同传感器、不同时间、不同视角拍摄的图像)中的信息整合到一幅图像中,保留各源图像的关键特征(如细节、结构、色彩等),最终生成一幅更全面、更清晰、更具分析价值的图像。该技术解决了单一图像存在的信息不完整、噪声干扰或视角局限等问题,在遥感、医学影像、机器视觉等领域有着广泛的应用。

核心目标

  • 信息互补:结合不同图像的优势(如红外图像的温度信息与可见光图像的纹理细节相结合)。
  • 冗余去除:减少图像中的重复信息,避免数据冗余。
  • 提升质量:增强图像的清晰度、对比度或信噪比,以便于后续的分析工作(如目标识别、诊断等)。
# 图像的融合
import cv2
import numpy as np

back = cv2.imread('555.jpg')
cv2.namedWindow('back', cv2.WINDOW_NORMAL)
cv2.imshow('back', back)
small = cv2.imread('666.png')
cv2.namedWindow('small', cv2.WINDOW_NORMAL)
cv2.imshow('small', small)

# 只有两张图像的属性相同才能进行融合

print(back.shape)
print(small.shape)
cv2.namedWindow('result', cv2.WINDOW_NORMAL)
result = cv2.addWeighted(back, 0.7, small, 0.3, 0)
cv2.imshow('result', result)
cv2.waitKey(0)

输出结果如下:
在这里插入图片描述

三、OpenCV位运算——图像的与、非、或、异或运算

在OpenCV中,图像的位运算(与、或、非、异或)是基于像素值的二进制位进行逐位操作的,常用于图像掩码(Mask)处理、区域选择、图像合成等场景。由于位运算直接对二进制数据进行操作,因此效率极高,且能够实现灵活的像素级控制。

位运算的前提

  • 参与运算的图像尺寸必须相同(确保像素位置一一对应)。
  • 通常针对单通道灰度图或多通道图像的每个通道分别进行运算(如RGB图像的R、G、B通道各自独立进行位运算)。
  • 像素值以二进制形式参与运算(例如8位图像的像素值范围为0-255,对应8位二进制数)。

1. 非运算(NOT)

逻辑规则:对单个二进制位取反(1=0,0=1)。
核心作用:反转图像的明暗(如将黑色变为白色,白色变为黑色),或生成反掩码。
示例:实现图像颜色的反转。

2. 与运算(AND)

逻辑规则:两个二进制位均为1时,结果为1;否则为0(1&1=1,1&0=0,0&1=0,0&0=0)。
核心作用:保留两幅图像中“共同为高值”的区域(常结合掩码提取感兴趣区域ROI)。
示例:使用掩码(白色区域为1,黑色区域为0)提取图像中的目标,结果图像中,只有掩码的白色区域保留原图内容,其他区域为黑色。

3. 或运算(OR)

逻辑规则:两个二进制位至少有一个为1时,结果为1;否则为0(1|1=1,1|0=1,0|1=1,0|0=0)。
核心作用:合并两幅图像的“高值区域”(如将两个目标区域合并为一个)。
示例:合并两个图像的白色区域,效果为结果图像同时包含两个方块区域。

4. 异或运算(XOR)

逻辑规则:两个二进制位不同时结果为1,相同时为0(11=0,10=1,01=1,00=0)。
核心作用:突出两幅图像的差异区域,或实现“叠加-去除”的切换效果。
示例:检测两幅图像的差异,效果为结果图像中,两图相同的区域为黑色,不同的区域(如新增目标)为亮色。

# 图像的非运算、与运算(同时为真即为真,否则为假)
import numpy as np
import cv2
from sqlalchemy import bitwise_not

# 创建两张图片
img = np.zeros((200, 200), np.uint8)
img2 = np.zeros((200, 200), np.uint8)

img[20:120, 20:120] = 255
img2[80:180, 80:180] = 255

# 非操作
new_img1 = cv2.bitwise_not(img)
cv2.imshow('new_img1', new_img1)

# 与运算
new_img2 = cv2.bitwise_and(img, img2)
# 显示合并后的结果图
cv2.imshow('new_img2', new_img2)

# 或操作
new_img3 = cv2.bitwise_or(img, img2)
cv2.imshow('new_img3', new_img3)

# 异或操作(相同为假,不同为真)
new_img4 = cv2.bitwise_xor(img, img2)
cv2.imshow('new_img4', new_img4)

cv2.imshow('img', img)
cv2.imshow('img2', img2)
cv2.waitKey(0)

输出结果为:
在这里插入图片描述

四、实战:给图片添加水印

# 给图片添加水印
# 1. 引入一张图片
# 2. 创建一个logo
# 3. 确定图片中添加水印的位置,并将该位置处理为黑色
# 4. 利用add函数,将Logo与图像叠加在一起

import numpy as np
import cv2

# 导入图片
lh = cv2.imread('10.jpg')

# 创建logo
logo = np.zeros((200, 200, 3), np.uint8)  # 三通道
mask = np.zeros((200, 200), np.uint8)     # 单通道

# 绘制logo
logo[20:120, 20:120] = [0, 0, 255]  # 红色
logo[80:180, 80:180] = [0, 255, 0]  # 绿色

# 白色为255
mask[20:120, 20:120] = 255
mask[80:180, 80:180] = 255

# 对mask按位求反,白色(255)变为黑色(0)
m = cv2.bitwise_not(mask)
cv2.imshow('m', m)

# 选择lh中添加图像的位置
roi = lh[0:200, 0:200]

# 与m进行与操作,roi是三通道
tmp = cv2.bitwise_and(roi, roi, mask=m)
cv2.imshow('tmp', tmp)

dst = cv2.add(tmp, logo)
cv2.imshow('dst', dst)

lh[0:200, 0:200] = dst
cv2.imshow('lh', lh)

cv2.imshow('logo', logo)
cv2.imshow('mask', mask)
cv2.waitKey(0)

这段代码的核心思路是通过OpenCV的图像处理函数,将自定义的logo水印添加到目标图片的指定位置,主要运用了位运算和图像叠加技术。

代码解释

1. 创建自定义Logo及掩码(mask)
(1)初始化Logo和掩码的画布

logo = np.zeros((200, 200, 3), np.uint8)  # 200x200的三通道黑色画布(用于绘制彩色logo)
mask = np.zeros((200, 200), np.uint8)     # 200x200的单通道黑色画布(用于标记logo的区域)
  • logo:用于绘制水印图案,初始状态为全黑(像素值[0,0,0])。
  • mask:掩码的作用是标记“哪些区域需要添加logo”,初始状态为全黑(像素值0)。

(2)绘制Logo图案

logo[20:120, 20:120] = [0, 0, 255]   # 在(20-120行, 20-120列)绘制红色矩形(BGR格式,[0,0,255]为红色)
logo[80:180, 80:180] = [0, 255, 0]   # 在(80-180行, 80-180列)绘制绿色矩形([0,255,0]为绿色)

最终logo呈现为两个重叠的矩形:红色矩形和绿色矩形的交叉部分形成黄色(红色与绿色叠加)。

(3)绘制掩码(标记logo区域)

mask[20:120, 20:120] = 255   # 红色矩形区域在掩码中设为白色(255)
mask[80:180, 80:180] = 255   # 绿色矩形区域在掩码中设为白色(255)

掩码中“白色区域(255)”对应logo需要显示的区域,“黑色区域(0)”对应不需要显示的区域。

2. 处理掩码,准备图像融合

m = cv2.bitwise_not(mask)  # 对掩码取反:白色(255)变黑色(0),黑色(0)变白色(255)

取反后的掩码m用于后续操作:保留目标图像中“非logo区域”的原始像素。

3. 选择目标图片的水印添加位置

roi = lh[0:200, 0:200]  # 从目标图像左上角截取200x200的区域(ROI:感兴趣区域)

此处选择图片左上角(0-200行,0-200列)作为水印添加的位置,roi是目标图像中需要被水印覆盖的区域。

4. 处理目标图像的ROI区域

tmp = cv2.bitwise_and(roi, roi, mask=m)  # 对ROI区域应用取反后的掩码m
# cv2.bitwise_and(a, b, mask):对a和b做按位与运算,结果只保留mask中白色区域(255)的像素。

此处a和b均为roi,因此运算结果为:保留roi中“掩码m为白色”的区域(即“非logo区域”),而“logo区域”被置为黑色(因为m中对应位置为0)。
效果:tmp是ROI区域中“扣除logo位置后剩余的原始图像部分”(logo位置变为黑色)。

5. 融合ROI与Logo

dst = cv2.add(tmp, logo)  # 将处理后的ROI(tmp)与logo叠加
# cv2.add(a, b):对两幅图像做像素值相加(若超过255则取255)。

tmp中logo位置为黑色(0),叠加logo后,该位置显示logo的颜色;tmp中其他位置保留原始图像像素,叠加黑色(logo的非图案区域)后保持不变。
效果:dst是“原始ROI区域+logo水印”的融合结果。

6. 将融合结果放回目标图像

lh[0:200, 0:200] = dst  # 用融合结果覆盖目标图像的ROI区域

将添加了水印的dst放回目标图像lh的左上角区域,完成整个图片的水印添加。

7. 显示所有中间结果和最终效果

cv2.imshow('m', m)        # 显示取反后的掩码
cv2.imshow('tmp', tmp)    # 显示处理后的ROI(logo位置为黑色)
cv2.imshow('dst', dst)    # 显示ROI与logo的融合结果
cv2.imshow('lh', lh)      # 显示最终添加水印的图片
cv2.imshow('logo', logo)  # 显示自定义的logo
cv2.imshow('mask', mask)  # 显示原始掩码
cv2.waitKey(0)            # 等待按键,保持窗口显示

输出结果:
在这里插入图片描述

总结
代码通过“掩码标记logo区域→扣除目标图像中logo位置的像素→将logo与剩余像素叠加”的流程,实现了水印的添加。其核心是利用掩码(mask)控制“哪些区域显示logo”以及“哪些区域保留原图”,最终通过add函数完成融合。

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐