1.我们首先来看一下opencv的读取效率:
# 加载时间函数用于计算效率 import time # opencv import cv2 N = 1000 tic = time.time() for i in range(N): img = cv2.imread('../data/train/cat.123.jpg') img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) print(N/(time.time()-tic), 'images decoded per second with opencv') imshow(img)
734.9363854754574 images decoded per second with opencv
opencv读取成numpy.array的速度为每秒734张。
2. 我们来看一下scipy的读取方式和它的效率:
# scipy from scipy.misc import imread N = 1000 tic = time.time() for i in range(N): img = imread('../data/train/cat.123.jpg') print(N/(time.time()-tic), 'images decoded per second with scipy.misc')
623.7528820826661 images decoded per second with scipy.misc
采用scipy中的misc函数进行读取效率略微比opencv低一点,速度为每秒623张
3. 如果采用scipy的亲儿子skimage进行读取呢?
# skimage from skimage import io N = 1000 tic = time.time() for i in range(N): img = io.imread('../data/train/cat.123.jpg') print(N/(time.time()-tic), 'images decoded per second with skimage')
613.2599892065876 images decoded per second with skimage 可以看出它的读取速度和scipy基本相当,甚至慢一点,可以确定的一点的是skimage是scipy的亲儿子。速度:每秒613张
4. 和大家重点说一下pillow这个老大,我们还是先做实验:
# pillow from PIL import Image N = 1000 tic = time.time() for i in range(N): img = Image.open('../data/train/cat.123.jpg') img = np.array(img) print(N/(time.time()-tic), 'images decoded per second with pillow')
606.2237641859305 images decoded per second with pillow
pillow看起来速度比上面还要慢一点,差别也不大,基本是每秒606张。但实际上,pillow在之星open语句的时候,实际上是通过读取二进制编码的方式进行读取图像,原则上应该是要比上面快很多,那么为什么速度会这么慢呢?我们再做个试验。
# pillow N = 1000 tic = time.time() for i in range(N): img = Image.open('../data/train/cat.123.jpg') #img = np.array(img) print(N/(time.time()-tic), 'images decoded per second with pillow')
10118.899305672832 images decoded per second with pillow 可以明显发现,读取速度直接提升
5. 既然已经考虑到了关于读取方式和解码问题的效率问题时,那么我们是不是有更好的图像读取方式呢?于是DMLC(创造MXNet的组织)调用了第一项中opencv中读取编码、解析编码的部分代码,并加入了自动多线程并行读取。
# mx.image import mxnet as mx N = 1000 tic = time.time() for i in range(N): img = mx.image.imdecode(open('../data/train/cat.123.jpg','rb').read()) mx.nd.waitall() print(N/(time.time()-tic), 'images decoded per second with mx.image') imshow(img.asnumpy())
3104.49234140315 images decoded per second with mx.image
直接爆炸!
这个读出来可是实打实的numpy.array()格式,性能直接提升五倍。在之前做了解释,MXNet是对读取的二进制文件做了opencv的解码,同时加入了自动多线程功能,所以速度真的飞起,真材实料的黑科技啊!
说点远的
实际上可以发现,各深度学习框架都有自己独特的数据读取方式,比如TensorFlow也同样加入了queue读取文件,也通过解码的方式提高效率;再比如各框架为了提高效率都开始采用一定的数据结构格式文件:keras的h5、TensorFlow的tfrecord、MXNet的rec,甚至早起caffe的IMDB格式等。