├── CMakeLists.txt
├── LICENSE
├── README.md
├── configs
├── config.yaml
├── homography_001.yaml
├── homography_006.yaml
└── kalman_param.yaml
├── images
├── area_cam_001.png
├── area_cam_006.png
├── planview.png
└── readme_image.png
├── src
├── apps
│ ├── CMakeLists.txt
│ └── src
│ │ ├── homography_app.cpp
│ │ └── multi_camera_tracker.cpp
├── config
│ ├── CMakeLists.txt
│ ├── include
│ │ ├── camera_param.h
│ │ ├── configmanager.h
│ │ ├── detector_param.h
│ │ ├── kalman_param.h
│ │ └── yamlmanager.h
│ └── src
│ │ ├── configmanager.cpp
│ │ └── yamlmanager.cpp
├── homography
│ ├── CMakeLists.txt
│ ├── include
│ │ └── homography.h
│ └── src
│ │ └── homography.cpp
├── object_detection
│ ├── CMakeLists.txt
│ ├── include
│ │ └── object_detector.h
│ └── src
│ │ └── object_detector.cpp
├── segmentation
│ ├── CMakeLists.txt
│ ├── include
│ │ └── bgsubtraction.h
│ └── src
│ │ └── bgsubtraction.cpp
├── tracker
│ ├── CMakeLists.txt
│ ├── include
│ │ ├── detection.h
│ │ ├── entity.h
│ │ ├── hungarianAlg.h
│ │ ├── hypothesis.h
│ │ ├── kalman.h
│ │ ├── lap.h
│ │ ├── track.h
│ │ └── tracker.h
│ └── src
│ │ ├── hungarianAlg.cpp
│ │ ├── hypothesis.cpp
│ │ ├── kalman.cpp
│ │ ├── lap.cpp
│ │ ├── track.cpp
│ │ └── tracker.cpp
└── utils
│ ├── CMakeLists.txt
│ ├── include
│ ├── camera.h
│ ├── camerastack.h
│ ├── drawing.h
│ ├── utility.h
│ └── utils.h
│ └── src
│ ├── camera.cpp
│ ├── camerastack.cpp
│ ├── drawing.cpp
│ └── utility.cpp
└── videos
├── View_001.mp4
└── View_006.mp4
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 2.8)
2 | cmake_policy(SET CMP0060 NEW)
3 | set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wall -O3 -g")
4 |
5 | project( mctracker )
6 |
7 |
8 | find_package(OpenCV REQUIRED)
9 | message(STATUS "OpenCV library status:")
10 | message(STATUS " version: ${OpenCV_VERSION}")
11 | message(STATUS " libraries: ${OpenCV_LIBS}")
12 | message(STATUS " include path: ${OpenCV_INCLUDE_DIRS}")
13 |
14 | find_package(yaml-cpp REQUIRED)
15 | message(STATUS "YAML-CPP library status:")
16 | message(STATUS " include path: ${YAML_CPP_INCLUDE_DIR}")
17 | message(STATUS " libraries: ${YAML_CPP_LIBRARIES}")
18 |
19 |
20 | add_definitions(-Wuninitialized)
21 | add_definitions(-Wreturn-type)
22 | add_definitions(-Wsign-compare)
23 | add_definitions(-Wuninitialized)
24 | add_definitions(-Wunused-function)
25 | add_definitions(-Wunused-label)
26 | add_definitions(-Wunused-value)
27 | add_definitions(-Wunused-variable)
28 |
29 | include(CheckCXXCompilerFlag)
30 | CHECK_CXX_COMPILER_FLAG("-std=c++14" COMPILER_SUPPORTS_CXX14)
31 | CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
32 | CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
33 | if(COMPILER_SUPPORTS_CXX14)
34 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
35 | elseif(COMPILER_SUPPORTS_CXX11)
36 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
37 | elseif(COMPILER_SUPPORTS_CXX0X)
38 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
39 | else()
40 | message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
41 | endif()
42 |
43 | include_directories( ${OpenCV_INCLUDE_DIRS} )
44 |
45 | set(LIBRARY_OUTPUT_PATH ../lib)
46 | set(EXECUTABLE_OUTPUT_PATH ../bin)
47 |
48 | include(${CMAKE_CURRENT_SOURCE_DIR}/src/utils/CMakeLists.txt)
49 | utils()
50 |
51 | include(${CMAKE_CURRENT_SOURCE_DIR}/src/config/CMakeLists.txt)
52 | config()
53 |
54 | include(${CMAKE_CURRENT_SOURCE_DIR}/src/object_detection/CMakeLists.txt)
55 | object_detection()
56 |
57 | include(${CMAKE_CURRENT_SOURCE_DIR}/src/segmentation/CMakeLists.txt)
58 | segmentation()
59 |
60 | include(${CMAKE_CURRENT_SOURCE_DIR}/src/homography/CMakeLists.txt)
61 | homography()
62 |
63 | include(${CMAKE_CURRENT_SOURCE_DIR}/src/tracker/CMakeLists.txt)
64 | tracker()
65 |
66 | include(${CMAKE_CURRENT_SOURCE_DIR}/src/apps//CMakeLists.txt)
67 | applications()
68 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Andrea Pennisi
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Multi Camera Tracker (MCTracker)
2 |
3 |
4 |
5 |
6 |
7 |
8 | MCTracker is a multi camera tracker based on homography and costs. The costs are computed according to the Mahalanobis distance. Then, a Linear Assignment approach together with a Munkres algorithm have been used for assigning the current detections to the previous tracks.
9 |
10 | # Requirements
11 | * C++14
12 | * OpenCV
13 | * Darknet ([https://github.com/AlexeyAB/darknet](https://github.com/AlexeyAB/darknet))
14 | * Boost
15 | * CUDA (not mandatory)
16 | * Yaml-cpp
17 |
18 | # How to build
19 |
20 | 1. Clone *darknet* repository into the main folder (mctracker).
21 | 2. Modify the Makefile in order to use GPU (if any), to use OPENCV, and to build the library:
22 | - GPU=1, LIBSO=1 and OPENCV=1
23 | 3. If necessary, modify the cuda path as well as the architecture (inside the makefile)
24 | 4. Inside the darknet folder, go into the forlder include and edit the file yolo_v2_class.hpp
25 | - Comment Lines 107 and 179 (_#ifdef_ _OPENCV_ and _#endif_)
26 | 5. Compile it with: ```make```
27 | 6. Download the COCO weights:
28 | - [https://pjreddie.com/media/files/yolov3.weights](https://pjreddie.com/media/files/yolov3.weights)
29 | - Move the downloaded file into the folder *weights*
30 | 7. In the main folder *mctracker*, create a folder build
31 | 8. navigate into the folder build and compile it with the following commands: ```cmake .. && make```
32 |
33 | # How it works
34 |
35 | 1. To launch the application: ```./multi_camera_tracker ../configs/config.yaml```
36 | 2. To create a new homography file: ```./homography_app /path/to/the/source/image /path/to/the/destination/image /path/to/yaml/file (where you save the homography)```
37 |
38 | # LICENSE
39 | MIT
40 |
--------------------------------------------------------------------------------
/configs/config.yaml:
--------------------------------------------------------------------------------
1 | Number: 2 #camera number
2 |
3 | #Plan View Params
4 | Planview: ../images/planview.png
5 | Show Planview: false
6 |
7 | #Camera Params
8 | Camera1: ../videos/View_001.mp4
9 | Homography1: ../configs/homography_001.yaml
10 | FOV1: ../images/area_cam_001.png
11 | Proximity1: false
12 |
13 | Camera2: ../videos/View_006.mp4
14 | Homography2: ../configs/homography_006.yaml
15 | FOV2: ../images/area_cam_006.png
16 | Proximity2: true
17 |
18 | #Tracker
19 | Kalman: ../configs/kalman_param.yaml
20 |
21 | #Detector Params
22 | Config: ../darknet/cfg/yolov3.cfg
23 | Weights: ../weights/yolov3.weights
24 | MinThreshold: 0.8
25 |
--------------------------------------------------------------------------------
/configs/homography_001.yaml:
--------------------------------------------------------------------------------
1 | Matrix: [3.775749870135431, 17.21097181186204, -986.1518665019161, 0.5492166781072961, 23.11494421915456, -1125.57892913749, 0.0007707595352949053, 0.01702218406881415, 1]
2 | Error: [5.316614]
--------------------------------------------------------------------------------
/configs/homography_006.yaml:
--------------------------------------------------------------------------------
1 | Matrix: [-0.6652451349651806, -9.620972855792273, 1144.561469988118, -0.2425185157379307, -10.66978068477464, 1315.254889450699, -0.000266117218104874, -0.01007590124612281, 1]
2 | Error: [5.846917]
--------------------------------------------------------------------------------
/configs/kalman_param.yaml:
--------------------------------------------------------------------------------
1 | ACD: 50 #Association Dummy Cost
2 | NHDC: 2 #New Hypothesis Dummy Cost
3 | MINPROPAGATE: 15 #NUMBER AFTER WHICH A TRACK IS ACCEPTED
4 | MAXMISSED: 15 #NUMBER AFTER WHICH A TRACK IS DELETED
5 | DT: 0.5 #INITIAL DT OF THE KALMAN FILTER
6 |
--------------------------------------------------------------------------------
/images/area_cam_001.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apennisi/mctracker/29a89046f796f84eac922b2dc9cf4cd6c7aebb6b/images/area_cam_001.png
--------------------------------------------------------------------------------
/images/area_cam_006.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apennisi/mctracker/29a89046f796f84eac922b2dc9cf4cd6c7aebb6b/images/area_cam_006.png
--------------------------------------------------------------------------------
/images/planview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apennisi/mctracker/29a89046f796f84eac922b2dc9cf4cd6c7aebb6b/images/planview.png
--------------------------------------------------------------------------------
/images/readme_image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apennisi/mctracker/29a89046f796f84eac922b2dc9cf4cd6c7aebb6b/images/readme_image.png
--------------------------------------------------------------------------------
/src/apps/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | function(applications)
2 | file(GLOB TRACKER_SRC "src/apps/src/multi_camera_tracker.cpp")
3 | add_executable( multi_camera_tracker ${TRACKER_SRC})
4 | target_link_libraries( multi_camera_tracker ${OpenCV_LIBS} objectdetector segmentation config utils homography tracker)
5 |
6 | file(GLOB HOMOGRAPHY_SRC "src/apps/src/homography_app.cpp")
7 | add_executable( homography_app ${HOMOGRAPHY_SRC})
8 | target_link_libraries( homography_app ${OpenCV_LIBS} homography config)
9 |
10 | endfunction()
11 |
--------------------------------------------------------------------------------
/src/apps/src/homography_app.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include "homography.h"
5 |
6 | std::vector mapPoints;
7 | std::vector rgbPoints;
8 | std::string filename;
9 |
10 | cv::Mat rgb;
11 | cv::Mat map;
12 |
13 | using namespace mctracker::geometry;
14 |
15 | static void add(cv::Mat& img, std::vector& points, int x, int y)
16 | {
17 | cv::circle(img, cv::Point2f(x, y), 3, cv::Scalar(0, 0, 255), -1);
18 | points.push_back(cv::Point2f(x, y));
19 | }
20 |
21 | static void compute(const std::vector& points_1, const std::vector& points_2, cv::Mat& img_1, cv::Mat& img_2)
22 | {
23 | if(points_1.size() == points_2.size())
24 | {
25 | Homography h;
26 | h.setPoints(points_1, points_2);
27 | cv::Mat H = h.calcHomography();
28 | h.draw(img_1, img_2, H);
29 | h.writeToFile(filename);
30 | }
31 | else
32 | {
33 | std::cout << "ERROR!!" << std::endl;
34 | }
35 | }
36 |
37 | void
38 | mouseHandlerRobot(int event, int x, int y, int flags, void *param)
39 | {
40 | if(event == CV_EVENT_LBUTTONDOWN)
41 | {
42 | add(map, mapPoints, x, y);
43 | cv::imshow("map", map);
44 | }
45 |
46 | if(event == CV_EVENT_RBUTTONDOWN)
47 | {
48 | compute(rgbPoints, mapPoints, rgb, map);
49 | }
50 | }
51 |
52 | void mouseHandlerRGB(int event, int x, int y, int flags, void *param)
53 | {
54 | if(event == CV_EVENT_LBUTTONDOWN)
55 | {
56 | add(rgb, rgbPoints, x, y);
57 | cv::imshow("rgb", rgb);
58 | }
59 |
60 | if(event == CV_EVENT_RBUTTONDOWN)
61 | {
62 | compute(rgbPoints, mapPoints, rgb, map);
63 | }
64 | }
65 |
66 |
67 |
68 | int main(int argc, char **argv) {
69 |
70 | if(argc != 4)
71 | {
72 | std::cout << "ERROR: " << argv[0] << " rgb_image map_image save_file_name" << std::endl;
73 | exit(-1);
74 | }
75 |
76 | rgb = cv::imread(argv[1]);
77 | map = cv::imread(argv[2]);
78 | filename = std::string(argv[3]);
79 |
80 |
81 | cv::namedWindow("map", CV_WINDOW_AUTOSIZE);
82 | cv::namedWindow("rgb", CV_WINDOW_AUTOSIZE);
83 |
84 | cv::setMouseCallback("map", &mouseHandlerRobot, NULL);
85 | cv::setMouseCallback("rgb", &mouseHandlerRGB, NULL);
86 |
87 |
88 | cv::imshow("rgb", rgb);
89 | cv::imshow("map", map);
90 |
91 | cv::waitKey(0);
92 |
93 | }
94 |
--------------------------------------------------------------------------------
/src/apps/src/multi_camera_tracker.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | #include "object_detector.h"
5 | #include "camerastack.h"
6 | #include "bgsubtraction.h"
7 | #include "track.h"
8 | #include "tracker.h"
9 | #include "kalman_param.h"
10 | #include "object_detector.h"
11 | #include "configmanager.h"
12 | #include "homography.h"
13 | #include "utility.h"
14 |
15 |
16 | using namespace mctracker;
17 | using namespace mctracker::config;
18 | using namespace mctracker::utils;
19 | using namespace mctracker::objectdetection;
20 | using namespace mctracker::segmentation;
21 |
22 |
23 | auto main(int argc, char **argv) -> int
24 | {
25 | if(argc != 2)
26 | {
27 | std::cout << "Error: too few/much arguments!" << std::endl;
28 | std::cout << "Usage: " << argv[0] << " /path/to/the/config/file" << std::endl;
29 | exit(-1);
30 | }
31 |
32 | ConfigManager config;
33 | config.read(std::string(argv[1]));
34 | config.print();
35 |
36 | const int w = config.getPlaview().cols;
37 | const int h = config.getPlaview().rows;
38 |
39 | //initialize all the main objects
40 | CameraStack streams(config.getCameraParam());
41 | ObjectDetector detector(config.getDetectorParam());
42 | std::vector bgSub(config.getCameraNumber());
43 | Tracker tr(config.getKalmanParam(), streams.getCameraStack());
44 |
45 | //set tracker space
46 | tr.setSize(w, h);
47 |
48 | //storing variables
49 | std::vector frames;
50 | std::vector detectionFrames(config.getCameraNumber());
51 | std::vector trackingFrames(config.getCameraNumber());
52 | std::vector fgMasks(config.getCameraNumber());
53 | std::vector< std::vector > detections(config.getCameraNumber());
54 | bool compute = false;
55 | cv::Mat imageTracks;
56 |
57 | auto& cameras = streams.getCameraStack();
58 |
59 | while(streams.getFrame(frames))
60 | {
61 | imageTracks = config.getPlaview().clone();
62 |
63 | std::stringstream ss;
64 | auto i = 0;
65 |
66 | for(const auto& frame : frames)
67 | {
68 | detectionFrames.at(i) = frame.clone();
69 | trackingFrames.at(i) = frame.clone();
70 | cv::Mat fgMask;
71 | bgSub.at(i).process(frame);
72 | compute = bgSub.at(i).getFgMask(fgMask);
73 | if(compute)
74 | {
75 | fgMasks.at(i) = fgMask.clone();
76 | detector.classify(detectionFrames.at(i), false);
77 | detections.at(i) = detector.detections();
78 | }
79 | i++;
80 | }
81 |
82 | if(compute)
83 | {
84 | auto observations =
85 | Utility::dets2Obs(detections, frames, fgMasks, cameras);
86 |
87 | tr.track(observations, w, h);
88 |
89 | const auto& tracks = tr.getTracks();
90 | for(auto& track : tracks)
91 | {
92 | track->drawTrack(trackingFrames, cameras);
93 | if(config.showPlanView())
94 | track->drawTrackPlanView(imageTracks);
95 | }
96 |
97 | cv::imshow("TRACKING", Utility::makeMosaic(trackingFrames));
98 | if(config.showPlanView())
99 | cv::imshow("TRACKS", imageTracks);
100 |
101 | cv::waitKey(1);
102 | }
103 | }
104 | return 0;
105 | }
106 |
--------------------------------------------------------------------------------
/src/config/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | function(config)
2 | include_directories(${PROJECT_BINARY_DIR}/../src/config/include)
3 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src/confg/include)
4 |
5 | file(GLOB_RECURSE CONFIG_SRC "src/config/src/*.cpp")
6 |
7 | add_library(config SHARED ${CONFIG_SRC})
8 | target_link_libraries(config ${OpenCV_LIBS} ${YAML_CPP_LIBRARIES})
9 |
10 | endfunction()
11 |
--------------------------------------------------------------------------------
/src/config/include/camera_param.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Written by Andrea Pennisi
3 | */
4 |
5 | #ifndef _CAMERA_PARAM_H_
6 | #define _CAMERA_PARAM_H_
7 |
8 | #include
9 |
10 | namespace mctracker
11 | {
12 | namespace config
13 | {
14 | class CameraParam
15 | {
16 | public:
17 | /**
18 | * @brief Constructor class KalmanParam
19 | */
20 | CameraParam() { ; }
21 |
22 | /**
23 | * @brief set the path to the stream device
24 | * @param s string containing the path
25 | */
26 | void
27 | setStream(const std::string& s)
28 | {
29 | stream = s;
30 | }
31 |
32 | /**
33 | * @brief get the path to the stream device
34 | * @return string containing the path
35 | */
36 | inline const std::string
37 | getStream() const
38 | {
39 | return stream;
40 | }
41 |
42 | /**
43 | * @brief set the path to the homography file
44 | * @param h string containing the path
45 | */
46 | void
47 | setHomography(const std::string& h)
48 | {
49 | homography = h;
50 | }
51 |
52 | /**
53 | * @brief get the path to the homography file
54 | * @return a string containing the path
55 | */
56 | inline const std::string
57 | getHomography() const
58 | {
59 | return homography;
60 | }
61 |
62 | /**
63 | * @brief set the path to the fov image
64 | * @param fov string containing the path
65 | */
66 | void
67 | setFOV(const std::string& fov)
68 | {
69 | fieldOfView = fov;
70 | }
71 |
72 | /**
73 | * @brief set the path to the fov image
74 | * @return string containing the path
75 | */
76 | inline const std::string
77 | getFOV() const
78 | {
79 | return fieldOfView;
80 | }
81 |
82 | /**
83 | * @brief set if a camera is close to the scene to monitor
84 | * @param prox a boolean value where true means that the camera is close to the scene, false otherwise
85 | */
86 | void
87 | setProximity(const bool prox)
88 | {
89 | proximity = prox;
90 | }
91 |
92 | /**
93 | * @brief get the proximity valuer
94 | * @return a boolean value where true means that the camera is close to the scene, false otherwise
95 | */
96 | inline const float
97 | getProximity() const
98 | {
99 | return proximity;
100 | }
101 |
102 | /**
103 | * @brief copy operator
104 | * @param _param object to copy
105 | * @return the pointer to the current instance
106 | */
107 | CameraParam& operator=(const CameraParam& _param)
108 | {
109 | stream = _param.getStream();
110 | homography = _param.getHomography();
111 | fieldOfView = _param.getFOV();
112 | proximity = _param.getProximity();
113 | return *this;
114 | }
115 |
116 | /**
117 | * @brief print all the parameters
118 | */
119 | void
120 | print()
121 | {
122 | std::cout << "[STREAM]: " << stream << std::endl;
123 | std::cout << "[HOMOGRAPHY]: " << homography << std::endl;
124 | std::cout << "[FOV]: " << fieldOfView << std::endl;
125 | std::cout << "[PROXIMITY]: " << proximity << std::endl;
126 | }
127 |
128 | private:
129 | std::string stream;
130 | std::string homography;
131 | std::string fieldOfView;
132 | bool proximity;
133 | };
134 | }
135 | }
136 |
137 | #endif
138 |
--------------------------------------------------------------------------------
/src/config/include/configmanager.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Written by Andrea Pennisi
3 | */
4 |
5 | #ifndef _CONFIG_MANAGER_H_
6 | #define _CONFIG_MANAGER_H_
7 |
8 | #include
9 | #include
10 | #include
11 |
12 | #include "detector_param.h"
13 | #include "camera_param.h"
14 | #include "kalman_param.h"
15 | #include "yamlmanager.h"
16 |
17 | namespace mctracker
18 | {
19 | namespace config
20 | {
21 | class ConfigManager
22 | {
23 | public:
24 | /**
25 | * @brief Constructor class ConfigManager
26 | */
27 | ConfigManager() { ; }
28 | public:
29 | /**
30 | * @brief read all the parameters included in a configuration files
31 | * @param config a string containing the path to the configuration file
32 | * @return true if the configuration file is correctly readed, false otherwise
33 | */
34 | bool read(const std::string& config);
35 | /**
36 | * @brief print all the values read from the configuration file
37 | */
38 | void print();
39 | public:
40 | /**
41 | * @brief get the number of cameras of the system specified in the file
42 | * @return the the number of cameras of the system specified in the file
43 | */
44 | inline const int
45 | getCameraNumber() const
46 | {
47 | return cameraNum;
48 | }
49 |
50 | /**
51 | * @brief get the kalman parameters specified in the configuration file
52 | * @return the kalman parameters specified in the configuration file
53 | */
54 | inline const KalmanParam
55 | getKalmanParam() const
56 | {
57 | return kalmanParam;
58 | }
59 |
60 | /**
61 | * @brief get the detector parameters specified in the configuration file
62 | * @return the detector parameters specified in the configuration file
63 | */
64 | inline const DetectorParam
65 | getDetectorParam() const
66 | {
67 | return detectorParam;
68 | }
69 |
70 | /**
71 | * @brief get the camera parameters specified in the configuration file
72 | * @return the camera parameters specified in the configuration file
73 | */
74 | inline const std::vector
75 | getCameraParam() const
76 | {
77 | return cameraParam;
78 | }
79 |
80 | /**
81 | * @brief get the plan view of the monitored environment
82 | * @return a cv::Mat containing the image of the plan view
83 | */
84 | inline const cv::Mat
85 | getPlaview() const
86 | {
87 | return planView;
88 | }
89 |
90 | /**
91 | * @brief get if the planview has to be showd
92 | * @return a bool value: true if the planview has to be showed, false otherwise
93 | */
94 | inline const bool
95 | showPlanView() const
96 | {
97 | return show;
98 | }
99 | private:
100 | /**
101 | * @brief check if a file exists on the hd
102 | * @return true if exists, false otherwise
103 | */
104 | bool exist(const std::string& name) const;
105 | private:
106 | KalmanParam kalmanParam;
107 | DetectorParam detectorParam;
108 | std::vector cameraParam;
109 | YamlManager yamlManager;
110 | cv::Mat planView;
111 | bool show;
112 | int cameraNum;
113 | };
114 | }
115 | }
116 |
117 | #endif
118 |
--------------------------------------------------------------------------------
/src/config/include/detector_param.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Written by Andrea Pennisi
3 | */
4 |
5 | #ifndef _DETECTOR_PARAM_H_
6 | #define _DETECTOR_PARAM_H_
7 |
8 | namespace mctracker
9 | {
10 | namespace config
11 | {
12 | class DetectorParam
13 | {
14 | public:
15 | /**
16 | * @brief Constructor class DetectorParam
17 | */
18 | DetectorParam() { ; }
19 |
20 | /**
21 | * @brief set the path to the weight file
22 | * @param w path to the weight file
23 | */
24 | void
25 | setWeights(const std::string& w)
26 | {
27 | weights = w;
28 | }
29 |
30 | /**
31 | * @brief get the path to the file containing the weights
32 | * @return a string containing the path
33 | */
34 | inline const std::string
35 | getWeights() const
36 | {
37 | return weights;
38 | }
39 |
40 | /**
41 | * @brief set the path to the file containing the network configuration
42 | * @param c value containing the path to the config file
43 | */
44 | void
45 | setConfig(const std::string& c)
46 | {
47 | config = c;
48 | }
49 |
50 | /**
51 | * @brief get the path to the file containing the network configuration
52 | * @return a string containing the path to the file containing the network configuration
53 | */
54 | inline const std::string
55 | getConfig() const
56 | {
57 | return config;
58 | }
59 |
60 | /**
61 | * @brief set the minimum threshold above which a detection is considered
62 | * @param thres value contianing the minimum threshold above which a detection is considered
63 | */
64 | void
65 | setThreshold(const float& thres)
66 | {
67 | minThreshold = thres;
68 | }
69 |
70 | /**
71 | * @brief get the minimum threshold above which a detection is considered
72 | * @return a float containing the minimum threshold above which a detection is considered
73 | */
74 | inline const float
75 | getThreshold() const
76 | {
77 | return minThreshold;
78 | }
79 |
80 | /**
81 | * @brief copy operator
82 | * @param _param object to copy
83 | * @return the pointer to the current instance
84 | */
85 | DetectorParam& operator=(const DetectorParam& _param)
86 | {
87 | config = _param.getConfig();
88 | weights = _param.getWeights();
89 | minThreshold = _param.getThreshold();
90 | return *this;
91 | }
92 |
93 | /**
94 | * @brief print all the parameters
95 | */
96 | void
97 | print()
98 | {
99 | std::cout << "[CONFIG]: " << config << std::endl;
100 | std::cout << "[WEIGHTS]: " << weights << std::endl;
101 | std::cout << "[THRESHOLD]: " << minThreshold << std::endl;
102 | }
103 |
104 | private:
105 | std::string config;
106 | std::string weights;
107 | float minThreshold;
108 | };
109 | }
110 | }
111 |
112 | #endif
113 |
--------------------------------------------------------------------------------
/src/config/include/kalman_param.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Written by Andrea Pennisi
3 | */
4 |
5 | #ifndef _KALMAN_PARAM_H_
6 | #define _KALMAN_PARAM_H_
7 |
8 | #include
9 | #include
10 | #include
11 | #include
12 |
13 | namespace mctracker
14 | {
15 | namespace config
16 | {
17 | class KalmanParam
18 | {
19 | public:
20 | /**
21 | * @brief Constructor class KalmanParam
22 | */
23 | KalmanParam() { ; }
24 |
25 | /**
26 | * @brief set the number of times after which a track is accepted
27 | * @param propagate unsigned integer containing the value of the propagation
28 | */
29 | void
30 | setMinPropagate(uint propagate)
31 | {
32 | min_propagate = propagate;
33 | }
34 |
35 | /**
36 | * @brief get the number of times after which a track is accepted
37 | * @return the number of times after which a track is accepted
38 | */
39 | inline const uint
40 | getMinpropagate() const
41 | {
42 | return min_propagate;
43 | }
44 |
45 | /**
46 | * @brief set the dt value for the transition matrix
47 | * @param dt float containing the value of the sample frequency
48 | */
49 | void
50 | setDt(const float& dt)
51 | {
52 | d_t = dt;
53 | }
54 |
55 | /**
56 | * @brief get the dt value of the transition matrix
57 | * @return the dt value
58 | */
59 | inline const float
60 | getDt() const
61 | {
62 | return d_t;
63 | }
64 |
65 | /**
66 | * @brief get the association dummy cost value for the lienar assignment cost
67 | * @return the value of the association cost
68 | */
69 | inline const uint
70 | getAssocdummycost() const
71 | {
72 | return assoc_dummy_cost;
73 | }
74 |
75 | /**
76 | * @brief set the association dummy cost for the lienar assignment cost
77 | * @param ass unsigned integer containing the association value
78 | */
79 | void
80 | setAssociationDummyCost(uint ass)
81 | {
82 | assoc_dummy_cost = ass;
83 | }
84 |
85 | /**
86 | * @brief set the dummy cost for new hypothesis in the linear assignment cost
87 | * @param nydc value containing the cost
88 | */
89 | void
90 | setNewHypDummyCost(uint nydc)
91 | {
92 | new_hyp_dummy_cost = nydc;
93 | }
94 |
95 | /**
96 | * @brief get the dymmy cost for the new hypothesis in the linear assignment cost
97 | * @return the value for the new hypothesis cost
98 | */
99 | inline const uint
100 | getNewhypdummycost() const
101 | {
102 | return new_hyp_dummy_cost;
103 | }
104 |
105 | /**
106 | * @brief set the maximum number of times after which a track is deleted
107 | * @param missed the value containing the maximum number of times after which a track is deleted
108 | */
109 | void
110 | setMaxMissed(uint missed)
111 | {
112 | max_missed = missed;
113 | }
114 |
115 | /**
116 | * @brief get the maximum number of times after which a track is deleted
117 | * @return the value containing the maximum number of times after which a track is deleted
118 | */
119 | inline const uint
120 | getMaxmissed() const
121 | {
122 | return max_missed;
123 | }
124 |
125 | /**
126 | * @brief copy operator
127 | * @param _param object to copy
128 | * @return the pointer to the current instance
129 | */
130 | KalmanParam& operator=(const KalmanParam& _param)
131 | {
132 | this->min_propagate = _param.getMinpropagate();
133 | this->d_t = _param.getDt();
134 | this->assoc_dummy_cost = _param.getAssocdummycost();
135 | this->new_hyp_dummy_cost = _param.getNewhypdummycost();
136 | this->max_missed = _param.getMaxmissed();
137 | return *this;
138 | }
139 |
140 | /**
141 | * @brief print all the parameters
142 | */
143 | void
144 | print()
145 | {
146 | std::cout << "[MINPROPAGATE]: " << min_propagate << std::endl;
147 | std::cout << "[MAXMISSED]: " << max_missed << std::endl;
148 | std::cout << "[ASSOCDUMMYCOST]: " << assoc_dummy_cost << std::endl;
149 | std::cout << "[NEW_HYP_DUMMY_COST]: " << new_hyp_dummy_cost << std::endl;
150 | std::cout << "[DT]: " << d_t << std::endl;
151 | }
152 | private:
153 | uint max_missed;
154 | uint min_propagate;
155 | float d_t;
156 | uint assoc_dummy_cost;
157 | uint new_hyp_dummy_cost;
158 | };
159 | }
160 | }
161 |
162 | #endif
163 |
--------------------------------------------------------------------------------
/src/config/include/yamlmanager.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Written by Andrea Pennisi
3 | */
4 |
5 | #ifndef _YAML_MANAGER_H_
6 | #define _YAML_MANAGER_H_
7 |
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 |
15 | namespace mctracker
16 | {
17 | namespace config
18 | {
19 | class YamlManager
20 | {
21 | public:
22 | /**
23 | * @brief Constructor class YamlManager
24 | */
25 | YamlManager();
26 | /**
27 | * @brief Write a new yaml file
28 | * @param filepath the path where you have to save your file, including the filename
29 | * @return true if the file is correctly written, false otherwise
30 | */
31 | bool write(const std::string& filepath);
32 | /**
33 | * @brief Read a yaml file
34 | * @param filepath the path where your file is stored
35 | * @return true if the fiel is correctly read, false otherwise
36 | */
37 | bool read(const std::string& filepath);
38 | /**
39 | * @brief Read an integer element from the yaml file given the key
40 | * @param name key to read
41 | * @param elem variable where the value is stored
42 | * @return true if the element exists and is correctly read, false otherwise
43 | */
44 | bool getElem(const std::string& name, int& elem);
45 | /**
46 | * @brief Read a float element from the yaml file given the key
47 | * @param name key to read
48 | * @param elem variable where the value is stored
49 | * @return true if the element exists and is correctly read, false otherwise
50 | */
51 | bool getElem(const std::string& name, float& elem);
52 | /**
53 | * @brief Read a double element from the yaml file given the key
54 | * @param name key to read
55 | * @param elem variable where the value is stored
56 | * @return true if the element exists and is correctly read, false otherwise
57 | */
58 | bool getElem(const std::string& name, double& elem);
59 | /**
60 | * @brief Read a boolean element from the yaml file given the key
61 | * @param name key to read
62 | * @param elem variable where the value is stored
63 | * @return true if the element exists and is correctly read, false otherwise
64 | */
65 | bool getElem(const std::string& name, bool& elem);
66 | /**
67 | * @brief Read a cv::Point2i element from the yaml file given the key
68 | * @param name key to read
69 | * @param elem variable where the value is stored
70 | * @return true if the element exists and is correctly read, false otherwise
71 | */
72 | bool getElem(const std::string& name, cv::Point2i& elem);
73 | /**
74 | * @brief Read a cv::Point2f element from the yaml file given the key
75 | * @param name key to read
76 | * @param elem variable where the value is stored
77 | * @return true if the element exists and is correctly read, false otherwise
78 | */
79 | bool getElem(const std::string& name, cv::Point2f& elem);
80 | /**
81 | * @brief Read a cv::Point2d element from the yaml file given the key
82 | * @param name key to read
83 | * @param elem variable where the value is stored
84 | * @return true if the element exists and is correctly read, false otherwise
85 | */
86 | bool getElem(const std::string& name, cv::Point2d& elem);
87 | /**
88 | * @brief Read a string element from the yaml file given the key
89 | * @param name key to read
90 | * @param elem variable where the value is stored
91 | * @return true if the element exists and is correctly read, false otherwise
92 | */
93 | bool getElem(const std::string& name, std::string& elem);
94 | /**
95 | * @brief Read a vector of integers from the yaml file given the key
96 | * @param name key to read
97 | * @param elem variable where the value is stored
98 | * @return true if the element exists and is correctly read, false otherwise
99 | */
100 | bool getElem(const std::string& name, std::vector& elem);
101 | /**
102 | * @brief Read a vector of boolean from the yaml file given the key
103 | * @param name key to read
104 | * @param elem variable where the value is stored
105 | * @return true if the element exists and is correctly read, false otherwise
106 | */
107 | bool getElem(const std::string& name, std::vector& elem);
108 | /**
109 | * @brief Read a vector of floats from the yaml file given the key
110 | * @param name key to read
111 | * @param elem variable where the value is stored
112 | * @return true if the element exists and is correctly read, false otherwise
113 | */
114 | bool getElem(const std::string& name, std::vector& elem);
115 | /**
116 | * @brief Read a vector of doubles from the yaml file given the key
117 | * @param name key to read
118 | * @param elem variable where the value is stored
119 | * @return true if the element exists and is correctly read, false otherwise
120 | */
121 | bool getElem(const std::string& name, std::vector& elem);
122 | /**
123 | * @brief Read a vector of cv::Point from the yaml file given the key
124 | * @param name key to read
125 | * @param elem variable where the value is stored
126 | * @return true if the element exists and is correctly read, false otherwise
127 | */
128 | bool getElem(const std::string& name, std::vector& elem);
129 | /**
130 | * @brief Read a vector of cv::Point2f from the yaml file given the key
131 | * @param name key to read
132 | * @param elem variable where the value is stored
133 | * @return true if the element exists and is correctly read, false otherwise
134 | */
135 | bool getElem(const std::string& name, std::vector& elem);
136 | /**
137 | * @brief Read a cv::Mat from the yaml file given the key
138 | * @param name key to read
139 | * @param elem variable where the value is stored
140 | * @param type the type of cv::Mat: CV_FC321 or CV_FC64U1
141 | * @return true if the element exists and is correctly read, false otherwise
142 | */
143 | bool getElem(const std::string& name, cv::Mat& elem, int type);
144 | /**
145 | * @brief Write a float into the yaml file given the key
146 | * @param name key to write
147 | * @param elem variable to write
148 | * @return true if the is correctly written, false otherwise
149 | */
150 | void writeElem(const std::string& key, const float& elem);
151 | /**
152 | * @brief Write a cv::Point into the yaml file given the key
153 | * @param name key to write
154 | * @param elem variable to write
155 | * @return true if the is correctly written, false otherwise
156 | */
157 | void writeElem(const std::string& key, const cv::Point& elem);
158 | /**
159 | * @brief Write a cv::Mat into the yaml file given the key
160 | * @param name key to write
161 | * @param elem variable to write
162 | * @return true if the is correctly written, false otherwise
163 | */
164 | void writeElem(const std::string& key, const cv::Mat& elem);
165 | /**
166 | * @brief Check if a key exists
167 | * @param name name of the key to check
168 | * @return true if exists, false otherwise
169 | */
170 | bool keyExists(const std::string& key);
171 |
172 | private:
173 | /**
174 | * @brief Check if a file exists on your local HD
175 | * @param name path of the file name to check
176 | * @return true if exists, false otherwise
177 | */
178 | inline bool
179 | exists(const std::string& name) const
180 | {
181 | if(name.find("://")!=std::string::npos) return true;
182 | struct stat buffer;
183 | return (stat (name.c_str(), &buffer) == 0);
184 | }
185 |
186 | private:
187 | YAML::Emitter out;
188 | YAML::Node in;
189 | };
190 | }
191 | }
192 |
193 |
194 | #endif
195 |
--------------------------------------------------------------------------------
/src/config/src/configmanager.cpp:
--------------------------------------------------------------------------------
1 | #include "configmanager.h"
2 |
3 | using namespace mctracker::config;
4 |
5 | bool
6 | ConfigManager::read(const std::string& config)
7 | {
8 | if(!exist(config))
9 | {
10 | throw std::invalid_argument("Invalid file name: " + config);
11 | }
12 | yamlManager.read(config);
13 |
14 | if(!yamlManager.getElem("Number", cameraNum))
15 | {
16 | std::cout << "Camera Number is not specified!" << std::endl;
17 | return false;
18 | }
19 |
20 | std::string planViewName;
21 | if(!yamlManager.getElem("Planview", planViewName))
22 | {
23 | std::cout << "Planview is not specified!" << std::endl;
24 | return false;
25 | }
26 |
27 | planView = cv::imread(planViewName);
28 |
29 | if(!yamlManager.getElem("Show Planview", show))
30 | {
31 | show = false;
32 | }
33 |
34 | std::stringstream ss;
35 | for(auto i = 0; i < cameraNum; ++i)
36 | {
37 | CameraParam param;
38 | ss << "Camera" << i+1;
39 | std::string tmpVar;
40 | if(!yamlManager.getElem(ss.str(), tmpVar))
41 | {
42 | std::cout << "Camera"<< i+1 << " Stream is not specified!" << std::endl;
43 | return false;
44 | }
45 | param.setStream(tmpVar);
46 |
47 | ss.str("");
48 | ss << "Homography" << i+1;
49 | if(!yamlManager.getElem(ss.str(), tmpVar))
50 | {
51 | std::cout << "Homography"<< i+1 << " is not specified!" << std::endl;
52 | return false;
53 | }
54 | param.setHomography(tmpVar);
55 |
56 | ss.str("");
57 | ss << "FOV" << i+1;
58 | if(!yamlManager.getElem(ss.str(), tmpVar))
59 | {
60 | std::cout << "FOV"<< i+1 << " is not specified!" << std::endl;
61 | return false;
62 | }
63 | param.setFOV(tmpVar);
64 |
65 | ss.str("");
66 | ss << "Proximity" << i+1;
67 | bool prox;
68 | if(!yamlManager.getElem(ss.str(), prox))
69 | {
70 | std::cout << "Proximity"<< i+1 << " is not specified!" << std::endl;
71 | return false;
72 | }
73 | ss.str("");
74 | param.setProximity(prox);
75 | cameraParam.push_back(param);
76 | }
77 |
78 |
79 | std::string kalman_file;
80 | if(!yamlManager.getElem("Kalman", kalman_file))
81 | {
82 | std::cout << "No Kalman file found, predefined values will be use." << std::endl;
83 | kalmanParam.setAssociationDummyCost(50);
84 | kalmanParam.setNewHypDummyCost(2);
85 | kalmanParam.setDt(1.0);
86 | kalmanParam.setMaxMissed(15);
87 | kalmanParam.setMinPropagate(15);
88 | }
89 | else
90 | {
91 | if(!exist(kalman_file))
92 | {
93 | throw std::invalid_argument("Invalid file name: " + kalman_file);
94 | }
95 |
96 | YamlManager kalmanReader;
97 | kalmanReader.read(kalman_file);
98 |
99 |
100 | int tmpValue;
101 | if(!kalmanReader.getElem("ACD", tmpValue))
102 | {
103 | kalmanParam.setAssociationDummyCost(50);
104 | }
105 | kalmanParam.setAssociationDummyCost(tmpValue);
106 |
107 | if(!kalmanReader.getElem("NHDC", tmpValue))
108 | {
109 | kalmanParam.setNewHypDummyCost(2);
110 | }
111 | kalmanParam.setNewHypDummyCost(uint(tmpValue) );
112 |
113 | if(!kalmanReader.getElem("MINPROPAGATE", tmpValue))
114 | {
115 | kalmanParam.setMinPropagate(15);
116 | }
117 | kalmanParam.setMinPropagate(uint(tmpValue) );
118 |
119 | if(!kalmanReader.getElem("MAXMISSED", tmpValue))
120 | {
121 | kalmanParam.setMaxMissed(15);
122 | }
123 | kalmanParam.setMaxMissed(uint(tmpValue) );
124 |
125 | float dt;
126 | if(!kalmanReader.getElem("DT", dt))
127 | {
128 | kalmanParam.setMaxMissed(1.0);
129 | }
130 | kalmanParam.setDt( dt );
131 | }
132 |
133 | std::string detectorTmpVal;
134 |
135 | if(!yamlManager.getElem("Config", detectorTmpVal))
136 | {
137 | std::cout << "Config is not specified!" << std::endl;
138 | return false;
139 | }
140 |
141 | if(!exist(detectorTmpVal))
142 | {
143 | throw std::invalid_argument("Invalid file name: " + detectorTmpVal);
144 | }
145 |
146 | detectorParam.setConfig(detectorTmpVal);
147 |
148 | if(!yamlManager.getElem("Weights", detectorTmpVal))
149 | {
150 | std::cout << "Weights is not specified!" << std::endl;
151 | return false;
152 | }
153 |
154 | if(!exist(detectorTmpVal))
155 | {
156 | throw std::invalid_argument("Invalid file name: " + detectorTmpVal);
157 | }
158 |
159 | detectorParam.setWeights(detectorTmpVal);
160 |
161 | float thresh;
162 |
163 | if(!yamlManager.getElem("MinThreshold", thresh))
164 | {
165 | thresh = .8;
166 | }
167 |
168 | detectorParam.setThreshold(thresh);
169 |
170 | return true;
171 | }
172 |
173 | void
174 | ConfigManager::print()
175 | {
176 | auto i = 0;
177 | for(auto& param : cameraParam)
178 | {
179 | std::cout << "CAMERA " << i+1 << std::endl;
180 | param.print();
181 | i++;
182 | std::cout << std::endl;
183 | }
184 |
185 | std::cout << std::endl;
186 | std::cout << "KALMAN" << std::endl;
187 | kalmanParam.print();
188 |
189 | std::cout << std::endl;
190 | std::cout << "DETECTOR" << std::endl;
191 | detectorParam.print();
192 | }
193 |
194 | bool
195 | ConfigManager::exist(const std::string& name) const
196 | {
197 | if(name.find("://")!=std::string::npos) return true;
198 |
199 | struct stat buffer;
200 | return (stat (name.c_str(), &buffer) == 0);
201 | }
202 |
--------------------------------------------------------------------------------
/src/config/src/yamlmanager.cpp:
--------------------------------------------------------------------------------
1 | #include "yamlmanager.h"
2 |
3 | using namespace mctracker::config;
4 |
5 | YamlManager
6 | ::YamlManager()
7 | {
8 | out << YAML::BeginMap;
9 | }
10 |
11 | bool
12 | YamlManager::keyExists(const std::string& key)
13 | {
14 | if(in.IsDefined())
15 | {
16 | if(in[key])
17 | {
18 | return true;
19 | }
20 | }
21 | else
22 | {
23 | throw std::invalid_argument("File YAML is not open!");
24 | }
25 | return false;
26 | }
27 |
28 |
29 |
30 | bool
31 | YamlManager::write(const std::string& filepath)
32 | {
33 | out << YAML::EndMap;
34 | std::ofstream fout(filepath);
35 | try
36 | {
37 | fout << out.c_str();
38 | }
39 | catch(const std::runtime_error& e)
40 | {
41 | std::cout << "ERROR: Cannot write the yaml file: " << filepath << std::endl;
42 | return false;
43 | }
44 | fout.close();
45 | return true;
46 | }
47 |
48 | bool
49 | YamlManager::read(const std::string& filepath)
50 | {
51 | if(!exists(filepath))
52 | {
53 | throw std::invalid_argument("The File " + filepath + " does not exist!!");
54 | exit(-1);
55 | }
56 | try
57 | {
58 | in = YAML::LoadFile(filepath);
59 | }
60 | catch(const std::runtime_error& e)
61 | {
62 | std::cout << "ERROR: Cannot read the yaml file: " << filepath << std::endl;
63 | return false;
64 | }
65 | return true;
66 | }
67 |
68 | void
69 | YamlManager::writeElem(const std::string& key, const cv::Mat& elem)
70 | {
71 | try
72 | {
73 | out << YAML::Key << key;
74 | }
75 | catch(const std::runtime_error& e)
76 | {
77 | std::cout << "ERROR: Cannot write the key: " << key << std::endl;
78 | }
79 |
80 |
81 | auto wirteMatrix = [](auto vec, YAML::Emitter& out)
82 | {
83 | try
84 | {
85 | out << YAML::Flow << vec;
86 | }
87 | catch(const std::runtime_error& e)
88 | {
89 | std::cout << "ERROR: Cannot write the matrix" << std::endl;
90 | return false;
91 | }
92 | return true;
93 | };
94 |
95 | const int depth = elem.type();
96 |
97 | switch (depth)
98 | {
99 | case CV_32FC1:
100 | {
101 | std::vector vec(elem.begin(), elem.end());
102 | if(!wirteMatrix(vec, out))
103 | throw std::invalid_argument("ERROR: Cannot write the Key : " + key);
104 | break;
105 | }
106 | case CV_64FC1:
107 | {
108 | std::vector vec(elem.begin(), elem.end());
109 | if(!wirteMatrix(vec, out))
110 | throw std::invalid_argument("ERROR: Cannot write the Key : " + key);
111 | break;
112 | }
113 |
114 | default:
115 | throw std::invalid_argument("Invalid depth type of matrix!");
116 | }
117 | }
118 |
119 |
120 | void
121 | YamlManager::writeElem(const std::string& key, const float& elem)
122 | {
123 | try
124 | {
125 | out << YAML::Key << key;
126 | }
127 | catch(const std::runtime_error& e)
128 | {
129 | std::cout << "ERROR: Cannot write the key: " << key << std::endl;
130 | }
131 | try
132 | {
133 | out << YAML::Flow;
134 | out << YAML::BeginSeq << elem << YAML::EndSeq;
135 | }
136 | catch(const std::runtime_error& e)
137 | {
138 | std::cout << "ERROR: Cannot write the elem: " << elem << std::endl;
139 | }
140 |
141 | }
142 |
143 | void
144 | YamlManager::writeElem(const std::string& key, const cv::Point& elem)
145 | {
146 | try
147 | {
148 | out << YAML::Key << key;
149 | }
150 | catch(const std::runtime_error& e)
151 | {
152 | std::cout << "ERROR: Cannot write the key: " << key << std::endl;
153 | }
154 | try
155 | {
156 | out << YAML::Flow;
157 | out << YAML::BeginSeq << elem.x << elem.y << YAML::EndSeq;
158 | }
159 | catch(const std::runtime_error& e)
160 | {
161 | std::cout << "ERROR: Cannot write the elem: " << elem << std::endl;
162 | }
163 |
164 | }
165 |
166 | bool
167 | YamlManager::getElem(const std::string& name, bool& elem)
168 | {
169 | if(in[name])
170 | {
171 | try
172 | {
173 | elem = in[name].as();
174 | }
175 | catch(const std::runtime_error& e)
176 | {
177 | std::cout << "ERROR: Cannot read element " << name << e.what() << std::endl;
178 | return false;
179 | }
180 | }
181 | else
182 | {
183 | return false;
184 | }
185 | return true;
186 | }
187 |
188 |
189 | bool
190 | YamlManager::getElem(const std::string& name, int& elem)
191 | {
192 | if(in[name])
193 | {
194 | try
195 | {
196 | elem = in[name].as();
197 | }
198 | catch(const std::runtime_error& e)
199 | {
200 | std::cout << "ERROR: Cannot read element " << name << e.what() << std::endl;
201 | return false;
202 | }
203 | }
204 | else
205 | {
206 | return false;
207 | }
208 | return true;
209 | }
210 |
211 |
212 | bool
213 | YamlManager::getElem(const std::string& name, float& elem)
214 | {
215 | if(in[name])
216 | {
217 | try
218 | {
219 | elem = in[name].as();
220 | }
221 | catch(const std::runtime_error& e)
222 | {
223 | std::cout << "ERROR: Cannot read element " << name << e.what() << std::endl;
224 | return false;
225 | }
226 | }
227 | else
228 | {
229 | return false;
230 | }
231 | return true;
232 | }
233 |
234 | bool
235 | YamlManager::getElem(const std::string& name, double& elem)
236 | {
237 | if(in[name])
238 | {
239 | try
240 | {
241 | elem = in[name].as();
242 | }
243 | catch(const std::runtime_error& e)
244 | {
245 | std::cout << "ERROR: Cannot read element " << name << e.what() << std::endl;
246 | return false;
247 | }
248 | }
249 | else
250 | {
251 | return false;
252 | }
253 | return true;
254 | }
255 |
256 |
257 | bool
258 | YamlManager::getElem(const std::string& name, std::string& elem)
259 | {
260 | if(in[name])
261 | {
262 | try
263 | {
264 | elem = in[name].as();
265 | }
266 | catch(const std::runtime_error& e)
267 | {
268 | std::cout << "ERROR: Cannot read element " << name << e.what() << std::endl;
269 | return false;
270 | }
271 | }
272 | else
273 | {
274 | return false;
275 | }
276 | return true;
277 | }
278 |
279 | bool
280 | YamlManager::getElem(const std::string& name, std::vector& elem)
281 | {
282 | if(in[name] && in[name].IsSequence())
283 | {
284 | uint i = 0;
285 | for(const auto& e : in[name])
286 | {
287 | try
288 | {
289 | elem.push_back(e.as());
290 | }
291 | catch(const std::runtime_error& e)
292 | {
293 | std::cout << "ERROR: Cannot read element " << i << e.what() << std::endl;
294 | return false;
295 | }
296 | }
297 | }
298 | else
299 | {
300 | return true;
301 | }
302 | return false;
303 | }
304 |
305 | bool
306 | YamlManager::getElem(const std::string& name, std::vector& elem)
307 | {
308 | if(in[name] && in[name].IsSequence())
309 | {
310 | uint i = 0;
311 | for(const auto& e : in[name])
312 | {
313 | try
314 | {
315 | elem.push_back(e.as());
316 | }
317 | catch(const std::runtime_error& e)
318 | {
319 | std::cout << "ERROR: Cannot read element " << i << e.what() << std::endl;
320 | return false;
321 | }
322 | }
323 | }
324 | else
325 | {
326 | return true;
327 | }
328 | return false;
329 | }
330 |
331 |
332 | bool
333 | YamlManager::getElem(const std::string& name, std::vector& elem)
334 | {
335 | if(in[name] && in[name].IsSequence())
336 | {
337 | uint i = 0;
338 | for(const auto& e : in[name])
339 | {
340 | try
341 | {
342 | elem.push_back(e.as());
343 | }
344 | catch(const std::runtime_error& e)
345 | {
346 | std::cout << "ERROR: Cannot read element " << i << e.what() << std::endl;
347 | return false;
348 | }
349 | }
350 | }
351 | else
352 | {
353 | return true;
354 | }
355 | return false;
356 | }
357 |
358 | bool
359 | YamlManager::getElem(const std::string& name, std::vector< cv::Point2f >& elem)
360 | {
361 | if(in[name] && in[name].IsSequence())
362 | {
363 | for (YAML::iterator it = in[name].begin(); it != in[name].end(); ++it)
364 | {
365 | try
366 | {
367 | elem.push_back(cv::Point2f((*it).as(), (*(++it)).as()));
368 | }
369 | catch(const std::runtime_error& e)
370 | {
371 | std::cout << "ERROR: Cannot read element " << e.what() << std::endl;
372 | return false;
373 | }
374 | }
375 | return true;
376 | }
377 | return false;
378 | }
379 |
380 |
381 |
382 | bool
383 | YamlManager::getElem(const std::string& name, cv::Mat& elem, int type)
384 | {
385 | if(in[name] && in[name].IsSequence())
386 | {
387 | elem = cv::Mat(cv::Size(3, 3), type);
388 | uint i = 0;
389 | for(const auto& e : in[name])
390 | {
391 | try
392 | {
393 | if(type == CV_32FC1)
394 | elem.at(i++) = e.as();
395 | else if(type == CV_64FC1)
396 | elem.at(i++) = e.as();
397 | }
398 | catch(const std::runtime_error& e)
399 | {
400 | std::cout << "ERROR: Cannot read element " << i << e.what() << std::endl;
401 | return false;
402 | }
403 | }
404 | return true;
405 | }
406 | else
407 | {
408 | return true;
409 | }
410 | return false;
411 | }
412 |
413 | bool
414 | YamlManager::getElem(const std::string& name, cv::Point2i& elem)
415 | {
416 | if(in[name] && in[name].IsSequence() && in[name].size() == 2)
417 | {
418 | try
419 | {
420 | elem.x = in[name][0].as();
421 | elem.y = in[name][1].as();
422 | }
423 | catch(const std::runtime_error& e)
424 | {
425 | std::cout << "ERROR: Cannot read element " << name << e.what() << std::endl;
426 | return false;
427 | }
428 | }
429 | else
430 | {
431 | return false;
432 | }
433 | return true;
434 | }
435 |
436 | bool
437 | YamlManager::getElem(const std::string& name, cv::Point2f& elem)
438 | {
439 | if(in[name] && in[name].IsSequence() && in[name].size() == 2)
440 | {
441 | try
442 | {
443 | elem.x = in[name][0].as();
444 | elem.y = in[name][1].as();
445 | }
446 | catch(const std::runtime_error& e)
447 | {
448 | std::cout << "ERROR: Cannot read element " << name << e.what() << std::endl;
449 | return false;
450 | }
451 | }
452 | else
453 | {
454 | return false;
455 | }
456 | return true;
457 | }
458 |
459 | bool
460 | YamlManager::getElem(const std::string& name, cv::Point2d& elem)
461 | {
462 | if(in[name] && in[name].IsSequence() && in[name].size() == 2)
463 | {
464 | try
465 | {
466 | elem.x = in[name][0].as();
467 | elem.y = in[name][1].as();
468 | }
469 | catch(const std::runtime_error& e)
470 | {
471 | std::cout << "ERROR: Cannot read element " << name << e.what() << std::endl;
472 | return false;
473 | }
474 | }
475 | else
476 | {
477 | return false;
478 | }
479 | return true;
480 | }
481 |
482 |
483 |
--------------------------------------------------------------------------------
/src/homography/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | function(homography)
2 | include_directories(${PROJECT_BINARY_DIR}/../src/homography/include)
3 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src/homography/include)
4 |
5 | file(GLOB_RECURSE HOMOGRAPHY_SRC "src/homography/src/*.cpp")
6 |
7 | add_library(homography SHARED ${HOMOGRAPHY_SRC})
8 | target_link_libraries(homography ${OpenCV_LIBS} utils)
9 |
10 | endfunction()
11 |
--------------------------------------------------------------------------------
/src/homography/include/homography.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Written by Andrea Pennisi
3 | */
4 |
5 | #ifndef _HOMOGRAPHY_H_
6 | #define _HOMOGRAPHY_H_
7 |
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 |
14 | #include
15 | #include
16 | #include
17 |
18 | #include "yamlmanager.h"
19 |
20 | namespace mctracker
21 | {
22 | namespace geometry
23 | {
24 | class Homography {
25 | public:
26 | /**
27 | * @brief Constructor class Homography
28 | */
29 | Homography() { ; }
30 | /**
31 | * @brief set the source and destination points
32 | * @param src a vecotor of points of the source image
33 | * @param dst a vecotor of points of the destination image
34 | */
35 | void setPoints(const std::vector& src, const std::vector& dst);
36 | /**
37 | * @brief calculate the homography
38 | * @return a cv::Mat 3x3 containing the homography
39 | */
40 | cv::Mat calcHomography();
41 | /**
42 | * @brief draw the original points and the reprojected into the images
43 | * @param srcImage image representing the source to be reprojected
44 | * @param dstImage image representing the detestination image
45 | * @param H the homography matrix
46 | */
47 | void draw(const cv::Mat& srcImage, const cv::Mat& dstImage, const cv::Mat& H);
48 | /**
49 | * @brief write the matrix into a yaml filepath
50 | * @param filepath path to the file in which the homography will be stored
51 | */
52 | void writeToFile(const std::string& filepath = "../config/homography.yaml");
53 | public:
54 | /**
55 | * @brief calculate the projection of point give the homography matrix
56 | * @param point point to be converted
57 | * @param H homography matrix
58 | * @param x variable where the x-coordinate of the converted point will be stored
59 | * @param y variable where the y-coordinate of the converted point will be stored
60 | */
61 | static void calcProjection(const cv::Point2f &point, const cv::Mat &H, double &x, double &y);
62 | private:
63 | std::vector srcPoints;
64 | std::vector dstPoints;
65 | cv::Mat H;
66 | float error;
67 | config::YamlManager configFileWriter;
68 | };
69 | }
70 | }
71 |
72 |
73 | #endif
74 |
--------------------------------------------------------------------------------
/src/homography/src/homography.cpp:
--------------------------------------------------------------------------------
1 | #include "homography.h"
2 |
3 | using namespace mctracker;
4 | using namespace mctracker::geometry;
5 |
6 | void
7 | Homography::setPoints(const std::vector& src, const std::vector& dst)
8 | {
9 | auto itPts = srcPoints.begin();
10 |
11 | for(const auto& point : src)
12 | {
13 | srcPoints.push_back(point);
14 | }
15 |
16 | for(const auto& point : dst)
17 | {
18 | dstPoints.push_back(point);
19 | }
20 | }
21 |
22 |
23 | cv::Mat
24 | Homography::calcHomography()
25 | {
26 |
27 | std::cout << "\nsrc points: " << std::endl;
28 |
29 | for(const auto& point : srcPoints)
30 | {
31 | std::cout << point << std::endl;
32 | }
33 |
34 | std::cout << "\ndst points: " << std::endl;
35 |
36 | for(const auto& point : dstPoints)
37 | {
38 | std::cout << point << std::endl;
39 | }
40 |
41 | H = cv::findHomography(
42 | cv::Mat(srcPoints), cv::Mat(dstPoints), // corresponding points
43 | //inliers, // outputed inliers matches
44 | 0, //force all corrispondences to be used
45 | 0.5); // max distance to reprojection point
46 |
47 | std::cout << std::endl;
48 | std::cout << "MATRIX H" << std::endl;
49 | std::cout << H << std::endl;
50 |
51 | cv::Mat invH = H.inv();
52 |
53 | std::cout << std::endl;
54 | std::cout << "INV MATRIX H" << std::endl;
55 | std::cout << invH << std::endl;
56 |
57 | return H;
58 | }
59 |
60 |
61 | void
62 | Homography::draw(const cv::Mat& srcImage, const cv::Mat& dstImage, const cv::Mat& H) {
63 |
64 | cv::Mat dstMat;
65 | dstImage.copyTo(dstMat);
66 | cv::Mat srcMat;
67 | srcImage.copyTo(srcMat);
68 |
69 | // Draw the inlier points
70 | std::vector::const_iterator itPts = dstPoints.begin();
71 |
72 | for(const auto& point : dstPoints)
73 | {
74 | cv::circle(dstMat, point, 6, cv::Scalar(120,120,120), 2);
75 | }
76 |
77 | for(const auto& point : srcPoints)
78 | {
79 | cv::circle(srcMat, point, 6, cv::Scalar(120,120,120), 2);
80 | ++itPts;
81 | }
82 |
83 | // Display the images with points
84 | cv::namedWindow("Dst Points");
85 | cv::imshow("Dst Points", dstMat);
86 | cv::namedWindow("Src Points");
87 | cv::imshow("Src Points",srcMat);
88 |
89 | //reprojection
90 | std::cout << "Reprojection..." << std::endl;
91 |
92 | cv::Mat reprojectionImage = dstMat.clone();
93 |
94 | int cnt = 0;
95 | auto dist = [] (const cv::Point2f& p1, const cv::Point2f& p2)
96 | {
97 | const auto& p = p1 - p2;
98 | return sqrt(p.x * p.x + p.y * p.y);
99 | };
100 |
101 | error = 0.0;
102 | auto ii = 0;
103 | for(const auto& point : srcPoints)
104 | {
105 | double x, y;
106 | cv::Point2f p(point.x, point.y);
107 | calcProjection(p, H, x, y);
108 |
109 | std::cout << "(" << p.x << "," << p.y << ") --> (" << x << "," << y << ")" << std::endl;
110 | error += dist(dstPoints.at(ii++), cv::Point2f(x, y));
111 |
112 | if(x < 0 || y < 0)
113 | {
114 | std::cout << "WARNING: Negative reprojection values" << std::endl;
115 | }
116 | else {
117 | cv::line(reprojectionImage, cv::Point2f(x, y),
118 | cv::Point2f(x+10, y), CV_RGB(0,0,255), 2);
119 | cv::line(reprojectionImage, cv::Point2f(x, y),
120 | cv::Point2f(x-10, y), CV_RGB(0,0,255), 2);
121 | cv::line(reprojectionImage, cv::Point2f(x, y),
122 | cv::Point2f(x, y+10), CV_RGB(0,0,255), 2);
123 | cv::line(reprojectionImage, cv::Point2f(x, y),
124 | cv::Point2f(x, y-10), CV_RGB(0,0,255), 2);
125 |
126 | std::string s;
127 | std::stringstream out;
128 | out << cnt;
129 | s.assign(out.str());
130 | cv::putText(reprojectionImage, s, cv::Point2f(x+5,y-5),
131 | CV_FONT_HERSHEY_SIMPLEX, 0.6, CV_RGB(0, 0, 255));
132 | }
133 | }
134 |
135 | error /= srcPoints.size();
136 |
137 | std::cout << "Reprojection error: " << error << std::endl;
138 |
139 | cv::namedWindow("Reprojected Points");
140 | cv::imshow("Reprojected Points", reprojectionImage);
141 |
142 | cv::Mat warpImage = cv::Mat::zeros(dstMat.size(), dstMat.type());
143 | cv::warpPerspective(srcImage, warpImage, H, dstMat.size());
144 |
145 |
146 | cv::Mat total;
147 | cv::addWeighted(warpImage, 0.7, dstImage, 1., 0, total);
148 |
149 | cv::imshow("Total", total);
150 |
151 | cv::namedWindow("Warp Image");
152 | cv::imshow("Warp Image", warpImage);
153 |
154 | cv::waitKey(0);
155 | }
156 |
157 | void
158 | Homography::calcProjection(const cv::Point2f &point, const cv::Mat &H, double &x, double &y)
159 | {
160 | if(H.empty())
161 | {
162 | throw std::invalid_argument("Invaling homography");
163 | }
164 |
165 | x = (point.x*H.at(0,0)+point.y*H.at(0,1)+H.at(0,2))/
166 | (point.x*H.at(2,0)+point.y*H.at(2,1)+H.at(2,2));
167 | y = (point.x*H.at(1,0)+point.y*H.at(1,1)+H.at(1,2))/
168 | (point.x*H.at(2,0)+point.y*H.at(2,1)+H.at(2,2));
169 | }
170 |
171 | void
172 | Homography::writeToFile(const std::string& filepath)
173 | {
174 | if(H.empty())
175 | {
176 | throw std::invalid_argument("Homography Matrix is empty");
177 | }
178 |
179 | configFileWriter.writeElem("Matrix", H);
180 | configFileWriter.writeElem("Error", error);
181 | configFileWriter.write(filepath);
182 | }
183 |
184 |
185 |
186 |
--------------------------------------------------------------------------------
/src/object_detection/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | function(object_detection)
2 | add_library(darknet SHARED IMPORTED)
3 | set_property(TARGET darknet PROPERTY IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/darknet/libdarknet.so)
4 |
5 |
6 | include_directories(${PROJECT_BINARY_DIR}/darknet/include)
7 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/darknet/include)
8 | include_directories(${PROJECT_BINARY_DIR}/../src/object_detection/include)
9 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src/object_detection/include)
10 |
11 | file(GLOB_RECURSE DETECTOR "src/object_detection/src/*.cpp")
12 |
13 | #compiling libraries
14 | add_library(objectdetector SHARED ${DETECTOR})
15 | target_link_libraries(objectdetector darknet)
16 | endfunction()
17 |
--------------------------------------------------------------------------------
/src/object_detection/include/object_detector.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Written by Andrea Pennisi
3 | */
4 |
5 | #ifndef _OBJECT_DETECTOR_H_
6 | #define _OBJECT_DETECTOR_H_
7 |
8 | #include
9 | #include
10 | #include
11 | #include "detector_param.h"
12 | #include "yolo_v2_class.hpp"
13 |
14 |
15 | using namespace mctracker::config;
16 | namespace mctracker
17 | {
18 | namespace objectdetection
19 | {
20 | class ObjectDetector
21 | {
22 | public:
23 | /**
24 | * @brief Constructor class Homography
25 | * @param params object detector params extracted from the configuration file
26 | */
27 | ObjectDetector(const DetectorParam& params);
28 | /**
29 | * @brief classify the current frame
30 | * @param frame cv::Mat containing the image to classify
31 | * @param draw boolean which if is true allow the function to draw the detections
32 | * @return a cv::Mat containing the original frame with the detections drawed on (if draw is true)
33 | */
34 | cv::Mat classify(cv::Mat& frame, bool draw = true);
35 | public:
36 | /**
37 | * @brief return the detections of the last classified frame
38 | * @brief a vector of bbo_t contianing all the detections
39 | */
40 | inline const std::vector
41 | detections() const
42 | {
43 | return final_dets;
44 | }
45 | private:
46 | /**
47 | * @brief draw a bounding box around the detections
48 | * @param img the cv::Mat where the detections are drawed on
49 | * @param result_vec the vector of bbox_t containing all the detections
50 | */
51 | void draw_boxes(cv::Mat& mat_img, std::vector& result_vec);
52 | /**
53 | * @brief refine all the detections according to the thresholds specified in the config file
54 | * @param dets the vector of bbox_t containing all the detections
55 | */
56 | void refining(const std::vector& dets);
57 | private:
58 | std::string cfg, weights;
59 | float minimum_thresh;
60 | std::shared_ptr detector;
61 | std::vector dets;
62 | std::vector final_dets;
63 | };
64 | }
65 | }
66 |
67 | #endif
68 |
--------------------------------------------------------------------------------
/src/object_detection/src/object_detector.cpp:
--------------------------------------------------------------------------------
1 | #include "object_detector.h"
2 |
3 | using namespace mctracker;
4 | using namespace mctracker::objectdetection;
5 |
6 | ObjectDetector
7 | ::ObjectDetector(const DetectorParam& params)
8 | {
9 | cfg = params.getConfig();
10 | weights = params.getWeights();
11 | minimum_thresh = params.getThreshold();
12 | detector = std::shared_ptr(new Detector(cfg, weights));
13 | }
14 |
15 |
16 | cv::Mat
17 | ObjectDetector::classify(cv::Mat& frame, bool draw)
18 | {
19 | final_dets.clear();
20 | dets = detector->detect(frame);
21 | refining(dets);
22 | if(draw)
23 | {
24 | draw_boxes(frame, final_dets);
25 | }
26 | return frame;
27 | }
28 |
29 |
30 | void
31 | ObjectDetector::refining(const std::vector& dets)
32 | {
33 | for(const auto& det : dets)
34 | {
35 | //0 corresponds to PERSON and minimum_thresh is the minimum threshold I consider for being a person
36 | if(det.obj_id == 0 && det.prob >= minimum_thresh)
37 | {
38 | final_dets.push_back(det);
39 | }
40 | }
41 | }
42 |
43 |
44 |
45 | void
46 | ObjectDetector::draw_boxes(cv::Mat& mat_img, std::vector& result_vec)
47 | {
48 | static const cv::Scalar color(0, 0, 255);
49 | static const std::string obj_name = "person";
50 |
51 | for (auto &i : result_vec)
52 | {
53 | cv::rectangle(mat_img, cv::Rect(i.x, i.y, i.w, i.h), color, 2);
54 |
55 | cv::Size const text_size = cv::getTextSize(obj_name, cv::FONT_HERSHEY_COMPLEX_SMALL, 1.2, 2, 0);
56 | int const max_width = (text_size.width > (int)i.w + 2) ? text_size.width : (i.w + 2);
57 | cv::rectangle(mat_img, cv::Point2f(std::max((int)i.x - 1, 0), std::max((int)i.y - 30, 0)),
58 | cv::Point2f(std::min((int)i.x + max_width, mat_img.cols-1), std::min((int)i.y, mat_img.rows-1)),
59 | color, CV_FILLED, 8, 0);
60 | cv::putText(mat_img, obj_name, cv::Point2f(i.x, i.y - 10), cv::FONT_HERSHEY_COMPLEX_SMALL, 1.2, cv::Scalar(0, 0, 0), 2);
61 |
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/segmentation/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | function(segmentation)
2 | include_directories(${PROJECT_BINARY_DIR}/../src/segmentation/include)
3 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src/segmentation/include)
4 |
5 | file(GLOB_RECURSE SEGMENTATION_SRC "src/segmentation/src/*.cpp")
6 |
7 | add_library(segmentation SHARED ${SEGMENTATION_SRC})
8 | target_link_libraries(segmentation ${OpenCV_LIBS})
9 |
10 | endfunction()
11 |
--------------------------------------------------------------------------------
/src/segmentation/include/bgsubtraction.h:
--------------------------------------------------------------------------------
1 | #ifndef _BGSUBTRACTION_H_
2 | #define _BGSUBTRACTION_H_
3 |
4 | #include
5 | #include
6 |
7 | namespace mctracker
8 | {
9 | namespace segmentation
10 | {
11 | class BgSubtraction
12 | {
13 | public:
14 | /**
15 | * @brief Constructor class BgSubtraction
16 | */
17 | BgSubtraction();
18 | /**
19 | * @brief compute the background model
20 | * @param frame cv::Mat containing the current frame
21 | * @param morph a boolean which if is true enable morphology operations on the resulting foreground mask
22 | */
23 | void process(const cv::Mat& frame, bool morph = true);
24 | public:
25 | /**
26 | * @brief get the foreground mask
27 | * @param mask cv::Mat variable in which the mask will be stored
28 | * @return true if the mask is ready, false otherwise
29 | */
30 | inline bool
31 | getFgMask(cv::Mat& mask) const
32 | {
33 | if(frameNum >= 2)
34 | {
35 | mask = fgMask.getMat(cv::ACCESS_WRITE).clone();
36 | return true;
37 | }
38 | return false;
39 | }
40 | private:
41 | cv::Ptr pMOG2;
42 | double learningRate;
43 | int frameNum;
44 | cv::UMat fgMask;
45 | cv::UMat ref_frame;
46 | };
47 | }
48 | }
49 |
50 | #endif
51 |
--------------------------------------------------------------------------------
/src/segmentation/src/bgsubtraction.cpp:
--------------------------------------------------------------------------------
1 | #include "bgsubtraction.h"
2 |
3 | using namespace mctracker;
4 | using namespace mctracker::segmentation;
5 |
6 | BgSubtraction
7 | ::BgSubtraction()
8 | {
9 | pMOG2 = cv::createBackgroundSubtractorKNN();
10 | frameNum = 0;
11 | }
12 |
13 | void
14 | BgSubtraction::process(const cv::Mat& frame, bool morph)
15 | {
16 | //Decrease the learning rate when the background model becomes more reliable
17 | if (frameNum < 100)
18 | {
19 | learningRate = -1;
20 | }
21 | else if (frameNum < 1000)
22 | {
23 | learningRate = -.1;
24 | }
25 | else
26 | {
27 | learningRate = -0.001;
28 | }
29 |
30 | cv::UMat frameUMat = frame.getUMat(cv::ACCESS_WRITE);
31 | cv::blur(frameUMat, ref_frame, cv::Size(15, 15));
32 |
33 | pMOG2->apply(ref_frame, fgMask, learningRate);
34 | cv::compare(fgMask, cv::Scalar(255), fgMask, cv::CMP_EQ);
35 |
36 | if(morph)
37 | {
38 | cv::erode(fgMask, fgMask, cv::Mat(), cv::Point(-1, -1), 1);
39 | cv::dilate(fgMask, fgMask, cv::Mat(), cv::Point(-1, -1), 2);
40 | }
41 |
42 | frameUMat.release();
43 |
44 | frameNum++;
45 | }
46 |
--------------------------------------------------------------------------------
/src/tracker/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | function(tracker)
2 | include_directories(${PROJECT_BINARY_DIR}/../src/tracker/include)
3 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src/tracker/include)
4 |
5 | file(GLOB_RECURSE TRACKER_SRC "src/tracker/src/*.cpp")
6 |
7 | add_library(tracker SHARED ${TRACKER_SRC})
8 | target_link_libraries(tracker ${OpenCV_LIBS} config)
9 |
10 | endfunction()
11 |
--------------------------------------------------------------------------------
/src/tracker/include/detection.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Written by Andrea Pennisi
3 | */
4 |
5 | #ifndef _DETECTION_H_
6 | #define _DETECTION_H_
7 |
8 | #include
9 | #include
10 |
11 | namespace mctracker
12 | {
13 | namespace tracker
14 | {
15 | class Detection
16 | {
17 | public:
18 | /**
19 | * @brief Constructor class Detection
20 | */
21 | Detection() { ; }
22 | /**
23 | * @brief Constructor class Detection
24 | * @param _x the x-coordinate of the top left point
25 | * @param _y the y-coordinate of the top left point
26 | * @param _w the width of the detection
27 | * @param _h the height of the detection
28 | * @param hist the hsv histogram of the observation
29 | */
30 | Detection(const float& _x, const float& _y, const float& _w, const float& _h, const cv::Mat& hist)
31 | : m_x(_x), m_y(_y) , m_w(_w), m_h(_h), m_hist(hist)
32 | {
33 | point = cv::Point2f(m_x, m_y);
34 | }
35 |
36 | /**
37 | * @brief get the x-coordinate of the top left point
38 | * @return the x value of the x-coordinate of the top left point
39 | */
40 | inline const float
41 | x() const
42 | {
43 | return m_x;
44 | }
45 |
46 | /**
47 | * @brief get the y-coordinate of the top left point
48 | * @return the y value of the y-coordinate of the top left point
49 | */
50 | inline const float
51 | y() const
52 | {
53 | return m_y;
54 | }
55 |
56 | /**
57 | * @brief get the width of the detection
58 | * @return the width value of the detection
59 | */
60 | inline const float
61 | w() const
62 | {
63 | return m_w;
64 | }
65 |
66 | /**
67 | * @brief get the height of the detection
68 | * @return the height value of the detection
69 | */
70 | inline const float
71 | h() const
72 | {
73 | return m_h;
74 | }
75 |
76 | /**
77 | * @brief get the hsv histogram of the detection
78 | * @return the hsv histogram of the detection
79 | */
80 | inline const cv::Mat
81 | hist() const
82 | {
83 | return m_hist;
84 | }
85 |
86 | /**
87 | * @brief set the x-coordinate of the top left point
88 | * @param x containing the value of the x-coordinate of the top left point
89 | */
90 | void
91 | setX(const float& x)
92 | {
93 | m_x = x;
94 | }
95 |
96 | /**
97 | * @brief set the y-coordinate of the top left point
98 | * @param y containing the value of the y-coordinate of the top left point
99 | */
100 | void
101 | setY(const float& y)
102 | {
103 | m_y = y;
104 | }
105 |
106 | /**
107 | * @brief set the hsv histrogram of the detection
108 | * @param hist containing the hsv histrogram of the detection
109 | */
110 | void
111 | setHist(const cv::Mat& hist)
112 | {
113 | m_hist = hist;
114 | }
115 |
116 | /**
117 | * @brief set the width and the height of the detection
118 | * @param w containing the width of the detection
119 | * @param h containing the height of the detection
120 | */
121 | void
122 | setSize(int w, int h)
123 | {
124 | m_w = w;
125 | m_h = h;
126 | }
127 |
128 | /**
129 | * @brief operator()
130 | * @return a cv::Point2f containing the topleft point of the detection
131 | */
132 | inline const cv::Point2f
133 | operator()() const
134 | {
135 | return point;
136 | }
137 |
138 | /**
139 | * @brief copy operator
140 | * @param d_copy object to copy
141 | * @return the pointer to the current instance
142 | */
143 | Detection& operator=(const Detection& d_copy)
144 | {
145 | this->m_x = d_copy.x();
146 | this->m_y = d_copy.y();
147 | this->m_h = d_copy.h();
148 | this->m_w = d_copy.w();
149 | this->m_hist = d_copy.hist().clone();
150 | return *this;
151 | }
152 |
153 | private:
154 | float m_x, m_y;
155 | float m_w, m_h;
156 | cv::Point2f point;
157 | cv::Mat m_hist;
158 | };
159 | }
160 | }
161 |
162 | #endif
163 |
--------------------------------------------------------------------------------
/src/tracker/include/entity.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Written by Andrea Pennisi
3 | */
4 |
5 |
6 | #ifndef _ENTITY_H_
7 | #define _ENTITY_H_
8 |
9 | #include
10 | #include
11 | #include
12 |
13 | #include "kalman.h"
14 | #include "drawing.h"
15 | #include "utils.h"
16 | #include "camera.h"
17 |
18 | using namespace mctracker::utils;
19 |
20 | namespace mctracker
21 | {
22 | namespace tracker
23 | {
24 | class Entity
25 | {
26 | friend class Tracker;
27 |
28 | public:
29 | /**
30 | * @brief Constructor class Entity
31 | */
32 | Entity() { ; }
33 | /**
34 | * @brief get the 2d point representing the last predicted position of the entity
35 | * @return the 2d point in a cv::Point2f format
36 | */
37 | virtual const cv::Point2f getPoint() = 0;
38 | /**
39 | * @brief get the id of the entity
40 | * @return the integer representing the id assigned to the entity
41 | */
42 | virtual const int label() const = 0;
43 | public:
44 | /**
45 | * @brief get the sizes of the the entity from all the views
46 | * @return a vector of cv::Size containing all the sizes from all the view
47 | */
48 | const std::vector getSizes() const
49 | {
50 | return sizes;
51 | }
52 |
53 | /**
54 | * @brief draw the tracked entities in all the camera views
55 | * @param images a vector containing the current frames grabbed from all the cameras
56 | * @param cameras a vector containing all the camera infos
57 | */
58 | inline const void
59 | drawTrack(std::vector& images, const std::vector& cameras)
60 | {
61 | if(isgood)
62 | {
63 | auto i = 0;
64 | for(auto& img : images)
65 | {
66 | auto p = getPoint();
67 | auto imPoint = cameras.at(i).world2camera(p);
68 | const std::vector& sz = sizes;
69 | const cv::Size& curr_size = sz.at(i);
70 | if(curr_size.width != 0)
71 | {
72 | imPoint.y -= curr_size.height;
73 | imPoint.x -= (curr_size.width>>1);
74 |
75 | if(imPoint.x >= 0 && imPoint.y >= 0 && (imPoint.x + curr_size.width) < (img.cols - 1) && (imPoint.y + curr_size.height) < (img.rows - 1))
76 | {
77 | tools::Drawing::rectangle(cv::Rect(imPoint.x, imPoint.y, curr_size.width, curr_size.height), color, img);
78 | std::stringstream ss;
79 | ss << "#" << label2string();
80 |
81 | cv::putText(img, ss.str().c_str(), imPoint, cv::FONT_HERSHEY_SIMPLEX,
82 | 0.55, cv::Scalar(0, 255, 0), 2, CV_AA);
83 | }
84 | }
85 | ++i;
86 | }
87 | }
88 | }
89 |
90 | /**
91 | * @brief draw all the entities on the planview
92 | * @param img cv::Mat containing the plan view
93 | * @param history boolean: if true all the history realted to the entity is drawed
94 | */
95 | inline const void
96 | drawTrackPlanView(cv::Mat& img, bool history = true)
97 | {
98 | if(isgood)
99 | {
100 | const auto& p = getPoint();
101 | cv::circle(img, p, 3, color, -1);
102 | cv::putText(img, label2string().c_str(), p, cv::FONT_HERSHEY_SIMPLEX,
103 | 0.55, cv::Scalar(0, 255, 0), 2, CV_AA);
104 |
105 | if(history)
106 | tools::Drawing::history(m_history, color, img);
107 | }
108 | }
109 |
110 | /**
111 | * @brief get the history of the entity
112 | * @return a vector of cv::Points containing the history of the entity
113 | */
114 | inline const Points
115 | history() const
116 | {
117 | return m_history;
118 | }
119 |
120 | protected:
121 | typedef std::shared_ptr Kalman_ptr;
122 | protected:
123 | virtual const std::string label2string() = 0;
124 | protected:
125 | /**
126 | * @brief set the color of the entity
127 | * @param _color a cv::Scalar containing the color
128 | */
129 | void
130 | setColor(const cv::Scalar& _color)
131 | {
132 | color = _color;
133 | }
134 |
135 | /**
136 | * @brief set the update frequencies of the entity
137 | * @param dt a float containing the value of dt
138 | */
139 | inline const void
140 | setDt(const float& dt)
141 | {
142 | kf->setDt(dt);
143 | }
144 |
145 | /**
146 | * @brief get the the control-input model of the kalman filter associated to the entity
147 | * @return the control-input model
148 | */
149 | inline const
150 | cv::Mat B() const
151 | {
152 | return kf->B();
153 | }
154 |
155 | /**
156 | * @brief get posteriori error covariance matrix of the kalman filter associated to the entity
157 | * @return the posteriori error covariance matrix
158 | */
159 | inline const cv::Mat
160 | P() const
161 | {
162 | return kf->P();
163 | }
164 |
165 | /**
166 | * @brief get the error measurement covariance matrix of the kalman filter associated to the entity
167 | * @return the error measurement covariance matrix
168 | */
169 | inline const
170 | cv::Mat S() const
171 | {
172 | return kf->S();
173 | }
174 |
175 | /**
176 | * @brief check the history of the entity in order to keep only the last 10 observations
177 | */
178 | const
179 | void checkHistory()
180 | {
181 | if(m_history.size() > history_size)
182 | {
183 | m_history.erase(m_history.begin());
184 | }
185 | }
186 |
187 | protected:
188 | Points m_history;
189 | cv::Scalar color;
190 | Kalman_ptr kf;
191 | uint w, h;
192 | bool isgood;
193 | std::vector sizes;
194 | protected:
195 | constexpr static uint history_size = 10;
196 | };
197 | }
198 | }
199 |
200 | #endif
201 |
--------------------------------------------------------------------------------
/src/tracker/include/hungarianAlg.h:
--------------------------------------------------------------------------------
1 | /************************************************************************
2 | *
3 | * hungarianAlg.h
4 | author Andrey Smorodov
5 | modified by Andrea Pennisi
6 |
7 | header file for Hungarian algorithm
8 | *
9 | **************************************************************************/
10 |
11 | #ifndef _HUNGARIAN_ALG_H_
12 | #define _HUNGARIAN_ALG_H_
13 |
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 |
20 | #include "utils.h"
21 |
22 | typedef float track_t;
23 | typedef std::vector assignments_t;
24 | typedef std::vector distMatrix_t;
25 |
26 | namespace mctracker
27 | {
28 | namespace tracker
29 | {
30 | namespace costs
31 | {
32 | class AssignmentProblemSolver
33 | {
34 | public:
35 | // enum containing the Method for searching the optimal solutions
36 | enum TMethod
37 | {
38 | optimal,
39 | many_forbidden_assignments,
40 | without_forbidden_assignments
41 | };
42 | public:
43 | /**
44 | * @brief Constructor class AssignmentProblemSolver
45 | */
46 | AssignmentProblemSolver() { ; }
47 | /**
48 | * @brief compute the hungarian algorithm
49 | * @param distMatrix matrix containing the costs
50 | * @param nOfRows representing the number of tracks already existing
51 | * @param nOfColumns number of detections
52 | * @param assignment a vector in which all the assignments are stored
53 | * @param Method the enum variable representing which method that will be used for the hungarian algorithm
54 | */
55 | track_t Solve(const distMatrix_t& distMatrixIn, const size_t& nOfRows, const size_t& nOfColumns, assignments_t& assignment, const TMethod& Method = optimal);
56 | private:
57 | typedef std::vector BoolVec;
58 | private:
59 | // --------------------------------------------------------------------------
60 | // Computes the optimal assignment (minimum overall costs) using Munkres algorithm.
61 | // --------------------------------------------------------------------------
62 | void assignmentoptimal(assignments_t& assignment, track_t& cost, const distMatrix_t& distMatrixIn, const size_t& nOfRows, const size_t& nOfColumns);
63 | void buildassignmentvector(assignments_t& assignment, BoolVec& starMatrix, const size_t& nOfRows, const size_t& nOfColumns);
64 | void computeassignmentcost(const assignments_t& assignment, track_t& cost, const distMatrix_t& distMatrixIn, const size_t& nOfRows);
65 | void step2a(assignments_t& assignment, distMatrix_t& distMatrix, BoolVec& starMatrix, BoolVec& newStarMatrix, BoolVec& primeMatrix, BoolVec& coveredColumns, BoolVec& coveredRows, const size_t& nOfRows, const size_t& nOfColumns, const size_t& minDim);
66 | void step2b(assignments_t& assignment, distMatrix_t& distMatrix, BoolVec& starMatrix, BoolVec& newStarMatrix, BoolVec& primeMatrix, BoolVec& coveredColumns, BoolVec& coveredRows, const size_t& nOfRows, const size_t& nOfColumns, const size_t& minDim);
67 | void step3(assignments_t& assignment, distMatrix_t& distMatrix, BoolVec& starMatrix, BoolVec& newStarMatrix, BoolVec& primeMatrix, BoolVec& coveredColumns, BoolVec& coveredRows, const size_t& nOfRows, const size_t& nOfColumns, const size_t& minDim);
68 | void step4(assignments_t& assignment, distMatrix_t& distMatrix, BoolVec& starMatrix, BoolVec& newStarMatrix, BoolVec& primeMatrix, BoolVec& coveredColumns, BoolVec& coveredRows, const size_t& nOfRows, const size_t& nOfColumns, const size_t& minDim, const size_t& row, const size_t& col);
69 | void step5(assignments_t& assignment, distMatrix_t& distMatrix, BoolVec& starMatrix, BoolVec& newStarMatrix, BoolVec& primeMatrix, BoolVec& coveredColumns, BoolVec& coveredRows, const size_t& nOfRows, const size_t& nOfColumns, const size_t& minDim);
70 | // --------------------------------------------------------------------------
71 | // Computes a suboptimal solution. Good for cases with many forbidden assignments.
72 | // --------------------------------------------------------------------------
73 | void assignmentsuboptimal1(assignments_t& assignment, track_t& cost, const distMatrix_t& distMatrixIn, const size_t& nOfRows, const size_t& nOfColumns);
74 | // --------------------------------------------------------------------------
75 | // Computes a suboptimal solution. Good for cases with many forbidden assignments.
76 | // --------------------------------------------------------------------------
77 | void assignmentsuboptimal2(assignments_t& assignment, track_t& cost, const distMatrix_t& distMatrixIn, const size_t& nOfRows, const size_t& nOfColumns);
78 | };
79 | }
80 | }
81 | }
82 |
83 | #endif
84 |
--------------------------------------------------------------------------------
/src/tracker/include/hypothesis.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Written by Andrea Pennisi
3 | */
4 |
5 | #ifndef _HYPHOTHESIS_H_
6 | #define _HYPHOTHESIS_H_
7 |
8 | #include
9 | #include
10 | #include
11 |
12 | #include
13 | #include "lap.h"
14 | #include "hungarianAlg.h"
15 | #include "detection.h"
16 | #include "kalman_param.h"
17 | #include "track.h"
18 | #include "utils.h"
19 |
20 | using namespace mctracker::tracker::costs;
21 |
22 | namespace mctracker
23 | {
24 | namespace tracker
25 | {
26 | class Hyphothesis
27 | {
28 | private:
29 | typedef std::shared_ptr