【OpenCV 入门到精通 05】核心操作与像素处理:ROI、运算与性能优化
标签 :
OpenCVROI图像运算位运算性能优化NumPy难度 :⭐⭐ | 阅读时长 :约 60 分钟 | 系列 :第 05/12 集

写在前面
掌握像素级操作是图像处理的根基。本集对应官方 3_1 图像基本操作、3_2 图像运算、3_3 性能优化,涵盖 ROI、通道分离、算术/位运算和性能调优。
本集学习目标
- 使用 ROI 裁剪和操作图像区域
- 进行通道分离与合并
- 掌握图像算术运算和位运算
- 了解 OpenCV 性能优化技巧
文章目录
- [【OpenCV 入门到精通 05】核心操作与像素处理:ROI、运算与性能优化](#【OpenCV 入门到精通 05】核心操作与像素处理:ROI、运算与性能优化)
-
- 写在前面
- 本集学习目标
- [5.1 ROI 区域操作](#5.1 ROI 区域操作)
- [5.2 通道分离与合并](#5.2 通道分离与合并)
- [5.3 图像算术运算](#5.3 图像算术运算)
- [5.4 位运算](#5.4 位运算)
- [5.5 性能优化](#5.5 性能优化)
-
- [1. 避免频繁 split/merge](#1. 避免频繁 split/merge)
- [2. 使用 numpy 向量化](#2. 使用 numpy 向量化)
- [3. 测量执行时间](#3. 测量执行时间)
- [4. 使用合适数据类型](#4. 使用合适数据类型)
- [5.6 踩坑指南](#5.6 踩坑指南)
- [5.7 本集小结](#5.7 本集小结)
5.1 ROI 区域操作
ROI(Region of Interest)= 感兴趣区域。
python
import cv2
img = cv2.imread("photo.jpg")
# 裁剪 ROI:注意 [y1:y2, x1:x2]
roi = img[100:300, 200:400]
# 修改 ROI 会影响原图(共享内存)
roi[:] = (0, 255, 0)
# 安全复制
roi_copy = img[100:300, 200:400].copy()
粘贴小图到大图
python
img = cv2.imread("background.jpg")
logo = cv2.imread("logo.png")
lh, lw = logo.shape[:2]
img[50:50+lh, 100:100+lw] = logo
5.2 通道分离与合并
python
b, g, r = cv2.split(img)
zeros = np.zeros(b.shape, dtype=np.uint8)
# 只显示红色通道
red_only = cv2.merge([zeros, zeros, r])
# 更快的方式
img[:,:,0] = 0 # 蓝色通道置零
img[:,:,1] = 0 # 绿色通道置零
| 操作 | 函数 |
|---|---|
| 分离 | cv2.split(img) → B, G, R |
| 合并 | cv2.merge([b,g,r]) |
| 颜色转换 | cv2.cvtColor(img, flag) |
5.3 图像算术运算
python
import cv2
import numpy as np
img1 = cv2.imread("a.jpg")
img2 = cv2.imread("b.jpg")
# 加法(饱和到 255)
result = cv2.add(img1, img2)
# 加权混合(透明度)
blended = cv2.addWeighted(img1, 0.7, img2, 0.3, 0)
# 标量运算
bright = cv2.add(img1, np.ones(img1.shape, dtype=np.uint8) * 50)
| 运算 | OpenCV 函数 | NumPy | 区别 |
|---|---|---|---|
| 加法 | cv2.add |
img1+img2 |
cv2 饱和截断,numpy 取模 |
| 减法 | cv2.subtract |
img1-img2 |
同上 |
| 乘法 | cv2.multiply |
img1*img2 |
同上 |
| 混合 | cv2.addWeighted |
- | 加权求和 |
⚠️ 图像运算要求两图 尺寸相同。
5.4 位运算
用于掩码操作、图像合成:
python
# 创建掩码
mask = np.zeros(img.shape[:2], dtype=np.uint8)
cv2.rectangle(mask, (100,100), (300,300), 255, -1)
# 按位与:提取 ROI
roi = cv2.bitwise_and(img, img, mask=mask)
# 按位或:合并
combined = cv2.bitwise_or(img1, img2)
# 按位非:反转
inverted = cv2.bitwise_not(img)
| 运算 | 作用 |
|---|---|
bitwise_and |
提取掩码区域 |
bitwise_or |
合并图像 |
bitwise_xor |
差异检测 |
bitwise_not |
反转 |
5.5 性能优化
1. 避免频繁 split/merge
python
# 慢
b, g, r = cv2.split(img)
b[:] = 0
img = cv2.merge([b, g, r])
# 快
img[:,:,0] = 0
2. 使用 numpy 向量化
python
# 慢:逐像素循环
for i in range(h):
for j in range(w):
img[i,j] = img[i,j] * 1.5
# 快:向量化
img = np.clip(img.astype(np.float32) * 1.5, 0, 255).astype(np.uint8)
3. 测量执行时间
python
import time
start = time.time()
# ... 你的代码 ...
print(f"耗时: {(time.time()-start)*1000:.2f} ms")
# OpenCV 内置
e1 = cv2.getTickCount()
# ... 代码 ...
e2 = cv2.getTickCount()
time_ms = (e2 - e1) / cv2.getTickFrequency() * 1000
4. 使用合适数据类型
| 场景 | 推荐 dtype |
|---|---|
| 显示/存储 | uint8 |
| 中间计算 | float32 / float64 |
| 避免 | 频繁 uint8↔float 转换 |
5.6 踩坑指南
| 坑 | 解决 |
|---|---|
| ROI 修改影响原图 | 用 .copy() |
| add 结果异常 | 用 cv2.add 而非 + |
| 两图尺寸不同 | 先 resize 到相同尺寸 |
| 运算溢出 | cv2 函数自动饱和到 0~255 |
5.7 本集小结
| 主题 | 核心 |
|---|---|
| ROI | img[y1:y2, x1:x2] |
| 通道 | split / merge / cvtColor |
| 运算 | add addWeighted subtract |
| 位运算 | bitwise_and/or/not + mask |
| 性能 | 向量化、避免循环、测时间 |
| ← 第04集 | 第06集:颜色与几何 → |
|---|
参考:3_1 图像基本操作 | 3_3 性能优化