Stereo Depth Remap
The example configures a pipeline to capture RGB and stereo depth streams, processes the depth data with percentile-based normalization and HOT colormap visualization, and displays both streams with synchronized rotated rectangles, demonstrating coordinate transformation between frames.Setup
This example requires the DepthAI v3 API, see installation instructions.Pipeline
Source code
Python
C++
Python
PythonGitHub
1import depthai as dai
2import cv2
3import numpy as np
4
5def draw_rotated_rectangle(frame, center, size, angle, color, thickness=2):
6 """
7 Draws a rotated rectangle on the given frame.
8
9 Args:
10 frame (numpy.ndarray): The image/frame to draw on.
11 center (tuple): The (x, y) coordinates of the rectangle's center.
12 size (tuple): The (width, height) of the rectangle.
13 angle (float): The rotation angle of the rectangle in degrees (counter-clockwise).
14 color (tuple): The color of the rectangle in BGR format (e.g., (0, 255, 0) for green).
15 thickness (int): The thickness of the rectangle edges. Default is 2.
16 """
17 # Create a rotated rectangle
18 rect = ((center[0], center[1]), (size[0], size[1]), angle)
19
20 # Get the four vertices of the rotated rectangle
21 box = cv2.boxPoints(rect)
22 box = np.intp(box) # Convert to integer coordinates
23
24 # Draw the rectangle on the frame
25 cv2.polylines(frame, [box], isClosed=True, color=color, thickness=thickness)
26
27def processDepthFrame(depthFrame):
28 depth_downscaled = depthFrame[::4]
29 if np.all(depth_downscaled == 0):
30 min_depth = 0
31 else:
32 min_depth = np.percentile(depth_downscaled[depth_downscaled != 0], 1)
33 max_depth = np.percentile(depth_downscaled, 99)
34 depthFrameColor = np.interp(depthFrame, (min_depth, max_depth), (0, 255)).astype(np.uint8)
35 return cv2.applyColorMap(depthFrameColor, cv2.COLORMAP_HOT)
36
37with dai.Pipeline() as pipeline:
38 color = pipeline.create(dai.node.Camera).build(dai.CameraBoardSocket.CAM_A)
39 monoLeft = pipeline.create(dai.node.Camera).build(dai.CameraBoardSocket.CAM_B)
40 monoRight = pipeline.create(dai.node.Camera).build(dai.CameraBoardSocket.CAM_C)
41 stereo = pipeline.create(dai.node.StereoDepth)
42
43 stereo.setDefaultProfilePreset(dai.node.StereoDepth.PresetMode.DEFAULT)
44 # stereo.setDepthAlign(dai.CameraBoardSocket.CAM_A)
45 # stereo.setOutputSize(640, 400)
46
47 colorCamOut = color.requestOutput((640, 480))
48
49 monoLeftOut = monoLeft.requestOutput((640, 480))
50 monoRightOut = monoRight.requestOutput((640, 480))
51
52 monoLeftOut.link(stereo.left)
53 monoRightOut.link(stereo.right)
54
55 colorOut = colorCamOut.createOutputQueue()
56 rightOut = monoRightOut.createOutputQueue()
57 stereoOut = stereo.depth.createOutputQueue()
58
59 pipeline.start()
60 while pipeline.isRunning():
61 colorFrame = colorOut.get()
62 stereoFrame = stereoOut.get()
63
64 assert colorFrame.validateTransformations()
65 assert stereoFrame.validateTransformations()
66
67 clr = colorFrame.getCvFrame()
68 depth = processDepthFrame(stereoFrame.getCvFrame())
69
70 rect = dai.RotatedRect(dai.Point2f(300, 200), dai.Size2f(200, 100), 10)
71 remappedRect = colorFrame.getTransformation().remapRectTo(stereoFrame.getTransformation(), rect)
72
73 print(f"Original rect x: {rect.center.x} y: {rect.center.y} width: {rect.size.width} height: {rect.size.height} angle: {rect.angle}")
74 print(f"Remapped rect x: {remappedRect.center.x} y: {remappedRect.center.y} width: {remappedRect.size.width} height: {remappedRect.size.height} angle: {remappedRect.angle}")
75
76 draw_rotated_rectangle(clr, (rect.center.x, rect.center.y), (rect.size.width, rect.size.height), rect.angle, (255, 0, 0))
77 draw_rotated_rectangle(depth, (remappedRect.center.x, remappedRect.center.y), (remappedRect.size.width, remappedRect.size.height), remappedRect.angle, (255, 0, 0))
78
79 cv2.imshow("color", clr)
80 cv2.imshow("depth", depth)
81
82 if cv2.waitKey(1) == ord('q'):
83 break
84 pipeline.stop()
Need assistance?
Head over to Discussion Forum for technical support or any other questions you might have.