我有一个 3d ndarray,我想使用 Zlib 解压缩。 我用这部分代码来压缩。
begin = 0
blockSize = 1024
compressImage = bytes('', 'utf-8')
while begin < len (nii_img1_data):
compressImage = compressImage +
compressImageObject.compress(nii_img1_data[begin:begin+blockSize])
begin += blockSize
compressImage = compressImage + compressImageObject.flush()
f = open('compressed.dat', 'wb')
f.write(compressImage)
f.close()
我的减压部分是
decompressedImageObject = zlib.decompressobj(wbits=+15)
my_file = open('compressed.dat', 'rb').read()
decompressedImage = zlib.decompress(my_file, bufsize=blockSize)
decompressedImage += decompressedImageObject.flush()
decompressedImage = np.frombuffer(decompressedImage, dtype=np.int8)
压缩之前,原始图像的形状为 (90, 104, 72)。 解压后,字节大小返回 5391360 字节,大于 9010472 = 673920 字节。
我将解压后的内容转换为 ndarray,使用
生成一维数组decompressedImage = np.frombuffer(decompressedImage, dtype=np.int8)
并尝试转换为与原始图像相同的形状
decompressedImage = np.reshape(decompressedImage, newshape=(-1,104,72))
返回形状 = (720,104,72) 的数组
我做错了什么?如何获取原始图像?
我无法重现您所描述的行为。不过,我可以观察到一些问题。
while begin < len (nii_img1_data):
compressImage = compressImage +
compressImageObject.compress(nii_img1_data[begin:begin+blockSize])
begin += blockSize
您指出
nii_img1_data
是一个维度为 (90,104,72) 的 ndarray。然而,这段代码似乎假设它是一个 bytes
对象或非常相似的东西。 len(nii_img1_data)
将返回第一个维度的大小,90。用 nii_img1_data[0:1024]
对它进行切片将返回整个内容,因为第一个维度的大小小于 1024。将切片提供给 zlib.Compress.compress
可以访问数组的底层缓冲区,即大小其中具体取决于您获取数组的方式,并且可能包含比数组本身更多的数据。我猜测在你的情况下nii_img1_data
是一个更大数组的切片,因为这可能解释接下来会发生什么。或者,它可能具有 np.int8
以外的 dtype?
一旦将此缓冲区提供给 zlib,循环似乎只运行一次,因为
len(nii_img1_data)
只有 90。当您解压缩时,您会重建缓冲区中的数据,但它不是您期望的数据。
我建议您确保首先将数组转换为字节或缓冲区,并且即使在尝试压缩或解压缩它之前,也要验证是否能够将这些字节转换回您期望的 ndarray 。只有当您感到满意后,您才应该在混音中添加压缩。
如果你看一下
zlib.compress()
的定义
def compress(*args, **kwargs): # real signature unknown
"""
Returns a bytes object containing compressed data.
data
Binary data to be compressed.
level
Compression level, in 0-9 or -1.
"""
pass
如果你用 zlib 解压,你会看到有 10 种不同的压缩级别,如果你想返回,你必须匹配压缩。
zlib.compress( zlib.decompress(byte_data), -1 ) == byte_data # False
zlib.compress( zlib.decompress(byte_data), 0 ) == byte_data # False
zlib.compress( zlib.decompress(byte_data), 1 ) == byte_data # True
zlib.compress( zlib.decompress(byte_data), 2 ) == byte_data # False
zlib.compress( zlib.decompress(byte_data), 3 ) == byte_data # False
# etc..
您将能够通过这种方式找到默认字节数据的压缩级别。 (如果zlib可以压缩到默认值。)