如何使用 pypng 将 Raspberry Pi 原始 10 位图像保存为 16 位 PNG

在我们的上一篇文章如何在 Python 中捕获 RaspberryPi 相机 10 位原始图像中,我们展示了如何使用 picamera Python 库捕获原始 10 位图像数据。

PNG 图像格式支持存储 16 位图像数据。此文章展示如何使用我们在上一篇文章中生成的 NumPy 数组来实现。我们使用 pypng 库。

save_10bit_to_16bit_png.py
with open('16bit.png', 'wb') as outfile:
    writer = png.Writer(width=rawimg.shape[1], height=rawimg.shape[0], bitdepth=16, greyscale=False)
    # rawimg 是 (w, h, 3) RGB uint16 数组
    # 但 PyPNG 需要 (w, h*3) 数组
    png_data = np.reshape(rawimg, (-1, rawimg.shape[1]*3))
    # 将 10 位数据缩放为 16 位值(否则会显示为黑色)
    # 注意:根据你的照片和设置,
    #  它可能仍然显得相当暗!
    png_data *= int(2**6)
    writer.write(outfile, png_data)

注意生成的 PNG 大小约为 9.9 MB,在我的 Raspberry Pi 3 上使用 pypng 保存图像大约需要 27 秒!

作为比较,原始 NumPy 数据约为 29 MB,而压缩 NumPy 数据为 9.3 MB,

因此如果你使用 PNG 的动机是节省空间,使用 NumPy 压缩数据可能更好,特别是如果你需要快速连续保存许多相机帧因此受限。

如果你需要使用 PNG,你可能想查看 Pypy,因为 pypng 是纯 Python 库,因此可能受益于 Pypy 提高的执行速度。但是,实际上,**pypy3 慢了 10 倍以上。**请阅读我们在在 Raspberry Pi 上使用 pypy 的 pypng 16 位 PNG 编码更快吗?上的详细分析

完整示例:

save_10bit_full_example.py
#!/usr/bin/env python3
import picamera
import picamera.array
import numpy as np
import png

# 捕获图像
print("正在捕获图像...")
with picamera.PiCamera() as camera:
    with picamera.array.PiBayerArray(camera) as stream:
        camera.capture(stream, 'jpeg', bayer=True)
        # 去马赛克数据并写入 rawimg
        # (stream.array 包含未去马赛克的数据)
        rawimg = stream.demosaic()

# 写入 PNG
print("正在写入 16 位 PNG...")
with open('16bit.png', 'wb') as outfile:
    writer = png.Writer(width=rawimg.shape[1], height=rawimg.shape[0], bitdepth=16, greyscale=False)
    # rawimg 是 (w, h, 3) RGB uint16 数组
    # 但 PyPNG 需要 (w, h*3) 数组
    png_data = np.reshape(rawimg, (-1, rawimg.shape[1]*3))
    # 将 10 位数据缩放为 16 位值(否则会显示为黑色)
    # 注意:根据你的照片和设置,
    #  它可能仍然显得相当暗!
    png_data *= int(2**6)
    writer.write(outfile, png_data)

Check out similar posts by category: Raspberry Pi