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 脚本和应用代码。一键创建完整项目结构,支持CLI、API、爬虫、Bot、Django等多种项目类型,包含完整的项目结构、配置文件、依赖管理、测试、README和文档。
-
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 就完全没竞争力了。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










