Visual Servoing Platform  version 3.6.1 under development (2024-12-09)
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 
293 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
294  inline void setMinimumStackSize(const rlim_t &requiredStackSize)
295  {
296  m_minStackSize = requiredStackSize;
297  }
298 #else
299  inline void setMinimumStackSize(const unsigned int &requiredStackSize)
300  {
301  (void)requiredStackSize;
302  static bool hasNotBeenDisplayed = true;
303  if (hasNotBeenDisplayed) {
304  std::cerr << "vpCannyEdgeDetection::setStackSize() has no effect on non-POSIX systems. The stack size is defined during compilation." << std::endl;
305  hasNotBeenDisplayed = false;
306  }
307  }
308 #endif
309 
316  inline void setStoreEdgePoints(const bool &storeEdgePoints)
317  {
318  m_storeListEdgePoints = storeEdgePoints;
319  }
321 
329  inline std::vector<vpImagePoint> getEdgePointsList() const
330  {
331  if (!m_storeListEdgePoints) {
332  throw(vpException(vpException::fatalError, "Asking for the edge-points list while not asking to store it"));
333  }
334  return m_edgePointsList;
335  }
336 
345 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
346  inline rlim_t getMinimumStackSize() const
347  {
348  return m_minStackSize;
349  }
350 #else
351  inline unsigned int getMinimumStackSize() const
352  {
353  const unsigned int limit = 65532000;
354  return limit;
355  }
356 #endif
357 
358 
360 private:
361  typedef enum EdgeType
362  {
363  STRONG_EDGE,
364  WEAK_EDGE,
365  ON_CHECK
366  } EdgeType;
367 
368  // Filtering + gradient methods choice
369  vpImageFilter::vpCannyFilteringAndGradientType m_filteringAndGradientType;
372  // // Gaussian smoothing attributes
373  int m_gaussianKernelSize;
374  float m_gaussianStdev;
375  vpArray2D<float> m_fg;
377  // // Gradient computation attributes
378  bool m_areGradientAvailable;
379  unsigned int m_gradientFilterKernelSize;
380  vpArray2D<float> m_gradientFilterX;
381  vpArray2D<float> m_gradientFilterY;
382  vpImage<float> m_dIx;
383  vpImage<float> m_dIy;
385  // // Edge thining attributes
386  std::map<std::pair<unsigned int, unsigned int>, float> m_edgeCandidateAndGradient;
388  // // Hysteresis thresholding attributes
389  float m_lowerThreshold;
391  float m_lowerThresholdRatio;
393  float m_upperThreshold;
394  float m_upperThresholdRatio;
397  // // Edge tracking attributes
398 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
399  rlim_t m_minStackSize;
400 #endif
401  bool m_storeListEdgePoints;
402  std::map<std::pair<unsigned int, unsigned int>, EdgeType> m_edgePointsCandidates;
404  vpImage<unsigned char> m_edgeMap;
405  std::vector<vpImagePoint> m_edgePointsList;
406  const vpImage<bool> *mp_mask;
413  void initGaussianFilters();
414 
418  void initGradientFilters();
420 
428  void computeFilteringAndGradient(const vpImage<unsigned char> &I);
429 
437  void performEdgeThinning(const float &lowerThreshold);
438 
452  void performHysteresisThresholding(const float &lowerThreshold, const float &upperThreshold);
453 
461  bool recursiveSearchForStrongEdge(const std::pair<unsigned int, unsigned int> &coordinates);
462 
469  void performEdgeTracking();
471 };
472 END_VISP_NAMESPACE
473 #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 recursive algorithm. If not called,...
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