Raspberry Pi Raw 10-Bit-Bild als 16-Bit-PNG mit pypng speichern
In unserem vorherigen Beitrag How to capture RaspberryPi camera 10-bit raw image in Python haben wir gezeigt, wie du die picamera-Python-Bibliothek verwenden kannst, um rohe 10-Bit-Bilddaten zu erfassen.
Das PNG-Bildformat unterstützt das Speichern von 16-Bit-Bilddaten. Dieser Beitrag zeigt dir, wie du das mit den NumPy-Arrays machst, die wir in unserem vorherigen Beitrag erzeugt haben. Wir verwenden die pypng-Bibliothek.
with open('16bit.png', 'wb') as outfile:
writer = png.Writer(width=rawimg.shape[1], height=rawimg.shape[0], bitdepth=16, greyscale=False)
# rawimg ist ein (w, h, 3) RGB uint16-Array
# aber PyPNG benötigt ein (w, h*3) Array
png_data = np.reshape(rawimg, (-1, rawimg.shape[1]*3))
# 10-Bit-Daten auf 16-Bit-Werte skalieren (sonst erscheint es schwarz)
# HINWEIS: Je nach Foto und Einstellungen
# kann es immer noch recht dunkel erscheinen!
png_data *= int(2**6)
writer.write(outfile, png_data)Beachte, dass die resultierenden PNGs ca. 9,9 Megabyte groß sind und das Speichern mit pypng auf meinem Raspberry Pi 3 etwa 27 Sekunden dauert!
Zum Vergleich: Die rohen NumPy-Daten sind ca. 29 Megabyte, während die komprimierten NumPy-Daten 9,3 Megabyte sind.
- Rohe NumPy-Daten (
np.save): 29 Megabyte, dauert 0,11 Sekunden zum Speichern. - Komprimierte NumPy-Daten (
np.savez_compressed): 9,3 Megabyte, dauert 12 Sekunden zum Speichern.
Wenn deine Motivation für die Verwendung von PNG also Platzersparnis ist, bist du möglicherweise besser mit komprimierten NumPy-Daten bedient, besonders wenn du viele Kamera-Frames in schneller Folge speichern musst und daher limitiert bist.
Falls du PNGs verwenden musst, könntest du Pypy ausprobieren, da pypng eine reine Python-Bibliothek ist und daher von Pypys erhöhter Ausführungsgeschwindigkeit profitieren könnte. In der Praxis ist pypy3 jedoch mehr als 10x langsamer. Bitte lies unsere detaillierte Analyse unter Is pypng 16-bit PNG encoding faster using pypy on the Raspberry Pi?
Vollständiges Beispiel:
#!/usr/bin/env python3
import picamera
import picamera.array
import numpy as np
import png
# Bild erfassen
print("Capturing image...")
with picamera.PiCamera() as camera:
with picamera.array.PiBayerArray(camera) as stream:
camera.capture(stream, 'jpeg', bayer=True)
# Daten demosaicing und in rawimg schreiben
# (stream.array enthält die nicht-demosaiced-Daten)
rawimg = stream.demosaic()
# In PNG schreiben
print("Writing 16-bit PNG...")
with open('16bit.png', 'wb') as outfile:
writer = png.Writer(width=rawimg.shape[1], height=rawimg.shape[0], bitdepth=16, greyscale=False)
# rawimg ist ein (w, h, 3) RGB uint16-Array
# aber PyPNG benötigt ein (w, h*3) Array
png_data = np.reshape(rawimg, (-1, rawimg.shape[1]*3))
# 10-Bit-Daten auf 16-Bit-Werte skalieren (sonst erscheint es schwarz)
# HINWEIS: Je nach Foto und Einstellungen
# kann es immer noch recht dunkel erscheinen!
png_data *= int(2**6)
writer.write(outfile, png_data)