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