Visual Servoing Platform  version 3.6.1 under development (2024-11-21)
vpCannyEdgeDetection.h
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2024 by Inria. All rights reserved.
4  *
5  * This software is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See https://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  */
30 
31 #ifndef VP_CANNY_EDGE_DETECTION_H
32 #define VP_CANNY_EDGE_DETECTION_H
33 
34 // System includes
35 #include <map>
36 #include <vector>
37 #include <iostream>
38 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
39 #include <sys/resource.h> // To dynamically change the stack size
40 #endif
41 
42 // ViSP include
43 #include <visp3/core/vpConfig.h>
44 #include <visp3/core/vpImage.h>
45 #include <visp3/core/vpImageFilter.h>
46 #include <visp3/core/vpRGBa.h>
47 
48 // 3rd parties include
49 #ifdef VISP_HAVE_NLOHMANN_JSON
50 #include VISP_NLOHMANN_JSON(json.hpp)
51 #endif
52 
53 BEGIN_VISP_NAMESPACE
63 class VISP_EXPORT vpCannyEdgeDetection
64 {
65 
66 public:
74 
96  vpCannyEdgeDetection(const int &gaussianKernelSize, const float &gaussianStdev, const unsigned int &sobelAperture,
97  const float &lowerThreshold = -1.f, const float &upperThreshold = -1.f,
98  const float &lowerThresholdRatio = 0.6f, const float &upperThresholdRatio = 0.8f,
100  const bool &storeEdgePoints = false);
101 
102  // // Configuration from files
103 #ifdef VISP_HAVE_NLOHMANN_JSON
109  vpCannyEdgeDetection(const std::string &jsonPath);
110 
118  void initFromJSON(const std::string &jsonPath);
119 
127  friend void from_json(const nlohmann::json &j, vpCannyEdgeDetection &detector);
128 
135  friend void to_json(nlohmann::json &j, const vpCannyEdgeDetection &detector);
136 #endif
138 
141 #ifdef HAVE_OPENCV_CORE
151  vpImage<unsigned char> detect(const cv::Mat &cv_I);
152 #endif
153 
163  vpImage<unsigned char> detect(const vpImage<vpRGBa> &I_color);
164 
175 
184  {
185  m_filteringAndGradientType = type;
186  initGradientFilters();
187  }
188 
195  inline void setGradients(const vpImage<float> &dIx, const vpImage<float> &dIy)
196  {
197  m_dIx = dIx;
198  m_dIy = dIy;
199  m_areGradientAvailable = true;
200  }
201 
213  inline void setCannyThresholds(const float &lowerThresh, const float &upperThresh)
214  {
215  m_lowerThreshold = lowerThresh;
216  m_upperThreshold = upperThresh;
217  }
218 
231  inline void setCannyThresholdsRatio(const float &lowerThreshRatio, const float &upperThreshRatio)
232  {
233  m_lowerThresholdRatio = lowerThreshRatio;
234  m_upperThresholdRatio = upperThreshRatio;
235  }
236 
245  inline void setGaussianFilterParameters(const int &kernelSize, const float &stdev)
246  {
247  m_gaussianKernelSize = kernelSize;
248  m_gaussianStdev = stdev;
249  initGaussianFilters();
250  }
251 
257  inline void setGradientFilterAperture(const unsigned int &apertureSize)
258  {
259  m_gradientFilterKernelSize = apertureSize;
260  initGradientFilters();
261  }
262 
273  inline void setMask(const vpImage<bool> *p_mask)
274  {
275  mp_mask = p_mask;
276  }
277 
291 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
292  inline void setMinimumStackSize(const rlim_t &requiredStackSize)
293  {
294  m_minStackSize = requiredStackSize;
295  }
296 #else
297  inline void setMinimumStackSize(const unsigned int &requiredStackSize)
298  {
299  (void)requiredStackSize;
300  static bool hasNotBeenDisplayed = true;
301  if (hasNotBeenDisplayed) {
302  std::cerr << "setStackSize has no effect on non-POSIX systems. The stack size is defined during compilation." << std::endl;
303  hasNotBeenDisplayed = false;
304  }
305  }
306 #endif
307 
314  inline void setStoreEdgePoints(const bool &storeEdgePoints)
315  {
316  m_storeListEdgePoints = storeEdgePoints;
317  }
319 
327  inline std::vector<vpImagePoint> getEdgePointsList() const
328  {
329  if (!m_storeListEdgePoints) {
330  throw(vpException(vpException::fatalError, "Asking for the edge-points list while not asking to store it"));
331  }
332  return m_edgePointsList;
333  }
334 
343 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
344  inline rlim_t getMinimumStackSize() const
345  {
346  return m_minStackSize;
347  }
348 #else
349  inline unsigned int getMinimumStackSize() const
350  {
351  const unsigned int limit = 65532000;
352  return limit;
353  }
354 #endif
355 
356 
358 private:
359  typedef enum EdgeType
360  {
361  STRONG_EDGE,
362  WEAK_EDGE,
363  ON_CHECK
364  } EdgeType;
365 
366  // Filtering + gradient methods choice
367  vpImageFilter::vpCannyFilteringAndGradientType m_filteringAndGradientType;
370  // // Gaussian smoothing attributes
371  int m_gaussianKernelSize;
372  float m_gaussianStdev;
373  vpArray2D<float> m_fg;
375  // // Gradient computation attributes
376  bool m_areGradientAvailable;
377  unsigned int m_gradientFilterKernelSize;
378  vpArray2D<float> m_gradientFilterX;
379  vpArray2D<float> m_gradientFilterY;
380  vpImage<float> m_dIx;
381  vpImage<float> m_dIy;
383  // // Edge thining attributes
384  std::map<std::pair<unsigned int, unsigned int>, float> m_edgeCandidateAndGradient;
386  // // Hysteresis thresholding attributes
387  float m_lowerThreshold;
389  float m_lowerThresholdRatio;
391  float m_upperThreshold;
392  float m_upperThresholdRatio;
395  // // Edge tracking attributes
396 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
397  rlim_t m_minStackSize;
398 #endif
399  bool m_storeListEdgePoints;
400  std::map<std::pair<unsigned int, unsigned int>, EdgeType> m_edgePointsCandidates;
402  vpImage<unsigned char> m_edgeMap;
403  std::vector<vpImagePoint> m_edgePointsList;
404  const vpImage<bool> *mp_mask;
411  void initGaussianFilters();
412 
416  void initGradientFilters();
418 
426  void computeFilteringAndGradient(const vpImage<unsigned char> &I);
427 
435  void performEdgeThinning(const float &lowerThreshold);
436 
450  void performHysteresisThresholding(const float &lowerThreshold, const float &upperThreshold);
451 
459  bool recursiveSearchForStrongEdge(const std::pair<unsigned int, unsigned int> &coordinates);
460 
467  void performEdgeTracking();
469 };
470 END_VISP_NAMESPACE
471 #endif
Class that implements the Canny's edge detector. It is possible to use a boolean mask to ignore some ...
unsigned int getMinimumStackSize() const
Get the minimum stack size used by the algorithm.
void setStoreEdgePoints(const bool &storeEdgePoints)
If set to true, the list of the detected edge-points will be available calling the method vpCannyEdge...
void setFilteringAndGradientType(const vpImageFilter::vpCannyFilteringAndGradientType &type)
Set the Filtering And Gradient operators to apply to the image before the edge detection operation.
std::vector< vpImagePoint > getEdgePointsList() const
Get the list of edge-points that have been detected.
void setMask(const vpImage< bool > *p_mask)
Set a mask to ignore pixels for which the mask is false.
void setCannyThresholdsRatio(const float &lowerThreshRatio, const float &upperThreshRatio)
Set the lower and upper Canny Thresholds ratio that are used to compute them automatically....
void setMinimumStackSize(const unsigned int &requiredStackSize)
Set the minimum stack size, expressed in bytes, due to the recursivity of the algorithm.
void setGradients(const vpImage< float > &dIx, const vpImage< float > &dIy)
Set the Gradients of the image that will be processed.
void setCannyThresholds(const float &lowerThresh, const float &upperThresh)
Set the lower and upper Canny Thresholds used to qualify the edge point candidates....
void setGradientFilterAperture(const unsigned int &apertureSize)
Set the parameters of the gradient filter (Sobel or Scharr) kernel size filters.
void setGaussianFilterParameters(const int &kernelSize, const float &stdev)
Set the Gaussian Filters kernel size and standard deviation and initialize the aforementioned filters...
error that can be emitted by ViSP classes.
Definition: vpException.h:60
@ fatalError
Fatal error.
Definition: vpException.h:72
vpCannyFilteringAndGradientType
Canny filter and gradient operators to apply on the image before the edge detection stage.
Definition: vpImageFilter.h:90
@ CANNY_GBLUR_SOBEL_FILTERING
Apply Gaussian blur + Sobel operator on the input image.
Definition: vpImageFilter.h:91