// This file is part of OpenCV project. // It is subject to the license terms in the LICENSE file found in the top-level directory // of this distribution and at http://opencv.org/license.html. // // Copyright (C) 2023 Intel Corporation #include "../test_precomp.hpp" #include #include #include "opencv2/gapi/streaming/meta.hpp" #include "opencv2/gapi/streaming/cap.hpp" namespace { cv::gapi::ot::TrackingStatus from_string(const std::string& status) { if (status == "NEW") { return cv::gapi::ot::TrackingStatus::NEW; } else if (status == "TRACKED") { return cv::gapi::ot::TrackingStatus::TRACKED; } else if (status == "LOST") { return cv::gapi::ot::TrackingStatus::LOST; } throw std::runtime_error("String representation for cv::gapi::ot::TrackingStatus: \"" + status + "\" contains incorrect value!"); } } // anonymous namespace namespace opencv_test { struct FrameDetections { std::size_t frame_no{}; std::vector> boxes; std::vector> box_ids; FrameDetections() {} FrameDetections(std::size_t in_frame_no, const std::vector>& in_boxes, const std::vector>& in_box_ids) : frame_no(in_frame_no), boxes(in_boxes), box_ids(in_box_ids) {} }; struct TrackerReference { std::size_t frame_no{}; std::vector> tracked_boxes; std::vector> tracked_box_ids; std::vector> tracking_ids; std::vector> tracking_statuses; TrackerReference() {} TrackerReference(std::size_t in_frame_no, const std::vector>& in_tracked_boxes, const std::vector>& in_tracked_box_ids, const std::vector>& in_tracking_ids, const std::vector>& in_tracking_statuses) : frame_no(in_frame_no), tracked_boxes(in_tracked_boxes), tracked_box_ids(in_tracked_box_ids), tracking_ids(in_tracking_ids), tracking_statuses(in_tracking_statuses) {} }; struct FrameDetectionsParams { FrameDetections value; }; struct TrackerReferenceParams { TrackerReference value; }; } // namespace opencv_test namespace cv { namespace detail { template<> struct CompileArgTag { static const char* tag() { return "org.opencv.test.frame_detections_params"; } }; } // namespace detail namespace detail { template<> struct CompileArgTag { static const char* tag() { return "org.opencv.test.tracker_reference_params"; } }; } // namespace detail } // namespace cv namespace opencv_test { G_API_OP(CvVideo768x576_Detect, , cv::GArray>(cv::GMat)>, "test.custom.cv_video_768x576_detect") { static std::tuple outMeta(cv::GMatDesc) { return std::make_tuple(cv::empty_array_desc(), cv::empty_array_desc()); } }; GAPI_OCV_KERNEL_ST(OCV_CvVideo768x576_Detect, CvVideo768x576_Detect, FrameDetections) { static void setup(cv::GMatDesc, std::shared_ptr &state, const cv::GCompileArgs &compileArgs) { auto params = cv::gapi::getCompileArg(compileArgs) .value_or(opencv_test::FrameDetectionsParams{ }); state = std::make_shared(params.value); } static void run(const cv::Mat&, std::vector &out_boxes, std::vector &out_box_ids, FrameDetections &state) { if (state.frame_no < state.boxes.size()) { out_boxes = state.boxes[state.frame_no]; out_box_ids = state.box_ids[state.frame_no]; ++state.frame_no; } } }; G_API_OP(CheckTrackerResults, (cv::GArray, cv::GArray, cv::GArray, cv::GArray)>, "test.custom.check_tracker_results") { static cv::GOpaqueDesc outMeta(cv::GArrayDesc, cv::GArrayDesc, cv::GArrayDesc, cv::GArrayDesc) { return cv::empty_gopaque_desc(); } }; GAPI_OCV_KERNEL_ST(OCVCheckTrackerResults, CheckTrackerResults, TrackerReference) { static void setup(cv::GArrayDesc, cv::GArrayDesc, cv::GArrayDesc, cv::GArrayDesc, std::shared_ptr &state, const cv::GCompileArgs &compileArgs) { auto params = cv::gapi::getCompileArg(compileArgs) .value_or(opencv_test::TrackerReferenceParams{ }); state = std::make_shared(params.value); } static void run(const std::vector &in_tr_rcts, const std::vector &in_det_ids, const std::vector &in_tr_ids, const std::vector &in_tr_statuses, bool& success, TrackerReference& state) { if (state.frame_no < state.tracked_boxes.size()) { auto reference_boxes = state.tracked_boxes[state.frame_no]; auto reference_box_ids = state.tracked_box_ids[state.frame_no]; auto reference_tr_ids = state.tracking_ids[state.frame_no]; auto reference_tr_statuses = state.tracking_statuses[state.frame_no]; success = true; GAPI_Assert(in_tr_rcts.size() == reference_boxes.size()); GAPI_Assert(in_det_ids.size() == reference_box_ids.size()); GAPI_Assert(in_tr_ids.size() == reference_tr_ids.size()); GAPI_Assert(in_tr_statuses.size() == reference_tr_statuses.size()); for (uint32_t i = 0; (i < in_tr_rcts.size() && success); ++i) { const cv::Rect& reference_rc = reference_boxes[i]; const cv::Rect& in_rc = in_tr_rcts[i]; success &= (reference_rc == in_rc); success &= (reference_box_ids[i] == in_det_ids[i]); success &= (reference_tr_ids[i] == in_tr_ids[i]); success &= (reference_tr_statuses[i] == in_tr_statuses[i]); } ++state.frame_no; } else { success = true; } } }; TEST(VASObjectTracker, PipelineTest) { constexpr int32_t frames_to_handle = 30; std::string pathToVideo = opencv_test::findDataFile("cv/video/768x576.avi"); std::vector> input_boxes(frames_to_handle); std::vector> input_det_ids(frames_to_handle); std::string path_to_boxes = opencv_test::findDataFile("cv/video/vas_object_tracking/detections_30_frames.yml"); cv::FileStorage fs_input_boxes(path_to_boxes, cv::FileStorage::READ); cv::FileNode fn_input_boxes = fs_input_boxes.root(); for (auto it = fn_input_boxes.begin(); it != fn_input_boxes.end(); ++it) { cv::FileNode fn_frame = *it; std::string frame_name = fn_frame.name(); int frame_no = std::stoi(frame_name.substr(frame_name.find("_") + 1)); for (auto fit = fn_frame.begin(); fit != fn_frame.end(); ++fit) { cv::FileNode fn_box = *fit; cv::Rect box((int)fn_box["x"], (int)fn_box["y"], (int)fn_box["width"], (int)fn_box["height"]); input_boxes[frame_no].push_back(box); input_det_ids[frame_no].push_back(fn_box["id"]); } } std::vector> reference_trackings(frames_to_handle); std::vector> reference_trackings_det_ids(frames_to_handle); std::vector> reference_trackings_tr_ids(frames_to_handle); std::vector> reference_trackings_tr_statuses(frames_to_handle); std::string path_to_trackings = opencv_test::findDataFile("cv/video/vas_object_tracking/trackings_30_frames.yml"); cv::FileStorage fs_reference_trackings(path_to_trackings, cv::FileStorage::READ); cv::FileNode fn_reference_trackings = fs_reference_trackings.root(); for (auto it = fn_reference_trackings.begin(); it != fn_reference_trackings.end(); ++it) { cv::FileNode fn_frame = *it; std::string frame_name = fn_frame.name(); int frame_no = std::stoi(frame_name.substr(frame_name.find("_") + 1)); for (auto fit = fn_frame.begin(); fit != fn_frame.end(); ++fit) { cv::FileNode fn_tracked_box = *fit; cv::Rect tracked_box((int)fn_tracked_box["x"], (int)fn_tracked_box["y"], (int)fn_tracked_box["width"], (int)fn_tracked_box["height"]); reference_trackings[frame_no].push_back(tracked_box); reference_trackings_det_ids[frame_no].push_back(fn_tracked_box["id"]); reference_trackings_tr_ids[frame_no].push_back(int(fn_tracked_box["tracking_id"])); reference_trackings_tr_statuses[frame_no].push_back( from_string(fn_tracked_box["tracking_status"])); } } cv::GMat in; cv::GArray detections; cv::GArray det_ids; std::tie(detections, det_ids) = CvVideo768x576_Detect::on(in); constexpr float delta_time = 0.055f; cv::GArray tracking_rects; cv::GArray tracking_det_ids; cv::GArray tracking_ids; cv::GArray tracking_statuses; std::tie(tracking_rects, tracking_det_ids, tracking_ids, tracking_statuses) = cv::gapi::ot::track(in, detections, det_ids, delta_time); cv::GOpaque check_result = CheckTrackerResults::on(tracking_rects, tracking_det_ids, tracking_ids, tracking_statuses); cv::GComputation ccomp(cv::GIn(in), cv::GOut(check_result)); opencv_test::FrameDetections fds { 0, input_boxes, input_det_ids }; opencv_test::TrackerReference tr { 0, reference_trackings, reference_trackings_det_ids, reference_trackings_tr_ids, reference_trackings_tr_statuses }; // Graph compilation for streaming mode: auto compiled = ccomp.compileStreaming(cv::compile_args( cv::gapi::combine(cv::gapi::kernels(), cv::gapi::ot::cpu::kernels()), opencv_test::FrameDetectionsParams{ fds }, opencv_test::TrackerReferenceParams{ tr })); EXPECT_TRUE(compiled); EXPECT_FALSE(compiled.running()); compiled.setSource(pathToVideo); // Start of streaming: compiled.start(); EXPECT_TRUE(compiled.running()); // Streaming: bool success; std::size_t counter { }, limit { 30 }; while(compiled.pull(cv::gout(success)) && (counter < limit)) { ++counter; } compiled.stop(); EXPECT_TRUE(success); EXPECT_FALSE(compiled.running()); } } // namespace opencv_test