OpenCV-Python通常比PIL快,但取决于操作类型、图像尺寸和是否启用硬件加速;cv2.imread读JPEG比PIL快20%–40%,而PIL在仅查尺寸或EXIF时更优,颜色空间转换和隐式复制是主要性能陷阱。
OpenCV-Python 通常比 PIL 快,但不是所有场景都成立——关键看操作类型、图像尺寸、是否启用硬件加速,以及你有没有踩进 cv2.cvtColor 或 Image.fromarray 的隐式转换坑里。
cv2.imread vs Image.open:IO阶段就拉开差距
读取 JPEG 文件时,cv2.imread 默认用 libjpeg-turbo(若编译时启用了),比 PIL 的 Pillow 默认后端快 20%–40%,尤其在批量读取小图时更明显。但注意:cv2.imread 返回 BGR 格式 numpy.ndarray,而 Image.open 返回 PIL.Image.Image 对象,延迟加载;如果你只检查尺寸或格式而不真正解码像素,PIL 反而更快。
- 需要立即访问像素(如做直方图、滤波)→ 优先用
cv2.imread - 仅遍历目录、筛选尺寸、提取 EXIF → 用
Image.open+img.size,不调load() - 读取 PNG 或 WebP 时差距缩小,甚至 PIL 更稳(OpenCV 对某些 WebP 编码支持不全)
颜色空间转换是最大性能陷阱
很多人把 PIL 图转 OpenCV 做处理,再转回 PIL 保存,结果速度反而更慢——问题出在 cv2.cvtColor(img, cv2.COLOR_RGB2BGR) 和 Image.fromarray(img) 这两步。前者是深拷贝+通道重排,后者会校验 dtype 并可能触发隐式复制。
- 避免来回切换:全程用 OpenCV 处理,最后用
cv2.imwrite保存 - 必须和 PIL 交互?用
np.array(img)[:, :, ::-1]替代cv2.cvtColor(..., COLOR_RGB2BGR)(省去函数调用开销) -
Image.fromarray传入dtype=np.uint8且 shape 为 (h,w,3) 时最快;若传入 float32 或 (h,w),它会额外做归一化和 reshape
resize / thumbnail 性能对比真实数据
对一张 4000×3000 的 JPEG 图缩放到 800×600:
Python 3.14.3
微软官方的 Python 扩展,是 VS Code 安装量最高的扩展(209M+)。集成 IntelliSense(通过 Pylance)、调试(通过 Python Debugger)、代码检查、格式化、重构和单元测试等功能。支持 Jupyter Notebook、虚拟环境管理和多 Python 版本切换。
-
cv2.resize(img, (800, 600), interpolation=cv2.INTER_AREA):约 3.2 ms -
img.resize((800, 600), resample=Image.Resampling.BILINEAR):约 8.7 ms -
img.thumbnail((800, 600), resample=Image.Resampling.BILINEAR):约 5.1 ms(原地修改,少一次 copy)
OpenCV 快的主因是 INTER_AREA 专为下采样优化,而 PIL 的 resize 是通用实现。但注意:cv2.INTER_LANCZOS4 质量高但比 PIL 的 LANCZOS 还慢,别盲目选“最高质量”。
批量处理时别让 PIL 成瓶颈
处理上千张图时,PIL 的单线程解码器容易成为 IO+CPU 混合瓶颈;OpenCV 在开启 OpenMP/TBB 后可自动并行解码(需源码编译,pip 安装版默认关闭)。简单验证方法:
- 运行
cv2.getBuildInformation(),搜Parallel framework: OpenMP或TBB - 若为
None,说明你用的是 pip 安装的预编译 wheel,无并行加速 - 此时批量
cv2.imread可能不如多线程 + PILImage.open,尤其在 SSD 上
真正要提速,得自己控制并发粒度:用 concurrent.futures.ThreadPoolExecutor 配合 cv2.imread,或改用 cv2.cuda_GpuMat(需 CUDA 环境)——这时候 PIL 就完全没竞争力了。