You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

image_processing.md 5.7 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. # Image Processing Pipeline
  2. This advanced example demonstrates a real-world image processing pipeline using Dora.
  3. ## Overview
  4. This example shows how to:
  5. 1. Create a complex multi-node pipeline
  6. 2. Handle binary data (images)
  7. 3. Use external libraries (OpenCV)
  8. 4. Implement error handling
  9. 5. Use async processing
  10. ## Project Structure
  11. ```
  12. image_processing/
  13. ├── dora.yml
  14. ├── requirements.txt
  15. └── nodes/
  16. ├── camera.py
  17. ├── preprocessor.py
  18. ├── detector.py
  19. └── visualizer.py
  20. ```
  21. ## Implementation
  22. ### 1. Dependencies (requirements.txt)
  23. ```
  24. opencv-python>=4.5.0
  25. numpy>=1.19.0
  26. ```
  27. ### 2. Camera Node (nodes/camera.py)
  28. ```python
  29. from dora import AsyncNode
  30. import cv2
  31. import numpy as np
  32. class CameraNode(AsyncNode):
  33. def __init__(self):
  34. super().__init__()
  35. self.cap = None
  36. async def setup(self):
  37. self.cap = cv2.VideoCapture(0)
  38. if not self.cap.isOpened():
  39. raise RuntimeError("Failed to open camera")
  40. async def on_input(self, input_data):
  41. ret, frame = self.cap.read()
  42. if not ret:
  43. raise RuntimeError("Failed to read frame")
  44. # Convert to RGB
  45. frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
  46. return {"image": frame_rgb.tobytes(), "shape": frame_rgb.shape}
  47. async def cleanup(self):
  48. if self.cap:
  49. self.cap.release()
  50. ```
  51. ### 3. Preprocessor Node (nodes/preprocessor.py)
  52. ```python
  53. from dora import Node
  54. import numpy as np
  55. class PreprocessorNode(Node):
  56. def __init__(self):
  57. super().__init__()
  58. def on_input(self, input_data):
  59. # Convert bytes back to numpy array
  60. image = np.frombuffer(input_data["image"], dtype=np.uint8)
  61. image = image.reshape(input_data["shape"])
  62. # Resize image
  63. resized = cv2.resize(image, (640, 480))
  64. # Normalize
  65. normalized = resized.astype(np.float32) / 255.0
  66. return {
  67. "image": normalized.tobytes(),
  68. "shape": normalized.shape
  69. }
  70. ```
  71. ### 4. Detector Node (nodes/detector.py)
  72. ```python
  73. from dora import Node
  74. import numpy as np
  75. class DetectorNode(Node):
  76. def __init__(self):
  77. super().__init__()
  78. # Load your ML model here
  79. self.model = None
  80. def on_input(self, input_data):
  81. # Convert to numpy array
  82. image = np.frombuffer(input_data["image"], dtype=np.float32)
  83. image = image.reshape(input_data["shape"])
  84. # Run detection (simulated)
  85. detections = self.simulate_detection(image)
  86. return {
  87. "detections": detections,
  88. "image": input_data["image"],
  89. "shape": input_data["shape"]
  90. }
  91. def simulate_detection(self, image):
  92. # Simulate object detection
  93. return [
  94. {"class": "person", "confidence": 0.95, "bbox": [100, 100, 200, 200]},
  95. {"class": "car", "confidence": 0.88, "bbox": [300, 150, 400, 250]}
  96. ]
  97. ```
  98. ### 5. Visualizer Node (nodes/visualizer.py)
  99. ```python
  100. from dora import Node
  101. import cv2
  102. import numpy as np
  103. class VisualizerNode(Node):
  104. def __init__(self):
  105. super().__init__()
  106. def on_input(self, input_data):
  107. # Convert back to numpy array
  108. image = np.frombuffer(input_data["image"], dtype=np.float32)
  109. image = image.reshape(input_data["shape"])
  110. # Convert to uint8 for display
  111. image = (image * 255).astype(np.uint8)
  112. # Draw detections
  113. for det in input_data["detections"]:
  114. bbox = det["bbox"]
  115. cv2.rectangle(image, (bbox[0], bbox[1]), (bbox[2], bbox[3]), (0, 255, 0), 2)
  116. cv2.putText(image, f"{det['class']} {det['confidence']:.2f}",
  117. (bbox[0], bbox[1] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
  118. # Display image
  119. cv2.imshow("Detection Results", image)
  120. cv2.waitKey(1)
  121. return None
  122. ```
  123. ### 6. Graph Configuration (dora.yml)
  124. ```yaml
  125. nodes:
  126. camera:
  127. inputs: []
  128. outputs: ["image", "shape"]
  129. python: nodes/camera.py
  130. preprocessor:
  131. inputs: ["image", "shape"]
  132. outputs: ["image", "shape"]
  133. python: nodes/preprocessor.py
  134. detector:
  135. inputs: ["image", "shape"]
  136. outputs: ["detections", "image", "shape"]
  137. python: nodes/detector.py
  138. visualizer:
  139. inputs: ["detections", "image", "shape"]
  140. outputs: []
  141. python: nodes/visualizer.py
  142. edges:
  143. - from: camera
  144. to: preprocessor
  145. data: [image, shape]
  146. - from: preprocessor
  147. to: detector
  148. data: [image, shape]
  149. - from: detector
  150. to: visualizer
  151. data: [detections, image, shape]
  152. ```
  153. ## Running the Example
  154. 1. Install dependencies:
  155. ```bash
  156. pip install -r requirements.txt
  157. ```
  158. 2. Start the application:
  159. ```bash
  160. dora run
  161. ```
  162. 3. You should see a window showing the camera feed with detected objects.
  163. ## Understanding the Example
  164. ### Advanced Concepts
  165. - **Async Processing**: Camera node uses async/await for non-blocking I/O
  166. - **Binary Data Handling**: Efficient image data transfer between nodes
  167. - **Error Handling**: Proper cleanup and error propagation
  168. - **External Libraries**: Integration with OpenCV
  169. - **Complex Data Flow**: Multi-stage processing pipeline
  170. ### Performance Considerations
  171. - Zero-copy data transfer where possible
  172. - Efficient image format conversions
  173. - Proper resource cleanup
  174. - Async processing for I/O operations
  175. ## Next Steps
  176. - Add real ML model integration
  177. - Implement frame rate control
  178. - Add configuration options
  179. - Implement error recovery
  180. - Add performance monitoring