33import asyncio
44import os
55import threading
6+ from typing import Dict
67
78import cv2 as cv
89import numpy as np
@@ -23,6 +24,45 @@ def zero_twist() -> np.ndarray:
2324 return np .array ([0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 ], dtype = np .float64 )
2425
2526
27+ def image_data_to_png (image_data : pa .UInt8Array , metadata : Dict [str , str ]) -> bytes :
28+ """Convert image data from pyarrow UInt8Array to PNG format.
29+
30+ The metadata should contain the encoding, width, and height of the image.
31+ For reference, this method can be used to convert images
32+ sent by https://github.com/dora-rs/dora/tree/main/node-hub/opencv-video-capture dora node.
33+
34+ Args:
35+ image_data (pa.UInt8Array): The image data as a pyarrow UInt8Array
36+ metadata (dict): Metadata containing 'encoding', 'width', and 'height'.
37+
38+ Returns:
39+ bytes: The image data in PNG format.
40+
41+ """
42+ encoding = metadata ["encoding" ]
43+ width = metadata ["width" ]
44+ height = metadata ["height" ]
45+ if encoding in {"bgr8" , "rgb8" }:
46+ channels = 3
47+ storage_type = np .uint8
48+ else :
49+ raise RuntimeError (f"Unsupported image encoding: { encoding } " )
50+
51+ frame = image_data .to_numpy ().astype (storage_type ).reshape ((height , width , channels ))
52+ if encoding == "bgr8" :
53+ pass
54+ elif encoding == "rgb8" :
55+ frame = frame [:, :, ::- 1 ] # Convert RGB to BGR
56+ else :
57+ raise RuntimeError (f"Unsupported image encoding: { encoding } " )
58+
59+ # Convert the frame to png
60+ ret , frame = cv .imencode (".png" , frame )
61+ if not ret :
62+ raise RuntimeError ("Failed to encode image to PNG format." )
63+ return frame .tobytes () # type: ignore[no-any-return]
64+
65+
2666def main () -> None :
2767 """TODO: Add docstring."""
2868 node = Node ()
@@ -54,36 +94,14 @@ def main() -> None:
5494 if event_id == "image" :
5595 storage = event ["value" ]
5696 metadata = event ["metadata" ]
57- encoding = metadata ["encoding" ]
58- width = metadata ["width" ]
59- height = metadata ["height" ]
60-
61- if encoding in {"bgr8" , "rgb8" }:
62- channels = 3
63- storage_type = np .uint8
64- else :
65- raise RuntimeError (f"Unsupported image encoding: { encoding } " )
66-
67- frame = storage .to_numpy ().astype (storage_type ).reshape ((height , width , channels ))
68- if encoding == "bgr8" :
69- pass
70- elif encoding == "rgb8" :
71- frame = frame [:, :, ::- 1 ] # Convert RGB to BGR
72- else :
73- raise RuntimeError (f"Unsupported image encoding: { encoding } " )
74-
75- # Convert the frame to png
76- ret , frame = cv .imencode (".png" , frame )
77- if not ret :
78- raise RuntimeError ("Failed to encode image to PNG format." )
79- last_image = frame
97+ last_image = image_data_to_png (storage , metadata )
8098 if event_id == "tick" :
8199 if last_image is None :
82100 continue
83101 if command == "" :
84102 cmd_vel = zero_twist ()
85103 continue
86- image_bytes = last_image . tobytes ()
104+ image_bytes = last_image
87105
88106 # For debugging: Dump image into a file for debugging
89107 # with open("last_image.png", "wb") as f:
0 commit comments