图片读取速度测试及加速
机器学习深度学习的发展意味着大批量的读取数据变得越来越多,读取速度也强调越来越快,本着研究一下各框架的读取速度进行测试一下,然后分享出来。电脑环境是i7-8700 + 16G内存 + GTX1060配置。
1、各类python包读取图片接口测试
import cv2, glob
import time
from scipy.misc import imread as scipy_imread
from skimage import io
from PIL import Image
import numpy as np
from keras.preprocessing import image as keras_imread
import mxnet as mx # mx.image
def ReadImage_SpeedTest():
image_path = './Test_Image/image_1_1000_750.jpg'
# image_path = './Test_Image/image_2_4608_3456.jpg'
readTimes = 100
img = cv2.imread(image_path)
print("图像大小高*宽: {} * {}: ".format(img.shape[0], img.shape[1]))
## OpenCV 读取图片
time1 = time.time()
for i in range(readTimes):
img_opencv = cv2.imread(image_path)
print("OpenCV读取图片速度:", round(readTimes / (time.time() - time1), 2), " 张图片每秒(files/sec)")
## scipy 读取图片
time1 = time.time()
for i in range(readTimes):
img_scipy = scipy_imread(image_path)
print("scipy读取图片速度:", round(readTimes / (time.time() - time1), 2), " 张图片每秒(files/sec)")
## skimage 读取图片
time1 = time.time()
for i in range(readTimes):
img_skimage = io.imread(image_path)
print("skimage读取图片速度:", round(readTimes / (time.time() - time1), 2), " 张图片每秒(files/sec)")
## PIL 读取图片
time1 = time.time()
for i in range(readTimes):
img = Image.open(image_path) ## img是Image内部的类文件,还需转换
# img_PIL = np.array(img) ## numpy转换
print("PIL 读取图片速度:", round(readTimes / (time.time() - time1), 2), " 张图片每秒(files/sec)")
## keras 读取图片
time1 = time.time()
for i in range(readTimes):
img = keras_imread.load_img(image_path)
img_keras = keras_imread.img_to_array(img)
print("keras 读取图片速度:", round(readTimes / (time.time() - time1), 2), " 张图片每秒(files/sec)")
## mxnet 读取图片
time1 = time.time()
for i in range(readTimes):
# img_mxnet = mx.image.imdecode(open(image_path,'rb').read())
img_mxnet = mx.image.imread(image_path)
mx.nd.waitall()
print("mxnet 读取图片速度:", round(readTimes / (time.time() - time1), 2), " 张图片每秒(files/sec)")
测试结果:
输入图片是高*宽为750 * 1000时 :
OpenCV读取图片速度: 118.8 张图片每秒(files/sec)
scipy读取图片速度: 92.08 张图片每秒(files/sec)
skimage读取图片速度: 92.93 张图片每秒(files/sec)
PIL 读取图片速度: 93.36 张图片每秒(files/sec)
PIL 读取图片速度: 6265.02 张图片每秒(files/sec)(不转换numpy)
keras 读取图片速度: 73.4 张图片每秒(files/sec)
mxnet 读取图片速度: 95.83 张图片每秒(files/sec)
图像大小高*宽: 3456 * 4608 :
OpenCV读取图片速度: 6.67 张图片每秒(files/sec)
scipy读取图片速度: 4.47 张图片每秒(files/sec)
skimage读取图片速度: 4.52 张图片每秒(files/sec)
PIL 读取图片速度: 4.54 张图片每秒(files/sec)(转换numpy)
PIL 读取图片速度: 4262.03 张图片每秒(files/sec)(不转换numpy)
keras 读取图片速度: 3.49 张图片每秒(files/sec)
**mxnet 读取图片速度: 5.44 张图片每秒(files/sec)
可以看到,不管多大图片,在正常读取为numpy格式后,仍然是OpenCV快。但PIL若只读取图片,只执行:
img = Image.open(image_path)
简直飞快,此时的img是Image内部的类文件,需要做相应的np.array()转换才可以进行图像操作。但这样有一个好处就是,在进行批量图像生成或增强的时候,可以查看自己得到的图片是否完全正确,仅仅通过open就可以验证了,而不需要每一张图片都读取出来。
2、通过多核进行加速读取
说完以上的读取速度,我们尝试着再快一些。首先,Python 程序是使用单 CPU 核心单个进程执行,但当前大部分设备cpu都是多核,比如i7-8700就是六核,我们可以考虑多核加速。即通过使用 Python 的 concurrent.futures 模块。
常规的读取批量数据都是以for循环开始,然后对每个文件进行处理至结束。如下代码:
image_path = 'H:\\DataSet'
#单独for循环 依次读取
start_time = time.time()
for image_filename in glob.glob(image_path + '\\*.jpg'):
img = cv2.imread(image_filename)
# img = cv2.resize(img, (600, 600))
print('for 循环 time:', round(time.time() - start_time, 2), " 秒")
得到的运行时间:
接下来利用concurrent.futures 模块多核处理,在我们图像列表中,可以让 Python 做类似的工作:
- 将 jpg 文件列表分成 6 个小组;
- 运行 Python 解释器中的 6 个独立实例;
- 让 Python 的每个实例处理 6 个数据小组中的一个;
- 结合四个处理过程得到的结果得出最终结果列表。
代码改写如下:
import concurrent.futures
def load_and_resize(image_filename):
img = cv2.imread(image_filename)
# img = cv2.resize(img, (600, 600))
start_time1 = time.time()
with concurrent.futures.ProcessPoolExecutor() as executor: ## 默认为1
image_files = glob.glob(image_path + '\\*.jpg')
'''
executor.map() 将你想要运行的函数和列表作为输入,列表中的每个元素
都是我们函数的单个输入,由于我们有6个核,我们将同时处理该列表中的6个项目
'''
executor.map(load_and_resize, image_files)
print('多核并行加速后运行 time:', round(time.time() - start_time1, 2), " 秒")
测试结果:
700 张图片 : (分辨率从400×800到3578×2596不等)
for 循环 time: 23.57 秒
多核并行加速后运行 time: 5.55 秒
6888 张图片 : (分辨率从120×240到4541×2277不等)
for 循环 time: 258.27 秒
多核并行加速后运行 time: 41.49 秒
六核心CPU, 数据量越大基本就是加速到6倍,极大的加速了数据的读取过程。
3、参考
[1]:https://blog.csdn.net/twt520ly/article/details/79760379
[2]:https://zhuanlan.zhihu.com/p/30383580
[3]:https://blog.csdn.net/u012193416/article/details/87531272
[4]:https://blog.csdn.net/e01528/article/details/83148892