内存中numpy数组(image,uint8)的有损压缩

2024-04-16 07:11:58 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试将一组包含1000.000个图像的数据集加载到内存中。作为标准的numpy数组(uint8),所有的图像组合起来占用大约100gb的RAM,但是我需要将其降低到<;50gb,同时仍然能够快速地将图像读回numpy(这是将所有内容都保存在内存中的关键)。像blosc这样的无损压缩只会将文件大小减少10%左右,所以我选择了JPEG压缩。最小示例:

import io
from PIL import Image

numpy_array = (255 * np.random.rand(256, 256, 3)).astype(np.uint8)
image = Image.fromarray(numpy_array)
output = io.BytesIO()
image.save(output, format='JPEG')

在运行时,我正在阅读图像:

^{pr2}$

JPEG压缩非常有效(<;10GB),但是将1000张图像读回numpy数组所需的时间大约为2.3秒,这严重影响了我的实验性能。我正在寻找在压缩和读取速度之间进行更好权衡的建议。在


Tags: 数据内存io图像imageimportltnumpy
1条回答
网友
1楼 · 发布于 2024-04-16 07:11:58

我仍然不确定我是否理解您要做的,但我创建了一些虚拟图像,并进行了以下测试。我将展示我是如何做到这一点的,以防其他人想尝试其他方法并想要一个数据集。在

首先,我使用GNU ParallelImageMagick创建了1000个图像,如下所示:

parallel convert -depth 8 -size 256x256 xc:red +noise random -fill white -gravity center -pointsize 72 -annotate 0 "{}" -alpha off s_{}.png ::: {0..999}

这给了我1000张图片,名为s_0.pngs_999.png,图像663如下所示:

enter image description here

然后我做了我认为你想做的事情——尽管从你的代码中很难看出:

^{pr2}$

从BytesIO对象读取所有1000个图像并将它们转换成numpy数组需要2.4秒。在

然后,我将图像减少到256种颜色(我同意这是有损的-就像您的方法一样),并保存了一个调色板图像对象的列表,稍后我可以通过调用以下命令将这些对象转换回numpy数组:

np.array(ImageList[i].convert('RGB'))

将数据存储为调色板图像可节省66%的空间,因为每个像素只存储一个字节的调色板索引,而不是3个字节的RGB,因此它比您所寻求的50%压缩要好。在

#!/usr/local/bin/python3

import io
import time
import numpy as np
from PIL import Image

# Empty list of images
ImageList = []

# Load all 1,000 images 
for i in range(1000):
   name="s_{}.png".format(i)
   print("Opening image: {}".format(name))
   im = Image.open(name)
   # Add palettised image to list
   ImageList.append(im.quantize(colors=256, method=2))

# Read back images into numpy arrays
start=time.clock()
l=[np.array(ImageList[i].convert('RGB')) for i in range(1000)]
diff=time.clock()-start
print("Time: {}".format(diff))

# Quick test
# Image.fromarray(l[999]).save("result.png")

现在需要0.2秒而不是2.4秒-希望您的未声明应用程序可以接受丢失的颜色精度:-)

相关问题 更多 >