1 #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>
15 using 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;
26 std::string chosenDetectionContainerToString(
const ChosenDetectionContainer &choice)
29 case DETECTION_CONTAINER_MAP:
31 case DETECTION_CONTAINER_VECTOR:
33 case DETECTION_CONTAINER_BOTH:
41 ChosenDetectionContainer 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;
55 std::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;
67 int main(
int argc,
const char *argv[])
70 #if defined(HAVE_OPENCV_DNN) && defined(HAVE_OPENCV_VIDEOIO) && \
71 ((__cplusplus >= 201703L) || (defined(_MSVC_LANG) && (_MSVC_LANG >= 201703L)))
73 std::string opt_device(
"0");
75 std::string opt_dnn_model =
"opencv_face_detector_uint8.pb";
76 std::string opt_dnn_config =
"opencv_face_detector.pbtxt";
77 std::string opt_dnn_framework =
"none";
78 std::string opt_dnn_label_file =
"";
79 vpDetectorDNNOpenCV::DNNResultsParsingType opt_dnn_type = vpDetectorDNNOpenCV::RESNET_10;
81 int opt_dnn_width = 300, opt_dnn_height = 300;
82 double opt_dnn_meanR = 104.0, opt_dnn_meanG = 177.0, opt_dnn_meanB = 123.0;
83 double opt_dnn_scale_factor = 1.0;
84 bool opt_dnn_swapRB =
false;
85 bool opt_step_by_step =
false;
86 float opt_dnn_confThresh = 0.5f;
87 float opt_dnn_nmsThresh = 0.4f;
88 double opt_dnn_filterThresh = 0.25;
89 ChosenDetectionContainer opt_dnn_containerType = DETECTION_CONTAINER_MAP;
90 bool opt_verbose =
false;
91 std::string opt_input_json =
"";
92 std::string opt_output_json =
"";
94 for (
int i = 1; i < argc; i++) {
95 if (std::string(argv[i]) ==
"--device" && i + 1 < argc) {
96 opt_device = std::string(argv[++i]);
98 else if (std::string(argv[i]) ==
"--step-by-step") {
99 opt_step_by_step =
true;
101 else if (std::string(argv[i]) ==
"--model" && i + 1 < argc) {
102 opt_dnn_model = std::string(argv[++i]);
104 else if (std::string(argv[i]) ==
"--type" && i + 1 < argc) {
105 opt_dnn_type = vpDetectorDNNOpenCV::dnnResultsParsingTypeFromString(std::string(argv[++i]));
107 else if (std::string(argv[i]) ==
"--config" && i + 1 < argc) {
108 opt_dnn_config = std::string(argv[++i]);
109 if (opt_dnn_config.find(
"none") != std::string::npos) {
110 opt_dnn_config = std::string();
113 else if (std::string(argv[i]) ==
"--framework" && i + 1 < argc) {
114 opt_dnn_framework = std::string(argv[++i]);
115 if (opt_dnn_framework.find(
"none") != std::string::npos) {
116 opt_dnn_framework = std::string();
119 else if (std::string(argv[i]) ==
"--width" && i + 1 < argc) {
120 opt_dnn_width = atoi(argv[++i]);
122 else if (std::string(argv[i]) ==
"--height" && i + 1 < argc) {
123 opt_dnn_height = atoi(argv[++i]);
125 else if (std::string(argv[i]) ==
"--mean" && i + 3 < argc) {
126 opt_dnn_meanR = atof(argv[++i]);
127 opt_dnn_meanG = atof(argv[++i]);
128 opt_dnn_meanB = atof(argv[++i]);
130 else if (std::string(argv[i]) ==
"--scale" && i + 1 < argc) {
131 opt_dnn_scale_factor = atof(argv[++i]);
133 else if (std::string(argv[i]) ==
"--swapRB") {
134 opt_dnn_swapRB =
true;
136 else if (std::string(argv[i]) ==
"--confThresh" && i + 1 < argc) {
137 opt_dnn_confThresh = (float)atof(argv[++i]);
139 else if (std::string(argv[i]) ==
"--nmsThresh" && i + 1 < argc) {
140 opt_dnn_nmsThresh = (float)atof(argv[++i]);
142 else if (std::string(argv[i]) ==
"--filterThresh" && i + 1 < argc) {
143 opt_dnn_filterThresh = atof(argv[++i]);
145 else if (std::string(argv[i]) ==
"--labels" && i + 1 < argc) {
146 opt_dnn_label_file = std::string(argv[++i]);
148 else if (std::string(argv[i]) ==
"--container" && i + 1 < argc) {
149 opt_dnn_containerType = chosenDetectionContainerFromString(std::string(argv[++i]));
151 else if (std::string(argv[i]) ==
"--input-json" && i + 1 < argc) {
152 opt_input_json = std::string(std::string(argv[++i]));
154 else if (std::string(argv[i]) ==
"--output-json" && i + 1 < argc) {
155 opt_output_json = std::string(std::string(argv[++i]));
157 else if (std::string(argv[i]) ==
"--verbose" || std::string(argv[i]) ==
"-v") {
160 else if (std::string(argv[i]) ==
"--help" || std::string(argv[i]) ==
"-h") {
161 std::cout <<
"\nSYNOPSIS " << std::endl
162 << argv[0] <<
" [--device <video>]"
163 <<
" [--model <dnn weights file>]"
164 <<
" [--type <dnn type>]"
165 <<
" [--config <dnn config file]"
166 <<
" [--framework <name>]"
167 <<
" [--width <blob width>] [--height <blob height>]"
168 <<
" [--mean <meanR meanG meanB>]"
169 <<
" [--scale <scale factor>]"
171 <<
" [--confThresh <threshold>]"
172 <<
" [--nmsThresh <threshold>]"
173 <<
" [--filterThresh <threshold>]"
174 <<
" [--labels <file>]"
175 <<
" [--container <type>]"
176 <<
" [--input-json <path_to_input_json>]"
177 <<
" [--output-json <path_to_output_json>]"
178 <<
" [--step-by-step]"
179 <<
" [--verbose, -v]"
180 <<
" [--help, -h]" << std::endl;
181 std::cout <<
"\nOPTIONS " << std::endl
182 <<
" --device <video>" << std::endl
183 <<
" Camera device number or video name used to stream images." << std::endl
184 <<
" To use the first camera found on the bus set 0. On Ubuntu setting 0" << std::endl
185 <<
" will use /dev/video0 device. To use a video simply put the name of" << std::endl
186 <<
" the video, like \"path/my-video.mp4\" or \"path/image-%04d.png\"" << std::endl
187 <<
" if your video is a sequence of images." << std::endl
188 <<
" Default: " << opt_device << std::endl
190 <<
" --model <dnn weights file>" << std::endl
191 <<
" Path to dnn network trained weights." << std::endl
192 <<
" Default: " << opt_dnn_model << std::endl
194 <<
" --type <dnn type>" << std::endl
195 <<
" Type of dnn network. Admissible values are in " << std::endl
196 <<
" " << vpDetectorDNNOpenCV::getAvailableDnnResultsParsingTypes() << std::endl
197 <<
" Default: " << opt_dnn_type << std::endl
199 <<
" --config <dnn config file>" << std::endl
200 <<
" Path to dnn network config file or \"none\" not to use one. " << std::endl
201 <<
" Default: " << opt_dnn_config << std::endl
203 <<
" --framework <name>" << std::endl
204 <<
" Framework name or \"none\" not to specify one. " << std::endl
205 <<
" Default: " << opt_dnn_framework << std::endl
207 <<
" --width <blob width>" << std::endl
208 <<
" Input images will be resized to this width. " << std::endl
209 <<
" Default: " << opt_dnn_width << std::endl
211 <<
" --height <blob height>" << std::endl
212 <<
" Input images will be resized to this height. " << std::endl
213 <<
" Default: " << opt_dnn_height << std::endl
215 <<
" --mean <meanR meanG meanB>" << std::endl
216 <<
" Mean RGB subtraction values. " << std::endl
217 <<
" Default: " << opt_dnn_meanR <<
" " << opt_dnn_meanG <<
" " << opt_dnn_meanB << std::endl
219 <<
" --scale <scale factor>" << std::endl
220 <<
" Scale factor used to normalize the range of pixel values. " << std::endl
221 <<
" Default: " << opt_dnn_scale_factor << std::endl
223 <<
" --swapRB" << std::endl
224 <<
" When used this option allows to swap Red and Blue channels. " << std::endl
226 <<
" --confThresh <threshold>" << std::endl
227 <<
" Confidence threshold. " << std::endl
228 <<
" Default: " << opt_dnn_confThresh << std::endl
230 <<
" --nmsThresh <threshold>" << std::endl
231 <<
" Non maximum suppression threshold. " << std::endl
232 <<
" Default: " << opt_dnn_nmsThresh << std::endl
234 <<
" --filterThresh <threshold >" << std::endl
235 <<
" Filter threshold. Set 0. to disable." << std::endl
236 <<
" Default: " << opt_dnn_filterThresh << std::endl
238 <<
" --labels <file>" << std::endl
239 <<
" Path to label file either in txt or yaml format. Keep empty if unknown." << std::endl
240 <<
" Default: \"" << opt_dnn_label_file <<
"\"" << std::endl
242 <<
" --container <type>" << std::endl
243 <<
" Container type in " << getAvailableDetectionContainer() << std::endl
244 <<
" Default: " << chosenDetectionContainerToString(opt_dnn_containerType) << std::endl
246 <<
" --input-json <path_to_input_json>" << std::endl
247 <<
" 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
248 <<
" Default: empty" << std::endl
250 <<
" --output-json <type>" << std::endl
251 <<
" Output JSON file where will be saved the DNN configuration. If empty, does not save the configuration." << std::endl
252 <<
" Default: empty" << std::endl
254 <<
" --step-by-step" << std::endl
255 <<
" Enable step by step mode, waiting for a user click to process next image." << std::endl
257 <<
" --verbose, -v" << std::endl
258 <<
" Enable verbose mode." << std::endl
260 <<
" --help, -h" << std::endl
261 <<
" Display this helper message." << std::endl
267 std::cout <<
"Video device : " << opt_device << std::endl;
268 std::cout <<
"Label file (optional): " << (opt_dnn_label_file.empty() ?
"None" : opt_dnn_label_file) << std::endl;
270 cv::VideoCapture capture;
271 bool hasCaptureOpeningSucceeded;
273 hasCaptureOpeningSucceeded = capture.open(std::atoi(opt_device.c_str()));
276 hasCaptureOpeningSucceeded = capture.open(opt_device);
278 if (!hasCaptureOpeningSucceeded) {
279 std::cout <<
"Capture from camera: " << opt_device <<
" didn't work" << std::endl;
284 #if defined(VISP_HAVE_X11)
286 #elif defined(VISP_HAVE_GDI)
288 #elif defined(HAVE_OPENCV_HIGHGUI)
295 "The file containing the classes labels \"" + opt_dnn_label_file +
"\" does not exist !"));
298 vpDetectorDNNOpenCV dnn;
299 #ifdef VISP_HAVE_NLOHMANN_JSON
300 if (!opt_input_json.empty()) {
302 dnn.initFromJSON(opt_input_json);
306 if (!opt_input_json.empty()) {
307 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;
313 vpDetectorDNNOpenCV::NetConfig netConfig(opt_dnn_confThresh, opt_dnn_nmsThresh, opt_dnn_label_file
314 , cv::Size(opt_dnn_width, opt_dnn_height), opt_dnn_filterThresh, cv::Scalar(opt_dnn_meanR, opt_dnn_meanG, opt_dnn_meanB)
315 , opt_dnn_scale_factor, opt_dnn_swapRB, opt_dnn_type
316 , opt_dnn_model, opt_dnn_config, opt_dnn_framework
318 dnn.setNetConfig(netConfig);
322 std::cout << dnn.getNetConfig() << std::endl;
324 #ifdef VISP_HAVE_NLOHMANN_JSON
325 if (!opt_output_json.empty()) {
326 dnn.saveConfigurationInJSON(opt_output_json);
329 if (!opt_output_json.empty()) {
330 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;
345 std::cout <<
"Process image: " << I.
getWidth() <<
" x " << I.
getHeight() << std::endl;
352 std::cout <<
"Process new image" << std::endl;
357 if (opt_dnn_containerType == DETECTION_CONTAINER_MAP || opt_dnn_containerType == DETECTION_CONTAINER_BOTH) {
360 std::map<std::string, std::vector<vpDetectorDNNOpenCV::DetectedFeatures2D> > detections;
361 dnn.detect(frame, detections);
366 for (
auto key_val : detections) {
368 std::cout <<
" Class name : " << key_val.first << std::endl;
370 for (vpDetectorDNNOpenCV::DetectedFeatures2D detection : key_val.second) {
372 std::cout <<
" Bounding box : " << detection.getBoundingBox() << std::endl;
373 std::cout <<
" Class Id : " << detection.getClassId() << std::endl;
374 if (detection.getClassName())
375 std::cout <<
" Class name : " << detection.getClassName().value() << std::endl;
376 std::cout <<
" Confidence score: " << detection.getConfidenceScore() << std::endl;
378 detection.display(I);
383 std::ostringstream oss_map;
384 oss_map <<
"Detection time (map): " << t <<
" ms";
387 std::cout <<
" " << oss_map.str() << std::endl;
393 if (opt_dnn_containerType == DETECTION_CONTAINER_VECTOR || opt_dnn_containerType == DETECTION_CONTAINER_BOTH) {
396 std::vector<vpDetectorDNNOpenCV::DetectedFeatures2D> detections_vec;
397 dnn.detect(frame, detections_vec);
402 for (
auto detection : detections_vec) {
404 std::cout <<
" Bounding box : " << detection.getBoundingBox() << std::endl;
405 std::cout <<
" Class Id : " << detection.getClassId() << std::endl;
406 std::optional<std::string> classname_opt = detection.getClassName();
407 std::cout <<
" Class name : " << (classname_opt ? *classname_opt :
"Not known") << std::endl;
408 std::cout <<
" Confidence score: " << detection.getConfidenceScore() << std::endl;
410 detection.display(I);
414 std::ostringstream oss_vec;
415 oss_vec <<
"Detection time (vector): " << t_vector <<
" ms";
418 std::cout <<
" " << oss_vec.str() << std::endl;
425 if (opt_step_by_step) {
447 std::cout << e.
what() << std::endl;
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="") vp_override
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)
unsigned int getWidth() const
unsigned int getSize() const
unsigned int getHeight() const
static bool isNumber(const std::string &str)
VISP_EXPORT double measureTimeMs()