ZLIB 在压缩和解压后返回不同的字节值

问题描述 投票:0回答:2

我有一个 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) 的数组

我做错了什么?如何获取原始图像?

compression gzip zlib lossless-compression nifti
2个回答
0
投票

我无法重现您所描述的行为。不过,我可以观察到一些问题。

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 。只有当您感到满意后,您才应该在混音中添加压缩。


0
投票

如果你看一下

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可以压缩到默认值。)

© www.soinside.com 2019 - 2024. All rights reserved.