OpenCV图像算术运算完全指南

9 阅读4分钟

OpenCV图像算术运算完全指南

mindmap
    root((图像运算))
        基础运算
            加/减 : 曝光调整
            乘/除 : 对比度调节
            位运算 : 掩模操作
        高级应用
            图像融合
            水印添加
            背景替换
        性能优化
            LUT加速
            并行处理

一、基础算术运算

1.1 四则运算原理

classDiagram
    class PixelMath {
        <<interface>>
        +add()
        +subtract()
        +multiply()
        +divide()
    }
    
    class OpenCV {
        +addWeighted()
        +bitwise_and()
        +threshold()
    }
    
    class NumPy {
        +clip()
        +astype()
    }
    
    PixelMath <|-- OpenCV
    PixelMath <|-- NumPy
运算公式对比
运算类型数学表达饱和处理典型应用
加法dst = src1 + src2cv2.add()图像增亮
减法dst = src1 - src2cv2.subtract()背景消除
乘法dst = src1 * src2 / scalecv2.multiply()对比度增强
除法dst = scale * src1 / src2cv2.divide()光照归一化

1.2 基础运算实现

import cv2
import numpy as np

# 创建示例图像
img1 = cv2.imread('img1.jpg')
img2 = cv2.imread('img2.jpg')

# 安全加法(防止溢出)
add_result = cv2.add(img1, img2)

# 带权重的减法
sub_result = cv2.subtract(img1 * 1.5, img2 * 0.5)

# 乘法运算(对比度增强)
mult_result = cv2.multiply(img1, 1.2)

# 除法运算(光照补偿)
div_result = cv2.divide(img1, img2 + 1)  # 避免除零
C++实现
#include <opencv2/opencv.hpp>
using namespace cv;

Mat img1 = imread("img1.jpg");
Mat img2 = imread("img2.jpg");

// 安全运算
Mat add_result, sub_result;
add(img1, img2, add_result);
subtract(img1, img2, sub_result);

// 标量乘法
Mat mult_result;
multiply(img1, Scalar(1.2, 1.2, 1.2), mult_result);

二、图像融合技术

2.1 线性混合(Alpha融合)

flowchart TD
    A[图像1] --> C[addWeighted]
    B[图像2] --> C
    D[权重α] --> C
    E[权重β] --> C
    C --> F[融合结果]
渐变融合效果
# 创建水平渐变权重
h, w = img1.shape[:2]
alpha = np.tile(np.linspace(0, 1, w), (h, 1))
alpha = cv2.merge([alpha]*3)  # 转为3通道

# 自定义融合
blend = cv2.addWeighted(img1, 0.7, img2, 0.3, 0)
custom_blend = img1 * alpha + img2 * (1 - alpha)

2.2 金字塔融合

gantt
    title 金字塔融合流程
    dateFormat  X
    axisFormat %s
    section 处理步骤
    高斯金字塔构建 : 0, 3
    拉普拉斯金字塔 : 3, 6
    层级融合 : 6, 9
    重建图像 : 9, 12
无缝拼接实现
def pyramid_blend(img1, img2, mask, levels=5):
    # 生成高斯金字塔
    G1 = img1.copy()
    G2 = img2.copy()
    GM = mask.copy()
    
    gp1 = [G1]
    gp2 = [G2]
    gpM = [GM]
    
    for _ in range(levels):
        G1 = cv2.pyrDown(G1)
        G2 = cv2.pyrDown(G2)
        GM = cv2.pyrDown(GM)
        gp1.append(G1)
        gp2.append(G2)
        gpM.append(GM)
    
    # 生成拉普拉斯金字塔
    lp1 = [gp1[levels-1]]
    lp2 = [gp2[levels-1]]
    for i in range(levels-1,0,-1):
        GE1 = cv2.pyrUp(gp1[i])
        GE2 = cv2.pyrUp(gp2[i])
        L1 = cv2.subtract(gp1[i-1], GE1)
        L2 = cv2.subtract(gp2[i-1], GE2)
        lp1.append(L1)
        lp2.append(L2)
    
    # 逐层融合
    LS = []
    for l1,l2,gm in zip(lp1,lp2,gpM):
        ls = l1 * gm + l2 * (1 - gm)
        LS.append(ls)
    
    # 重建图像
    ls_ = LS[0]
    for i in range(1,levels):
        ls_ = cv2.pyrUp(ls_)
        ls_ = cv2.add(ls_, LS[i])
    
    return ls_

三、位运算与遮罩

3.1 位操作原理

pie
    title 位运算使用场景
    "掩模应用" : 45
    "ROI提取" : 30
    "水印嵌入" : 15
    "其他" : 10
实战:Logo添加
# 读取主图和Logo
img = cv2.imread('background.jpg')
logo = cv2.imread('logo.png', cv2.IMREAD_UNCHANGED)

# 提取Alpha通道
alpha = logo[:,:,3] / 255.0
logo = logo[:,:,:3]

# 定位叠加位置
x, y = 100, 50
roi = img[y:y+logo.shape[0], x:x+logo.shape[1]]

# 融合处理
for c in range(3):
    roi[:,:,c] = roi[:,:,c] * (1 - alpha) + logo[:,:,c] * alpha

3.2 高级遮罩应用

flowchart LR
    A[原始图像] --> B[创建掩模]
    B --> C{位运算选择}
    C -->|AND| D[区域提取]
    C -->|OR| E[图像合成]
    C -->|XOR| F[特效生成]
    C -->|NOT| G[反相处理]
背景替换案例
# 创建HSV颜色掩模
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
lower_green = np.array([35, 50, 50])
upper_green = np.array([85, 255, 255])
mask = cv2.inRange(hsv, lower_green, upper_green)

# 优化掩模边缘
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5))
mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)

# 替换背景
bg = cv2.imread('new_bg.jpg')
bg = cv2.resize(bg, (img.shape[1], img.shape[0]))
result = np.where(mask[...,None]==0, img, bg)

四、性能优化技巧

4.1 LUT加速技术

stateDiagram-v2
    [*] --> 创建查找表
    创建查找表 --> 预计算映射
    预计算映射 --> 应用LUT
    应用LUT --> 输出结果
批量像素变换
# 创建Gamma校正LUT
gamma = 0.5
lut = np.array([((i / 255.0) ** gamma) * 255 
               for i in range(256)], dtype=np.uint8)

# 应用查找表
result = cv2.LUT(img, lut)

# 多通道分别处理
luts = [lut] * 3  # 每个通道相同处理
result = cv2.merge([cv2.LUT(img[:,:,i], luts[i]) 
                   for i in range(3)])

4.2 并行处理

pie
    title 运算耗时分布
    "像素计算" : 65
    "内存访问" : 20
    "其他" : 15
Python多线程处理
from concurrent.futures import ThreadPoolExecutor

def process_channel(channel, lut):
    return cv2.LUT(channel, lut)

with ThreadPoolExecutor() as executor:
    futures = []
    for i in range(3):
        futures.append(executor.submit(
            process_channel, 
            img[:,:,i], 
            luts[i]
        ))
    results = [f.result() for f in futures]
    
result = cv2.merge(results)

五、实战应用案例

5.1 双重曝光特效

flowchart TD
    A[肖像图] --> C[高光提取]
    B[风景图] --> D[边缘保留]
    C --> E[线性混合]
    D --> E
    E --> F[效果增强]
实现代码
# 提取人像高光区域
gray = cv2.cvtColor(portrait, cv2.COLOR_BGR2GRAY)
_, mask = cv2.threshold(gray, 220, 255, cv2.THRESH_BINARY)

# 风景图模糊处理
landscape_blur = cv2.GaussianBlur(landscape, (0,0), 5)

# 混合处理
result = cv2.bitwise_and(portrait, portrait, mask=mask)
result += cv2.bitwise_and(landscape_blur, landscape_blur, 
                         mask=cv2.bitwise_not(mask))

5.2 图像HDR合成

gantt
    title HDR合成流程
    dateFormat  X
    axisFormat %s
    section 处理步骤
    读取曝光序列 : 0, 2
    对齐图像 : 2, 5
    计算响应曲线 : 5, 10
    合成HDR : 10, 15
多曝光合成
# 读取不同曝光图像
imgs = [cv2.imread(f'exposure_{i}.jpg') 
        for i in range(3)]

# 转换为32位浮点
imgs = [img.astype(np.float32)/255 for img in imgs]

# 手动设置权重
weights = [0.2, 0.7, 0.1]  # 低/中/高曝光权重

# 加权融合
hdr = np.zeros_like(imgs[0])
for img, w in zip(imgs, weights):
    hdr += img * w

# 色调映射
hdr = np.clip(hdr * 255, 0, 255).astype(np.uint8)

六、调试与优化

6.1 常见问题排查

现象原因解决方案
图像出现异常色斑数值溢出未处理使用cv2.add()替代+
融合边缘不自然掩模羽化不足高斯模糊掩模边缘
运算速度慢Python循环未优化改用NumPy矢量化
透明效果失效Alpha通道未正确处理预乘Alpha值

6.2 可视化调试工具

def show_blend_process(img1, img2, alpha):
    plt.figure(figsize=(12,4))
    
    plt.subplot(131)
    plt.imshow(cv2.cvtColor(img1, cv2.COLOR_BGR2RGB))
    plt.title('Image 1')
    
    plt.subplot(132)
    plt.imshow(alpha, cmap='gray')
    plt.title('Alpha Mask')
    
    plt.subplot(133)
    blend = img1 * alpha[...,None] + img2 * (1-alpha[...,None])
    plt.imshow(cv2.cvtColor(blend.astype(np.uint8), 
              cv2.COLOR_BGR2RGB)
    plt.title('Blend Result')
    
    plt.tight_layout()
    plt.show()

# 创建渐变掩模
h,w = img1.shape[:2]
alpha = np.linspace(0,1,w).reshape(1,-1)
show_blend_process(img1, img2, alpha)

总结:本文系统讲解了OpenCV算术运算的核心技术,关键要点:

  1. 优先使用OpenCV内置函数(如addWeighted)避免溢出
  2. 位运算配合掩模可实现精确区域控制
  3. 金字塔融合适合多分辨率图像合成
  4. LUT加速技术可提升批量像素操作性能

下期预告:《图像阈值化》将深入讲解全局/自适应阈值、Otsu算法等二值化技术。