使用CV2读取图像速度太慢

3

我有6000张300*300像素的图片,当我在Python中读取这些图片时,遇到了时间问题。 我需要将所有的图片收集到一个列表中,以便我可以用它们来训练模型。 所以我写了一个for循环,读取每个图片,并将其附加到X中,如下面的代码:

train_img=sorted(list(paths.list_images("path")))
X=[]
y=[]
for img in train_img:
    X.append(cv2.imread(img))
    y.append(img.split(os.path.sep)[6])

但它非常慢!每次我想处理这些数据的时候,都需要花费大量时间将所有图像收集到一个列表中!

那么,你能给我一些关于我的问题的建议或推荐吗?还有,是否有比Open-CV读取图像更快的包?


读取图像文件取决于文件的格式。你有哪些图像文件格式?你尝试过哪些格式?你愿意将数据存储为未压缩的TIFF或BMP吗? - Christoph Rackwitz
你可以将列表X进行序列化,这样下次读取时速度会更快。 - Cris Luengo
选取操作相当于将图像文件重新保存为位图/TIFF格式。 - Christoph Rackwitz
你没有提及图片在磁盘上存储的格式,也没有说明它们是8/16位还是32位。另外也没有说明图片是彩色的还是灰度的,也没有说明你使用的操作系统是什么。同时,也没说明目前读取这些图片需要多长时间,你拥有多少个 CPU 核心,以及是否使用了 turbo-jpeg 库。此外,你还没有提到你使用的是什么类型的硬盘和文件系统。 - Mark Setchell
或许也可以安装固态硬盘。 - fmw42
3个回答

1

这里有一篇不错的读取方式的比较基准在这里。根据比较,pyvipsPIL是值得考虑的好选择。

例如,

from PIL import Image
import numpy as np
...
im = np.asarray(Image.open(f))
...

此外,正如评论中建议的那样,考虑使用其他格式来存储图像可能会很有用。我猜TIFF或BMP可能会起作用。

2
内存预分配是一种微观优化。这里的时间成本是由文件格式引起的。 - Christoph Rackwitz
同意。我已经把它加到答案中了。 - user1635327

0

这个任务可能是I/O绑定的。尝试使用concurrent.futures并行/异步读取图像。如果文件存储在慢速媒体上,例如网络共享,请使用大量线程(例如32个),否则请使用较少的线程(约等于CPU数量)。

from concurrent.futures import ThreadPoolExecutor

with ThreadPoolExecutor(max_workers=32) as executor:
    X = list(executor.map(cv2.imread, train_img))

针对更复杂的用例,可以考虑使用daskdask-image


0

保存和加载压缩图像格式总是比读取未压缩格式需要更多时间。

您没有说明您使用的是JPEG还是PNG,它们都是压缩格式,或者是BMP,它是未压缩的。TIFF可以是压缩或未压缩的(它可以包含JPEG数据)。

您应该将数据转换为未压缩格式。这将占用更多的磁盘空间。某些特定格式的BMP或TIFF甚至可以进行“内存映射”,因此不需要太多RAM,无论大小如何。

我不建议“腌制”您的数据。这只是图像数据,而不是任意/通用数据。它应该以典型的图像文件格式存储。

您可以选择以下库:

还可以看看pyvips,它似乎是libvips的一个包装器。我没有使用过它,但另一个答案指出了它。


1
保存和加载压缩图像格式并不总是会增加成本。在某些情况下,使用压缩反而会加快速度,比如当从磁盘(或通过NFS远程磁盘)读取速度成为瓶颈而不是CPU时。 - undefined
1
明白了。单纯的吞吐量可能会成为瓶颈...而且理想情况下,如果其他一切都能够达到最佳状态(包括压缩),它应该成为瓶颈。如果存储数据未经压缩会显著增大,这是一个需要更加谨慎考虑的权衡。-- 存储类型确实会影响所花费的时间。存储的另一个问题可能是大量的文件。在硬盘驱动器上寻找、在操作系统/文件系统驱动程序中进行处理,甚至像病毒扫描器这样的安全措施,可能会导致每次打开文件时额外的成本,有时无论文件的大小如何。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接