|
| 1 | +import depthai as dai |
| 2 | +import cv2 |
| 3 | +import numpy as np |
| 4 | +import math |
| 5 | + |
| 6 | +# User-defined constants |
| 7 | +WARNING = 500 # 50cm, orange |
| 8 | +CRITICAL = 300 # 30cm, red |
| 9 | + |
| 10 | +# Create pipeline |
| 11 | +pipeline = dai.Pipeline() |
| 12 | + |
| 13 | +# Color camera |
| 14 | +camRgb = pipeline.create(dai.node.ColorCamera) |
| 15 | +camRgb.setPreviewSize(300, 300) |
| 16 | +camRgb.setInterleaved(False) |
| 17 | + |
| 18 | +# Define source - stereo depth cameras |
| 19 | +left = pipeline.create(dai.node.MonoCamera) |
| 20 | +left.setResolution(dai.MonoCameraProperties.SensorResolution.THE_720_P) |
| 21 | +left.setBoardSocket(dai.CameraBoardSocket.LEFT) |
| 22 | + |
| 23 | +right = pipeline.create(dai.node.MonoCamera) |
| 24 | +right.setResolution(dai.MonoCameraProperties.SensorResolution.THE_720_P) |
| 25 | +right.setBoardSocket(dai.CameraBoardSocket.RIGHT) |
| 26 | + |
| 27 | +# Create stereo depth node |
| 28 | +stereo = pipeline.create(dai.node.StereoDepth) |
| 29 | +stereo.setConfidenceThreshold(50) |
| 30 | +stereo.setLeftRightCheck(True) |
| 31 | +stereo.setExtendedDisparity(True) |
| 32 | + |
| 33 | +# Linking |
| 34 | +left.out.link(stereo.left) |
| 35 | +right.out.link(stereo.right) |
| 36 | + |
| 37 | +# Spatial location calculator configuration |
| 38 | +slc = pipeline.create(dai.node.SpatialLocationCalculator) |
| 39 | +for x in range(15): |
| 40 | + for y in range(9): |
| 41 | + config = dai.SpatialLocationCalculatorConfigData() |
| 42 | + config.depthThresholds.lowerThreshold = 200 |
| 43 | + config.depthThresholds.upperThreshold = 10000 |
| 44 | + config.roi = dai.Rect(dai.Point2f((x+0.5)*0.0625, (y+0.5)*0.1), dai.Point2f((x+1.5)*0.0625, (y+1.5)*0.1)) |
| 45 | + config.calculationAlgorithm = dai.SpatialLocationCalculatorAlgorithm.MEDIAN |
| 46 | + slc.initialConfig.addROI(config) |
| 47 | + |
| 48 | +stereo.depth.link(slc.inputDepth) |
| 49 | +stereo.setDepthAlign(dai.CameraBoardSocket.RGB) |
| 50 | + |
| 51 | +# Create output |
| 52 | +slcOut = pipeline.create(dai.node.XLinkOut) |
| 53 | +slcOut.setStreamName('slc') |
| 54 | +slc.out.link(slcOut.input) |
| 55 | + |
| 56 | +colorOut = pipeline.create(dai.node.XLinkOut) |
| 57 | +colorOut.setStreamName('color') |
| 58 | +camRgb.video.link(colorOut.input) |
| 59 | + |
| 60 | +# Connect to device and start pipeline |
| 61 | +with dai.Device(pipeline) as device: |
| 62 | + # Output queues will be used to get the color mono frames and spatial location data |
| 63 | + qColor = device.getOutputQueue(name="color", maxSize=4, blocking=False) |
| 64 | + qSlc = device.getOutputQueue(name="slc", maxSize=4, blocking=False) |
| 65 | + |
| 66 | + fontType = cv2.FONT_HERSHEY_TRIPLEX |
| 67 | + |
| 68 | + while True: |
| 69 | + inColor = qColor.get() # Try to get a frame from the color camera |
| 70 | + inSlc = qSlc.get() # Try to get spatial location data |
| 71 | + |
| 72 | + if inColor is None: |
| 73 | + print("No color camera data") |
| 74 | + if inSlc is None: |
| 75 | + print("No spatial location data") |
| 76 | + |
| 77 | + colorFrame = None |
| 78 | + if inColor is not None: |
| 79 | + colorFrame = inColor.getCvFrame() # Fetch the frame from the color mono camera |
| 80 | + |
| 81 | + |
| 82 | + if inSlc is not None and colorFrame is not None: |
| 83 | + slc_data = inSlc.getSpatialLocations() |
| 84 | + for depthData in slc_data: |
| 85 | + roi = depthData.config.roi |
| 86 | + roi = roi.denormalize(width=colorFrame.shape[1], height=colorFrame.shape[0]) |
| 87 | + |
| 88 | + xmin = int(roi.topLeft().x) |
| 89 | + ymin = int(roi.topLeft().y) |
| 90 | + xmax = int(roi.bottomRight().x) |
| 91 | + ymax = int(roi.bottomRight().y) |
| 92 | + |
| 93 | + coords = depthData.spatialCoordinates |
| 94 | + distance = math.sqrt(coords.x ** 2 + coords.y ** 2 + coords.z ** 2) |
| 95 | + |
| 96 | + if distance == 0: # Invalid |
| 97 | + continue |
| 98 | + |
| 99 | + # Determine color based on distance |
| 100 | + if distance < CRITICAL: |
| 101 | + color = (0, 0, 255) # Red |
| 102 | + elif distance < WARNING: |
| 103 | + color = (0, 140, 255) # Orange |
| 104 | + else: |
| 105 | + continue # Skip drawing for non-critical/non-warning distances |
| 106 | + |
| 107 | + # Draw rectangle and distance text on the color frame |
| 108 | + cv2.rectangle(colorFrame, (xmin, ymin), (xmax, ymax), color, thickness=2) |
| 109 | + cv2.putText(colorFrame, "{:.1f}m".format(distance / 1000), (xmin + 10, ymin + 20), fontType, 0.5, color) |
| 110 | + |
| 111 | + # Display the color frame |
| 112 | + cv2.imshow('Left Mono Camera', colorFrame) |
| 113 | + if cv2.waitKey(1) == ord('q'): |
| 114 | + break |
0 commit comments