raspberry-pipicamera

Why does picamera2 capture_array('raw') method call returns an uint8 array


I try to get raw bayer data from the camera module 3 on a raspberry pi 5 using picamera2 python module.

I am experimenting with some code derived from the raw.py example (https://github.com/raspberrypi/picamera ... les/raw.py).

To my surprise, the call

picam2.capture_array("raw") 

returns a numpy ndarray with dtype uint8.

I expect the data to be uint16. It seems that the upper 4 bit of each pixel are truncated. Here is the code I am using:

import time

from picamera2 import Picamera2, Preview

picam2 = Picamera2()
#picam2.start_preview(Preview.QTGL)

config = picam2.create_still_configuration()

print(config)
print()

picam2.configure(config)

picam2.start()
time.sleep(2)

raw = picam2.capture_array("raw")

print(picam2.stream_configuration("raw"))
print()

print(raw.dtype)

It creates in the following output:

{'use_case': 'still', 'transform': <libcamera.Transform 'identity'>, 'colour_space': <libcamera.ColorSpace 'sYCC'>, 'buffer_count': 1, 'queue': True, 'main': {'format': 'BGR888', 'size': (4056, 3040)}, 'lores': None, 'raw': {'format': 'SRGGB12_CSI2P', 'size': (4056, 3040)}, 'controls': {'NoiseReductionMode': <NoiseReductionModeEnum.HighQuality: 2>, 'FrameDurationLimits': (100, 1000000000)}, 'sensor': {}, 'display': None, 'encode': None}

{'format': 'BGGR16_PISP_COMP1', 'size': (4056, 3040), 'stride': 4096, 'framesize': 12451840}

uint8

As you see, the stream configuration format is described as 'BGGR16_PISP_COMP1', however, the dtype of the returned numpy array is uint8.

I wonder, what to do, to get the data with the full color depth of 12 bit?.


Solution

  • With help from sandyol from the Raspberry Pi forum I could solve the issue.

    The following shows how to get raw bayer data in full 12 bit color depth from raspberry-pi hq-camera module.

    import time
    import numpy as np
    
    from picamera2 import Picamera2, Preview
    from matplotlib import pyplot as plt
    
    tuning = Picamera2.load_tuning_file("imx477_noir.json")
    picam2 = Picamera2(tuning=tuning)
    
    config = picam2.create_still_configuration(raw={'format': 'SBGGR12', 'size': (4056, 3040)})
    picam2.configure(config)
    print('Sensor configuration:', picam2.camera_configuration()['sensor'])
    print('Stream Configuration:', picam2.camera_configuration()['raw'])
    
    picam2.start()
    time.sleep(2)
    
    data8 = picam2.capture_array('raw')
    data16 = data8.view(np.uint16)
    plt.imshow(data16, cmap='gray')
    
    picam2.stop()
    

    Note: The image still is returned as an uint8-array with but with the shape (3040, 8128), which has to be casted to an uint16-array. This can be done with data16 = data8.view(np.uint16)