DepthAI
Software Stack

ON THIS PAGE

  • Pipeline
  • Source code

ImageManip remap

Supported on:RVC2RVC4
This examples shows an application that processes a camera stream through two image manipulation nodes with 90-degree rotations and different output sizes, displaying the original and manipulated frames with synchronized rotated rectangles, using DepthAI's pipeline and transformation handling.This example requires the DepthAI v3 API, see installation instructions.

Pipeline

Source code

Python

Python
GitHub
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
27with dai.Pipeline() as pipeline:
28    cam = pipeline.create(dai.node.Camera).build()
29    camOut = cam.requestOutput((640, 400), dai.ImgFrame.Type.BGR888i, fps = 30.0)
30    manip1 = pipeline.create(dai.node.ImageManip)
31    manip2 = pipeline.create(dai.node.ImageManip)
32
33    camOut.link(manip1.inputImage)
34    manip1.out.link(manip2.inputImage)
35
36    manip1.initialConfig.addRotateDeg(90)
37    manip1.initialConfig.setOutputSize(200, 320)
38
39    manip2.initialConfig.addRotateDeg(90)
40    manip2.initialConfig.setOutputSize(320, 200)
41    manip2.setRunOnHost(True)
42
43    outQcam = camOut.createOutputQueue()
44    outQ1 = manip1.out.createOutputQueue()
45    outQ2 = manip2.out.createOutputQueue()
46
47    pipeline.start()
48
49    while True:
50        camFrame: dai.ImgFrame = outQcam.get()
51        manip1Frame: dai.ImgFrame = outQ1.get()
52        manip2Frame: dai.ImgFrame = outQ2.get()
53
54        camCv = camFrame.getCvFrame()
55        manip1Cv = manip1Frame.getCvFrame()
56        manip2Cv = manip2Frame.getCvFrame()
57
58        rect2 = dai.RotatedRect(dai.Rect(dai.Point2f(100, 100), dai.Point2f(200, 150)), 0)
59        rect1 = manip2Frame.getTransformation().remapRectTo(manip1Frame.getTransformation(), rect2)
60        rectcam = manip1Frame.getTransformation().remapRectTo(camFrame.getTransformation(), rect1)
61
62        draw_rotated_rectangle(manip2Cv, (rect2.center.x, rect2.center.y), (rect2.size.width, rect2.size.height), rect2.angle, (255, 0, 0))
63        draw_rotated_rectangle(manip1Cv, (rect1.center.x, rect1.center.y), (rect1.size.width, rect1.size.height), rect1.angle, (255, 0, 0))
64        draw_rotated_rectangle(camCv, (rectcam.center.x, rectcam.center.y), (rectcam.size.width, rectcam.size.height), rectcam.angle, (255, 0, 0))
65
66        cv2.imshow("cam", camCv)
67        cv2.imshow("manip1", manip1Cv)
68        cv2.imshow("manip2", manip2Cv)
69        if cv2.waitKey(1) == ord('q'):
70            break

C++

1#include <atomic>
2#include <csignal>
3#include <iostream>
4#include <memory>
5#include <opencv2/opencv.hpp>
6
7#include "depthai/depthai.hpp"
8
9// Global flag for graceful shutdown
10std::atomic<bool> quitEvent(false);
11
12// Signal handler
13void signalHandler(int signum) {
14    quitEvent = true;
15}
16
17// Helper function to draw rotated rectangle
18void draw_rotated_rectangle(cv::Mat& frame, const cv::Point2f& center, const cv::Size2f& size, float angle, const cv::Scalar& color, int thickness = 2) {
19    // Create a rotated rectangle
20    cv::RotatedRect rect(center, size, angle);
21
22    // Get the four vertices of the rotated rectangle
23    cv::Point2f vertices[4];
24    rect.points(vertices);
25
26    // Convert to integer points for drawing
27    std::vector<cv::Point> points;
28    for(int i = 0; i < 4; i++) {
29        points.push_back(cv::Point(static_cast<int>(vertices[i].x), static_cast<int>(vertices[i].y)));
30    }
31
32    // Draw the rectangle on the frame
33    cv::polylines(frame, std::vector<std::vector<cv::Point>>{points}, true, color, thickness);
34}
35
36int main() {
37    // Set up signal handlers
38    signal(SIGTERM, signalHandler);
39    signal(SIGINT, signalHandler);
40
41    try {
42        // Create pipeline
43        dai::Pipeline pipeline;
44
45        // Create nodes
46        auto cam = pipeline.create<dai::node::Camera>();
47        cam->build();
48
49        auto manip1 = pipeline.create<dai::node::ImageManip>();
50        auto manip2 = pipeline.create<dai::node::ImageManip>();
51
52        // Configure camera output
53        auto camOut = cam->requestOutput(std::make_pair(640, 400), dai::ImgFrame::Type::BGR888i, dai::ImgResizeMode::LETTERBOX, 20, 20);
54
55        // Configure image manipulators
56        manip1->initialConfig->addRotateDeg(90);
57        manip1->initialConfig->setOutputSize(200, 320);
58
59        manip2->initialConfig->addRotateDeg(90);
60        manip2->initialConfig->setOutputSize(320, 200);
61        manip2->setRunOnHost(true);
62
63        // Linking
64        camOut->link(manip1->inputImage);
65        manip1->out.link(manip2->inputImage);
66
67        // Create output queues
68        auto outQcam = camOut->createOutputQueue();
69        auto outQ1 = manip1->out.createOutputQueue();
70        auto outQ2 = manip2->out.createOutputQueue();
71
72        // Start pipeline
73        pipeline.start();
74
75        // Main loop
76        while(!quitEvent) {
77            // Get frames
78            auto camFrame = outQcam->get<dai::ImgFrame>();
79            auto manip1Frame = outQ1->get<dai::ImgFrame>();
80            auto manip2Frame = outQ2->get<dai::ImgFrame>();
81
82            // Convert to OpenCV format
83            cv::Mat camCv = camFrame->getCvFrame();
84            cv::Mat manip1Cv = manip1Frame->getCvFrame();
85            cv::Mat manip2Cv = manip2Frame->getCvFrame();
86
87            // Create and remap rectangles
88            dai::RotatedRect rect2(dai::Rect(dai::Point2f(100, 100), dai::Point2f(200, 150)), 0);
89            auto rect1 = manip2Frame->transformation.remapRectTo(manip1Frame->transformation, rect2);
90            auto rectcam = manip1Frame->transformation.remapRectTo(camFrame->transformation, rect1);
91
92            // Draw rectangles
93            draw_rotated_rectangle(
94                manip2Cv, cv::Point2f(rect2.center.x, rect2.center.y), cv::Size2f(rect2.size.width, rect2.size.height), rect2.angle, cv::Scalar(255, 0, 0));
95
96            draw_rotated_rectangle(
97                manip1Cv, cv::Point2f(rect1.center.x, rect1.center.y), cv::Size2f(rect1.size.width, rect1.size.height), rect1.angle, cv::Scalar(255, 0, 0));
98
99            draw_rotated_rectangle(camCv,
100                                   cv::Point2f(rectcam.center.x, rectcam.center.y),
101                                   cv::Size2f(rectcam.size.width, rectcam.size.height),
102                                   rectcam.angle,
103                                   cv::Scalar(255, 0, 0));
104
105            // Display frames
106            cv::imshow("cam", camCv);
107            cv::imshow("manip1", manip1Cv);
108            cv::imshow("manip2", manip2Cv);
109
110            // Check for quit key
111            if(cv::waitKey(1) == 'q') {
112                break;
113            }
114        }
115
116        // Cleanup
117        pipeline.stop();
118        pipeline.wait();
119
120    } catch(const std::exception& e) {
121        std::cerr << "Error: " << e.what() << std::endl;
122        return 1;
123    }
124
125    return 0;
126}

Need assistance?

Head over to Discussion Forum for technical support or any other questions you might have.