Header

Let's go ahead and define the structure for our tutorial class.

We'll start with our imports: these are pretty straightforward, with a bunch of STL headers, OpenCV header, DepthAI headers, and finally, Smart Capture headers.

Next, we'll define our LuxonisDemo class inside the SmartCapture namespace. Along with the using statements for handling the std and std::chrono namespaces, these are just a bunch of quality of life improvements.

We have two public methods: a constructor, and a run_demo method that takes as an argument the number of frames to process before exiting the tutorial.

Privately, we have a bunch of depthAI objects to manage the data coming out of the Luxonis Camera, as well as a bunch of time_point objects and OpenCV frames to allocate memory efficiently once we're in the run loop.

Along with a few helper methods, the two Smart Capture related private fields we have are the string trigger_file_path and the std::shared_ptr<Client> client. We'll initialize both of these in the implementation of the constructor.

📘

So little Smart Capture!

If it feels like there's a lot of non-Smart Capture content in this Tutorial, you're not wrong.

In order to really show Smart Capture, we need object detection output to work with.

This isn't a trivial task no matter how you approach it in C++, but hopefully by using the Luxonis camera, it's a little more palatable.

The final header file in it's entirety below.

#include <iostream>
#include <string>
#include <vector>
#include <filesystem>
#include <fstream>
#include <memory>
#include <chrono>

#include <opencv2/opencv.hpp>
#include <opencv2/video.hpp>
#include <opencv2/core.hpp>

#include <client/client.hpp>
#include <rapidjson/document.h>

#include "depthai/depthai.hpp"

using namespace std::chrono;

using namespace std;

namespace SmartCapture {

    static const std::vector<std::string> labelMap = {"background", "aeroplane", 
                                                      "bicycle", "bird", "boat", 
                                                      "bottle", "bus", "car", "cat", 
                                                      "chair", "cow", "diningtable", 
                                                      "dog", "horse", "motorbike", 
                                                      "person", "pottedplant", "sheep", 
                                                      "sofa", "train", "tvmonitor"};
    static std::atomic<bool> syncNN{true};

    class LuxonisDemo {
    public:
        LuxonisDemo(const string &trigger_file_path, const string &blob_path);

        void run_demo(int frame_count);

    private:
        dai::Pipeline pipeline;
        std::shared_ptr<dai::Device> device;

        cv::Mat rightFrame;
        cv::Mat disparityFrame;
        std::vector<dai::ImgDetection> detections;

        std::shared_ptr<dai::DataOutputQueue> qRgb;
        std::shared_ptr<dai::DataOutputQueue> qNN;
        std::shared_ptr<dai::DataOutputQueue> qDet;

        cv::Mat frame;
        time_point<std::chrono::system_clock> startTime;
        time_point<std::chrono::system_clock> reload_time;
        time_point<std::chrono::system_clock> print_time;
        int counter = 0;
        float fps = 0;

        string trigger_file_path;

        std::shared_ptr<Client> client;

        void show(std::string name, 
                  cv::Mat frame, 
                  std::vector<dai::ImgDetection> &detections);

        void update_detection_state();
    };
}

Did this page help you?