Browse Source

Adding pyrealsense

tags/0.3.8-rc
haixuanTao haixuantao 1 year ago
parent
commit
9a732ea002
5 changed files with 200 additions and 0 deletions
  1. +70
    -0
      node-hub/dora-pyrealsense/README.md
  2. +11
    -0
      node-hub/dora-pyrealsense/dora_pyrealsense/__init__.py
  3. +89
    -0
      node-hub/dora-pyrealsense/dora_pyrealsense/main.py
  4. +21
    -0
      node-hub/dora-pyrealsense/pyproject.toml
  5. +9
    -0
      node-hub/dora-pyrealsense/tests/test_dora_pyrealsense.py

+ 70
- 0
node-hub/dora-pyrealsense/README.md View File

@@ -0,0 +1,70 @@
# Dora Node for capturing video with OpenCV

This node is used to capture video from a camera using OpenCV.

# YAML

```yaml
- id: opencv-video-capture
build: pip install ../../node-hub/opencv-video-capture
path: opencv-video-capture
inputs:
tick: dora/timer/millis/16 # try to capture at 60fps
outputs:
- image: # the captured image

env:
PATH: 0 # optional, default is 0

IMAGE_WIDTH: 640 # optional, default is video capture width
IMAGE_HEIGHT: 480 # optional, default is video capture height
```

# Inputs

- `tick`: empty Arrow array to trigger the capture

# Outputs

- `image`: an arrow array containing the captured image

```Python
## Image data
image_data: UInt8Array # Example: pa.array(img.ravel())
metadata = {
"width": 640,
"height": 480,
"encoding": str, # bgr8, rgb8
}

## Example
node.send_output(
image_data, {"width": 640, "height": 480, "encoding": "bgr8"}
)

## Decoding
storage = event["value"]

metadata = event["metadata"]
encoding = metadata["encoding"]
width = metadata["width"]
height = metadata["height"]

if encoding == "bgr8":
channels = 3
storage_type = np.uint8

frame = (
storage.to_numpy()
.astype(storage_type)
.reshape((height, width, channels))
)
```

## Examples

Check example at [examples/python-dataflow](examples/python-dataflow)

## License

This project is licensed under Apache-2.0. Check out [NOTICE.md](../../NOTICE.md) for more information.

+ 11
- 0
node-hub/dora-pyrealsense/dora_pyrealsense/__init__.py View File

@@ -0,0 +1,11 @@
import os

# Define the path to the README file relative to the package directory
readme_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), "README.md")

# Read the content of the README file
try:
with open(readme_path, "r", encoding="utf-8") as f:
__doc__ = f.read()
except FileNotFoundError:
__doc__ = "README file not found."

+ 89
- 0
node-hub/dora-pyrealsense/dora_pyrealsense/main.py View File

@@ -0,0 +1,89 @@
import argparse
import os
import time

import cv2
import numpy as np
import pyarrow as pa

from dora import Node

RUNNER_CI = True if os.getenv("CI") == "true" else False
import pyrealsense2 as rs

FLIP = os.getenv("FLIP", "")
DEVICE_ID = os.getenv("DEVICE_ID", "")
pipeline = rs.pipeline()
config = rs.config()
config.enable_device(DEVICE_ID)
config.enable_stream(rs.stream.color, 640, 480, rs.format.rgb8, 15)
align_to = rs.stream.color
align = rs.align(align_to)
pipeline.start(config)


def main():
node = Node()
start_time = time.time()

pa.array([]) # initialize pyarrow array

for event in node:

# Run this example in the CI for 10 seconds only.
if RUNNER_CI and time.time() - start_time > 10:
break

event_type = event["type"]

if event_type == "INPUT":
event_id = event["id"]

if event_id == "tick":
frames = pipeline.wait_for_frames()
# 使用线程锁来确保只有一个线程能访问数据流
# 获取各种数据流
color_frames = frames.get_color_frame()
frame = np.asanyarray(color_frames.get_data())

if FLIP == "VERTICAL":
frame = cv2.flip(frame, 0)
elif FLIP == "HORIZONTAL":
frame = cv2.flip(frame, 1)
elif FLIP == "BOTH":
frame = cv2.flip(frame, -1)

# resize the frame
if (
image_width is not None
and image_height is not None
and (
frame.shape[1] != image_width or frame.shape[0] != image_height
)
):
frame = cv2.resize(frame, (image_width, image_height))

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

# Get the right encoding
if encoding == "rgb8":
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
elif encoding in ["jpeg", "jpg", "jpe", "bmp", "webp", "png"]:
ret, frame = cv2.imencode("." + encoding, frame)
if not ret:
print("Error encoding image...")
continue

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

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

elif event_type == "ERROR":
raise RuntimeError(event["error"])


if __name__ == "__main__":
main()

+ 21
- 0
node-hub/dora-pyrealsense/pyproject.toml View File

@@ -0,0 +1,21 @@
[tool.poetry]
name = "dora-pyrealsense"
version = "0.0.1"
authors = ["Haixuan Xavier Tao <tao.xavier@outlook.com>"]
description = "Dora Node for capturing video with Pyrealsense"
readme = "README.md"

packages = [{ include = "dora_pyrealsense" }]

[tool.poetry.dependencies]
dora-rs = "^0.3.6"
numpy = "< 2.0.0"
opencv-python = ">= 4.1.1"
pyrealsense2 = "2.54.1.5216"

[tool.poetry.scripts]
dora-pyrealsense = "dora_pyrealsense.main:main"

[build-system]
requires = ["poetry-core>=1.8.0"]
build-backend = "poetry.core.masonry.api"

+ 9
- 0
node-hub/dora-pyrealsense/tests/test_dora_pyrealsense.py View File

@@ -0,0 +1,9 @@
import pytest


def test_import_main():
from opencv_video_capture.main import main

# Check that everything is working, and catch dora Runtime Exception as we're not running in a dora dataflow.
with pytest.raises(RuntimeError):
main()

Loading…
Cancel
Save