2#include <visp3/core/vpConfig.h>
3#include <visp3/core/vpIoTools.h>
4#include <visp3/detection/vpDetectorDNNOpenCV.h>
5#include <visp3/gui/vpDisplayGDI.h>
6#include <visp3/gui/vpDisplayOpenCV.h>
7#include <visp3/gui/vpDisplayX.h>
9#if defined(HAVE_OPENCV_VIDEOIO)
10#include <opencv2/videoio.hpp>
13#ifdef VISP_HAVE_NLOHMANN_JSON
14#include <nlohmann/json.hpp>
15using json = nlohmann::json;
20 DETECTION_CONTAINER_MAP = 0,
21 DETECTION_CONTAINER_VECTOR = 1,
22 DETECTION_CONTAINER_BOTH = 2,
23 DETECTION_CONTAINER_COUNT = 3
24} ChosenDetectionContainer;
26std::string chosenDetectionContainerToString(
const ChosenDetectionContainer &choice)
29 case DETECTION_CONTAINER_MAP:
31 case DETECTION_CONTAINER_VECTOR:
33 case DETECTION_CONTAINER_BOTH:
41ChosenDetectionContainer chosenDetectionContainerFromString(
const std::string &choiceStr)
43 ChosenDetectionContainer choice(DETECTION_CONTAINER_COUNT);
44 bool hasFoundMatch =
false;
45 for (
unsigned int i = 0; i < DETECTION_CONTAINER_COUNT && !hasFoundMatch; i++) {
46 ChosenDetectionContainer candidate = (ChosenDetectionContainer)i;
55std::string getAvailableDetectionContainer()
57 std::string availableContainers(
"< ");
58 for (
unsigned int i = 0; i < DETECTION_CONTAINER_COUNT - 1; i++) {
59 std::string name = chosenDetectionContainerToString((ChosenDetectionContainer)i);
60 availableContainers += name +
" , ";
62 availableContainers +=
63 chosenDetectionContainerToString((ChosenDetectionContainer)(DETECTION_CONTAINER_COUNT - 1)) +
" >";
64 return availableContainers;
67int main(
int argc,
const char *argv [])
69#if defined(HAVE_OPENCV_DNN) && defined(HAVE_OPENCV_VIDEOIO) && (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_17)
71 std::string opt_device(
"0");
73 std::string opt_dnn_model =
"opencv_face_detector_uint8.pb";
74 std::string opt_dnn_config =
"opencv_face_detector.pbtxt";
75 std::string opt_dnn_framework =
"none";
76 std::string opt_dnn_label_file =
"";
79 int opt_dnn_width = 300, opt_dnn_height = 300;
80 double opt_dnn_meanR = 104.0, opt_dnn_meanG = 177.0, opt_dnn_meanB = 123.0;
81 double opt_dnn_scale_factor = 1.0;
82 bool opt_dnn_swapRB =
false;
83 bool opt_step_by_step =
false;
84 float opt_dnn_confThresh = 0.5f;
85 float opt_dnn_nmsThresh = 0.4f;
86 double opt_dnn_filterThresh = 0.25;
87 ChosenDetectionContainer opt_dnn_containerType = DETECTION_CONTAINER_MAP;
88 bool opt_verbose =
false;
89 std::string opt_input_json =
"";
90 std::string opt_output_json =
"";
92 for (
int i = 1; i < argc; i++) {
93 if (std::string(argv[i]) ==
"--device" && i + 1 < argc) {
94 opt_device = std::string(argv[++i]);
96 else if (std::string(argv[i]) ==
"--step-by-step") {
97 opt_step_by_step =
true;
99 else if (std::string(argv[i]) ==
"--model" && i + 1 < argc) {
100 opt_dnn_model = std::string(argv[++i]);
102 else if (std::string(argv[i]) ==
"--type" && i + 1 < argc) {
105 else if (std::string(argv[i]) ==
"--config" && i + 1 < argc) {
106 opt_dnn_config = std::string(argv[++i]);
107 if (opt_dnn_config.find(
"none") != std::string::npos) {
108 opt_dnn_config = std::string();
111 else if (std::string(argv[i]) ==
"--framework" && i + 1 < argc) {
112 opt_dnn_framework = std::string(argv[++i]);
113 if (opt_dnn_framework.find(
"none") != std::string::npos) {
114 opt_dnn_framework = std::string();
117 else if (std::string(argv[i]) ==
"--width" && i + 1 < argc) {
118 opt_dnn_width = atoi(argv[++i]);
120 else if (std::string(argv[i]) ==
"--height" && i + 1 < argc) {
121 opt_dnn_height = atoi(argv[++i]);
123 else if (std::string(argv[i]) ==
"--mean" && i + 3 < argc) {
124 opt_dnn_meanR = atof(argv[++i]);
125 opt_dnn_meanG = atof(argv[++i]);
126 opt_dnn_meanB = atof(argv[++i]);
128 else if (std::string(argv[i]) ==
"--scale" && i + 1 < argc) {
129 opt_dnn_scale_factor = atof(argv[++i]);
131 else if (std::string(argv[i]) ==
"--swapRB") {
132 opt_dnn_swapRB =
true;
134 else if (std::string(argv[i]) ==
"--confThresh" && i + 1 < argc) {
135 opt_dnn_confThresh = (float)atof(argv[++i]);
137 else if (std::string(argv[i]) ==
"--nmsThresh" && i + 1 < argc) {
138 opt_dnn_nmsThresh = (float)atof(argv[++i]);
140 else if (std::string(argv[i]) ==
"--filterThresh" && i + 1 < argc) {
141 opt_dnn_filterThresh = atof(argv[++i]);
143 else if (std::string(argv[i]) ==
"--labels" && i + 1 < argc) {
144 opt_dnn_label_file = std::string(argv[++i]);
146 else if (std::string(argv[i]) ==
"--container" && i + 1 < argc) {
147 opt_dnn_containerType = chosenDetectionContainerFromString(std::string(argv[++i]));
149 else if (std::string(argv[i]) ==
"--input-json" && i + 1 < argc) {
150 opt_input_json = std::string(std::string(argv[++i]));
152 else if (std::string(argv[i]) ==
"--output-json" && i + 1 < argc) {
153 opt_output_json = std::string(std::string(argv[++i]));
155 else if (std::string(argv[i]) ==
"--verbose" || std::string(argv[i]) ==
"-v") {
158 else if (std::string(argv[i]) ==
"--help" || std::string(argv[i]) ==
"-h") {
159 std::cout <<
"\nSYNOPSIS " << std::endl
160 << argv[0] <<
" [--device <video>]"
161 <<
" [--model <dnn weights file>]"
162 <<
" [--type <dnn type>]"
163 <<
" [--config <dnn config file]"
164 <<
" [--framework <name>]"
165 <<
" [--width <blob width>] [--height <blob height>]"
166 <<
" [--mean <meanR meanG meanB>]"
167 <<
" [--scale <scale factor>]"
169 <<
" [--confThresh <threshold>]"
170 <<
" [--nmsThresh <threshold>]"
171 <<
" [--filterThresh <threshold>]"
172 <<
" [--labels <file>]"
173 <<
" [--container <type>]"
174 <<
" [--input-json <path_to_input_json>]"
175 <<
" [--output-json <path_to_output_json>]"
176 <<
" [--step-by-step]"
177 <<
" [--verbose, -v]"
178 <<
" [--help, -h]" << std::endl;
179 std::cout <<
"\nOPTIONS " << std::endl
180 <<
" --device <video>" << std::endl
181 <<
" Camera device number or video name used to stream images." << std::endl
182 <<
" To use the first camera found on the bus set 0. On Ubuntu setting 0" << std::endl
183 <<
" will use /dev/video0 device. To use a video simply put the name of" << std::endl
184 <<
" the video, like \"path/my-video.mp4\" or \"path/image-%04d.png\"" << std::endl
185 <<
" if your video is a sequence of images." << std::endl
186 <<
" Default: " << opt_device << std::endl
188 <<
" --model <dnn weights file>" << std::endl
189 <<
" Path to dnn network trained weights." << std::endl
190 <<
" Default: " << opt_dnn_model << std::endl
192 <<
" --type <dnn type>" << std::endl
193 <<
" Type of dnn network. Admissible values are in " << std::endl
195 <<
" Default: " << opt_dnn_type << std::endl
197 <<
" --config <dnn config file>" << std::endl
198 <<
" Path to dnn network config file or \"none\" not to use one. " << std::endl
199 <<
" Default: " << opt_dnn_config << std::endl
201 <<
" --framework <name>" << std::endl
202 <<
" Framework name or \"none\" not to specify one. " << std::endl
203 <<
" Default: " << opt_dnn_framework << std::endl
205 <<
" --width <blob width>" << std::endl
206 <<
" Input images will be resized to this width. " << std::endl
207 <<
" Default: " << opt_dnn_width << std::endl
209 <<
" --height <blob height>" << std::endl
210 <<
" Input images will be resized to this height. " << std::endl
211 <<
" Default: " << opt_dnn_height << std::endl
213 <<
" --mean <meanR meanG meanB>" << std::endl
214 <<
" Mean RGB subtraction values. " << std::endl
215 <<
" Default: " << opt_dnn_meanR <<
" " << opt_dnn_meanG <<
" " << opt_dnn_meanB << std::endl
217 <<
" --scale <scale factor>" << std::endl
218 <<
" Scale factor used to normalize the range of pixel values. " << std::endl
219 <<
" Default: " << opt_dnn_scale_factor << std::endl
221 <<
" --swapRB" << std::endl
222 <<
" When used this option allows to swap Red and Blue channels. " << std::endl
224 <<
" --confThresh <threshold>" << std::endl
225 <<
" Confidence threshold. " << std::endl
226 <<
" Default: " << opt_dnn_confThresh << std::endl
228 <<
" --nmsThresh <threshold>" << std::endl
229 <<
" Non maximum suppression threshold. " << std::endl
230 <<
" Default: " << opt_dnn_nmsThresh << std::endl
232 <<
" --filterThresh <threshold >" << std::endl
233 <<
" Filter threshold. Set 0. to disable." << std::endl
234 <<
" Default: " << opt_dnn_filterThresh << std::endl
236 <<
" --labels <file>" << std::endl
237 <<
" Path to label file either in txt or yaml format. Keep empty if unknown." << std::endl
238 <<
" Default: \"" << opt_dnn_label_file <<
"\"" << std::endl
240 <<
" --container <type>" << std::endl
241 <<
" Container type in " << getAvailableDetectionContainer() << std::endl
242 <<
" Default: " << chosenDetectionContainerToString(opt_dnn_containerType) << std::endl
244 <<
" --input-json <path_to_input_json>" << std::endl
245 <<
" Input JSON file used to configure the DNN. If set, the other arguments will be used to override the values set in the json file." << std::endl
246 <<
" Default: empty" << std::endl
248 <<
" --output-json <type>" << std::endl
249 <<
" Output JSON file where will be saved the DNN configuration. If empty, does not save the configuration." << std::endl
250 <<
" Default: empty" << std::endl
252 <<
" --step-by-step" << std::endl
253 <<
" Enable step by step mode, waiting for a user click to process next image." << std::endl
255 <<
" --verbose, -v" << std::endl
256 <<
" Enable verbose mode." << std::endl
258 <<
" --help, -h" << std::endl
259 <<
" Display this helper message." << std::endl
265 std::cout <<
"Video device : " << opt_device << std::endl;
266 std::cout <<
"Label file (optional): " << (opt_dnn_label_file.empty() ?
"None" : opt_dnn_label_file) << std::endl;
268 cv::VideoCapture capture;
269 bool hasCaptureOpeningSucceeded;
271 hasCaptureOpeningSucceeded = capture.open(std::atoi(opt_device.c_str()));
274 hasCaptureOpeningSucceeded = capture.open(opt_device);
276 if (!hasCaptureOpeningSucceeded) {
277 std::cout <<
"Capture from camera: " << opt_device <<
" didn't work" << std::endl;
282#if defined(VISP_HAVE_X11)
284#elif defined(VISP_HAVE_GDI)
286#elif defined(HAVE_OPENCV_HIGHGUI)
293 "The file containing the classes labels \"" + opt_dnn_label_file +
"\" does not exist !"));
297#ifdef VISP_HAVE_NLOHMANN_JSON
298 if (!opt_input_json.empty()) {
304 if (!opt_input_json.empty()) {
305 std::cerr <<
"Error: NLOHMANN JSON library is not installed, please install it following ViSP documentation to configure the vpDetectorDNNOpenCV from a JSON file." << std::endl;
312 , cv::Size(opt_dnn_width, opt_dnn_height), opt_dnn_filterThresh, cv::Scalar(opt_dnn_meanR, opt_dnn_meanG, opt_dnn_meanB)
313 , opt_dnn_scale_factor, opt_dnn_swapRB, opt_dnn_type
314 , opt_dnn_model, opt_dnn_config, opt_dnn_framework
322#ifdef VISP_HAVE_NLOHMANN_JSON
323 if (!opt_output_json.empty()) {
327 if (!opt_output_json.empty()) {
328 std::cerr <<
"Error: NLOHMANN JSON library is not installed, please install it following ViSP documentation to save the configuration in a JSON file." << std::endl;
343 std::cout <<
"Process image: " << I.
getWidth() <<
" x " << I.
getHeight() << std::endl;
350 std::cout <<
"Process new image" << std::endl;
355 if (opt_dnn_containerType == DETECTION_CONTAINER_MAP || opt_dnn_containerType == DETECTION_CONTAINER_BOTH) {
358 std::map<std::string, std::vector<vpDetectorDNNOpenCV::DetectedFeatures2D> > detections;
359 dnn.
detect(frame, detections);
364 for (
auto key_val : detections) {
366 std::cout <<
" Class name : " << key_val.first << std::endl;
370 std::cout <<
" Bounding box : " << detection.getBoundingBox() << std::endl;
371 std::cout <<
" Class Id : " << detection.getClassId() << std::endl;
372 if (detection.getClassName())
373 std::cout <<
" Class name : " << detection.getClassName().value() << std::endl;
374 std::cout <<
" Confidence score: " << detection.getConfidenceScore() << std::endl;
376 detection.display(I);
381 std::ostringstream oss_map;
382 oss_map <<
"Detection time (map): " << t <<
" ms";
385 std::cout <<
" " << oss_map.str() << std::endl;
391 if (opt_dnn_containerType == DETECTION_CONTAINER_VECTOR || opt_dnn_containerType == DETECTION_CONTAINER_BOTH) {
394 std::vector<vpDetectorDNNOpenCV::DetectedFeatures2D> detections_vec;
395 dnn.
detect(frame, detections_vec);
400 for (
auto detection : detections_vec) {
402 std::cout <<
" Bounding box : " << detection.getBoundingBox() << std::endl;
403 std::cout <<
" Class Id : " << detection.getClassId() << std::endl;
404 std::optional<std::string> classname_opt = detection.getClassName();
405 std::cout <<
" Class name : " << (classname_opt ? *classname_opt :
"Not known") << std::endl;
406 std::cout <<
" Confidence score: " << detection.getConfidenceScore() << std::endl;
408 detection.display(I);
412 std::ostringstream oss_vec;
413 oss_vec <<
"Detection time (vector): " << t_vector <<
" ms";
416 std::cout <<
" " << oss_vec.str() << std::endl;
423 if (opt_step_by_step) {
445 std::cout << e.
what() << std::endl;
Structure containing the bounding box, expressed in pixels, confidence and class information about an...
Structure containing some information required for the configuration of a vpDetectorDNNOpenCV object.
void initFromJSON(const std::string &jsonPath)
static std::string getAvailableDnnResultsParsingTypes()
Get the list of the parsing methods / types of DNNs supported by the vpDetectorDNNOpenCV class.
DNNResultsParsingType
Enumeration listing the types of DNN for which the vpDetectorDNNOpenCV furnishes the methods permitti...
static DNNResultsParsingType dnnResultsParsingTypeFromString(const std::string &name)
void setNetConfig(const NetConfig &config)
virtual bool detect(const vpImage< unsigned char > &I, std::vector< DetectedFeatures2D > &output)
Object detection using OpenCV DNN module.
const NetConfig & getNetConfig() const
void saveConfigurationInJSON(const std::string &jsonPath) const
Save the network configuration in a JSON file.
Display for windows using GDI (available on any windows 32 platform).
The vpDisplayOpenCV allows to display image using the OpenCV library. Thus to enable this class OpenC...
Use the X11 console to display images on unix-like OS. Thus to enable this class X11 should be instal...
void init(vpImage< unsigned char > &I, int win_x=-1, int win_y=-1, const std::string &win_title="")
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
virtual void setDownScalingFactor(unsigned int scale)
static void display(const vpImage< unsigned char > &I)
static void setTitle(const vpImage< unsigned char > &I, const std::string &windowtitle)
static void flush(const vpImage< unsigned char > &I)
static void displayText(const vpImage< unsigned char > &I, const vpImagePoint &ip, const std::string &s, const vpColor &color)
error that can be emitted by ViSP classes.
const char * what() const
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
Definition of the vpImage class member functions.
unsigned int getWidth() const
unsigned int getSize() const
unsigned int getHeight() const
static bool isNumber(const std::string &str)
VISP_EXPORT double measureTimeMs()