DepthAI
Software Stack

ON THIS PAGE

  • Pipeline
  • Source code

Camera still image at max resolution

Supported on:RVC2RVC4
This example shows how to capture a max resolution still image while streaming lower resolution frames to the host.By default, camera will stream (1333x1000) frames to the host computer, and when the user presses c key, it will capture a still image at max resolution (for OAK4 cameras that's 48MP) and save it to the .png file in the current directory.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
5import numpy as np
6
7# Create pipeline
8with dai.Pipeline() as pipeline:
9    # Define source and output
10    cam = pipeline.create(dai.node.Camera).build(dai.CameraBoardSocket.CAM_A)
11    cam_q_in = cam.inputControl.createInputQueue()
12
13    cam_input_q = cam.inputControl.createInputQueue()
14    # In some cases (IMX586), this requires an 8k screen to be able to see the full resolution at once
15    stream_highest_res = cam.requestFullResolutionOutput(useHighestResolution=True)
16
17    script = pipeline.create(dai.node.Script)
18    stream_highest_res.link(script.inputs["in"])
19    # Current workaround for OAK4 cameras, as Camera node doesn't yet support "still" frame capture
20    script.setScript(
21        """
22        while True:
23            message = node.inputs["in"].get()
24            trigger = node.inputs["trigger"].tryGet()
25            if trigger is not None:
26                node.warn("Trigger received!")
27                node.io["highest_res"].send(message)
28        """)
29
30    # If 8k, we can only have 1 output stream, so we need to use ImageManip to downscale
31    imgManip = pipeline.create(dai.node.ImageManip)
32    stream_highest_res.link(imgManip.inputImage)
33    imgManip.initialConfig.setOutputSize(1333, 1000)
34    imgManip.setMaxOutputFrameSize(1333*1000*3)
35    downscaled_res_q = imgManip.out.createOutputQueue()
36
37    highest_res_q = script.outputs["highest_res"].createOutputQueue()
38    q_trigger = script.inputs["trigger"].createInputQueue()
39
40    # Connect to device and start pipeline
41    ctrl = dai.CameraControl()
42    pipeline.start()
43    print("To capture an image, press 'c'")
44    while pipeline.isRunning():
45        img_hd: dai.ImgFrame = downscaled_res_q.get()
46        frame = img_hd.getCvFrame()
47        cv2.imshow("video", frame)
48
49        key = cv2.waitKey(1)
50        if key == ord("q"):
51            break
52        if key == ord('c'):
53            # Send a trigger message to the Script node
54            q_trigger.send(dai.Buffer())
55
56        if highest_res_q.has():
57            highres_img = highest_res_q.get()
58            frame = highres_img.getCvFrame()
59            # Save the full image
60            cv2.imwrite("full_image.png", frame)

C++

1#include <iostream>
2#include <memory>
3#include <opencv2/opencv.hpp>
4
5#include "depthai/depthai.hpp"
6
7int main() {
8    // Create device
9    std::shared_ptr<dai::Device> device = std::make_shared<dai::Device>();
10
11    // Create pipeline
12    dai::Pipeline pipeline(device);
13
14    // Create nodes
15    auto cam = pipeline.create<dai::node::Camera>()->build(dai::CameraBoardSocket::CAM_A);
16    auto camQIn = cam->inputControl.createInputQueue();
17
18    // In some cases (IMX586), this requires an 8k screen to be able to see the full resolution at once
19    auto streamHighestRes = cam->requestFullResolutionOutput();
20
21    // Create script node for still capture
22    auto script = pipeline.create<dai::node::Script>();
23    streamHighestRes->link(script->inputs["in"]);
24
25    // Current workaround for OAK4 cameras, as Camera node doesn't yet support "still" frame capture
26    script->setScript(R"(
27        while True:
28            message = node.inputs["in"].get()
29            trigger = node.inputs["trigger"].tryGet()
30            if trigger is not None:
31                node.warn("Trigger received!")
32                node.io["highest_res"].send(message)
33    )");
34
35    // If 8k, we can only have 1 output stream, so we need to use ImageManip to downscale
36    auto imgManip = pipeline.create<dai::node::ImageManip>();
37    streamHighestRes->link(imgManip->inputImage);
38    imgManip->initialConfig->setOutputSize(1333, 1000);
39    imgManip->setMaxOutputFrameSize(1333 * 1000 * 3);
40    auto downscaledResQ = imgManip->out.createOutputQueue();
41
42    auto highestResQ = script->outputs["highest_res"].createOutputQueue();
43    auto qTrigger = script->inputs["trigger"].createInputQueue();
44
45    // Start pipeline
46    pipeline.start();
47    std::cout << "To capture an image, press 'c'" << std::endl;
48
49    while(true) {
50        auto imgHd = downscaledResQ->get<dai::ImgFrame>();
51        if(imgHd == nullptr) continue;
52
53        cv::Mat frame = imgHd->getCvFrame();
54        cv::imshow("video", frame);
55
56        int key = cv::waitKey(1);
57        if(key == 'q') {
58            break;
59        }
60        if(key == 'c') {
61            // Send a trigger message to the Script node
62            qTrigger->send(std::make_shared<dai::Buffer>());
63        }
64
65        if(highestResQ->has()) {
66            auto highresImg = highestResQ->get<dai::ImgFrame>();
67            if(highresImg != nullptr) {
68                cv::Mat frame = highresImg->getCvFrame();
69                // Save the full image
70                cv::imwrite("full_image.png", frame);
71            }
72        }
73    }
74
75    return 0;
76}

Need assistance?

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