DepthAI
Software Stack

ON THIS PAGE

  • Demo
  • Pipeline
  • Source code

Camera ROI-based exposure and focus

Supported on:RVC2RVC4
This example lets user select a region of interest (ROI) on the frame (on the host computer), and after selection is complete, it will set the auto-exposure (AE) and auto-focus (AF) of the camera to the selected ROI.Similar application could be to set AF/AE based on object detection results, so the camera would automatically refocus and adjust exposure when a specific object is detected.

Demo

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

Pipeline

Source code

Python

Python
GitHub
1#!/usr/bin/env python3
2
3import cv2
4import depthai as dai
5
6# Create pipeline
7with dai.Pipeline() as pipeline:
8    # Define source and output
9    cam = pipeline.create(dai.node.Camera).build(dai.CameraBoardSocket.CAM_A)
10    cam_input_q = cam.inputControl.createInputQueue()
11    stream_q = cam.requestOutput((1920, 1080)).createOutputQueue()
12
13    cam_q_in = cam.inputControl.createInputQueue()
14
15    # Connect to device and start pipeline
16    pipeline.start()
17
18    # ROI selection variables
19    start_points = []
20    roi_rect = None
21    scale_factors = None
22    # Mouse callback function for ROI selection
23    def select_roi(event, x, y, flags, param):
24        global start_points, roi_rect
25        def set_roi_rect():
26            global roi_rect
27            x1, y1 = start_points
28            x2, y2 = (x, y)
29            roi_rect = (min(x1, x2), min(y1, y2), abs(x2-x1), abs(y2-y1))
30
31        if event == cv2.EVENT_LBUTTONDOWN:
32            roi_rect = None
33            start_points = (x, y)
34        elif event == cv2.EVENT_MOUSEMOVE and start_points:
35            set_roi_rect()
36        elif event == cv2.EVENT_LBUTTONUP and start_points:
37            set_roi_rect()
38            roi_rect_scaled = (
39                int(roi_rect[0] * scale_factors[0]),
40                int(roi_rect[1] * scale_factors[1]),
41                int(roi_rect[2] * scale_factors[0]),
42                int(roi_rect[3] * scale_factors[1])
43            )
44            print(f"ROI selected: {roi_rect}")
45            ctrl = dai.CameraControl()
46            print(f"Scaled ROI selected: {roi_rect_scaled}. Setting exposure and focus to this region.")
47            ctrl.setAutoExposureRegion(*roi_rect_scaled)
48            ctrl.setAutoFocusRegion(*roi_rect_scaled)
49            cam_q_in.send(ctrl)
50            start_points = None
51
52    # Create a window and set the mouse callback
53    cv2.namedWindow("video")
54    cv2.setMouseCallback("video", select_roi)
55
56    while pipeline.isRunning():
57        img_hd: dai.ImgFrame = stream_q.get()
58        if scale_factors is None:
59            print(img_hd.getTransformation().getSourceSize(), img_hd.getTransformation().getSize())
60            scale_factors = (img_hd.getTransformation().getSourceSize()[0] / img_hd.getTransformation().getSize()[0],
61                            img_hd.getTransformation().getSourceSize()[1] / img_hd.getTransformation().getSize()[1])
62        frame = img_hd.getCvFrame()
63
64        # Draw the ROI rectangle if it exists
65        if roi_rect is not None:
66            x, y, w, h = roi_rect
67            cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2)
68
69        cv2.imshow("video", frame)
70
71        key = cv2.waitKey(1)
72        if key == ord("q"):
73            break

C++

1#include <iostream>
2#include <memory>
3#include <opencv2/opencv.hpp>
4#include <tuple>
5
6#include "depthai/depthai.hpp"
7
8// Global variables for ROI selection
9std::vector<cv::Point> startPoints;
10cv::Rect roiRect;
11std::pair<float, float> scaleFactors;
12
13// Mouse callback function for ROI selection
14void selectRoi(int event, int x, int y, int flags, void* userdata) {
15    auto* camQIn = static_cast<std::shared_ptr<dai::InputQueue>*>(userdata);
16
17    if(event == cv::EVENT_LBUTTONDOWN) {
18        roiRect = cv::Rect();
19        startPoints.clear();
20        startPoints.push_back(cv::Point(x, y));
21    } else if(event == cv::EVENT_MOUSEMOVE && !startPoints.empty()) {
22        cv::Point start = startPoints[0];
23        roiRect = cv::Rect(std::min(start.x, x), std::min(start.y, y), std::abs(x - start.x), std::abs(y - start.y));
24    } else if(event == cv::EVENT_LBUTTONUP && !startPoints.empty()) {
25        cv::Point start = startPoints[0];
26        roiRect = cv::Rect(std::min(start.x, x), std::min(start.y, y), std::abs(x - start.x), std::abs(y - start.y));
27
28        // Scale ROI to original resolution
29        cv::Rect roiRectScaled(static_cast<int>(roiRect.x * scaleFactors.first),
30                               static_cast<int>(roiRect.y * scaleFactors.second),
31                               static_cast<int>(roiRect.width * scaleFactors.first),
32                               static_cast<int>(roiRect.height * scaleFactors.second));
33
34        std::cout << "ROI selected: " << roiRect << std::endl;
35        std::cout << "Scaled ROI selected: " << roiRectScaled << ". Setting exposure and focus to this region." << std::endl;
36
37        // Create and send control message
38        auto ctrl = std::make_shared<dai::CameraControl>();
39        ctrl->setAutoExposureRegion(roiRectScaled.x, roiRectScaled.y, roiRectScaled.width, roiRectScaled.height);
40        ctrl->setAutoFocusRegion(roiRectScaled.x, roiRectScaled.y, roiRectScaled.width, roiRectScaled.height);
41        (*camQIn)->send(ctrl);
42
43        startPoints.clear();
44    }
45}
46
47int main() {
48    // Create device
49    std::shared_ptr<dai::Device> device = std::make_shared<dai::Device>();
50
51    // Create pipeline
52    dai::Pipeline pipeline(device);
53
54    // Create nodes
55    auto cam = pipeline.create<dai::node::Camera>()->build(dai::CameraBoardSocket::CAM_A);
56    auto camQIn = cam->inputControl.createInputQueue();
57    auto streamQ = cam->requestOutput(std::make_pair(1920, 1080))->createOutputQueue();
58
59    // Start pipeline
60    pipeline.start();
61
62    // Create window and set mouse callback
63    cv::namedWindow("video");
64    cv::setMouseCallback("video", selectRoi, &camQIn);
65
66    while(true) {
67        auto imgHd = streamQ->get<dai::ImgFrame>();
68        if(imgHd == nullptr) continue;
69
70        // Calculate scale factors if not set
71        if(scaleFactors.first == 0.0f) {
72            auto sourceSize = imgHd->transformation.getSourceSize();
73            auto targetSize = imgHd->transformation.getSize();
74            scaleFactors = std::make_pair(static_cast<float>(sourceSize.first) / targetSize.first, static_cast<float>(sourceSize.second) / targetSize.second);
75            std::cout << "Source size: " << sourceSize.first << "x" << sourceSize.second << std::endl;
76            std::cout << "Target size: " << targetSize.first << "x" << targetSize.second << std::endl;
77        }
78
79        cv::Mat frame = imgHd->getCvFrame();
80
81        // Draw ROI rectangle if it exists
82        if(roiRect.width > 0 && roiRect.height > 0) {
83            cv::rectangle(frame, roiRect, cv::Scalar(0, 255, 0), 2);
84        }
85
86        cv::imshow("video", frame);
87
88        if(cv::waitKey(1) == 'q') {
89            break;
90        }
91    }
92
93    return 0;
94}

Need assistance?

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