Acquiring 10/12 bit RGB images from a JAI AP-3200T-PGE

Hi again - i managed to decode the image data with help from JAI support, sharing the code for anyone interested here.
The RGB12V1Packed stores the three 12 bits color components in 4.5 bytes:

The following python code seems to do the trick:

import cvb # to prevent watermark in image
from harvesters.core import Harvester
import numpy as np 
import cv2


h = Harvester()
h.add_file("C:/Program Files/STEMMER IMAGING/Common Vision Blox/GenICam/bin/win64_x64/TLIs/GEVTL.cti")
h.update()

ia = h.create_image_acquirer(0)
pixelformat = "RGB12V1Packed"
width = 1280
height = 800
ia.remote_device.node_map.PixelFormat.value = pixelformat
ia.remote_device.node_map.Width.value = width
ia.remote_device.node_map.Height.value = height
ia.start_acquisition()


with ia.fetch_buffer() as buffer: 
    if buffer.payload.components[0] is None:
        buffer_raw = buffer._buffer.raw_buffer
        if pixelformat == "RGB10p32":
            # buffer is a byte array of <H>x<W>x4 8-bit bytes, where each 4 bytes represent 3 10-bit RGB pixels
            # bit 0:9 is red, 10:19 green and 20:29 blue, the last two bits being spare and always 0.
            bit_depth = 10
            clearing_byte = np.uint16(0b0000001111111111)
            buffer_int = np.frombuffer(buffer_raw, dtype=np.uint32)
            R = np.uint16(buffer_int) & clearing_byte
            G = np.uint16(buffer_int >> 10) & clearing_byte
            B = np.uint16(buffer_int >> 20) & clearing_byte

        elif pixelformat == "RGB12V1Packed":
            # information stored in 12 x 3 = 36 or 4.5 bytes. 
            bit_depth = 12
            clearing_byte = np.uint16(0b0000111111111111)
            clearing_byte_4 = np.uint16(0b0000000000001111)
            
            # inpack into 8-bit integer array
            buffer_int = np.uint16(np.frombuffer(buffer_raw, dtype=np.uint8))

            # unpack red, green and blue channels. Bit pattern repeats every 9 bytes, which contain two pixels.
            unpack_1 = lambda buff, b1, b2: ((buff[b1:buff.shape[0]:9] << 4) | (buff[b2:buff.shape[0]:9] & clearing_byte_4)) & clearing_byte
            unpack_2 = lambda buff, b1, b2: ((buff[b1:buff.shape[0]:9] >> 4) | (buff[b2:buff.shape[0]:9] << 4)) & clearing_byte

            R1 = unpack_1(buffer_int, 0, 1) # byte 0 has last 8 bits of red1, byte 1 first 4.
            R2 = unpack_2(buffer_int, 4, 5) # byte 4 has first 4 bits of red2, byte 5 last 8
            R = np.c_[R1, R2].reshape(R1.shape[0] + R2.shape[0])

            G1 = unpack_2(buffer_int, 1, 2) # byte 1 has first 4 bits of green2, byte 2 last 8
            G2 = unpack_1(buffer_int, 6, 7) # byte 6 has last 8 bits of red1, byte 7 first 4.
            G = np.c_[G1, G2].reshape(G1.shape[0] + G2.shape[0])

            B1 = unpack_1(buffer_int, 3, 4) # byte 3 has last 8 bits of blue1, byte 1 first 4.
            B2 = unpack_2(buffer_int, 7, 8) # byte 4 has first 4 bits of red2, byte 5 last 8
            B = np.c_[B1, B2].reshape(B1.shape[0] + B2.shape[0])


        img_data = np.c_[R, G, B]
    else:
        img_data = buffer.payload.components[0].data

# reshape and rescale as 16 bit integer array
img = np.uint16((2 ** 16 - 1) * (img_data.reshape(height, width, 3) / (2 ** bit_depth - 1)))
cv2.imshow("image", img)
cv2.waitKey()

ia.destroy()
h.reset()

Kind regards,

Jesper

3 Likes