使用CV2读取6000张300*300图片速度过慢,求优化方案及更快的读图库
图片读取性能优化方案
现有代码直接优化点
- 预分配列表空间,避免动态扩容开销:你当前用
append方法动态扩展列表,Python列表每次扩容都需要重新申请内存并复制旧数据,6000次操作的累计开销很高。可以提前初始化固定长度的列表,用索引直接赋值,示例如下:
train_img = sorted(list(paths.list_images("path"))) data_len = len(train_img) # 提前分配固定大小空间 X = [None] * data_len y = [None] * data_len for idx, img_path in enumerate(train_img): # 明确指定读取三通道,避免自动判断开销 X[idx] = cv2.imread(img_path, cv2.IMREAD_COLOR) y[idx] = img_path.split(os.path.sep)[6]
- 避免多余格式转换:
cv2.imread默认返回BGR格式数组,如果你的模型需要RGB格式,不要单独调用cv2.cvtColor转换,可以更换读取库直接返回RGB格式,减少一次数组遍历开销。
比OpenCV更快的图片读取库
- TurboJPEG:专门针对JPG格式做了硬件指令级优化,是目前Python生态中读取JPG速度最快的库,相同场景下速度比OpenCV高30%~100%,适合数据集全为JPG的场景,使用示例:
from turbojpeg import TurboJPEG # 全局初始化一次即可,不要放在循环内 jpeg = TurboJPEG() for idx, img_path in enumerate(train_img): with open(img_path, 'rb') as f: # 直接返回RGB格式数组,无需额外转码 X[idx] = jpeg.decode(f.read()) y[idx] = img_path.split(os.path.sep)[6]
- Pillow-SIMD:普通Pillow库的SIMD指令优化版本,兼容Pillow所有接口,支持JPG、PNG等多种格式,读取速度比OpenCV高20%~60%,x86架构下适配性更好。
- 框架自带读取接口:如果你用PyTorch/TensorFlow训练模型,可以直接用
torchvision.io.read_image/tf.io.decode_jpeg,读取后直接返回框架张量,省去Numpy数组转张量的额外开销。
进阶优化方案
- 并行读取:图片读取是IO密集型操作,单线程循环会被磁盘IO阻塞,你可以用多线程并行读取,开816个线程就能把磁盘带宽占满,速度提升38倍,示例如下:
from concurrent.futures import ThreadPoolExecutor def read_single_img(img_path): with open(img_path, 'rb') as f: img = jpeg.decode(f.read()) label = img_path.split(os.path.sep)[6] return img, label # 线程数根据你的磁盘性能调整,一般8~16即可 with ThreadPoolExecutor(max_workers=12) as executor: res = list(executor.map(read_single_img, train_img)) X, y = zip(*res) X = list(X) y = list(y)
- 预转二进制数据集:如果需要反复读取这批数据,可以第一次读取后把整个数据集序列化为
pkl文件,或者存为LMDB、TFRecord等打包二进制格式,下次加载时直接读单个大文件,避免逐个读取小文件的IO开销,加载速度可以提升10倍以上。 - 内存缓存:如果你的机器内存足够,第一次加载完数据集后直接缓存到内存中,后续训练无需重复读取。
内容的提问来源于stack exchange,提问作者Robben Esh
相关产品推荐
相关产品推荐

