如何用Python+Numpy+CV2将二进制文件转为4bpp(16级灰度)图像?
问题描述
我希望将二进制数据表示为黑白图像,每个像素仅使用16种灰度等级(即4bpp,每像素4比特),且每两个相邻像素(横向)代表一个字节。目前我使用如下代码将二进制文件转为PNG序列,每个20×20像素块代表一个字节,但该方式生成的图像有256种灰度,不符合需求。请问如何修改代码,将每个字节拆分为两个4bpp像素,同时保持图像分辨率不变?采用4bpp后,由于每个字节需用两个像素表示,图像文件数量应翻倍。
原代码:
import numpy as np path = r'mybinaryfile.bin' bin_data = np.fromfile(path, dtype='uint8') scalar = 20 width = int(1800/scalar) height = int(1000/scalar) for jj in range(50): wid = int(width*height) img = bin_data[int(jj*wid):int((jj+1)*wid)].reshape(height,width) final_img = cv2.resize(img, (scalar*width, scalar*height), interpolation = cv2.INTER_NEAREST) fn = f'tmp/output_{jj}.png' cv2.imwrite(fn, final_img)
修改后的代码
import numpy as np import cv2 path = r'mybinaryfile.bin' bin_data = np.fromfile(path, dtype='uint8') scalar = 20 original_width = int(1800 / scalar) height = int(1000 / scalar) # 每个图像承载的字节数减半(每个字节用两个像素表示) bytes_per_image = original_width * height // 2 # 计算实际需要生成的图像总数 total_images = len(bin_data) // bytes_per_image for jj in range(total_images): # 截取当前图像对应的字节块 byte_block = bin_data[jj * bytes_per_image : (jj + 1) * bytes_per_image] # 将每个字节拆分为高4位和低4位,得到两组4bpp像素数据 pixels_high = (byte_block >> 4).astype(np.uint8) pixels_low = (byte_block & 0x0F).astype(np.uint8) # 交错合并两组像素:[字节1高4位, 字节1低4位, 字节2高4位, 字节2低4位,...] interleaved_pixels = np.stack([pixels_high, pixels_low], axis=1).flatten() # 重塑为原高度、宽度翻倍的图像矩阵 img = interleaved_pixels.reshape(height, original_width * 2) # 放大到目标分辨率1800x1000,用近邻插值避免灰度失真 final_img = cv2.resize(img, (1800, 1000), interpolation=cv2.INTER_NEAREST) # 保存图像 fn = f'tmp/output_{jj}.png' cv2.imwrite(fn, final_img)
关键修改说明
- 拆分字节为4bpp像素:通过位运算把每个uint8字节拆成高4位(
byte >> 4)和低4位(byte & 0x0F),每个字节对应两个仅含16种灰度(0-15)的像素。 - 调整图像承载量:原代码每张图承载
original_width*height个字节,现在每个字节占两个像素,因此每张图的字节数减半,图像总数自动翻倍。 - 保持输出分辨率:重塑图像时把宽度翻倍,再通过
cv2.resize放大到原有的1800x1000分辨率,确保输出尺寸不变。 - 严格控制灰度等级:拆分后的像素值范围固定为0-15,完全符合4bpp的16级灰度要求。
内容的提问来源于stack exchange,提问作者EllipticalInitial
相关产品推荐
相关产品推荐

