ZLIB压缩解压后返回不同字节值,3D ndarray解压形状异常如何解决?
问题分析与修复方案
问题根因
- 压缩环节输入处理错误:若
nii_img1_data为原始3D numpy数组,直接对数组切片压缩得到的是numpy数组对象序列化数据而非原始二进制流;且len(nii_img1_data)返回的是数组第一维长度90,并非总元素对应的字节长度,压缩的源数据本身就存在错误。 - 解压环节API调用逻辑错误:你创建了
decompressobj对象但未实际使用它执行解压,而是直接调用了全局zlib.decompress方法,后续调用该对象的flush()不仅无效,还会将多余空字节追加到解压结果中,刚好符合你遇到的字节数膨胀8倍的现象。 - 数据类型不匹配风险:解压后你强制用
dtype=np.int8解析字节流,若原始数组的实际dtype不是int8(比如为int16、float32等),会直接导致解析出的元素数、数组形状完全不符。 - 压缩解压参数不匹配:如果压缩时创建
compressImageObject的wbits参数和解压时的wbits=+15不一致,也会引发解压失败、数据异常。
正确实现代码
压缩环节
import zlib import numpy as np # nii_img1_data为原始3D数组,形状(90,104,72) # 先将numpy数组转为原始二进制字节流 raw_bytes = nii_img1_data.tobytes() blockSize = 1024 # 压缩参数和解压保持一致,wbits=+15对应默认zlib格式 compress_obj = zlib.compressobj(wbits=+15) compressed_data = b'' begin = 0 while begin < len(raw_bytes): compressed_data += compress_obj.compress(raw_bytes[begin:begin+blockSize]) begin += blockSize compressed_data += compress_obj.flush() # 写入压缩文件 with open('compressed.dat', 'wb') as f: f.write(compressed_data) # 存储原始数组的元信息,用于后续解压还原,可根据需求选择存储方式 with open('array_meta.txt', 'w') as f: f.write(f"{nii_img1_data.shape[0]},{nii_img1_data.shape[1]},{nii_img1_data.shape[2]}\n{str(nii_img1_data.dtype)}")
解压环节
import zlib import numpy as np blockSize = 1024 # 读取原始数组元信息 with open('array_meta.txt', 'r') as f: shape_str, dtype_str = f.read().strip().split('\n') original_shape = tuple(map(int, shape_str.split(','))) original_dtype = np.dtype(dtype_str) # 读取压缩文件 with open('compressed.dat', 'rb') as f: compressed_data = f.read() # 用创建的decompressobj对象执行解压 decompress_obj = zlib.decompressobj(wbits=+15) decompressed_bytes = decompress_obj.decompress(compressed_data) decompressed_bytes += decompress_obj.flush() # 还原为原始形状的numpy数组 decompressed_arr = np.frombuffer(decompressed_bytes, dtype=original_dtype) decompressed_arr = decompressed_arr.reshape(original_shape)
验证方法
执行print(np.array_equal(nii_img1_data, decompressed_arr)),返回True即说明解压还原完全正确。
内容的提问来源于stack exchange,提问作者theNinthElement
相关产品推荐
相关产品推荐

