# ImageManip all operations

Showcases all available [ImageManip](https://docs.luxonis.com/software-v3/depthai/depthai-components/nodes/image_manip.md)
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](https://docs.luxonis.com/software-v3/depthai.md).

## Pipeline

## Source code

#### Python

```python
import depthai as dai
import cv2

pipeline = dai.Pipeline()

manip_input = pipeline.create(dai.node.ImageManip)
manip_input.initialConfig.setFrameType(dai.ImgFrame.Type.BGR888p)
inputQueue = manip_input.inputImage.createInputQueue()

manip_ops = [
    # Resize operations. If aspect ratio isn't the same, the image will be stretched/cropped/letterboxed (depending on resize mode)
    # Docs here: https://docs.luxonis.com/software/depthai/resolution-techniques/
    ('resize_stretch', lambda conf: conf.setOutputSize(256, 200, dai.ImageManipConfig.ResizeMode.STRETCH)),
    ('resize_letterbox', lambda conf: conf.setOutputSize(256, 200, dai.ImageManipConfig.ResizeMode.LETTERBOX)),
    ('resize_center_crop', lambda conf: conf.setOutputSize(256, 200, dai.ImageManipConfig.ResizeMode.CENTER_CROP)),
    # Crop the image topLeft (10,40) to bottomRight (310,110)
    ('crop', lambda conf: conf.addCrop(x=50, y=50, w=150, h=200)),
    # Flip the frame vertically/horizontally
    ('flip_vertical', lambda conf: conf.addFlipVertical()),
    ('flip_horizontal', lambda conf: conf.addFlipHorizontal()),
    # Scale the image by 0.7x in x and 0.5x in y
    ('scale', lambda conf: conf.addScale(0.7, 0.5)),
    # Rotate. If center isn't specified, it will rotate around center (0.5, 0.5)
    ('rotate_90_deg', lambda conf: conf.addRotateDeg(90)),
    ('rotate_90_deg_center', lambda conf: conf.addRotateDeg(90, center=dai.Point2f(0.2, 0.3)).setOutputCenter(False)),
    ('transform_affine', lambda conf: conf.addTransformAffine( # Shearing
        [1, 0.5,
         0.2, 1])),
    ('transform_perspective', lambda conf: conf.addTransformPerspective(
        [1.0, 0.2, 0.0,  # First row
        0.1, 1.0, 0.0,  # Second row
        0.001, 0.002, 1.0])),  # Third row
    ('frame_type', lambda conf: conf.setFrameType(dai.ImgFrame.Type.RAW8)), # to Grayscale
]

# Dynamically create ImageManip nodes, apply configurations, and set up queues
queues = {}
for name, config in manip_ops:
    print(name, config)
    manip = pipeline.create(dai.node.ImageManip)
    config(manip.initialConfig)
    manip_input.out.link(manip.inputImage)
    queues[name] = manip.out.createOutputQueue(maxSize=4, blocking=False)

imgFrame = dai.ImgFrame()

input_frame = cv2.imread('../models/lenna.png') # 512x512
# Send 256x256 image to the device
imgFrame.setCvFrame(cv2.pyrDown(input_frame), dai.ImgFrame.Type.BGR888i)
inputQueue.send(imgFrame)

cv2.imshow('input_image', input_frame)

pipeline.start()

for name, queue in queues.items():
    inFrame = queue.get()
    cv2.imshow(name, inFrame.getCvFrame())

key = cv2.waitKey(0)
```

#### C++

```cpp
#include <atomic>
#include <csignal>
#include <functional>
#include <iostream>
#include <map>
#include <memory>
#include <opencv2/opencv.hpp>

#include "depthai/depthai.hpp"

std::atomic<bool> quitEvent(false);

void signalHandler(int) {
    quitEvent = true;
}

int main() {
    signal(SIGTERM, signalHandler);
    signal(SIGINT, signalHandler);

    try {
        // Create pipeline
        dai::Pipeline pipeline;

        // Create input manipulator
        auto manipInput = pipeline.create<dai::node::ImageManip>();
        manipInput->initialConfig->setFrameType(dai::ImgFrame::Type::BGR888p);
        auto inputQueue = manipInput->inputImage.createInputQueue();

        // Define manipulation operations
        std::vector<std::pair<std::string, std::function<void(dai::ImageManipConfig&)>>> manipOps = {
            // Resize operations
            {"resize_stretch", [](dai::ImageManipConfig& conf) { conf.setOutputSize(256, 200, dai::ImageManipConfig::ResizeMode::STRETCH); }},
            {"resize_letterbox", [](dai::ImageManipConfig& conf) { conf.setOutputSize(256, 200, dai::ImageManipConfig::ResizeMode::LETTERBOX); }},
            {"resize_center_crop", [](dai::ImageManipConfig& conf) { conf.setOutputSize(256, 200, dai::ImageManipConfig::ResizeMode::CENTER_CROP); }},
            // Crop operation
            {"crop", [](dai::ImageManipConfig& conf) { conf.addCrop(50, 50, 150, 200); }},
            // Flip operations
            {"flip_vertical", [](dai::ImageManipConfig& conf) { conf.addFlipVertical(); }},
            {"flip_horizontal", [](dai::ImageManipConfig& conf) { conf.addFlipHorizontal(); }},
            // Scale operation
            {"scale", [](dai::ImageManipConfig& conf) { conf.addScale(0.7f, 0.5f); }},
            // Rotate operations
            {"rotate_90_deg", [](dai::ImageManipConfig& conf) { conf.addRotateDeg(90); }},
            {"rotate_90_deg_center",
             [](dai::ImageManipConfig& conf) {
                 conf.addRotateDeg(90, dai::Point2f(0.2f, 0.3f));
                 conf.setOutputCenter(false);
             }},
            // Transform operations
            {"transform_affine",
             [](dai::ImageManipConfig& conf) {
                 std::array<float, 4> matrix = {1.0f, 0.5f, 0.2f, 1.0f};
                 conf.addTransformAffine(matrix);
             }},
            {"transform_perspective",
             [](dai::ImageManipConfig& conf) {
                 std::array<float, 9> matrix = {
                     1.0f,
                     0.2f,
                     0.0f,  // First row
                     0.1f,
                     1.0f,
                     0.0f,  // Second row
                     0.001f,
                     0.002f,
                     1.0f  // Third row
                 };
                 conf.addTransformPerspective(matrix);
             }},
            // Frame type conversion
            {"frame_type", [](dai::ImageManipConfig& conf) { conf.setFrameType(dai::ImgFrame::Type::RAW8); }}};

        // Create manipulator nodes and queues
        std::map<std::string, std::shared_ptr<dai::MessageQueue>> queues;
        for(const auto& [name, config] : manipOps) {
            std::cout << "Creating manipulator: " << name << std::endl;
            auto manip = pipeline.create<dai::node::ImageManip>();
            config(*manip->initialConfig);
            manipInput->out.link(manip->inputImage);
            queues[name] = manip->out.createOutputQueue(4, false);
        }

        // Load and prepare input image
        cv::Mat inputFrame = cv::imread(LENNA_PATH);  // 512x512
        if(inputFrame.empty()) {
            throw std::runtime_error("Could not read input image");
        }

        // Create and send input frame
        auto imgFrame = std::make_shared<dai::ImgFrame>();
        cv::Mat downscaled;
        cv::pyrDown(inputFrame, downscaled);
        imgFrame->setCvFrame(downscaled, dai::ImgFrame::Type::BGR888i);
        inputQueue->send(imgFrame);

        // Display input image
        cv::imshow("input_image", inputFrame);

        // Start pipeline
        pipeline.start();

        // Process and display results
        for(const auto& [name, queue] : queues) {
            auto inFrame = queue->get<dai::ImgFrame>();
            cv::imshow(name, inFrame->getCvFrame());
        }

        // Wait for key press or signal
        while(!quitEvent) {
            if(cv::waitKey(50) >= 0) break;
        }

        // Cleanup
        pipeline.stop();
        pipeline.wait();

    } catch(const std::exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
        return 1;
    }

    return 0;
}
```

### Need assistance?

Head over to [Discussion Forum](https://discuss.luxonis.com/) for technical support or any other questions you might have.
