wangrong
2025-03-19 291afb9c81aae1d15d9e3edcea618d0a2e1fc5a6
add samples
7个文件已添加
21个文件已修改
1259 ■■■■■ 已修改文件
nodes/ba/vp_ba_crossline_node.cpp 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
nodes/ba/vp_ba_jam_node.cpp 34 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
nodes/ba/vp_ba_jam_node.h 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
nodes/ba/vp_ba_stop_node.cpp 31 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
nodes/ba/vp_ba_stop_node.h 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
nodes/ba/vp_ba_width_calibration_node.cpp 182 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
nodes/ba/vp_ba_width_calibration_node.h 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
nodes/infers/vp_yolo_detector_node.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
nodes/osd/vp_ba_stop_osd_node.cpp 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
nodes/vp_infer_node.cpp 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
nodes/vp_rtsp_ffmpeg_src_node.cpp 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
objects/vp_frame_target.h 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
samples/CMakeLists.txt 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
samples/face_recognize/face_recognize_pipeline 补丁 | 查看 | 原始文档 | blame | 历史
samples/from_argv_all_in_one_sample.cpp 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
samples/from_argv_ba_crossline.cpp 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
samples/from_argv_ba_crossline_bak.cpp 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
samples/from_argv_ba_crossline_rtsp.cpp 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
samples/from_argv_ba_crossline_rtsp_mr.cpp 200 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
samples/from_argv_ba_jam_rtsp_m.cpp 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
samples/from_argv_ba_jam_rtsp_mr.cpp 206 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
samples/from_argv_test_width.cpp 140 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
samples/from_argv_width_calibration.cpp 199 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
samples/lpr_camera/plate_recognize_pipeline 补丁 | 查看 | 原始文档 | blame | 历史
samples/similiarity_search/face_encoding_pipeline 补丁 | 查看 | 原始文档 | blame | 历史
samples/similiarity_search/vehicle_encoding_pipeline 补丁 | 查看 | 原始文档 | blame | 历史
samples/vehicle_behaviour_analysis/vehicle_ba_pipeline 补丁 | 查看 | 原始文档 | blame | 历史
samples/vehicle_property_and_similiarity_search/vehicle_encoding_classify_pipeline 补丁 | 查看 | 原始文档 | blame | 历史
nodes/ba/vp_ba_crossline_node.cpp
@@ -42,6 +42,9 @@
        // for vp_frame_target only
        for (auto& target : meta->targets) {
            auto len = target->tracks.size();
            if (target->primary_label != target->class_label_of_car) {
                continue;
            }
            std::vector<int> involve_targets;
            if (len > 1 && target->track_id >= 0) {
                // check the last 2 points in tracks
@@ -54,11 +57,11 @@
                // `true and false`  or `false and true`
                // means target passed the line in current frame
                if (check1 ^ check2) {
                    total_crossline++;
                    involve_targets.push_back(target->track_id);
                    // not empty need fill ba result back to frame meta
                    if (involve_targets.size() > 0) {
                        bool is_entering = p1.y > p2.y;
                        total_crossline += (is_entering ? 1 : -1);
                        // send record image and record video signal, recording actions would occur if record nodes exist in pipeline
                        std::string image_file_name_without_ext = "";    // empty means no recording image
                        std::string video_file_name_without_ext = "";    // empty means no recording video
@@ -82,7 +85,7 @@
                                                                                    meta->frame_index, 
                                                                                    involve_targets, 
                                                                                    involve_region,
                                                                                    "cross_line",   // meaningful label
                                                                                    is_entering ? "cross_line_in" : "cross_line_out",   // meaningful label
                                                                                    image_file_name_without_ext, 
                                                                                    video_file_name_without_ext);
                        // fill back to frame meta
nodes/ba/vp_ba_jam_node.cpp
@@ -60,23 +60,23 @@
        // for vp_frame_target only
        std::vector<int> hit_traget_ids;
        for (auto& target : meta->targets) {
            auto len = target->tracks.size();
            auto loc = target->get_rect().track_point();
            // target has been tracked AND tracked enough frames
            if (len < check_interval_frames || target->track_id < 0) {
                continue;
            }
            // if target inside of stop region or not
            if (!point_in_poly(loc, jam_region)) {
                continue;
            }
            auto pre_loc = target->tracks[len - check_interval_frames].track_point();
            if (pre_loc.distance_with(loc) <= check_max_distance) {
                stop_checking_status[target->track_id]++;
                hit_traget_ids.push_back(target->track_id);
        for (auto &target : meta->targets) {
            if (target->primary_label != target->class_label_of_person) {
                auto len = target->tracks.size();
                auto loc = target->get_rect().track_point();
                // target has been tracked AND tracked enough frames
                if (len < check_interval_frames || target->track_id < 0) {
                    continue;
                }
                // if target inside of stop region or not
                if (!point_in_poly(loc, jam_region)) {
                    continue;
                }
                auto pre_loc = target->tracks[len - check_interval_frames].track_point();
                if (pre_loc.distance_with(loc) <= check_max_distance) {
                    stop_checking_status[target->track_id]++;
                    hit_traget_ids.push_back(target->track_id);
                }
            }
        }
nodes/ba/vp_ba_jam_node.h
@@ -32,11 +32,11 @@
        bool point_in_poly(vp_objects::vp_point p, std::vector<vp_objects::vp_point> region);
        // jam checking logic parameters which may be configed by constructor passed in by user
        const int check_interval_frames = 20;
        const int check_min_hit_frames = 25 * 2;  // 25 fps * 2 seconds
        const int check_max_distance = 8;
        const int check_min_stops = 8;
        const int check_notify_interval = 10;  // interval time (seconds) to notify (ensure not frequently)
        const int check_interval_frames = 70;
        const int check_min_hit_frames = 20 * 60 /3;  // 25 fps * 2 seconds
        const int check_max_distance = 10; //The closer the camera, the larger the pixel distance.
        const int check_min_stops = 2;
        const int check_notify_interval = 30;  // interval time (seconds) to notify (ensure not frequently)
    protected:
        virtual std::shared_ptr<vp_objects::vp_meta> handle_frame_meta(std::shared_ptr<vp_objects::vp_frame_meta> meta) override;
    public:
nodes/ba/vp_ba_stop_node.cpp
@@ -59,22 +59,25 @@
        // for vp_frame_target only
        std::vector<int> hit_traget_ids;
        for (auto& target : meta->targets) {
            auto len = target->tracks.size();
            auto loc = target->get_rect().track_point();
            if (target->primary_label == target->class_label_of_car)
            {
                auto len = target->tracks.size();
                auto loc = target->get_rect().track_point();
            // target has been tracked AND tracked enough frames
            if (len < check_interval_frames || target->track_id < 0) {
                continue;
            }
            // if target inside of stop region or not
            if (!point_in_poly(loc, stop_region)) {
                continue;
            }
                // target has been tracked AND tracked enough frames
                if (len < check_interval_frames || target->track_id < 0) {
                    continue;
                }
                // if target inside of stop region or not
                if (!point_in_poly(loc, stop_region)) {
                    continue;
                }
            auto pre_loc = target->tracks[len - check_interval_frames].track_point();
            if (pre_loc.distance_with(loc) <= check_max_distance) {
                stop_checking_status[target->track_id]++;
                hit_traget_ids.push_back(target->track_id);
                auto pre_loc = target->tracks[len - check_interval_frames].track_point();
                if (pre_loc.distance_with(loc) <= check_max_distance) {
                    stop_checking_status[target->track_id]++;
                    hit_traget_ids.push_back(target->track_id);
                }
            }
        }
nodes/ba/vp_ba_stop_node.h
@@ -26,9 +26,9 @@
        bool point_in_poly(vp_objects::vp_point p, std::vector<vp_objects::vp_point> region);
        // stop checking logic parameters which may be configed by constructor passed in by user
        const int check_interval_frames = 20;
        const int check_min_hit_frames = 25 * 2;  // 25 fps * 2 seconds
        const int check_max_distance = 5;
        const int check_interval_frames = 70;
        const int check_min_hit_frames = 20/3 * 60;  // 25 fps * 2 seconds
        const int check_max_distance = 15; //The closer the camera, the larger the pixel distance.
    protected:
        virtual std::shared_ptr<vp_objects::vp_meta> handle_frame_meta(std::shared_ptr<vp_objects::vp_frame_meta> meta) override;
    public:
nodes/ba/vp_ba_width_calibration_node.cpp
New file
@@ -0,0 +1,182 @@
#include "vp_ba_stop_node.h"
namespace vp_nodes {
    vp_ba_stop_node::vp_ba_stop_node(std::string node_name,
                                    std::map<int, std::vector<vp_objects::vp_point>> stop_regions,
                                    bool need_record_image,
                                    bool need_record_video):
                                    vp_node(node_name), all_stop_regions(stop_regions), need_record_image(need_record_image), need_record_video(need_record_video) {
        VP_INFO(vp_utils::string_format("[%s] %s", node_name.c_str(), to_string().c_str()));
        this->initialized();
    }
    vp_ba_stop_node::~vp_ba_stop_node() {
        deinitialized();
    }
    std::string vp_ba_stop_node::to_string() {
        /*
        * return vertexs of all stop regions
        * [channel0: x1,y1 x2,y2 ...][channel1: x1,y1 x2,y2 ...]...
        */
        std::stringstream ss;
        for(auto& r: all_stop_regions) {
            ss << "[channel" << r.first << ":";
            for(auto& p: r.second) {
                ss << " " << p.x << "," << p.y;
            }
            ss << "]";
        }
        return ss.str();
    }
    bool vp_ba_stop_node::point_in_poly(vp_objects::vp_point p, std::vector<vp_objects::vp_point> region) {
        int i, j, c = 0;
        int nvert = region.size();
        for (i = 0, j = nvert-1; i < nvert; j = i++) {
            if (((region[i].y > p.y) != (region[j].y > p.y)) &&
            (p.x < (region[j].x - region[i].x) * (p.y - region[i].y)
                / (region[j].y - region[i].y) + region[i].x))
            c = !c;
        }
        return c;
    }
    std::shared_ptr<vp_objects::vp_meta> vp_ba_stop_node::handle_frame_meta(std::shared_ptr<vp_objects::vp_frame_meta> meta) {
        // if need applied on current channel or not
        if (all_stop_regions.count(meta->channel_index) == 0) {
            return meta;
        }
        // for current channel
        auto& stop_region = all_stop_regions[meta->channel_index];
        auto& stop_checking_status = all_stop_checking_status[meta->channel_index];
        // for vp_frame_target only
        std::vector<int> hit_traget_ids;
        for (auto& target : meta->targets) {
            auto rect = target->get_rect();
            // VP_INFO(vp_utils::string_format("Target ID: %d, %d, %d, %d, %d, %s ",
            //     target->track_id, rect.x, rect.y, rect.width, rect.height, target->primary_label));
            if (target->primary_label == target->class_label_of_car)
            {
                auto len = target->tracks.size();
                auto loc = target->get_rect().track_point();
                // target has been tracked AND tracked enough frames
                if (len < check_interval_frames || target->track_id < 0) {
                    continue;
                }
                // if target inside of stop region or not
                if (!point_in_poly(loc, stop_region)) {
                    continue;
                }
                VP_INFO(vp_utils::string_format("Target ID: %d, %d, %d, %d, %d, %s ",
                    target->track_id, rect.x, rect.y, rect.width, rect.height, target->primary_label));
                auto pre_loc = target->tracks[len - check_interval_frames].track_point();
                if (pre_loc.distance_with(loc) <= check_max_distance) {
                    stop_checking_status[target->track_id]++;
                    hit_traget_ids.push_back(target->track_id);
                }
            }
        }
        for (auto i = stop_checking_status.begin(); i != stop_checking_status.end();) {
            if (std::find(hit_traget_ids.begin(), hit_traget_ids.end(), i->first) == hit_traget_ids.end()) {
                // statisfy unstop condition
                if (i->second >= check_min_hit_frames) {
                    std::vector<int> involve_targets;
                    involve_targets.push_back(i->first);
                    // send record image and record video signal, recording actions would occur if record nodes exist in pipeline
                    std::string image_file_name_without_ext = "";    // empty means no recording image
                    std::string video_file_name_without_ext = "";    // empty means no recording video
                    // send image record control meta
                    if (need_record_image) {
                        image_file_name_without_ext = vp_utils::time_format(NOW, "unstop_image__<year><mon><day><hour><min><sec><mili>");
                        auto image_record_control_meta = std::make_shared<vp_objects::vp_image_record_control_meta>(meta->channel_index, image_file_name_without_ext, true);
                        pendding_meta(image_record_control_meta);
                    }
                    // send video record control meta
                    if (need_record_video) {
                        video_file_name_without_ext = vp_utils::time_format(NOW, "unstop_video__<year><mon><day><hour><min><sec><mili>");
                        auto video_record_control_meta = std::make_shared<vp_objects::vp_video_record_control_meta>(meta->channel_index, video_file_name_without_ext);
                        pendding_meta(video_record_control_meta);
                    }
                    std::vector<vp_objects::vp_point> involve_region = stop_region;
                    auto ba_result = std::make_shared<vp_objects::vp_ba_result>(vp_objects::vp_ba_type::UNSTOP,
                                                                                meta->channel_index,
                                                                                meta->frame_index,
                                                                                involve_targets,
                                                                                involve_region,
                                                                                "unstop",   // meaningful label
                                                                                image_file_name_without_ext,
                                                                                video_file_name_without_ext);
                    // fill back to frame meta
                    meta->ba_results.push_back(ba_result);
                    // info log
                    VP_INFO(vp_utils::string_format("[%s] [channel %d] has found target unstop", node_name.c_str(), meta->channel_index));
                    if (need_record_image || need_record_video) {
                        VP_INFO(vp_utils::string_format("[%s] [channel %d] image & video record file names are: [%s & %s]", node_name.c_str(), meta->channel_index, image_file_name_without_ext.c_str(), video_file_name_without_ext.c_str()));
                    }
                }
                // remove since it not satisfy stop condition
                i = stop_checking_status.erase(i);
                continue;
            }
            // equal means first time to satisfy stop condition
            if (i->second == check_min_hit_frames) {
                std::vector<int> involve_targets;
                involve_targets.push_back(i->first);
                // send record image and record video signal, recording actions would occur if record nodes exist in pipeline
                std::string image_file_name_without_ext = "";    // empty means no recording image
                std::string video_file_name_without_ext = "";    // empty means no recording video
                // send image record control meta
                if (need_record_image) {
                    image_file_name_without_ext = vp_utils::time_format(NOW, "stop_image__<year><mon><day><hour><min><sec><mili>");
                    auto image_record_control_meta = std::make_shared<vp_objects::vp_image_record_control_meta>(meta->channel_index, image_file_name_without_ext, true);
                    pendding_meta(image_record_control_meta);
                }
                // send video record control meta
                if (need_record_video) {
                    video_file_name_without_ext = vp_utils::time_format(NOW, "stop_video__<year><mon><day><hour><min><sec><mili>");
                    auto video_record_control_meta = std::make_shared<vp_objects::vp_video_record_control_meta>(meta->channel_index, video_file_name_without_ext);
                    pendding_meta(video_record_control_meta);
                }
                std::vector<vp_objects::vp_point> involve_region = stop_region;
                auto ba_result = std::make_shared<vp_objects::vp_ba_result>(vp_objects::vp_ba_type::STOP,
                                                                            meta->channel_index,
                                                                            meta->frame_index,
                                                                            involve_targets,
                                                                            involve_region,
                                                                            "stop",   // meaningful label
                                                                            image_file_name_without_ext,
                                                                            video_file_name_without_ext);
                // fill back to frame meta
                meta->ba_results.push_back(ba_result);
                // info log
                VP_INFO(vp_utils::string_format("[%s] [channel %d] has found target stop", node_name.c_str(), meta->channel_index));
                if (need_record_image || need_record_video) {
                    VP_INFO(vp_utils::string_format("[%s] [channel %d] image & video record file names are: [%s & %s]", node_name.c_str(), meta->channel_index, image_file_name_without_ext.c_str(), video_file_name_without_ext.c_str()));
                }
            }
            i++;
        }
        return meta;
    }
}
nodes/ba/vp_ba_width_calibration_node.h
New file
@@ -0,0 +1,46 @@
#pragma once
#include <map>
#include "../vp_node.h"
#include "../../objects/shapes/vp_point.h"
#include "../../objects/shapes/vp_line.h"
#include "../../objects/vp_image_record_control_meta.h"
#include "../../objects/vp_video_record_control_meta.h"
namespace vp_nodes {
    // behaviour analysis node for stop (support multi channels)
    class vp_ba_stop_node: public vp_node
    {
    private:
        // channel -> vertexs of region, 1 channel supports only 1 region at most (can be 0, which means no stop check on this channel)
        std::map<int, std::vector<vp_objects::vp_point>> all_stop_regions;
        // channel -> status of targets (id -> num of hit frames)
        std::map<int, std::map<int, int>> all_stop_checking_status;
        std::ofstream record_file;  // File stream for recording
        // record params
        bool need_record_image;
        bool need_record_video;
        // check if point inside of polygon
        bool point_in_poly(vp_objects::vp_point p, std::vector<vp_objects::vp_point> region);
        // stop checking logic parameters which may be configed by constructor passed in by user
        const int check_interval_frames = 70;
        const int check_min_hit_frames = 20/3 * 60;  // 25 fps * 2 seconds
        const int check_max_distance = 15; //The closer the camera, the larger the pixel distance
        void open_record_file();
        void close_record_file();
    protected:
        virtual std::shared_ptr<vp_objects::vp_meta> handle_frame_meta(std::shared_ptr<vp_objects::vp_frame_meta> meta) override;
    public:
        vp_ba_stop_node(std::string node_name,
                            std::map<int, std::vector<vp_objects::vp_point>> stop_regions,
                            bool need_record_image = true,
                            bool need_record_video = true);
        ~vp_ba_stop_node();
        std::string to_string() override;
    };
}
nodes/infers/vp_yolo_detector_node.h
@@ -23,7 +23,7 @@
                            int input_height = 416, 
                            int batch_size = 1,
                            int class_id_offset = 0,
                            float score_threshold = 0.5,
                            float score_threshold = 0.7,
                            float confidence_threshold = 0.5,
                            float nms_threshold = 0.5,
                            float scale = 1 / 255.0,
nodes/osd/vp_ba_stop_osd_node.cpp
@@ -27,6 +27,7 @@
            // track_id
            auto id = std::to_string(i->track_id);
            auto labels_to_display = i->primary_label;
            auto primary_score_ = std::to_string(i->primary_score);
            // tracked
            if (i->track_id != -1) {
@@ -34,7 +35,7 @@
            }
            
            for (auto& label : i->secondary_labels) {
                labels_to_display += "|" + label;
                labels_to_display += "|" + label + "|" + primary_score_;
            }
            
            // draw tracks if size>=2
nodes/vp_infer_node.cpp
@@ -1,5 +1,6 @@
#include <fstream>
#include <iostream>
#include "vp_infer_node.h"
@@ -33,6 +34,8 @@
        // try to load network from file,
        // failing means maybe it has a custom implementation for model loading in derived class such as using other backends other than opencv::dnn.
        try {
            std::cout << "Model path: " << model_path << std::endl;
            std::cout << "Model config path: " << model_config_path << std::endl;
            net = cv::dnn::readNet(model_path, model_config_path);
            #ifdef VP_WITH_CUDA
            net.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA);
nodes/vp_rtsp_ffmpeg_src_node.cpp
@@ -59,7 +59,7 @@
                result += buffer;
            }
            pclose(pipe);
            VP_INFO(vp_utils::string_format("FFPROBE RESULT:%s ", result));
            VP_INFO(vp_utils::string_format("FFPROBE RESULT:%s url: %s", result, rtsp_url.c_str()));
            // Parse the output (expected format: width,height,r_frame_rate)
            std::stringstream ss(result);
@@ -364,4 +364,4 @@
    {
        return rtsp_url;
    }
}
}
objects/vp_frame_target.h
@@ -30,6 +30,10 @@
    public:
        // default person label
        std::string class_label_of_person = "person";
        // default car label
        std::string class_label_of_car = "car";
        // default trush label
        std::string class_label_of_trush = "trush";
        // x of top left
        int x;
        // y of top left
samples/CMakeLists.txt
@@ -3,6 +3,29 @@
    message(FATAL_ERROR "can ONLY be called by parent CMakeLists.txt.")
endif()
# 查找 pkg-config 包
find_package(PkgConfig REQUIRED)
# 使用 pkg-config 查找 GStreamer 和 gstreamer-rtsp-server
pkg_check_modules(GSTREAMER REQUIRED gstreamer-1.0)
pkg_check_modules(GSTREAMER_RTSP_SERVER REQUIRED gstreamer-rtsp-server-1.0)
# 将 GStreamer 和 RTSP 头文件路径添加到 include 目录中
include_directories(${GSTREAMER_INCLUDE_DIRS} ${GSTREAMER_RTSP_SERVER_INCLUDE_DIRS})
# 将库路径添加到链接目录
link_directories(${GSTREAMER_LIBRARY_DIRS} ${GSTREAMER_RTSP_SERVER_LIBRARY_DIRS})
# 通过 pkg-config 提供的 flags,设置编译和链接的 flags
add_definitions(${GSTREAMER_DEFINITIONS} ${GSTREAMER_RTSP_SERVER_DEFINITIONS})
# 在编译时链接 GStreamer 和 RTSP 相关的库
#target_link_libraries(your_target_name
#    ${GSTREAMER_LIBRARIES}
#    ${GSTREAMER_RTSP_SERVER_LIBRARIES}
#)
message("start build for simple samples...")
# save all exe to 'build/bin'
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
@@ -167,7 +190,9 @@
    add_executable(from_argv_ba_jam_rtsp_m "from_argv_ba_jam_rtsp_m.cpp")
    target_link_libraries(from_argv_ba_jam_rtsp_m ${PROJECT_NAME})
    add_executable(from_argv_ba_jam_rtsp_mr "from_argv_ba_jam_rtsp_mr.cpp")
    target_link_libraries(from_argv_ba_jam_rtsp_mr ${PROJECT_NAME})
    add_executable(from_argv_ba_stop "from_argv_ba_stop.cpp")
    target_link_libraries(from_argv_ba_stop ${PROJECT_NAME})
samples/face_recognize/face_recognize_pipeline
Binary files differ
samples/from_argv_all_in_one_sample.cpp
@@ -51,8 +51,8 @@
        return -1;
    }
    // create nodes
    auto file_src_0 = std::make_shared<vp_nodes::vp_file_src_node>("file_src_0", 0, video_path, resize_ratio);
    // create nodes bool cycle = true,  std::string gst_decoder_name = "avdec_h264",  int skip_interval = 0
    auto file_src_0 = std::make_shared<vp_nodes::vp_file_src_node>("file_src_0", 0, video_path, resize_ratio, true, "avdec_h264",3);
    //auto file_src_1 = std::make_shared<vp_nodes::vp_file_src_node>("file_src_1", 1, "./vp_data/test_video/falldown.mp4", 0.5);
    //auto split = std::make_shared<vp_nodes::vp_split_node>("split", false, true);  // split by deep-copy not by channel!
    
@@ -64,11 +64,13 @@
    
    auto tracker = std::make_shared<vp_nodes::vp_sort_track_node>("sort_tracker");
    
    // define a region in frame for every channel (value MUST in the scope of frame'size)
    // define a region in frame for every channel (value MUST in the scope of frame'size) (224,74),(346,64),(486,342),(9,342) vp_point(450, 100), vp_objects::vp_point(792, 80), vp_objects::vp_point(1100, 684), vp_objects::vp_point(18, 682)
    std::map<int, std::vector<vp_objects::vp_point>> regions = {
        {0, std::vector<vp_objects::vp_point>{vp_objects::vp_point(20, 30), vp_objects::vp_point(600, 40), vp_objects::vp_point(600, 300), vp_objects::vp_point(10, 300)}},  // channel0 -> region
        {1, std::vector<vp_objects::vp_point>{vp_objects::vp_point(20, 30), vp_objects::vp_point(1000, 40), vp_objects::vp_point(1000, 600), vp_objects::vp_point(10, 600)}}   // channel1 -> region
    };
        {0, std::vector<vp_objects::vp_point>{vp_objects::vp_point(int(616*resize_ratio), int(13*resize_ratio)),
            vp_objects::vp_point(int(670*resize_ratio), int(11*resize_ratio)),
            vp_objects::vp_point(int(1100*resize_ratio), int(684*resize_ratio)),
            vp_objects::vp_point(int(18*resize_ratio), int(610*resize_ratio))}},  // channel0 -> region
     };
    auto ba_jam = std::make_shared<vp_nodes::vp_ba_jam_node>("ba_jam", regions);
    auto ba_stop = std::make_shared<vp_nodes::vp_ba_stop_node>("ba_stop", regions);
    
@@ -79,7 +81,7 @@
    vp_objects::vp_point right_end(10, 10);  // change to proper value
    std::map<int, std::vector<vp_objects::vp_point>> left_lines = {{0, {left_start, left_end}}};  // channel0 -> point vector
    std::map<int, std::vector<vp_objects::vp_point>> right_lines = {{0, {right_start, right_end}}};  // channel0 -> point vector
    int half_screen_width = 384;
    int half_screen_width = 640;
    auto ba_wrong_direction = std::make_shared<vp_nodes::vp_ba_wrong_direction_node>("vp_ba_wrong_direction_node", left_lines,right_lines,half_screen_width,true,true);
       
    int min_gathering_count = 2;
@@ -90,7 +92,7 @@
    auto ba_report_detect = std::make_shared<vp_nodes::vp_ba_report_detect_node>("ba_report_detect_node","fire_smoke",std::vector<int>{1000,1001,1002}, true,true);
    auto json_kafka_broker_0 = std::make_shared<vp_nodes::vp_json_kafka_broker_node>("json_kafka_broker_0", "192.168.0.85:9092", "vp_ba_vehicle", vp_nodes::vp_broke_for::BARESULT);
    auto json_kafka_broker_0 = std::make_shared<vp_nodes::vp_json_kafka_broker_node>("json_kafka_broker_0", "172.18.0.247:9092", "vp_ba_result", vp_nodes::vp_broke_for::BARESULT);
    auto osd_0 = std::make_shared<vp_nodes::vp_ba_stop_osd_node>("osd_0");
    auto recorder = std::make_shared<vp_nodes::vp_record_node>("recorder", "./record", "./record");
    
@@ -119,8 +121,8 @@
    file_src_0->start();
    // for debug purpose
    vp_utils::vp_analysis_board board({file_src_0});
    board.display(1, false);
    // vp_utils::vp_analysis_board board({file_src_0});
    // board.display(1, false);
    std::string wait;
    std::getline(std::cin, wait);
samples/from_argv_ba_crossline.cpp
@@ -38,16 +38,17 @@
    // create nodes
    auto file_src_0 = std::make_shared<vp_nodes::vp_file_src_node>("file_src_0", 0, video_path, resize_ratio);
    //auto file_src_0 = std::make_shared<vp_nodes::vp_file_src_node>("file_src_0", 0, video_path, resize_ratio);
    auto file_src_0 = std::make_shared<vp_nodes::vp_rtsp_ffmpeg_src_node>("rtsp_src_1", 0, video_path, resize_ratio, 3, false);
    auto yolo_detector = std::make_shared<vp_nodes::vp_yolo_detector_node>("yolo_detector", "./vp_data/models/det_cls/yolov3-tiny-2022-0721_best.weights", "./vp_data/models/det_cls/yolov3-tiny-2022-0721.cfg", "./vp_data/models/det_cls/yolov3_tiny_5classes.txt");
    auto tracker = std::make_shared<vp_nodes::vp_sort_track_node>("sort_tracker");
    
    // define a line in frame for every channel (value MUST in the scope of frame'size)
    vp_objects::vp_point start(0, 250);  // change to proper value
    vp_objects::vp_point end(700, 220);  // change to proper value
    vp_objects::vp_point start(30, 140);  // change to proper value     0,250
    vp_objects::vp_point end(610, 110);  // change to proper value     700,220
    std::map<int, vp_objects::vp_line> lines = {{0, vp_objects::vp_line(start, end)}};  // channel0 -> line
    auto ba_crossline = std::make_shared<vp_nodes::vp_ba_crossline_node>("ba_crossline", lines);
    auto json_kafka_broker_0 = std::make_shared<vp_nodes::vp_json_kafka_broker_node>("json_kafka_broker_0", "192.168.130.228:9092", "vp_ba_crossline", vp_nodes::vp_broke_for::BARESULT);
    auto json_kafka_broker_0 = std::make_shared<vp_nodes::vp_json_kafka_broker_node>("json_kafka_broker_0", "172.18.0.247:9092", "vp_ba_result", vp_nodes::vp_broke_for::BARESULT);
    auto osd = std::make_shared<vp_nodes::vp_ba_crossline_osd_node>("osd");
    auto screen_des_0 = std::make_shared<vp_nodes::vp_screen_des_node>("screen_des_0", 0);
    
samples/from_argv_ba_crossline_bak.cpp
New file
@@ -0,0 +1,71 @@
#include "../nodes/vp_file_src_node.h"
#include "../nodes/infers/vp_yolo_detector_node.h"
#include "../nodes/track/vp_sort_track_node.h"
#include "../nodes/ba/vp_ba_crossline_node.h"
#include "../nodes/osd/vp_ba_crossline_osd_node.h"
#include "../nodes/vp_screen_des_node.h"
#include "../nodes/vp_rtmp_des_node.h"
#include "../nodes/broker/vp_json_kafka_broker_node.h"
#include "../utils/analysis_board/vp_analysis_board.h"
/*
* ## ba crossline sample ##
* behaviour analysis for crossline.
*/
int main(int argc, char* argv[]) {
    VP_SET_LOG_LEVEL(vp_utils::vp_log_level::INFO);
    VP_LOGGER_INIT();
    std::vector<std::string> args(argv + 1, argv + argc);
    // 默认的命令行参数
    std::string video_path = "./vp_data/test_video/vehicle_count.mp4";
    float resize_ratio = 0.4;
    // 如果提供了第一个和第二个参数,则覆盖默认的路径
    if (args.size() >= 1) {
        video_path = args[0];
        if (args.size() >= 2){
            resize_ratio = std::stof(args[1]);
        }
    } else {
        std::cout << "Usage: " << argv[0] << " <video_path> [resize_ratio]\n";
        std::cout << "Example: " << argv[0] << " ./vp_data/test_video/vehicle_count.mp4 0.4\n";
        return -1;
    }
    // create nodes
    auto file_src_0 = std::make_shared<vp_nodes::vp_file_src_node>("file_src_0", 0, video_path, resize_ratio);
    auto yolo_detector = std::make_shared<vp_nodes::vp_yolo_detector_node>("yolo_detector", "./vp_data/models/det_cls/yolov3-tiny-2022-0721_best.weights", "./vp_data/models/det_cls/yolov3-tiny-2022-0721.cfg", "./vp_data/models/det_cls/yolov3_tiny_5classes.txt");
    auto tracker = std::make_shared<vp_nodes::vp_sort_track_node>("sort_tracker");
    // define a line in frame for every channel (value MUST in the scope of frame'size)
    vp_objects::vp_point start(0, 250);  // change to proper value
    vp_objects::vp_point end(700, 220);  // change to proper value
    std::map<int, vp_objects::vp_line> lines = {{0, vp_objects::vp_line(start, end)}};  // channel0 -> line
    auto ba_crossline = std::make_shared<vp_nodes::vp_ba_crossline_node>("ba_crossline", lines);
    auto json_kafka_broker_0 = std::make_shared<vp_nodes::vp_json_kafka_broker_node>("json_kafka_broker_0", "192.168.130.228:9092", "vp_ba_crossline", vp_nodes::vp_broke_for::BARESULT);
    auto osd = std::make_shared<vp_nodes::vp_ba_crossline_osd_node>("osd");
    auto screen_des_0 = std::make_shared<vp_nodes::vp_screen_des_node>("screen_des_0", 0);
    // construct pipeline
    yolo_detector->attach_to({file_src_0});
    tracker->attach_to({yolo_detector});
    ba_crossline->attach_to({tracker});
    json_kafka_broker_0->attach_to({ba_crossline});
    osd->attach_to({json_kafka_broker_0});
    screen_des_0->attach_to({osd});
    file_src_0->start();
    // for debug purpose
    vp_utils::vp_analysis_board board({file_src_0});
    board.display(1, false);
    std::string wait;
    std::getline(std::cin, wait);
    file_src_0->detach_recursively();
}
samples/from_argv_ba_crossline_rtsp.cpp
@@ -1,6 +1,5 @@
#include "../nodes/vp_file_src_node.h"
#include "../nodes/vp_rtsp_src_node.h"
#include "../nodes/vp_rtsp_ffmpeg_src_node.h"
#include "../nodes/infers/vp_yolo_detector_node.h"
#include "../nodes/track/vp_sort_track_node.h"
#include "../nodes/ba/vp_ba_crossline_node.h"
@@ -8,7 +7,6 @@
#include "../nodes/vp_screen_des_node.h"
#include "../nodes/vp_rtmp_des_node.h"
#include "../nodes/broker/vp_json_kafka_broker_node.h"
#include "../nodes/vp_file_des_node.h"
#include "../utils/analysis_board/vp_analysis_board.h"
@@ -23,56 +21,54 @@
    std::vector<std::string> args(argv + 1, argv + argc);
    // 默认的命令行参数
    std::string rtsp_path = "rtsp://192.168.1.24:8554/demo";
    std::string kafka_server_point = "192.168.130.228:9092";
    std::string video_path = "./vp_data/test_video/vehicle_count.mp4";
    float resize_ratio = 0.4;
    int channel_index = 0;
    int skip_interval = 4;
    // 如果提供了第一个和第二个参数,则覆盖默认的路径
    if (args.size() >= 3) {
        rtsp_path = args[0];
    if (args.size() >= 4) {
        video_path = args[0];
        resize_ratio = std::stof(args[1]);
        kafka_server_point = args[2];
        channel_index = std::stof(args[2]);
        skip_interval = std::stof(args[3]);
    } else {
        std::cout << "Usage: " << argv[0] << " <rtsp_path> <resize_ratio> <kafka_server_point>\n";
        std::cout << "Example: " << argv[0] << " rtsp://192.168.1.24:8554/demo 0.4 192.168.130.228:9092\n";
        std::cout << "Usage: " << argv[0] << " <video_path> [resize_ratio]\n";
        std::cout << "Example: " << argv[0] << " ./vp_data/test_video/vehicle_count.mp4 0.4\n";
        return -1;
    }
    // create nodes
    //auto file_src_0 = std::make_shared<vp_nodes::vp_file_src_node>("file_src_0", 0, video_path, resize_ratio);
    auto rtsp_src_1 = std::make_shared<vp_nodes::vp_rtsp_src_node>("rtsp_src_1", 0, rtsp_path, resize_ratio, "avdec_h264");
    auto file_src_0 = std::make_shared<vp_nodes::vp_rtsp_ffmpeg_src_node>("rtsp_src_"+channel_index, channel_index, video_path, resize_ratio, skip_interval, false);
    auto yolo_detector = std::make_shared<vp_nodes::vp_yolo_detector_node>("yolo_detector", "./vp_data/models/det_cls/yolov3-tiny-2022-0721_best.weights", "./vp_data/models/det_cls/yolov3-tiny-2022-0721.cfg", "./vp_data/models/det_cls/yolov3_tiny_5classes.txt");
    auto tracker = std::make_shared<vp_nodes::vp_sort_track_node>("sort_tracker");
    
    // define a line in frame for every channel (value MUST in the scope of frame'size)
    vp_objects::vp_point start(30, 140);  // change to proper value     0,250
    vp_objects::vp_point end(610, 110);  // change to proper value     700,220
    std::map<int, vp_objects::vp_line> lines = {{0, vp_objects::vp_line(start, end)}};  // channel0 -> line
    std::map<int, vp_objects::vp_line> lines = {{channel_index, vp_objects::vp_line(start, end)}};  // channel0 -> line
    auto ba_crossline = std::make_shared<vp_nodes::vp_ba_crossline_node>("ba_crossline", lines);
    auto json_kafka_broker_0 = std::make_shared<vp_nodes::vp_json_kafka_broker_node>("json_kafka_broker_0", kafka_server_point, "vp_ba_crossline", vp_nodes::vp_broke_for::BARESULT);
    auto json_kafka_broker_0 = std::make_shared<vp_nodes::vp_json_kafka_broker_node>("json_kafka_broker_"+channel_index, "172.18.0.247:9092", "vp_ba_result", vp_nodes::vp_broke_for::BARESULT);
    auto osd = std::make_shared<vp_nodes::vp_ba_crossline_osd_node>("osd");
    auto screen_des_0 = std::make_shared<vp_nodes::vp_screen_des_node>("screen_des_0", 0);
    auto file_des_node_0 = std::make_shared<vp_nodes::vp_file_des_node>("file_des_0", 0, "out-a-osd", "out-a-osd", 1);
    auto screen_des_0 = std::make_shared<vp_nodes::vp_screen_des_node>("screen_des_0", channel_index);
    
    // construct pipeline
    yolo_detector->attach_to({rtsp_src_1});
    yolo_detector->attach_to({file_src_0});
    tracker->attach_to({yolo_detector});
    ba_crossline->attach_to({tracker});
    json_kafka_broker_0->attach_to({ba_crossline});
    osd->attach_to({json_kafka_broker_0});
    screen_des_0->attach_to({osd});
    file_des_node_0->attach_to({osd});
    rtsp_src_1->start();
    file_src_0->start();
    // for debug purpose
    vp_utils::vp_analysis_board board({rtsp_src_1});
    vp_utils::vp_analysis_board board({file_src_0});
    board.display(1, false);
    std::string wait;
    std::getline(std::cin, wait);
    rtsp_src_1->detach_recursively();
    file_src_0->detach_recursively();
}
samples/from_argv_ba_crossline_rtsp_mr.cpp
New file
@@ -0,0 +1,200 @@
#include "../nodes/vp_file_src_node.h"
#include "../nodes/vp_rtsp_src_node.h"
#include "../nodes/vp_rtsp_ffmpeg_src_node.h"
#include "../nodes/vp_split_node.h"
#include "../nodes/infers/vp_trt_vehicle_detector.h"
#include "../nodes/infers/vp_trt_vehicle_plate_detector.h"
#include "../nodes/infers/vp_trt_vehicle_color_classifier.h"
#include "../nodes/infers/vp_yolo_detector_node.h"
#include "../nodes/osd/vp_osd_node.h"
#include "../nodes/vp_sync_node.h"
#include "../nodes/track/vp_sort_track_node.h"
#include "../nodes/ba/vp_ba_crossline_node.h"
#include "../nodes/osd/vp_ba_crossline_osd_node.h"
#include "../nodes/broker/vp_json_kafka_broker_node.h"
#include "../nodes/record/vp_record_node.h"
#include "../nodes/vp_screen_des_node.h"
#include "../nodes/vp_fake_des_node.h"
#include "../nodes/vp_placeholder_node.h"
#include "../utils/analysis_board/vp_analysis_board.h"
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <map>
#include <sstream>
// Function to read configuration from a file
std::vector<std::vector<std::string>> read_config_file(const std::string& file_path) {
    std::vector<std::vector<std::string>> config_lines;
    std::string line;
    try {
        std::ifstream infile(file_path);
        while (std::getline(infile, line)) {
            std::vector<std::string> params;
            size_t start = 0;
            size_t end = line.find(" ");
            while (end != std::string::npos) {
                params.push_back(line.substr(start, end - start));
                start = end + 1;
                end = line.find(" ", start);
            }
            params.push_back(line.substr(start, end));  // add the last parameter
            config_lines.push_back(params);
        }
    } catch (const std::exception& e) {
        std::cerr << "read config file ex: " << std::string(e.what()) << " <config_file>\n";
    } catch (...) {
        std::cerr << "read config file ex end1111\n";
    }
    return config_lines;
}
// Function to parse polygon coordinates from string
std::vector<vp_objects::vp_point> parse_polygon(const std::string& polygon_str, float resize_ratio) {
    std::vector<vp_objects::vp_point> polygon;
    std::stringstream ss(polygon_str);
    std::string point_str;
    while (std::getline(ss, point_str, ')')) {
        size_t start = point_str.find('(');
        if (start != std::string::npos) {
            std::string coordinates = point_str.substr(start + 1);
            size_t comma_pos = coordinates.find(',');
            if (comma_pos != std::string::npos) {
                int x = std::stoi(coordinates.substr(0, comma_pos));
                int y = std::stoi(coordinates.substr(comma_pos + 1));
                x = static_cast<int>(std::round(x * resize_ratio));
                y = static_cast<int>(std::round(y * resize_ratio));
                polygon.push_back(vp_objects::vp_point(x, y));
            }
        }
    }
    return polygon;
}
int main(int argc, char* argv[]) {
    VP_SET_LOG_LEVEL(vp_utils::vp_log_level::INFO);
    VP_LOGGER_INIT();
    // Read configuration file
    if (argc < 2) {
        std::cerr << "Usage: " << argv[0] << " <config_file>\n";
        return -1;
    }
    try {
        std::string config_file = argv[1];
        auto configs = read_config_file(config_file);
        VP_INFO(vp_utils::string_format("Launch a thread for each configuration  [%s]", config_file));
        // Correct type declarations
        std::string kafka_server_point = "";
        std::vector<std::string> rtsp_srcs;
        std::vector<int> channel_indexs;
        std::vector<int> skip_intervals;
        std::vector<bool> use_gpus;
        std::vector<float> resize_ratios;
        // Use shared pointers for nodes
        std::vector<std::shared_ptr<vp_nodes::vp_node>> rtsp_nodes;
        // std::vector<std::shared_ptr<vp_nodes::vp_src_node>> rtsp_nodes;
        // Des节点
        std::vector<std::shared_ptr<vp_nodes::vp_des_node>> des_nodes;
        // define a region in frame for every channel (value MUST in the scope of frame'size)
        std::map<int, vp_objects::vp_line> lines = {};
        for (const auto& config : configs) {
            if (config.size() >= 5) {
                float resize_ratio = std::stof(config[1]);
                int skip_interval = std::stoi(config[3]);
                int channel_index = std::stoi(config[4]);
                bool usegpu = config.size() >= 6 && config[5] == "1";
                rtsp_srcs.push_back(config[0]);
                resize_ratios.push_back(resize_ratio);
                kafka_server_point = config[2];
                skip_intervals.push_back(skip_interval);
                channel_indexs.push_back(channel_index);
                use_gpus.push_back(usegpu);
                // Read and parse the polygon coordinates
                if (config.size() >= 7) {
                    std::string polygon_str = config[6];  // Assuming the polygon coordinates are in the 7th column
                    vp_objects::vp_point start(30, 140);  // change to proper value     0,250
                    vp_objects::vp_point end(610, 110);  // change to proper value     700,220
                    lines[channel_index] = vp_objects::vp_line(start, end);
                } else {
                    vp_objects::vp_point start(30, 140);  // change to proper value     0,250
                    vp_objects::vp_point end(610, 110);  // change to proper value     700,220
                    lines[channel_index] = vp_objects::vp_line(start, end);
                }
                rtsp_nodes.push_back(std::make_shared<vp_nodes::vp_rtsp_ffmpeg_src_node>(
                    "rtsp_src_" + config[4], channel_index, config[0], resize_ratio, skip_interval, usegpu));
                des_nodes.push_back(std::make_shared<vp_nodes::vp_fake_des_node>("fake_des_" + config[4], channel_index));
            } else {
                std::cerr << "Invalid config line: ";
                for (const auto& param : config) {
                    std::cerr << param << " ";
                }
                std::cerr << "\n";
            }
        }
        // branch 0
        auto vehicle_detector = std::make_shared<vp_nodes::vp_yolo_detector_node>("vehicle_detector", "./vp_data/models/det_cls/yolov3-tiny-2022-0721_best.weights", "./vp_data/models/det_cls/yolov3-tiny-2022-0721.cfg", "./vp_data/models/det_cls/yolov3_tiny_5classes.txt");
        auto tracker = std::make_shared<vp_nodes::vp_sort_track_node>("sort_tracker");
        // vp_objects::vp_point start(30, 140);  // change to proper value     0,250
        // vp_objects::vp_point end(610, 110);  // change to proper value     700,220
        // std::map<int, vp_objects::vp_line> lines = {{channel_index, vp_objects::vp_line(start, end)}};  // channel0 -> line
        auto ba_crossline = std::make_shared<vp_nodes::vp_ba_crossline_node>("ba_crossline", lines);
        auto json_kafka_broker_0 = std::make_shared<vp_nodes::vp_json_kafka_broker_node>("json_kafka_broker_0", kafka_server_point, "vp_ba_result", vp_nodes::vp_broke_for::BARESULT);
        auto osd = std::make_shared<vp_nodes::vp_ba_crossline_osd_node>("osd");
        auto recorder = std::make_shared<vp_nodes::vp_record_node>("recorder", "./record", "./record");
        auto split = std::make_shared<vp_nodes::vp_split_node>("split", true);
        // for testing. USING fake_des node in production
        auto fake_des_0 = std::make_shared<vp_nodes::vp_fake_des_node>("fake_des_0", 0);
        // construct pipeline
        vehicle_detector->attach_to(rtsp_nodes);
        tracker->attach_to({vehicle_detector});
        ba_crossline->attach_to({tracker});
        json_kafka_broker_0->attach_to({ba_crossline});
        osd->attach_to({json_kafka_broker_0});
        recorder->attach_to({osd});
        split->attach_to({recorder});
        for (size_t i = 0; i < des_nodes.size(); ++i) {
            des_nodes[i]->attach_to({split});
        }
        for (auto node : rtsp_nodes) {
            ((vp_nodes::vp_src_node*)node.get())->start();
        }
        std::string wait;
        std::getline(std::cin, wait);
        for (auto node : rtsp_nodes) {
            ((vp_nodes::vp_src_node*)node.get())->detach_recursively();
        }
    } catch (const std::exception& e) {
        std::cerr << "read config file ex: " << std::string(e.what()) << " <config_file>\n";
    } catch (...) {
        std::cerr << "read config file ex end\n";
    }
    return 0;
}
samples/from_argv_ba_jam_rtsp_m.cpp
@@ -110,7 +110,8 @@
                rtsp_nodes.push_back(std::make_shared<vp_nodes::vp_rtsp_ffmpeg_src_node>(
                    "rtsp_src_" + config[4], channel_index, config[0], resize_ratio, skip_interval, usegpu));
                des_nodes.push_back(std::make_shared<vp_nodes::vp_fake_des_node>("fake_des_" + config[4], channel_index));
                //des_nodes.push_back(std::make_shared<vp_nodes::vp_fake_des_node>("fake_des_" + config[4], channel_index));
                des_nodes.push_back(std::make_shared<vp_nodes::vp_screen_des_node>("screen_des_" + config[4], channel_index));
            } else {
                std::cerr << "Invalid config line: ";
@@ -136,9 +137,7 @@
        auto osd_0 = std::make_shared<vp_nodes::vp_ba_stop_osd_node>("osd_0", "./vp_data/font/NotoSansCJKsc-Medium.otf");
        auto recorder = std::make_shared<vp_nodes::vp_record_node>("recorder", "./record", "./record");
        auto split = std::make_shared<vp_nodes::vp_split_node>("split", true);
        // for testing. USING fake_des node in production
        auto fake_des_0 = std::make_shared<vp_nodes::vp_fake_des_node>("fake_des_0", 0);
        // construct pipeline
        vehicle_detector->attach_to(rtsp_nodes);
@@ -162,8 +161,8 @@
        }
        // for debug purpose
        // vp_utils::vp_analysis_board board(rtsp_nodes);
        // board.display(1, false);
        vp_utils::vp_analysis_board board(rtsp_nodes);
        board.display(1, true);
        std::string wait;
        std::getline(std::cin, wait);
samples/from_argv_ba_jam_rtsp_mr.cpp
New file
@@ -0,0 +1,206 @@
#include "../nodes/vp_file_src_node.h"
#include "../nodes/vp_rtsp_src_node.h"
#include "../nodes/vp_rtsp_ffmpeg_src_node.h"
#include "../nodes/vp_split_node.h"
#include "../nodes/infers/vp_trt_vehicle_detector.h"
#include "../nodes/infers/vp_trt_vehicle_plate_detector.h"
#include "../nodes/infers/vp_trt_vehicle_color_classifier.h"
#include "../nodes/infers/vp_yolo_detector_node.h"
#include "../nodes/osd/vp_osd_node.h"
#include "../nodes/vp_sync_node.h"
#include "../nodes/track/vp_sort_track_node.h"
#include "../nodes/ba/vp_ba_jam_node.h"
#include "../nodes/ba/vp_ba_stop_node.h"
#include "../nodes/osd/vp_ba_stop_osd_node.h"
#include "../nodes/broker/vp_json_kafka_broker_node.h"
#include "../nodes/record/vp_record_node.h"
#include "../nodes/vp_screen_des_node.h"
#include "../nodes/vp_fake_des_node.h"
#include "../nodes/vp_placeholder_node.h"
#include "../utils/analysis_board/vp_analysis_board.h"
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <map>
#include <sstream>
// Function to read configuration from a file
std::vector<std::vector<std::string>> read_config_file(const std::string& file_path) {
    std::vector<std::vector<std::string>> config_lines;
    std::string line;
    try {
        std::ifstream infile(file_path);
        while (std::getline(infile, line)) {
            std::vector<std::string> params;
            size_t start = 0;
            size_t end = line.find(" ");
            while (end != std::string::npos) {
                params.push_back(line.substr(start, end - start));
                start = end + 1;
                end = line.find(" ", start);
            }
            params.push_back(line.substr(start, end));  // add the last parameter
            config_lines.push_back(params);
        }
    } catch (const std::exception& e) {
        std::cerr << "read config file ex: " << std::string(e.what()) << " <config_file>\n";
    } catch (...) {
        std::cerr << "read config file ex end1111\n";
    }
    return config_lines;
}
// Function to parse polygon coordinates from string
std::vector<vp_objects::vp_point> parse_polygon(const std::string& polygon_str, float resize_ratio) {
    std::vector<vp_objects::vp_point> polygon;
    std::stringstream ss(polygon_str);
    std::string point_str;
    while (std::getline(ss, point_str, ')')) {
        size_t start = point_str.find('(');
        if (start != std::string::npos) {
            std::string coordinates = point_str.substr(start + 1);
            size_t comma_pos = coordinates.find(',');
            if (comma_pos != std::string::npos) {
                int x = std::stoi(coordinates.substr(0, comma_pos));
                int y = std::stoi(coordinates.substr(comma_pos + 1));
                x = static_cast<int>(std::round(x * resize_ratio));
                y = static_cast<int>(std::round(y * resize_ratio));
                polygon.push_back(vp_objects::vp_point(x, y));
            }
        }
    }
    return polygon;
}
int main(int argc, char* argv[]) {
    VP_SET_LOG_LEVEL(vp_utils::vp_log_level::INFO);
    VP_LOGGER_INIT();
    // Read configuration file
    if (argc < 2) {
        std::cerr << "Usage: " << argv[0] << " <config_file>\n";
        return -1;
    }
    try {
        std::string config_file = argv[1];
        auto configs = read_config_file(config_file);
        VP_INFO(vp_utils::string_format("Launch a thread for each configuration  [%s]", config_file));
        // Correct type declarations
        std::string kafka_server_point = "";
        std::vector<std::string> rtsp_srcs;
        std::vector<int> channel_indexs;
        std::vector<int> skip_intervals;
        std::vector<bool> use_gpus;
        std::vector<float> resize_ratios;
        // Use shared pointers for nodes
        std::vector<std::shared_ptr<vp_nodes::vp_node>> rtsp_nodes;
        // std::vector<std::shared_ptr<vp_nodes::vp_src_node>> rtsp_nodes;
        // Des节点
        std::vector<std::shared_ptr<vp_nodes::vp_des_node>> des_nodes;
        // define a region in frame for every channel (value MUST in the scope of frame'size)
        std::map<int, std::vector<vp_objects::vp_point>> regions = {};
        for (const auto& config : configs) {
            if (config.size() >= 5) {
                float resize_ratio = std::stof(config[1]);
                int skip_interval = std::stoi(config[3]);
                int channel_index = std::stoi(config[4]);
                bool usegpu = config.size() >= 6 && config[5] == "1";
                rtsp_srcs.push_back(config[0]);
                resize_ratios.push_back(resize_ratio);
                kafka_server_point = config[2];
                skip_intervals.push_back(skip_interval);
                channel_indexs.push_back(channel_index);
                use_gpus.push_back(usegpu);
                // Read and parse the polygon coordinates
                if (config.size() >= 7) {
                    std::string polygon_str = config[6];  // Assuming the polygon coordinates are in the 7th column
                    regions[channel_index] = parse_polygon(polygon_str,resize_ratio);
                } else {
                    // Default region if polygon is not provided
                    regions[channel_index] = std::vector<vp_objects::vp_point>{
                        vp_objects::vp_point(280, 30),
                        vp_objects::vp_point(340, 30),
                        vp_objects::vp_point(600, 330),
                        vp_objects::vp_point(30, 350)
                    };
                }
                rtsp_nodes.push_back(std::make_shared<vp_nodes::vp_rtsp_ffmpeg_src_node>(
                    "rtsp_src_" + config[4], channel_index, config[0], resize_ratio, skip_interval, usegpu));
                des_nodes.push_back(std::make_shared<vp_nodes::vp_fake_des_node>("fake_des_" + config[4], channel_index));
            } else {
                std::cerr << "Invalid config line: ";
                for (const auto& param : config) {
                    std::cerr << param << " ";
                }
                std::cerr << "\n";
            }
        }
        // branch 0
        auto vehicle_detector = std::make_shared<vp_nodes::vp_yolo_detector_node>("vehicle_detector", "./vp_data/models/det_cls/yolov3-tiny-2022-0721_best.weights", "./vp_data/models/det_cls/yolov3-tiny-2022-0721.cfg", "./vp_data/models/det_cls/yolov3_tiny_5classes.txt");
        auto trt_vehicle_plate_detector = std::make_shared<vp_nodes::vp_trt_vehicle_plate_detector>("vehicle_plate_detector", "./vp_data/models/trt/plate/vehicle_plate_box_detection.trt", "./vp_data/models/trt/plate/vehicle_plate_text_recognition.trt");
        auto trt_vehicle_color_classifier = std::make_shared<vp_nodes::vp_trt_vehicle_color_classifier>("color_cls", "./vp_data/models/trt/vehicle/vehicle_color_detection.trt", std::vector<int>{0, 1, 2});
        auto tracker = std::make_shared<vp_nodes::vp_sort_track_node>("sort_tracker");
        auto ba_jam = std::make_shared<vp_nodes::vp_ba_jam_node>("ba_jam", regions);
        auto ba_stop = std::make_shared<vp_nodes::vp_ba_stop_node>("ba_stop", regions);
        auto json_kafka_broker_0 = std::make_shared<vp_nodes::vp_json_kafka_broker_node>("json_kafka_broker_0", kafka_server_point, "vp_ba_result", vp_nodes::vp_broke_for::BARESULT);
        auto osd_0 = std::make_shared<vp_nodes::vp_ba_stop_osd_node>("osd_0", "./vp_data/font/NotoSansCJKsc-Medium.otf");
        auto recorder = std::make_shared<vp_nodes::vp_record_node>("recorder", "./record", "./record");
        auto split = std::make_shared<vp_nodes::vp_split_node>("split", true);
        // for testing. USING fake_des node in production
        auto fake_des_0 = std::make_shared<vp_nodes::vp_fake_des_node>("fake_des_0", 0);
        // construct pipeline
        vehicle_detector->attach_to(rtsp_nodes);
        trt_vehicle_plate_detector->attach_to({vehicle_detector});
        trt_vehicle_color_classifier->attach_to({trt_vehicle_plate_detector});
        tracker->attach_to({trt_vehicle_color_classifier});
        ba_jam->attach_to({tracker});
        ba_stop->attach_to({ba_jam});
        json_kafka_broker_0->attach_to({ba_stop});
        osd_0->attach_to({json_kafka_broker_0});
        recorder->attach_to({osd_0});
        split->attach_to({recorder});
        for (size_t i = 0; i < des_nodes.size(); ++i) {
            des_nodes[i]->attach_to({split});
        }
        for (auto node : rtsp_nodes) {
            ((vp_nodes::vp_src_node*)node.get())->start();
        }
        std::string wait;
        std::getline(std::cin, wait);
        for (auto node : rtsp_nodes) {
            ((vp_nodes::vp_src_node*)node.get())->detach_recursively();
        }
    } catch (const std::exception& e) {
        std::cerr << "read config file ex: " << std::string(e.what()) << " <config_file>\n";
    } catch (...) {
        std::cerr << "read config file ex end\n";
    }
    return 0;
}
samples/from_argv_test_width.cpp
New file
@@ -0,0 +1,140 @@
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <regex>
#include <cmath>
#include <limits>
using namespace std;
// 定义一个结构体来保存每一行的值
struct TargetData {
    int id;
    double x, y, width, height;
};
// 读取日志文件并提取目标数据
vector<TargetData> readLogFile(const string& filepath) {
    vector<TargetData> data;
    ifstream file(filepath);
    string line;
    // 正则表达式来匹配Target ID后的五个值
    regex targetRegex("Target ID: (-?\\d+),\\s*(-?\\d+),\\s*(-?\\d+),\\s*(-?\\d+),\\s*(-?\\d+)");
    while (getline(file, line)) {
        smatch matches;
        if (regex_search(line, matches, targetRegex)) {
            TargetData target;
            target.id = stoi(matches[1].str());
            target.x = stod(matches[2].str());
            target.y = stod(matches[3].str());
            target.width = stod(matches[4].str());
            target.height = stod(matches[5].str());
            data.push_back(target);
        }
    }
    return data;
}
// 清洗数据,去掉横坐标小于100或大于600的数据,以及极端值
void cleanData(vector<TargetData>& data, double n) {
    // 计算平均值
    double sum = 0;
    for (const auto& target : data) {
        sum += target.width;
    }
    double mean = sum / data.size();
    // 计算标准差
    double variance = 0;
    for (const auto& target : data) {
        variance += pow(target.width - mean, 2);
    }
    double stddev = sqrt(variance / data.size());
    // 根据误差系数范围n清洗数据
    vector<TargetData> cleanedData;
    for (const auto& target : data) {
        // 添加条件,去掉横坐标小于100或大于600的数据
        if (target.x >= 100 && target.x <= 600 &&
            abs(target.width - mean) <= n * stddev) {
            cleanedData.push_back(target);
        }
    }
    data = cleanedData;
}
// 用最小二乘法来计算线性回归的参数 (width = a * y + b)
void fitLinearModel(const vector<TargetData>& data, double& a, double& b) {
    int n = data.size();
    double sum_y = 0, sum_width = 0, sum_yy = 0, sum_yw = 0;
    // 计算所需的累加和
    for (const auto& target : data) {
        sum_y += target.y;
        sum_width += target.width;
        sum_yy += target.y * target.y;
        sum_yw += target.y * target.width;
    }
    // 计算线性回归的系数 a 和 b
    double denominator = n * sum_yy - sum_y * sum_y;
    if (denominator == 0) {
        a = 0;
        b = 0;
        return;
    }
    a = (n * sum_yw - sum_y * sum_width) / denominator;
    b = (sum_yy * sum_width - sum_y * sum_yw) / denominator;
}
// 输出拟合结果
void printFitEquation(double a, double b) {
    cout << "拟合结果: width = " << a << " * y + " << b << endl;
}
// 打印data中的所有数据
void printData(const vector<TargetData>& data) {
    for (const auto& target : data) {
        cout << "ID: " << target.id
             << ", x: " << target.x
             << ", y: " << target.y
             << ", width: " << target.width
             << ", height: " << target.height << endl;
    }
}
int main(int argc, char* argv[]) {
    if (argc < 3) {
        cout << "使用方法: " << argv[0] << " <日志文件路径> <误差系数范围>" << endl;
        return 1;
    }
    string logFilePath = argv[1];
    double n = stod(argv[2]);  // 误差系数范围
    // 读取日志文件中的目标数据
    vector<TargetData> data = readLogFile(logFilePath);
    // 数据清洗
    cleanData(data, n);
    // 打印清洗后的数据
    cout << "\n清洗后的数据:" << endl;
    printData(data);
    // 使用最小二乘法拟合数据
    double a, b;
    fitLinearModel(data, a, b);
    // 输出拟合的函数公式
    printFitEquation(a, b);
    return 0;
}
samples/from_argv_width_calibration.cpp
New file
@@ -0,0 +1,199 @@
#include "../nodes/vp_file_src_node.h"
#include "../nodes/vp_rtsp_src_node.h"
#include "../nodes/vp_rtsp_ffmpeg_src_node.h"
#include "../nodes/vp_split_node.h"
#include "../nodes/infers/vp_trt_vehicle_detector.h"
#include "../nodes/infers/vp_trt_vehicle_plate_detector.h"
#include "../nodes/infers/vp_trt_vehicle_color_classifier.h"
#include "../nodes/infers/vp_yolo_detector_node.h"
#include "../nodes/osd/vp_osd_node.h"
#include "../nodes/vp_sync_node.h"
#include "../nodes/track/vp_sort_track_node.h"
#include "../nodes/ba/vp_ba_jam_node.h"
#include "../nodes/ba/vp_ba_stop_node.h"
#include "../nodes/osd/vp_ba_stop_osd_node.h"
#include "../nodes/broker/vp_json_kafka_broker_node.h"
#include "../nodes/record/vp_record_node.h"
#include "../nodes/vp_screen_des_node.h"
#include "../nodes/vp_fake_des_node.h"
#include "../nodes/vp_placeholder_node.h"
#include "../utils/analysis_board/vp_analysis_board.h"
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <map>
#include <sstream>
// Function to read configuration from a file
std::vector<std::vector<std::string>> read_config_file(const std::string& file_path) {
    std::vector<std::vector<std::string>> config_lines;
    std::string line;
    try {
        std::ifstream infile(file_path);
        while (std::getline(infile, line)) {
            std::vector<std::string> params;
            size_t start = 0;
            size_t end = line.find(" ");
            while (end != std::string::npos) {
                params.push_back(line.substr(start, end - start));
                start = end + 1;
                end = line.find(" ", start);
            }
            params.push_back(line.substr(start, end));  // add the last parameter
            config_lines.push_back(params);
        }
    } catch (const std::exception& e) {
        std::cerr << "read config file ex: " << std::string(e.what()) << " <config_file>\n";
    } catch (...) {
        std::cerr << "read config file ex end1111\n";
    }
    return config_lines;
}
// Function to parse polygon coordinates from string
std::vector<vp_objects::vp_point> parse_polygon(const std::string& polygon_str, float resize_ratio) {
    std::vector<vp_objects::vp_point> polygon;
    std::stringstream ss(polygon_str);
    std::string point_str;
    while (std::getline(ss, point_str, ')')) {
        size_t start = point_str.find('(');
        if (start != std::string::npos) {
            std::string coordinates = point_str.substr(start + 1);
            size_t comma_pos = coordinates.find(',');
            if (comma_pos != std::string::npos) {
                int x = std::stoi(coordinates.substr(0, comma_pos));
                int y = std::stoi(coordinates.substr(comma_pos + 1));
                x = static_cast<int>(std::round(x * resize_ratio));
                y = static_cast<int>(std::round(y * resize_ratio));
                polygon.push_back(vp_objects::vp_point(x, y));
            }
        }
    }
    return polygon;
}
int main(int argc, char* argv[]) {
    VP_SET_LOG_LEVEL(vp_utils::vp_log_level::INFO);
    VP_LOGGER_INIT();
    // Read configuration file
    if (argc < 2) {
        std::cerr << "Usage: " << argv[0] << " <config_file>\n";
        return -1;
    }
    try {
        std::string config_file = argv[1];
        auto configs = read_config_file(config_file);
        VP_INFO(vp_utils::string_format("Launch a thread for each configuration  [%s]", config_file));
        // Correct type declarations
        std::string kafka_server_point = "";
        std::vector<std::string> rtsp_srcs;
        std::vector<int> channel_indexs;
        std::vector<int> skip_intervals;
        std::vector<bool> use_gpus;
        std::vector<float> resize_ratios;
        // Use shared pointers for nodes
        std::vector<std::shared_ptr<vp_nodes::vp_node>> rtsp_nodes;
        // std::vector<std::shared_ptr<vp_nodes::vp_src_node>> rtsp_nodes;
        // Des节点
        std::vector<std::shared_ptr<vp_nodes::vp_des_node>> des_nodes;
        // define a region in frame for every channel (value MUST in the scope of frame'size)
        std::map<int, std::vector<vp_objects::vp_point>> regions = {};
        for (const auto& config : configs) {
            if (config.size() >= 5) {
                float resize_ratio = std::stof(config[1]);
                int skip_interval = std::stoi(config[3]);
                int channel_index = std::stoi(config[4]);
                bool usegpu = config.size() >= 6 && config[5] == "1";
                rtsp_srcs.push_back(config[0]);
                resize_ratios.push_back(resize_ratio);
                kafka_server_point = config[2];
                skip_intervals.push_back(skip_interval);
                channel_indexs.push_back(channel_index);
                use_gpus.push_back(usegpu);
                // Read and parse the polygon coordinates
                if (config.size() >= 7) {
                    std::string polygon_str = config[6];  // Assuming the polygon coordinates are in the 7th column
                    regions[channel_index] = parse_polygon(polygon_str,resize_ratio);
                } else {
                    // Default region if polygon is not provided
                    regions[channel_index] = std::vector<vp_objects::vp_point>{
                        vp_objects::vp_point(280, 30),
                        vp_objects::vp_point(340, 30),
                        vp_objects::vp_point(600, 330),
                        vp_objects::vp_point(30, 350)
                    };
                }
                rtsp_nodes.push_back(std::make_shared<vp_nodes::vp_rtsp_ffmpeg_src_node>(
                    "rtsp_src_" + config[4], channel_index, config[0], resize_ratio, skip_interval, usegpu));
                des_nodes.push_back(std::make_shared<vp_nodes::vp_fake_des_node>("fake_des_" + config[4], channel_index));
            } else {
                std::cerr << "Invalid config line: ";
                for (const auto& param : config) {
                    std::cerr << param << " ";
                }
                std::cerr << "\n";
            }
        }
        // branch 0
        auto vehicle_detector = std::make_shared<vp_nodes::vp_yolo_detector_node>("vehicle_detector", "./vp_data/models/det_cls/yolov3-tiny-2022-0721_best.weights", "./vp_data/models/det_cls/yolov3-tiny-2022-0721.cfg", "./vp_data/models/det_cls/yolov3_tiny_5classes.txt");
        auto tracker = std::make_shared<vp_nodes::vp_sort_track_node>("sort_tracker");
        auto ba_stop = std::make_shared<vp_nodes::vp_ba_stop_node>("ba_stop", regions);
        auto json_kafka_broker_0 = std::make_shared<vp_nodes::vp_json_kafka_broker_node>("json_kafka_broker_0", kafka_server_point, "vp_ba_tracker", vp_nodes::vp_broke_for::BARESULT);
        auto osd_0 = std::make_shared<vp_nodes::vp_ba_stop_osd_node>("osd_0", "./vp_data/font/NotoSansCJKsc-Medium.otf");
        auto recorder = std::make_shared<vp_nodes::vp_record_node>("recorder", "./record", "./record");
        auto split = std::make_shared<vp_nodes::vp_split_node>("split", true);
        // for testing. USING fake_des node in production
        auto fake_des_0 = std::make_shared<vp_nodes::vp_fake_des_node>("fake_des_0", 0);
        // construct pipeline
        vehicle_detector->attach_to(rtsp_nodes);
        tracker->attach_to({vehicle_detector});
        ba_stop->attach_to({tracker});
        json_kafka_broker_0->attach_to({ba_stop});
        osd_0->attach_to({json_kafka_broker_0});
        recorder->attach_to({osd_0});
        split->attach_to({recorder});
        for (size_t i = 0; i < des_nodes.size(); ++i) {
            des_nodes[i]->attach_to({split});
        }
        for (auto node : rtsp_nodes) {
            ((vp_nodes::vp_src_node*)node.get())->start();
        }
        std::string wait;
        std::getline(std::cin, wait);
        for (auto node : rtsp_nodes) {
            ((vp_nodes::vp_src_node*)node.get())->detach_recursively();
        }
    } catch (const std::exception& e) {
        std::cerr << "read config file ex: " << std::string(e.what()) << " <config_file>\n";
    } catch (...) {
        std::cerr << "read config file ex end\n";
    }
    return 0;
}
samples/lpr_camera/plate_recognize_pipeline
Binary files differ
samples/similiarity_search/face_encoding_pipeline
Binary files differ
samples/similiarity_search/vehicle_encoding_pipeline
Binary files differ
samples/vehicle_behaviour_analysis/vehicle_ba_pipeline
Binary files differ
samples/vehicle_property_and_similiarity_search/vehicle_encoding_classify_pipeline
Binary files differ