本节摘要:SOURCE 1.2:图像在内存中是行优先的多维数组;OpenCV 用 BGR 顺序。本节动手:裁剪 ROI、通道分离、理解
contiguous与img[y1:y2, x1:x2]切片。
(rows, cols, channels) 与坐标 (x,y) 对应关系split/mergepyrDown 的多尺度含义import cv2 img = cv2.imread('color.jpg') # BGR, shape (H,W,3) b, g, r = cv2.split(img) roi = img[100:200, 50:150] # 注意 y 在前 print(roi.shape)
像素访问:img[y, x] 或 img.item(y,x,c)。修改 ROI 会影响原图(视图)— 需要副本用 .copy()。
img1 = cv2.imread('a.png', 0) img2 = cv2.imread('b.png', 0) add = cv2.add(img1, img2) # 饱和 255 sub = cv2.subtract(img1, img2) # 背景减除基础 mask = cv2.bitwise_and(img1, img2)
| 运算 | 函数 | 应用 |
|---|---|---|
| 加 | cv2.add | 曝光合成 |
| 减 | subtract | 背景建模 |
| 与 | bitwise_and | 掩膜 |

SOURCE 1.2.3:PNG 无损、JPEG 有损、TIFF 科研常用。OpenCV imwrite 质量参数 JPEG cv2.IMWRITE_JPEG_QUALITY。
原点左上,x 向右,y 向下 — 与数学笛卡尔 y 向上不同,几何变换节需注意。
pyrDown 两次,记录 shape 变化(约 1/4 面积)absdiff⚠️ 常见坑:
img[x,y]写反导致行列颠倒。
💡 关键直觉:ROI 是零拷贝视图 — 算法流水线注意
.copy()时机。
下一节 RGB/HSV 颜色空间转换。
NumPy 数组默认行优先存储:shape 为 (H, W, 3) 的彩色图,内存里先连续存放第一行的所有像素(每像素 3 个通道),再放第二行。img[y, x] 与 img[y][x] 等价但前者更快,因为它只做一次下标解析。切片 img[100:200, 50:150] 返回的是原数组的视图,共享内存——修改切片会改动原图,这在裁剪 ROI 后继续处理时很容易造成"悄悄污染原图"的 bug。需要独立副本时用 .copy(),这个习惯建议从一开始就建立。
import cv2, numpy as np img = cv2.imread('color.jpg') roi = img[100:200, 50:150] # 视图:与原图共享内存 roi[:, :] = 0 # 原图区域也被清零 img_copy = img.copy() # 深拷贝,独立内存
另一个易错点:图像数据是 BGR 顺序,但 numpy 不知道"通道顺序"这个概念,它只把第三维当成 3 个通道。如果直接把 OpenCV 读出的图用 matplotlib 显示,红蓝会互换。这也是为什么显示前要先 cvtColor(BGR2RGB)。
图像金字塔是"多尺度表示"的最简单形式:pyrDown 每级把长宽减半、面积变四分之一,pyrUp 反之。金字塔的意义在于让算法能在不同尺度上搜索目标——大物体在小尺度图里检测省算力,小物体在原始尺度才有足够像素。SIFT 的尺度空间、目标检测的多尺度特征图,本质上都是金字塔思想的延伸。做实验时记录每级 shape 和细节变化(比如文字在第几级开始看不清),能直观理解"尺度"对视觉任务的约束。
cv2.add 是饱和运算(超过 255 截断到 255),np.add 是模运算(回绕),两者行为完全不同。bitwise_and 配合掩膜实现"只处理感兴趣区域"是最高频的组合用法:先二值化得到掩膜,再用 bitwise_and 抠出区域,最后统计区域内的直方图或均值。这套"掩膜、抠图、统计"的套路在后续阈值分割、颜色分割章节会反复出现,值得现在就练熟。
坐标系统也值得单独记牢:OpenCV 的坐标系原点在图像左上角,x 轴向右、y 轴向下,与数学里 y 向上的笛卡尔坐标系相反。几何变换(2.3 节)和特征点匹配(第 5 章)里所有坐标换算都基于这个约定,一旦混淆,变换结果会上下颠倒。建议在实验里打印几个关键点的坐标验证方向,形成肌肉记忆。
最后补充一点:图像金字塔之外,还有"多尺度特征"在深度学习里被广泛使用,比如特征金字塔网络(FPN)就是在多个尺度特征上做检测。掌握金字塔背后的"多尺度抽象"思想,对后续学习深度学习检测框架有直接帮助,这也是本节把它单独拎出来的原因。至此,你应该能回答:BGR 与 RGB 谁先谁后、切片是视图还是副本、pyrDown 一次面积缩多少。答对这三问,本节的核心就掌握了,可以放心进入色彩空间章节。
补一个性能视角:图像处理的核心运算(滤波、阈值、形态学)在 Python 里直接写双重循环会非常慢,OpenCV 的 C 实现要快几十上百倍。工程习惯是"能用 OpenCV/NumPy 向量化就绝不用 Python 循环",比如整图加减用 img + 50(NumPy 广播)而不是逐像素遍历。写自定义算法时,先检查是否能用 reshape、切片、np.where 这类向量化操作表达,这对处理视频帧率级别的图像尤其重要。