6#include <visp3/core/vpConfig.h>
7#include <visp3/core/vpException.h>
8#include <visp3/core/vpImage.h>
9#include <visp3/core/vpImageConvert.h>
10#include <visp3/core/vpImageDraw.h>
11#include <visp3/core/vpIoTools.h>
12#include <visp3/core/vpTime.h>
13#include <visp3/gui/vpDisplayFactory.h>
14#include <visp3/imgproc/vpCircleHoughTransform.h>
15#include <visp3/imgproc/vpImgproc.h>
16#include <visp3/io/vpImageIo.h>
17#include <visp3/io/vpVideoReader.h>
19#include "drawingHelpers.h"
21#ifdef ENABLE_VISP_NAMESPACE
27 const bool &displayCanny);
31 const bool &displayCanny)
35 std::vector<vpImageCircle> detectedCircles = detector.
detect(I_src, nbCirclesToDetect);
39 std::cout <<
"Process time = " << (tF - t0) * 0.001 <<
"ms" << std::endl << std::flush;
43#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
46 std::vector<vpColor> v_colors;
53 unsigned int idColor = 0;
55 const unsigned int nbCircle =
static_cast<unsigned int>(detectedCircles.size());
56 for (
unsigned int idCircle = 0; idCircle < nbCircle; ++idCircle) {
57 const vpImageCircle &circleCandidate = detectedCircles[idCircle];
59 std::cout <<
"Circle #" <<
id <<
":" << std::endl;
60 std::cout <<
"\tCenter: (" << circleCandidate.
getCenter() <<
")" << std::endl;
61 std::cout <<
"\tRadius: (" << circleCandidate.
getRadius() <<
")" << std::endl;
62 std::cout <<
"\tProba: " << probas[id] << std::endl;
65 idColor = (idColor + 1) % v_colors.size();
67#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_17)
68 std::optional<vpImage<bool>> opt_mask = std::nullopt;
69 std::optional<std::vector<std::vector<std::pair<unsigned int, unsigned int> > > > opt_votingPoints = std::nullopt;
72 std::vector<std::vector<std::pair<unsigned int, unsigned int> > > *opt_votingPoints =
nullptr;
76#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_17)
79 if (opt_votingPoints !=
nullptr)
82 const unsigned int crossSize = 3;
83 const unsigned int crossThickness = 1;
84 unsigned int nbVotedCircles =
static_cast<unsigned int>(opt_votingPoints->size());
85 for (
unsigned int idCircle = 0; idCircle < nbVotedCircles; ++idCircle) {
87 const std::vector<std::pair<unsigned int, unsigned int> > &votingPoints = (*opt_votingPoints)[idCircle];
88 unsigned int nbVotingPoints =
static_cast<unsigned int>(votingPoints.size());
89 for (
unsigned int idPoint = 0; idPoint < nbVotingPoints; ++idPoint) {
91 const std::pair<unsigned int, unsigned int> &pt = votingPoints[idPoint];
96#if (VISP_CXX_STANDARD < VISP_CXX_STANDARD_17)
97 if (opt_mask !=
nullptr) {
100 if (opt_votingPoints !=
nullptr) {
101 delete opt_votingPoints;
107 drawingHelpers::display(edgeMap, I_dispCanny,
"Edge map", blockingMode);
109 return drawingHelpers::display(I_disp,
"Detection results", blockingMode);
112int main(
int argc,
char **argv)
114 const std::string def_input(
"coins2.jpg");
115 const std::string def_jsonFilePath = std::string(
"");
116 const int def_nbCirclesToDetect = -1;
117 const int def_gaussianKernelSize = 5;
118 const float def_gaussianSigma = 1.f;
119 const int def_sobelKernelSize = 3;
120 const float def_lowerCannyThresh = -1.f;
121 const float def_upperCannyThresh = -1.f;
122 const int def_nbEdgeFilteringIter = 3;
123 const std::pair<int, int> def_centerXlimits = std::pair<int, int>(0, 1920);
124 const std::pair<int, int> def_centerYlimits = std::pair<int, int>(0, 1080);
125 const unsigned int def_minRadius = 34;
126 const unsigned int def_maxRadius = 75;
127 const int def_dilatationKernelSize = 5;
128 const float def_centerThresh = 70.f;
129 const float def_circleProbaThresh = 0.725f;
130 const float def_circlePerfectness = 0.85f;
131 const float def_centerDistanceThresh = 5.f;
132 const float def_radiusDifferenceThresh = 5.f;
133 const int def_averagingWindowSize = 5;
136 const float def_lowerCannyThreshRatio = 0.6f;
137 const float def_upperCannyThreshRatio = 0.9f;
138 const int def_expectedNbCenters = -1;
139 const bool def_recordVotingPoints =
false;
140 const float def_visibilityRatioThresh = 0.1f;
142 std::string opt_input(def_input);
143 std::string opt_jsonFilePath = def_jsonFilePath;
144 int opt_nbCirclesToDetect = def_nbCirclesToDetect;
145 int opt_gaussianKernelSize = def_gaussianKernelSize;
146 float opt_gaussianSigma = def_gaussianSigma;
147 int opt_sobelKernelSize = def_sobelKernelSize;
148 float opt_lowerCannyThresh = def_lowerCannyThresh;
149 float opt_upperCannyThresh = def_upperCannyThresh;
150 int opt_nbEdgeFilteringIter = def_nbEdgeFilteringIter;
151 std::pair<int, int> opt_centerXlimits = def_centerXlimits;
152 std::pair<int, int> opt_centerYlimits = def_centerYlimits;
153 unsigned int opt_minRadius = def_minRadius;
154 unsigned int opt_maxRadius = def_maxRadius;
155 int opt_dilatationKerneSize = def_dilatationKernelSize;
156 float opt_centerThresh = def_centerThresh;
157 float opt_circleProbaThresh = def_circleProbaThresh;
158 float opt_circlePerfectness = def_circlePerfectness;
159 float opt_centerDistanceThresh = def_centerDistanceThresh;
160 float opt_radiusDifferenceThresh = def_radiusDifferenceThresh;
161 int opt_averagingWindowSize = def_averagingWindowSize;
164 float opt_lowerCannyThreshRatio = def_lowerCannyThreshRatio;
165 float opt_upperCannyThreshRatio = def_upperCannyThreshRatio;
166 int opt_expectedNbCenters = def_expectedNbCenters;
167 bool opt_recordVotingPoints = def_recordVotingPoints;
168 float opt_visibilityRatioThresh = def_visibilityRatioThresh;
169 bool opt_displayCanny =
false;
171 for (
int i = 1;
i < argc;
i++) {
172 std::string argName(argv[i]);
173 if (argName ==
"--input" && i + 1 < argc) {
174 opt_input = std::string(argv[i + 1]);
177#ifdef VISP_HAVE_NLOHMANN_JSON
178 else if (argName ==
"--config" && i + 1 < argc) {
179 opt_jsonFilePath = std::string(argv[i + 1]);
183 else if (argName ==
"--nb-circles" && i + 1 < argc) {
184 opt_nbCirclesToDetect = atoi(argv[i + 1]);
187 else if (argName ==
"--gaussian-kernel" && i + 1 < argc) {
188 opt_gaussianKernelSize = atoi(argv[i + 1]);
191 else if (argName ==
"--gaussian-sigma" && i + 1 < argc) {
192 opt_gaussianSigma =
static_cast<float>(atof(argv[i + 1]));
195 else if (argName ==
"--gradient-kernel" && i + 1 < argc) {
196 opt_sobelKernelSize = atoi(argv[i + 1]);
199 else if (argName ==
"--canny-thresh" && i + 2 < argc) {
200 opt_lowerCannyThresh =
static_cast<float>(atof(argv[i + 1]));
201 opt_upperCannyThresh =
static_cast<float>(atof(argv[i + 2]));
204 else if (argName ==
"--edge-filter" && i + 1 < argc) {
205 opt_nbEdgeFilteringIter = atoi(argv[i + 1]);
208 else if (argName ==
"--dilatation-kernel-size" && i + 1 < argc) {
209 opt_dilatationKerneSize = atoi(argv[i + 1]);
212 else if (argName ==
"--averaging-window-size" && i + 1 < argc) {
213 opt_averagingWindowSize = atoi(argv[i + 1]);
216 else if (argName ==
"--radius-limits" && i + 2 < argc) {
217 opt_minRadius = atoi(argv[i + 1]);
218 opt_maxRadius = atoi(argv[i + 2]);
221 else if (argName ==
"--center-thresh" && i + 1 < argc) {
222 opt_centerThresh =
static_cast<float>(atof(argv[i + 1]));
225 else if (argName ==
"--center-xlim" && i + 2 < argc) {
226 opt_centerXlimits = std::pair<int, int>(atoi(argv[i + 1]), atoi(argv[i + 2]));
229 else if (argName ==
"--center-ylim" && i + 2 < argc) {
230 opt_centerYlimits = std::pair<int, int>(atoi(argv[i + 1]), atoi(argv[i + 2]));
233 else if (argName ==
"--circle-probability-thresh" && i + 1 < argc) {
234 opt_circleProbaThresh =
static_cast<float>(atof(argv[i + 1]));
237 else if (argName ==
"--circle-perfectness" && i + 1 < argc) {
238 opt_circlePerfectness =
static_cast<float>(atof(argv[i + 1]));
241 else if (argName ==
"--merging-thresh" && i + 2 < argc) {
242 opt_centerDistanceThresh =
static_cast<float>(atof(argv[i + 1]));
243 opt_radiusDifferenceThresh =
static_cast<float>(atof(argv[i + 2]));
246 else if (argName ==
"--filtering-type" && i + 1 < argc) {
250 else if (argName ==
"--canny-backend" && i + 1 < argc) {
254 else if (argName ==
"--lower-canny-ratio" && i + 1 < argc) {
255 opt_lowerCannyThreshRatio =
static_cast<float>(atof(argv[i + 1]));
258 else if (argName ==
"--upper-canny-ratio" && i + 1 < argc) {
259 opt_upperCannyThreshRatio =
static_cast<float>(atof(argv[i + 1]));
262 else if (argName ==
"--expected-nb-centers" && i + 1 < argc) {
263 opt_expectedNbCenters = atoi(argv[i + 1]);
266 else if (argName ==
"--visibility-ratio-thresh" && i + 1 < argc) {
267 opt_visibilityRatioThresh =
static_cast<float>(atof(argv[i + 1]));
270 else if (argName ==
"--record-voting-points") {
271 opt_recordVotingPoints =
true;
273 else if (argName ==
"--display-edge-map") {
274 opt_displayCanny =
true;
276 else if (argName ==
"--help" || argName ==
"-h") {
277 std::cout <<
"NAME" << std::endl;
278 std::cout <<
"\t" << argv[0] <<
" Test program for the home-made Hough Circle Detection algorithm" << std::endl
280 std::cout <<
"SYNOPSIS" << std::endl;
281 std::cout <<
"\t" << argv[0]
282 <<
"\t [--input <path/to/file>]" << std::endl
283#ifdef VISP_HAVE_NLOHMANN_JSON
284 <<
"\t [--config <path/to/json/file>] (default: " << (def_jsonFilePath.empty() ?
"unused" : def_jsonFilePath) <<
")" << std::endl
286 <<
"\t [--nb-circles <number-circles-to-detect>] (default: " << def_nbCirclesToDetect <<
")" << std::endl
287 <<
"\t [--gaussian-kernel <kernel-size>] (default: " << def_gaussianKernelSize <<
")" << std::endl
288 <<
"\t [--gaussian-sigma <stddev>] (default: " << def_gaussianSigma <<
")" << std::endl
289 <<
"\t [--gradient-kernel <kernel-size>] (default: " << def_sobelKernelSize <<
")" << std::endl
290 <<
"\t [--canny-thresh <lower-canny-thresh upper-canny-thresh>] (default: " << def_lowerCannyThresh <<
" ; " << def_upperCannyThresh <<
")" << std::endl
291 <<
"\t [--edge-filter <nb-iter>] (default: " << def_nbEdgeFilteringIter <<
")" << std::endl
292 <<
"\t [--radius-limits <radius-min> <radius-max>] (default: min = " << def_minRadius <<
", max = " << def_maxRadius <<
")" << std::endl
293 <<
"\t [--dilatation-kernel-size <kernel-size>] (default: " << def_dilatationKernelSize <<
")" << std::endl
294 <<
"\t [--averaging-window-size <size>] (default: " << def_averagingWindowSize <<
")" << std::endl
295 <<
"\t [--center-thresh <center-detection-threshold>] (default: " << def_centerThresh <<
")" << std::endl
296 <<
"\t [--center-xlim <center-horizontal-min center-horizontal-max>] (default: " << def_centerXlimits.first <<
" , " << def_centerXlimits.second <<
")" << std::endl
297 <<
"\t [--center-ylim <center-vertical-min center-vertical-max>] (default: " << def_centerYlimits.first <<
" , " << def_centerYlimits.second <<
")" << std::endl
298 <<
"\t [--circle-probability-thresh <probability-threshold>] (default: " << def_circleProbaThresh <<
")" << std::endl
299 <<
"\t [--circle-perfectness <circle-perfectness-threshold>] (default: " << def_circlePerfectness <<
")" << std::endl
300 <<
"\t [--merging-thresh <center-distance-thresh> <radius-difference-thresh>] (default: centers distance threshold = " << def_centerDistanceThresh <<
", radius difference threshold = " << def_radiusDifferenceThresh <<
")" << std::endl
301 <<
"\t [--filtering-type <type-name>]"
303 <<
"\t [--canny-backend <backend-name>]"
305 <<
"\t [--lower-canny-ratio <value>]"
306 <<
" (default: " << def_lowerCannyThreshRatio<<
")" << std::endl
307 <<
"\t [--upper-canny-ratio <value>]"
308 <<
" (default: " << def_upperCannyThreshRatio <<
")" << std::endl
309 <<
"\t [--expected-nb-centers <number>]"
310#if (VISP_CXX_STANDARD > VISP_CXX_STANDARD_98)
311 <<
" (default: " << (def_expectedNbCenters < 0 ?
"no limits" : std::to_string(def_expectedNbCenters)) <<
")" << std::endl
315 <<
"\t [--visibility-ratio-thresh <ratio ]0; 1[> ]"
316 <<
" (default: " << def_visibilityRatioThresh <<
")" << std::endl
317 <<
"\t [--record-voting-points]" << std::endl
318 <<
"\t [--display-edge-map]" << std::endl
319 <<
"\t [--help, -h]" << std::endl
322 std::cout <<
"DESCRIPTION" << std::endl
323 <<
"\t--input" << std::endl
324 <<
"\t\tPermit to choose the input of the Hough Circle Algorithm." << std::endl
325 <<
"\t\tIf you want to use a succession of images as video, their name must be in the format ${BASENAME}%d.{jpg, png}." << std::endl
326 <<
"\t\tDefault: " << def_input << std::endl
328#ifdef VISP_HAVE_NLOHMANN_JSON
329 <<
"\t--config" << std::endl
330 <<
"\t\tPermit to configure the Hough Circle Algorithm using a JSON file." << std::endl
331 <<
"\t\tDefault: " << (def_jsonFilePath.empty() ?
"unused" : def_jsonFilePath) << std::endl
334 <<
"\t--nb-circles" << std::endl
335 <<
"\t\tPermit to choose the number of circles we want to detect in the image" << std::endl
336 <<
"\t\tThe results will be the circles having the greatest number of votes." << std::endl
337 <<
"\t\tDefault: " << def_nbCirclesToDetect << std::endl
339 <<
"\t--gaussian-kernel" << std::endl
340 <<
"\t\tPermit to set the size of the Gaussian filter used to smooth the input image and compute its gradients." << std::endl
341 <<
"\t\tMust be an odd value." << std::endl
342 <<
"\t\tDefault: " << def_gaussianKernelSize << std::endl
344 <<
"\t--gaussian-sigma" << std::endl
345 <<
"\t\tPermit to set the standard deviation of the Gaussian filter." << std::endl
346 <<
"\t\tMust be a positive value." << std::endl
347 <<
"\t\tDefault: " << def_gaussianSigma << std::endl
349 <<
"\t--gradient-kernel" << std::endl
350 <<
"\t\tPermit to set the size of the Gaussian filter used to smooth the input image and compute its gradients." << std::endl
351 <<
"\t\tMust be an odd value." << std::endl
352 <<
"\t\tDefault: " << def_gaussianKernelSize << std::endl
354 <<
"\t--canny-thresh" << std::endl
355 <<
"\t\tPermit to set the lower and upper thresholds of the Canny edge detector." << std::endl
356 <<
"\t\tIf a value is negative, it will be automatically computed." << std::endl
357 <<
"\t\tDefault: " << def_lowerCannyThresh <<
" ; " << def_upperCannyThresh << std::endl
359 <<
"\t--edge-filter" << std::endl
360 <<
"\t\tPermit to set the number of iteration of 8-neighbor filter iterations of the result of the Canny edge detector." << std::endl
361 <<
"\t\tIf negative, no filtering is performed." << std::endl
362 <<
"\t\tDefault: " << def_nbEdgeFilteringIter << std::endl
364 <<
"\t--radius-limits" << std::endl
365 <<
"\t\tPermit to set the minimum and maximum radii of the circles we are looking for." << std::endl
366 <<
"\t\tDefault: min = " << def_minRadius <<
", max = " << def_maxRadius << std::endl
368 <<
"\t--dilatation-kernel-size" << std::endl
369 <<
"\t\tPermit to set the size of the kernel of the dilatation operation used to detect the maxima of the centers votes." << std::endl
370 <<
"\t\tMinimum tolerated value is 1." << std::endl
371 <<
"\t\tDefault: " << def_dilatationKernelSize << std::endl
373 <<
"\t--averaging-window-size" << std::endl
374 <<
"\t\tPermit to set the number size of the averaging window used to detect the maxima of the centers votes." << std::endl
375 <<
"\t\tMust be odd." << std::endl
376 <<
"\t\tDefault: " << def_averagingWindowSize << std::endl
378 <<
"\t--center-thresh" << std::endl
379 <<
"\t\tPermit to set the minimum number of votes a point must reach to be considered as a center candidate." << std::endl
380 <<
"\t\tIf the input is a real image, must be a positive value." << std::endl
381 <<
"\t\tOtherwise, if the input is a synthetic image and the value is negative, a fine-tuned value will be used." << std::endl
382 <<
"\t\tDefault: " << def_centerThresh << std::endl
384 <<
"\t--center-xlim" << std::endl
385 <<
"\t\tPermit to set the minimum and maximum horizontal position to be considered as a center candidate." << std::endl
386 <<
"\t\tThe search area is limited to [-maxRadius; +image.width + maxRadius]." << std::endl
387 <<
"\t\tDefault: " << def_centerXlimits.first <<
" , " << def_centerXlimits.second << std::endl
389 <<
"\t--center-ylim" << std::endl
390 <<
"\t\tPermit to set the minimum and maximum vertical position to be considered as a center candidate." << std::endl
391 <<
"\t\tThe search area is limited to [-maxRadius; +image.height + maxRadius]." << std::endl
392 <<
"\t\tDefault: " << def_centerYlimits.first <<
" , " << def_centerYlimits.second << std::endl
394 <<
"\t--circle-probability-thresh" << std::endl
395 <<
"\t\tPermit to to set the minimum probability a circle must reach to be kept." << std::endl
396 <<
"\t\tDefault: " << def_circleProbaThresh << std::endl
398 <<
"\t--circle-perfectness" << std::endl
399 <<
"\t\tPermit to set the set the circle perfectness threshold." << std::endl
400 <<
"\t\tThis parameter is used during the radius candidates computation." << std::endl
401 <<
"\t\tThe scalar product radius RC_ij . gradient(Ep_j) >= m_circlePerfectness * || RC_ij || * || gradient(Ep_j) || to add a vote for the radius RC_ij." << std::endl
402 <<
"\t\tDefault: " << def_circlePerfectness << std::endl
404 <<
"\t--merging-thresh" << std::endl
405 <<
"\t\tPermit to set the thresholds used during the merging stage of the algorithm." << std::endl
406 <<
"\t\tThe center distance threshold indicates the maximum distance the centers can be in order to be merged." << std::endl
407 <<
"\t\tThe radius difference threshold indicates the maximum absolute difference between the two circle candidates in order to be merged." << std::endl
408 <<
"\t\tTwo circle candidates must met these two conditions in order to be merged together." << std::endl
409 <<
"\t\tDefault: centers distance threshold = " << def_centerDistanceThresh <<
", radius difference threshold = " << def_radiusDifferenceThresh << std::endl
411 <<
"\t--filtering-type" << std::endl
412 <<
"\t\tPermit to choose the gradient filters." << std::endl
415 <<
"\t--canny-backend" << std::endl
416 <<
"\t\tPermit to choose the backend used to compute the edge map." << std::endl
419 <<
"\t--lower-canny-ratio" << std::endl
420 <<
"\t\tPermit to choose the ratio for the lower threshold if automatic thresholding is chosen." << std::endl
421 <<
"\t\tDefault: " << def_lowerCannyThreshRatio << std::endl
423 <<
"\t--upper-canny-ratio" << std::endl
424 <<
"\t\tPermit to choose the ratio for the upper threshold if automatic thresholding is chosen." << std::endl
425 <<
"\t\tDefault: " << def_upperCannyThreshRatio << std::endl
427 <<
"\t--expected-nb-centers" << std::endl
428 <<
"\t\tPermit to choose the maximum number of centers having more votes than the threshold that are kept." << std::endl
429 <<
"\t\tA negative value makes that all the centers having more votes than the threshold are kept." << std::endl
430#if (VISP_CXX_STANDARD > VISP_CXX_STANDARD_98)
431 <<
"\t\tDefault: " << (def_expectedNbCenters < 0 ?
"no limits" : std::to_string(def_expectedNbCenters)) << std::endl
436 <<
"\t--expected-nb-centers" << std::endl
437 <<
"\t\tPermit to choose the maximum number of centers having more votes than the threshold that are kept." << std::endl
438 <<
"\t\tA negative value makes that all the centers having more votes than the threshold are kept." << std::endl
439#
if (VISP_CXX_STANDARD > VISP_CXX_STANDARD_98)
440 <<
"\t\tDefault: " << (def_expectedNbCenters < 0 ?
"no limits" : std::to_string(def_expectedNbCenters)) << std::endl
445 <<
"\t--record-voting-points" << std::endl
446 <<
"\t\tPermit to display the edge map used to detect the circles" << std::endl
447 <<
"\t\tDefault: off" << std::endl
449 <<
"\t--display-edge-map" << std::endl
450 <<
"\t\tPermit to display the edge map used to detect the circles" << std::endl
451 <<
"\t\tDefault: off" << std::endl
459 algoParams(opt_gaussianKernelSize
461 , opt_sobelKernelSize
462 , opt_lowerCannyThresh
463 , opt_upperCannyThresh
464 , opt_nbEdgeFilteringIter
467 ,
static_cast<float>(opt_minRadius)
468 ,
static_cast<float>(opt_maxRadius)
469 , opt_dilatationKerneSize
470 , opt_averagingWindowSize
472 , opt_circleProbaThresh
473 , opt_circlePerfectness
474 , opt_centerDistanceThresh
475 , opt_radiusDifferenceThresh
476 , opt_filteringAndGradientType
477 , opt_cannyBackendType
478 , opt_lowerCannyThreshRatio
479 , opt_upperCannyThreshRatio
480 , opt_expectedNbCenters
481 , opt_recordVotingPoints
482 , opt_visibilityRatioThresh
488 if (opt_jsonFilePath.empty()) {
489 std::cout <<
"Initializing detector from the program arguments [...]" << std::endl;
490 detector.
init(algoParams);
493#ifdef VISP_HAVE_NLOHMANN_JSON
494 std::cout <<
"Initializing detector from JSON file \"" << opt_jsonFilePath <<
"\", some of the program arguments will be ignored [...]" << std::endl;
501 std::cout << detector;
508 if (opt_input.find(
"%") != std::string::npos) {
510 bool hasToContinue =
true;
518#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
520 std::shared_ptr<vpDisplay> dCanny(
nullptr);
521 if (opt_displayCanny) {
527 if (opt_displayCanny) {
532 while (!g.
end() && hasToContinue) {
534 hasToContinue = run_detection(I_src, I_disp, I_dispCanny, detector, opt_nbCirclesToDetect,
false, opt_displayCanny);
538#if (VISP_CXX_STANDARD < VISP_CXX_STANDARD_11)
540 if (dCanny !=
nullptr) {
541 if (opt_displayCanny) {
559#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
561 std::shared_ptr<vpDisplay> dCanny(
nullptr);
562 if (opt_displayCanny) {
568 if (opt_displayCanny) {
573 run_detection(I_src, I_disp, I_dispCanny, detector, opt_nbCirclesToDetect,
true, opt_displayCanny);
575#if (VISP_CXX_STANDARD < VISP_CXX_STANDARD_11)
577 if (dCanny !=
nullptr) {
578 if (opt_displayCanny) {
static const vpColor orange
static const vpColor blue
static const vpColor purple
static const vpColor yellow
Class that defines generic functionalities for display.
error that can be emitted by ViSP classes.
@ functionNotImplementedError
Function not implemented.
Class that defines a 2D circle in an image.
vpImagePoint getCenter() const
float computeArcLengthInRoI(const vpRect &roi, const float &roundingTolerance=0.001f) const
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
static void drawCircle(vpImage< unsigned char > &I, const vpImageCircle &circle, unsigned char color, unsigned int thickness=1)
static void drawCross(vpImage< unsigned char > &I, const vpImagePoint &ip, unsigned int size, unsigned char color, unsigned int thickness=1)
static std::string vpCannyBackendTypeToString(const vpCannyBackendType &type)
Cast a vpImageFilter::vpCannyBackendTypeToString into a string, to know its name.
static std::string vpCannyBackendTypeList(const std::string &pref="<", const std::string &sep=" , ", const std::string &suf=">")
Get the list of available vpCannyBackendType.
static std::string vpCannyFiltAndGradTypeToStr(const vpCannyFilteringAndGradientType &type)
Cast a vpImageFilter::vpCannyFilteringAndGradientType into a string, to know its name.
vpCannyFilteringAndGradientType
Canny filter and gradient operators to apply on the image before the edge detection stage.
@ CANNY_GBLUR_SCHARR_FILTERING
Apply Gaussian blur + Scharr operator on the input image.
vpCannyBackendType
Canny filter backends for the edge detection operations.
@ CANNY_OPENCV_BACKEND
Use OpenCV.
static vpCannyFilteringAndGradientType vpCannyFiltAndGradTypeFromStr(const std::string &name)
Cast a string into a vpImageFilter::vpCannyFilteringAndGradientType.
static vpCannyBackendType vpCannyBackendTypeFromString(const std::string &name)
Cast a string into a vpImageFilter::vpCannyBackendTypeToString.
static std::string vpGetCannyFiltAndGradTypes(const std::string &pref="<", const std::string &sep=" , ", const std::string &suf=">")
Get the list of available vpCannyFilteringAndGradientType.
static void read(vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition of the vpImage class member functions.
unsigned int getWidth() const
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
unsigned int getHeight() const
Defines a rectangle in the plane.
Class that enables to manipulate easily a video file or a sequence of images. As it inherits from the...
void open(vpImage< vpRGBa > &I) VP_OVERRIDE
void setFileName(const std::string &filename)
void acquire(vpImage< vpRGBa > &I) VP_OVERRIDE
std::shared_ptr< vpDisplay > createDisplay()
Return a smart pointer vpDisplay specialization if a GUI library is available or nullptr otherwise.
vpDisplay * allocateDisplay()
Return a newly allocated vpDisplay specialization if a GUI library is available or nullptr otherwise.
VISP_EXPORT int wait(double t0, double t)
VISP_EXPORT double measureTimeMicros()