Skip to content

Commit

Permalink
Add additional image encoding (#661)
Browse files Browse the repository at this point in the history
Enable the use of `jpeg` encoding to send camera data as jpeg as it is
more efficient when using remote connections.

I also provided a notebook example to run the camera example within a
jupyter notebook for fast protoyping.
  • Loading branch information
haixuanTao authored Sep 26, 2024
2 parents f53263b + 7d2d994 commit 825313a
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 5 deletions.
20 changes: 20 additions & 0 deletions examples/camera/dataflow_jupyter.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
nodes:
- id: camera
build: pip install ../../node-hub/opencv-video-capture
path: opencv-video-capture
inputs:
tick: dora/timer/millis/20
outputs:
- image
env:
CAPTURE_PATH: 0
IMAGE_WIDTH: 640
IMAGE_HEIGHT: 480
ENCODING: "jpeg"

- id: plot
path: dynamic
inputs:
image:
source: camera/image
queue_size: 1
53 changes: 53 additions & 0 deletions examples/camera/notebook.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from dora import Node\n",
"import IPython.display\n",
"from IPython.display import clear_output"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"\n",
"node = Node(\"plot\")\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"\n",
"for event in node:\n",
" if event[\"type\"] != \"INPUT\":\n",
" continue\n",
" data = event[\"value\"].to_numpy()\n",
" IPython.display.display(IPython.display.Image(data=data))\n",
" clear_output(wait=True)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "base",
"language": "python",
"name": "python3"
},
"language_info": {
"name": "python",
"version": "3.10.13"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
22 changes: 22 additions & 0 deletions node-hub/opencv-plot/opencv_plot/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ def plot_frame(plot):
cv2.imshow("Dora Node: opencv-plot", plot.frame)


def yuv420p_to_bgr_opencv(yuv_array, width, height):
yuv = yuv_array.reshape((height * 3 // 2, width))
return cv2.cvtColor(yuv, cv2.COLOR_YUV420p2RGB)


def main():

# Handle dynamic nodes, ask for the name of the node in the dataflow, and the same values as the ENV variables.
Expand Down Expand Up @@ -155,6 +160,23 @@ def main():
)

plot.frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)

elif encoding in ["jpeg", "jpg", "jpe", "bmp", "webp", "png"]:
channels = 3
storage_type = np.uint8
storage = storage.to_numpy()
plot.frame = cv2.imdecode(storage, cv2.IMREAD_COLOR)

elif encoding == "yuv420":

storage = storage.to_numpy()

# Convert back to BGR results in more saturated image.
channels = 3
storage_type = np.uint8
img_bgr_restored = yuv420p_to_bgr_opencv(storage, width, height)

plot.frame = img_bgr_restored
else:
raise RuntimeError(f"Unsupported image encoding: {encoding}")

Expand Down
12 changes: 7 additions & 5 deletions node-hub/opencv-video-capture/opencv_video_capture/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,11 @@ def main():
1,
)

metadata = event["metadata"]
metadata["encoding"] = encoding
metadata["width"] = int(frame.shape[1])
metadata["height"] = int(frame.shape[0])

# resize the frame
if (
image_width is not None
Expand All @@ -114,14 +119,11 @@ def main():
# Get the right encoding
if encoding == "rgb8":
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
elif encoding in ["jpeg", "jpg", "jpe", "bmp", "webp", "png"]:
frame = cv2.imencode("." + encoding, frame)[1]

storage = pa.array(frame.ravel())

metadata = event["metadata"]
metadata["width"] = int(frame.shape[1])
metadata["height"] = int(frame.shape[0])
metadata["encoding"] = encoding

node.send_output("image", storage, metadata)

elif event_type == "ERROR":
Expand Down

0 comments on commit 825313a

Please sign in to comment.