python - 如何在 Python 中加载图像,但保持压缩?
问题描述
我有一系列图像,在 JP2 和 PNG 上都可用,我需要在 python 程序上加载这个图像以按顺序显示它们。现在我只需要显示序列的一部分,例如:
加载所有图像会占用我太多的内存,并且每次新序列都是一项漫长的任务时加载。
有一个函数/方法可以在程序中加载图像,但保持压缩?我可以将这些图像保存在内存中以备使用,但内存占用率低吗?
解决方案
您可以将可爱的小型 JPEG/PNG/JP2 图像作为一堆字节读入内存,并将它们压缩到与磁盘上相同的大小,然后在需要时从内存中解压缩它们。
首先,让我们看看 RGB888 的 1280x1024 图像在内存中所需的内存 - 高达 3.9MB:
# Decompressed image in memory takes 3.9MB memory
im = np.zeros([1280,1024,3], dtype=np.uint8)
# print(im.nbytes) => 3932160
现在让我们看一个相同大小的JPEG:
这是在磁盘上,带有ls -l
:
-rw-r--r--@ 1 mark staff 47276 2 Apr 17:13 image.jpg
在这里,它仍然在内存中压缩,大小也为 47kB 或仅为 1.2%:
# Same image as JPEG takes 47kB of memory
with open('image.jpg','rb') as f:
jpg = f.read()
# print(len(jpg)) => 47276
现在当你想要一个图像时,从内存而不是磁盘解压缩它
# Read with 'imageio'
from io import BytesIO
import imageio
numpyArray = imageio.imread(BytesIO(jpg))
# print(numpyArray.shape) =>(1024, 1280, 3)
# Or, alternatively, and probably faster, read with OpenCV
import cv2
numpyArray = cv2.imdecode(np.frombuffer(jpg,dtype=np.uint8), -1)
# print(numpyArray.shape) =>(1024, 1280, 3)
另一个完全不同的选择是对图像进行调色,它可以更快地解码英里,但只会将内存占用减少 3 倍。您将颜色数量减少到少于 256 种独特颜色,并存储具有 256 种颜色的调色板。然后在每个像素位置存储一个字节,它是调色板的索引,而不是 RGB 的 3 个字节。这会将您的内存使用量从 3.9MB/图像减少到 1.3MB/图像。它不需要任何解码。但可能会导致色彩保真度和/或条纹的轻微损失——这可能是也可能不是问题,具体取决于您的相机/图像的质量。
看起来像这样:
from PIL import Image
import numpy as np
im = Image.open('image.jpg')
# Make into Numpy array - size is 3.9MB
a = np.array(im)
# Now make a 256 colour palletised version
p = im.convert('P',palette=Image.ADAPTIVE)
# Make into Numpy array - size is now only 1.3MB
a = np.array(p)
推荐阅读
- android - 未来
在 Flutter 中转为 Base64 或 PNG - html - HTML – 在多个框架中选择多个文本
- javascript - Js调用带参数的函数
- react-native - onScroll 不是 useNatveDriver 和 ScrollView 的函数错误
- android - Android app虚拟内存空间布局问题
- flutter - 如何正确地将文本换行到新行?
- javascript - 如何创建一个打开页面并在其中显示隐藏 div 的链接?
- google-bigquery - BigQuery:在复制数据集时包含过程
- c# - 如何在 C# Entity Framework Core 中使用类作为字段的类的构造函数?
- php - 已弃用:必需参数 $to_addr 遵循可选参数