Camera raw output
This example shows how to use theraw
output from the Camera node. It also unpacks RAW10 (sensor) data into viewable OpenCV frame, and shows it in a window.Setup
This example requires the DepthAI v3 API, see installation instructions.Pipeline
Source code
Python
C++
Python
PythonGitHub
1#!/usr/bin/env python3
2
3import cv2
4import depthai as dai
5import numpy as np
6
7def unpackRaw10(rawData, width, height, stride=None):
8 """
9 Unpacks RAW10 data from DepthAI pipeline into a 16-bit grayscale array.
10 :param raw_data: List of raw bytes from DepthAI (1D numpy array)
11 :param width: Image width
12 :param height: Image height
13 :param stride: Row stride in bytes (if None, calculated as width*10/8)
14 :return: Unpacked 16-bit grayscale image with dimensions width×height
15 """
16 if stride is None:
17 stride = width * 10 // 8
18 expectedSize = stride * height
19
20 if len(rawData) < expectedSize:
21 raise ValueError(f"Data too small: {len(rawData)} bytes, expected {expectedSize}")
22
23 # Convert raw_data to numpy array
24 packedData = np.frombuffer(rawData, dtype=np.uint8)
25
26 # Process image row by row to handle stride correctly
27 result = np.zeros((height, width), dtype=np.uint16)
28
29 for row in range(height):
30 # Get row data using stride
31 rowStart = row * stride
32 rowData = packedData[rowStart:rowStart + stride]
33 # Calculate how many complete 5-byte groups we need for width pixels
34 numGroups = (width + 3) // 4 # Ceiling division
35 rowBytes = numGroups * 5
36 # Ensure we don't go beyond available data
37 if len(rowData) < rowBytes:
38 break
39
40 # Process only the bytes we need for this row
41 rowPacked = rowData[:rowBytes].reshape(-1, 5)
42 rowUnpacked = np.zeros((rowPacked.shape[0], 4), dtype=np.uint16)
43
44 # Extract 8 most significant bits
45 rowUnpacked[:, 0] = rowPacked[:, 0].astype(np.uint16) << 2
46 rowUnpacked[:, 1] = rowPacked[:, 1].astype(np.uint16) << 2
47 rowUnpacked[:, 2] = rowPacked[:, 2].astype(np.uint16) << 2
48 rowUnpacked[:, 3] = rowPacked[:, 3].astype(np.uint16) << 2
49
50 # Extract least significant 2 bits from 5th byte
51 rowUnpacked[:, 0] |= (rowPacked[:, 4] & 0b00000011)
52 rowUnpacked[:, 1] |= (rowPacked[:, 4] & 0b00001100) >> 2
53 rowUnpacked[:, 2] |= (rowPacked[:, 4] & 0b00110000) >> 4
54 rowUnpacked[:, 3] |= (rowPacked[:, 4] & 0b11000000) >> 6
55
56 # Flatten and copy only the required width pixels to result
57 rowFlat = rowUnpacked.flatten()
58 result[row, :width] = rowFlat[:width]
59
60 # Scale from 10-bit (0-1023) to 16-bit (0-65535) for proper display
61 result16bit = (result * 64).astype(np.uint16)
62 return result16bit
63
64# Create pipeline
65with dai.Pipeline() as pipeline:
66 # Define source and output
67 cam = pipeline.create(dai.node.Camera).build(dai.CameraBoardSocket.CAM_A)
68 rawQueue = cam.raw.createOutputQueue()
69 videoQueue = cam.requestFullResolutionOutput().createOutputQueue()
70 # Connect to device and start pipeline
71 pipeline.start()
72 while pipeline.isRunning():
73 videoIn = videoQueue.tryGet()
74 rawFrame = rawQueue.tryGet()
75 if rawFrame is not None:
76 assert isinstance(rawFrame, dai.ImgFrame)
77 dataRaw = rawFrame.getData()
78 parsedImage = unpackRaw10(dataRaw, rawFrame.getWidth(), rawFrame.getHeight(), rawFrame.getStride())
79 cv2.imshow("raw", parsedImage)
80 if videoIn is not None:
81 assert isinstance(videoIn, dai.ImgFrame)
82 cv2.imshow("video", videoIn.getCvFrame())
83
84 if cv2.waitKey(1) == ord("q"):
85 break
Need assistance?
Head over to Discussion Forum for technical support or any other questions you might have.