原文地址:

https://zhuanlan.zhihu.com/p/91078855

---------------------------------------------------------------------------

今天要说的事情很简单,就是比较了一下 PIL 和 cv2 resize 图片的速度。我们都知道,Python 中有关图像处理的库有很多,常见的有 cv2,scikit-image,PIL (严谨点应该叫 Pillow,下文就用 PIL 来代替了) 等等。在用 Python 进行深度学习图像任务的时候,我们常常会使用 PIL 这个库来读取图片(尤其是在用 PyTorch 的时候)。至于为什么 PIL 比较常用,我也不知道... 难道是 TorchVision 带来的风气(https://github.com/pytorch/vision#image-backend)? 但在进行视频流处理的时候,我们往往会用到 cv2,因为都会用到 cv2.VideoCapture() 来读视频(应该没有人第一反应是其他的库吧)。

为什么会想到对比这二者 resize 图片的速度?原因是最近处理视频流的时候用的是 cv2 读取,每一帧读出来的结果是一个3维的 Numpy Array。然后要 resize 一下送到模型嘛,因为惯性我就用了 PIL 来做图片 resize (而没有用 cv2.resize)。PIL 的 resize 只能对 PIL Image 类做处理,所以我先把 Numpy Array 转成 PIL Image, 然后 resize, 然后再转回 Numpy Array。 我后来再看代码的时候心想这 tm 是什么操作?那索性来比一比这二者的速度吧。

因为这不是什么严肃的对比,所以我就不列啥硬件软件配置了。但大体上就是,一台普通的电脑,用着 pip3 安装来的普通的 cv2 和 PIL,做的一次简单的对比。

1. resize 对比

对比中我们使用的是 CV 界的经典图像,512x512 的豪华彩色三通道 Lena 的 png 图片:

// 看看这高清的像素,看看这左上角标的 2014 的独特 logo,看看这被截到只剩头和肩膀的 Lena, 还有知乎你为什么不支持删除线??

首先我们先测试一下 cv2 的速度,我们采用双线性插值,将 512x512 的图片 resize 到 1024x1024:

repeat = 2000
im = cv2.imread('lena512_colour.png')
print(type(im), im.shape)
# <class 'numpy.ndarray'> (512, 512, 3) start = time.time()
for i in range(repeat):
im_resized = cv2.resize(im, (1024, 1024), interpolation=cv2.INTER_LINEAR) print('cv2 resize - total time of %d is %.3f s' % (repeat, time.time()-start))
# cv2 resize - total time of 2000 is 3.789 s

然后试试 PIL 吧,所以条件一致的情况下,我们假定需要的输入和输出都是 Numpy Array

repeat = 2000
im = cv2.imread('lena512_colour.png') start = time.time()
for i in range(repeat):
tmp = Image.fromarray(im)
tmp = tmp.resize((1024, 1024), resample=Image.BILINEAR)
im_resized = np.array(tmp) print('PIL resize - total time of %d is %.3f s' % (repeat, time.time()-start))
# PIL resize - total time of 2000 is 40.714 s
 

这... 被吊打好嘛。当然这对 PIL 有些不公平,毕竟 Numpy Array 和 PIL Image 互相转换也要花费时间,所以我们来测一下输入输出都是 PIL Image 时候的速度:

repeat = 2000

im = Image.open('lena512_colour.png')
print(type(im))
# <class 'PIL.PngImagePlugin.PngImageFile'> start = time.time()
for i in range(repeat):
im_resized = im.resize((1024, 1024), resample=Image.BILINEAR) print('PIL resize - total time of %d is %.3f s' % (repeat, time.time()-start))
# PIL resize - total time of 2000 is 27.219 s

好嘛,还是被吊打... 我查了查资料,Kaggle 上有位老哥做了比较全的对比,比我严谨多了,结果也是 PIL 被吊打(https://www.kaggle.com/vfdev5/pil-vs-opencv)。还有老哥建议用优化过的 Pillow-SIMD,但是貌似官方的测试结果(https://python-pillow.org/pillow-perf/)还是差 OpenCV 好多啊... well...

2. 买一送一:cv2 的 BGR

我们都知道,用 cv2 打开彩色三通道图像的时候,通道的顺序是 BGR,所以比如我们用 pyplot 来显示图片的时候,图片是不正常的,效果如下:

冷色调的 Lena

所以我们在预处理的时候,还要把通道给变成 RGB。怎么变呢,我知道有三种方法:

# 方法一:
repeat = 50000
im = cv2.imread('lena512_colour.png') start = time.time()
for i in range(repeat):
b, g, r = cv2.split(im)
im_rgb1 = cv2.merge([r, g, b]) print('method 1 - total time of %d is %.3f s' % (repeat, time.time()-start))
# method 1 - total time of 50000 is 9.279 s

# 方法二:
repeat = 50000
im = cv2.imread('lena512_colour.png') start = time.time()
for i in range(repeat):
im_rgb2 = cv2.cvtColor(im, cv2.COLOR_BGR2RGB) print('method 2 - total time of %d is %.3f s' % (repeat, time.time()-start))
# method 2 - total time of 50000 is 1.602 s


# 方法三:
repeat = 50000
im = cv2.imread('lena512_colour.png') start = time.time()
for i in range(repeat):
im_rgb3 = im[: , : , ::-1] print('method 3 - total time of %d is %.3f s' % (repeat, time.time()-start))
# method 3 - total time of 50000 is 0.027 s

 
 
 

三种方法的结果都是一样的。但是大家需要主要的是,虽然第三种速度最快,但 im_rgb3 和 im 是共享内存的哦,也就是如果在后边 im 的值被(inplace)修改了,im_rgb3 的值也会跟着相应变化,而前两种方法是不会有这种情况的。

3. 总结

经过不严谨的对比显示,cv2 比 PIL 快不少,至少在图像 resize 上。好了,不多说了,周一的时候把改正的代码测试一下,估计模型的实时处理速度会提升一点,没准老板会夸我优化做得不错呢(玩笑,测试用的 demo 而已),CV 从业者的一天,往往就是这么朴实无华且枯燥。

-------------------------------------------

【转载】 Python Pillow 和 cv2 图片 resize 速度的比较的更多相关文章

  1. [Python]-opencv-python模块(cv2)-图片读取和格式转换

    python常常用opencv模块来处理图像. import cv2 as cv 读取图片:imread() 默认按照彩色三通道读取: img = cv2.imread(path) 读取灰度图: im ...

  2. python中用Pillow库进行图片处理

    一.Python中 PIL 图像处理库简介 PIL可以做很多和图像处理相关的事情: 图像归档(Image Archives).PIL非常适合于图像归档以及图像的批处理任务.你可以使用PIL创建缩略图, ...

  3. 尝试用python开发一款图片压缩工具1:尝试 pillow库

    开发目的 我经常使用图片.公众号文章发文也好,还是生活中要使用素材.图片是一种比文字更加直观的载体.但是图片更加占用带宽,很多软件都对图片有大小限制.图片太大也会影响加载速度.我试过几款图片压缩工具, ...

  4. python Pillow 图片处理模块,好强大有没有

    python Pillow 图片处理模块,好强大有没有 Pillow 需要给 python 另外安装 第一个用法:https://www.cnblogs.com/ibingshan/p/1105739 ...

  5. Python,PIL压缩裁剪图片

    自己写了用来压缩 DC 照片的,批量处理整目录文件,非常方便.需要安装 PIL #!/usr/bin/env python import Image import os import os.path ...

  6. Python 3 实现色情图片识别

    Python 3 实现色情图片识别 项目简介 项目内容 本实验将使用 Python3 去识别图片是否为色情图片,我们会使用到 PIL 这个图片处理库,会编写算法来划分图像的皮肤区域. 项目知识点 Py ...

  7. python 开发一款图片压缩工具(四):上传图床

    上一篇使用了 pngquant 图片压缩工具进行压缩,并通过 click 命令行工具构建了 picom 包.这篇的主要功能是实现图片上传. 图片上传功能的实现 通过 pngquant 压缩图片后,得到 ...

  8. 用 Python 和 OpenCV 检测图片上的条形码

      用 Python 和 OpenCV 检测图片上的的条形码 这篇博文的目的是应用计算机视觉和图像处理技术,展示一个条形码检测的基本实现.我所实现的算法本质上基于StackOverflow 上的这个问 ...

  9. Python爬虫下载美女图片(不同网站不同方法)

    声明:以下代码,Python版本3.6完美运行 一.思路介绍 不同的图片网站设有不同的反爬虫机制,根据具体网站采取对应的方法 1. 浏览器浏览分析地址变化规律 2. Python测试类获取网页内容,从 ...

  10. Python下尝试实现图片的高斯模糊化

    资源下载 #本文PDF版下载Python下尝试实现图片的高斯模糊化#本文代码下载高斯模糊代码下载 高斯模糊是什么? (先来看一下维基百科对它的定义) 高斯模糊是模糊图像的结果.它是一种广泛使用的图形软 ...

随机推荐

  1. ArrayList、LinkedList、Vector 的区别

    ArrayList,Vector 底层是由数组实现,LinkedList 底层是由双线链表实现,从底层的实现可以得出它们的性能问题, ArrayList,Vector 插入速度相对较慢,查询速度相对较 ...

  2. email邮件(带附件,模拟文件上传,跨服务器)发送核心代码 Couldn't connect to host, port: smtp.163.com, 25; timeout -1;

    邮件(带附件,模拟文件上传,跨服务器)发送核心代码1.测试邮件发送附件接口 /** * 测试邮件发送附件 * @param multipartFile * @return */ @RequestMap ...

  3. es应用服务初始化步骤

    第一步:创建索引+settings+mappingtestes_v1 PUT { "settings": { "index.mapping.total_fields.li ...

  4. Linux 增加 swap 分区

    检查当前swap分区 [root@localhost ~]# free -g total used free shared buffers cached Mem: 15 0 14 0 0 0 -/+ ...

  5. python重拾第七天-面向对象进阶

    本节内容: 面向对象高级语法部分 经典类vs新式类 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 作业:开发一个支持多用户在线的FTP程序 面向对象高级语法部分 经典 ...

  6. Netty(一)IO模型

    1. Netty介绍 Netty 是由JBOSS提供的一个Jave开源框架,是一个异步地.基于事件驱动的网络应用框架,用以快速开发高性能.高可靠的网络IO程序. Netty主要针对在TCP协议下,面向 ...

  7. Android 8.0 开机时间优化

    Android 8.0 开机时间优化 背景 在嵌入式行业中,有些搭载 了Android系统的设备由于 开机时间 过长而导致无法被接受. 介绍 启动时间是系统性能的重要组成部分,因为用户必须等待启动完成 ...

  8. 3568F-麒麟KylinOS国产操作系统演示案例

  9. P8571 题解

    既然字符串的总长一定,不妨对于每个询问中的 \(s_k\) 的长度根号分治,假定分治阈值为 \(B\).下面令 \(L\) 为所有串长度总和. 对于长度大于 \(B\) 的字符串,这样的不同字符串至多 ...

  10. linux scp自动填充密码脚本

    在linux上使用scp命令传输文件时,每传输一次,都要填写目标服务器的登录密码,十分麻烦. 配置系统密钥又比较复杂,于是想到的使用expect写一个自动填充密码的脚本,脚本内容如下: scp.sh ...