DepthAI
Software Stack

ON THIS PAGE

  • Demo
  • Pipeline
  • Source code

ImageManip all operations

Supported on:RVC2RVC4
Showcases all available ImageManip operations:
  • Resize (conf.setOutputSize())
  • Crop (conf.addCrop())
  • Flip vertical (conf.addFlipVertical())
  • Flip horizontal (conf.addFlipHorizontal())
  • Scale (conf.addScale())
  • Rotate (conf.addRotateDeg())
  • Transform (conf.addTransformAffine() and conf.addTransformPerspective())
Each operation is done on a separate ImageManip node, so you can see the effect of each operation separately.

Demo

This example requires the DepthAI v3 API, see installation instructions.

Pipeline

Source code

Python

Python
GitHub
1import depthai as dai
2import cv2
3
4pipeline = dai.Pipeline()
5
6manip_input = pipeline.create(dai.node.ImageManip)
7manip_input.initialConfig.setFrameType(dai.ImgFrame.Type.BGR888p)
8inputQueue = manip_input.inputImage.createInputQueue()
9
10manip_ops = [
11    # Resize operations. If aspect ratio isn't the same, the image will be stretched/cropped/letterboxed (depending on resize mode)
12    # Docs here: https://docs.luxonis.com/software/depthai/resolution-techniques/
13    ('resize_stretch', lambda conf: conf.setOutputSize(256, 200, dai.ImageManipConfig.ResizeMode.STRETCH)),
14    ('resize_letterbox', lambda conf: conf.setOutputSize(256, 200, dai.ImageManipConfig.ResizeMode.LETTERBOX)),
15    ('resize_center_crop', lambda conf: conf.setOutputSize(256, 200, dai.ImageManipConfig.ResizeMode.CENTER_CROP)),
16    # Crop the image topLeft (10,40) to bottomRight (310,110)
17    ('crop', lambda conf: conf.addCrop(x=50, y=50, w=150, h=200)),
18    # Flip the frame vertically/horizontally
19    ('flip_vertical', lambda conf: conf.addFlipVertical()),
20    ('flip_horizontal', lambda conf: conf.addFlipHorizontal()),
21    # Scale the image by 0.7x in x and 0.5x in y
22    ('scale', lambda conf: conf.addScale(0.7, 0.5)),
23    # Rotate. If center isn't specified, it will rotate around center (0.5, 0.5)
24    ('rotate_90_deg', lambda conf: conf.addRotateDeg(90)),
25    ('rotate_90_deg_center', lambda conf: conf.addRotateDeg(90, center=dai.Point2f(0.2, 0.3)).setOutputCenter(False)),
26    ('transform_affine', lambda conf: conf.addTransformAffine( # Shearing
27        [1, 0.5,
28         0.2, 1])),
29    ('transform_perspective', lambda conf: conf.addTransformPerspective(
30        [1.0, 0.2, 0.0,  # First row
31        0.1, 1.0, 0.0,  # Second row
32        0.001, 0.002, 1.0])),  # Third row
33    ('frame_type', lambda conf: conf.setFrameType(dai.ImgFrame.Type.RAW8)), # to Grayscale
34]
35
36# Dynamically create ImageManip nodes, apply configurations, and set up queues
37queues = {}
38for name, config in manip_ops:
39    print(name, config)
40    manip = pipeline.create(dai.node.ImageManip)
41    config(manip.initialConfig)
42    manip_input.out.link(manip.inputImage)
43    queues[name] = manip.out.createOutputQueue(maxSize=4, blocking=False)
44
45
46imgFrame = dai.ImgFrame()
47
48input_frame = cv2.imread('../models/lenna.png') # 512x512
49# Send 256x256 image to the device
50imgFrame.setCvFrame(cv2.pyrDown(input_frame), dai.ImgFrame.Type.BGR888i)
51inputQueue.send(imgFrame)
52
53cv2.imshow('input_image', input_frame)
54
55
56pipeline.start()
57
58for name, queue in queues.items():
59    inFrame = queue.get()
60    cv2.imshow(name, inFrame.getCvFrame())
61
62key = cv2.waitKey(0)

C++

1#include <atomic>
2#include <csignal>
3#include <functional>
4#include <iostream>
5#include <map>
6#include <memory>
7#include <opencv2/opencv.hpp>
8
9#include "depthai/depthai.hpp"
10
11std::atomic<bool> quitEvent(false);
12
13void signalHandler(int) {
14    quitEvent = true;
15}
16
17int main() {
18    signal(SIGTERM, signalHandler);
19    signal(SIGINT, signalHandler);
20
21    try {
22        // Create pipeline
23        dai::Pipeline pipeline;
24
25        // Create input manipulator
26        auto manipInput = pipeline.create<dai::node::ImageManip>();
27        manipInput->initialConfig->setFrameType(dai::ImgFrame::Type::BGR888p);
28        auto inputQueue = manipInput->inputImage.createInputQueue();
29
30        // Define manipulation operations
31        std::vector<std::pair<std::string, std::function<void(dai::ImageManipConfig&)>>> manipOps = {
32            // Resize operations
33            {"resize_stretch", [](dai::ImageManipConfig& conf) { conf.setOutputSize(256, 200, dai::ImageManipConfig::ResizeMode::STRETCH); }},
34            {"resize_letterbox", [](dai::ImageManipConfig& conf) { conf.setOutputSize(256, 200, dai::ImageManipConfig::ResizeMode::LETTERBOX); }},
35            {"resize_center_crop", [](dai::ImageManipConfig& conf) { conf.setOutputSize(256, 200, dai::ImageManipConfig::ResizeMode::CENTER_CROP); }},
36            // Crop operation
37            {"crop", [](dai::ImageManipConfig& conf) { conf.addCrop(50, 50, 150, 200); }},
38            // Flip operations
39            {"flip_vertical", [](dai::ImageManipConfig& conf) { conf.addFlipVertical(); }},
40            {"flip_horizontal", [](dai::ImageManipConfig& conf) { conf.addFlipHorizontal(); }},
41            // Scale operation
42            {"scale", [](dai::ImageManipConfig& conf) { conf.addScale(0.7f, 0.5f); }},
43            // Rotate operations
44            {"rotate_90_deg", [](dai::ImageManipConfig& conf) { conf.addRotateDeg(90); }},
45            {"rotate_90_deg_center",
46             [](dai::ImageManipConfig& conf) {
47                 conf.addRotateDeg(90, dai::Point2f(0.2f, 0.3f));
48                 conf.setOutputCenter(false);
49             }},
50            // Transform operations
51            {"transform_affine",
52             [](dai::ImageManipConfig& conf) {
53                 std::array<float, 4> matrix = {1.0f, 0.5f, 0.2f, 1.0f};
54                 conf.addTransformAffine(matrix);
55             }},
56            {"transform_perspective",
57             [](dai::ImageManipConfig& conf) {
58                 std::array<float, 9> matrix = {
59                     1.0f,
60                     0.2f,
61                     0.0f,  // First row
62                     0.1f,
63                     1.0f,
64                     0.0f,  // Second row
65                     0.001f,
66                     0.002f,
67                     1.0f  // Third row
68                 };
69                 conf.addTransformPerspective(matrix);
70             }},
71            // Frame type conversion
72            {"frame_type", [](dai::ImageManipConfig& conf) { conf.setFrameType(dai::ImgFrame::Type::RAW8); }}};
73
74        // Create manipulator nodes and queues
75        std::map<std::string, std::shared_ptr<dai::MessageQueue>> queues;
76        for(const auto& [name, config] : manipOps) {
77            std::cout << "Creating manipulator: " << name << std::endl;
78            auto manip = pipeline.create<dai::node::ImageManip>();
79            config(*manip->initialConfig);
80            manipInput->out.link(manip->inputImage);
81            queues[name] = manip->out.createOutputQueue(4, false);
82        }
83
84        // Load and prepare input image
85        cv::Mat inputFrame = cv::imread(LENNA_PATH);  // 512x512
86        if(inputFrame.empty()) {
87            throw std::runtime_error("Could not read input image");
88        }
89
90        // Create and send input frame
91        auto imgFrame = std::make_shared<dai::ImgFrame>();
92        cv::Mat downscaled;
93        cv::pyrDown(inputFrame, downscaled);
94        imgFrame->setCvFrame(downscaled, dai::ImgFrame::Type::BGR888i);
95        inputQueue->send(imgFrame);
96
97        // Display input image
98        cv::imshow("input_image", inputFrame);
99
100        // Start pipeline
101        pipeline.start();
102
103        // Process and display results
104        for(const auto& [name, queue] : queues) {
105            auto inFrame = queue->get<dai::ImgFrame>();
106            cv::imshow(name, inFrame->getCvFrame());
107        }
108
109        // Wait for key press or signal
110        while(!quitEvent) {
111            if(cv::waitKey(50) >= 0) break;
112        }
113
114        // Cleanup
115        pipeline.stop();
116        pipeline.wait();
117
118    } catch(const std::exception& e) {
119        std::cerr << "Error: " << e.what() << std::endl;
120        return 1;
121    }
122
123    return 0;
124}

Need assistance?

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