Visual Servoing Platform  version 3.6.1 under development (2024-02-13)
vpCannyEdgeDetection.h
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2023 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 _vpCannyEdgeDetection_h_
32 #define _vpCannyEdgeDetection_h_
33 
34 // System includes
35 #include <map>
36 #include <vector>
37 
38 // ViSP include
39 #include <visp3/core/vpConfig.h>
40 #include <visp3/core/vpImage.h>
41 #include <visp3/core/vpImageFilter.h>
42 
43 // 3rd parties include
44 #ifdef VISP_HAVE_NLOHMANN_JSON
45 #include <nlohmann/json.hpp>
46 using json = nlohmann::json;
47 #endif
48 
49 class VISP_EXPORT vpCannyEdgeDetection
50 {
51 private:
52  typedef enum EdgeType
53  {
54  STRONG_EDGE,
55  WEAK_EDGE,
56  ON_CHECK
57  } EdgeType;
58 
59  // Filtering + gradient methods choice
60  vpImageFilter::vpCannyFilteringAndGradientType m_filteringAndGradientType;
63  // // Gaussian smoothing attributes
64  int m_gaussianKernelSize;
65  float m_gaussianStdev;
66  vpArray2D<float> m_fg;
68  // // Gradient computation attributes
69  bool m_areGradientAvailable;
70  unsigned int m_gradientFilterKernelSize;
71  vpArray2D<float> m_gradientFilterX;
72  vpArray2D<float> m_gradientFilterY;
73  vpImage<float> m_dIx;
74  vpImage<float> m_dIy;
76  // // Edge thining attributes
77  std::map<std::pair<unsigned int, unsigned int>, float> m_edgeCandidateAndGradient;
79  // // Hysteresis thresholding attributes
80  float m_lowerThreshold;
82  float m_lowerThresholdRatio;
84  float m_upperThreshold;
85  float m_upperThresholdRatio;
88  // // Edge tracking attributes
89  std::map<std::pair<unsigned int, unsigned int>, EdgeType> m_edgePointsCandidates;
91  vpImage<unsigned char> m_edgeMap;
92  const vpImage<bool> *mp_mask;
99  void initGaussianFilters();
100 
104  void initGradientFilters();
106 
114  void performFilteringAndGradientComputation(const vpImage<unsigned char> &I);
115 
123  void performEdgeThinning(const float &lowerThreshold);
124 
138  void performHysteresisThresholding(const float &lowerThreshold, const float &upperThreshold);
139 
147  bool recursiveSearchForStrongEdge(const std::pair<unsigned int, unsigned int> &coordinates);
148 
155  void performEdgeTracking();
157 
158 public:
166 
186  vpCannyEdgeDetection(const int &gaussianKernelSize, const float &gaussianStdev, const unsigned int &sobelAperture,
187  const float &lowerThreshold = -1.f, const float &upperThreshold = -1.f,
188  const float &lowerThresholdRatio = 0.6f, const float &upperThresholdRatio = 0.8f,
190 
191  // // Configuration from files
192 #ifdef VISP_HAVE_NLOHMANN_JSON
198  vpCannyEdgeDetection(const std::string &jsonPath);
199 
207  void initFromJSON(const std::string &jsonPath);
208 
216  friend inline void from_json(const json &j, vpCannyEdgeDetection &detector)
217  {
218  std::string filteringAndGradientName = vpImageFilter::vpCannyFilteringAndGradientTypeToString(detector.m_filteringAndGradientType);
219  filteringAndGradientName = j.value("filteringAndGradientType", filteringAndGradientName);
220  detector.m_filteringAndGradientType = vpImageFilter::vpCannyFilteringAndGradientTypeFromString(filteringAndGradientName);
221  detector.m_gaussianKernelSize = j.value("gaussianSize", detector.m_gaussianKernelSize);
222  detector.m_gaussianStdev = j.value("gaussianStdev", detector.m_gaussianStdev);
223  detector.m_lowerThreshold = j.value("lowerThreshold", detector.m_lowerThreshold);
224  detector.m_lowerThresholdRatio = j.value("lowerThresholdRatio", detector.m_lowerThresholdRatio);
225  detector.m_gradientFilterKernelSize = j.value("gradientFilterKernelSize", detector.m_gradientFilterKernelSize);
226  detector.m_upperThreshold = j.value("upperThreshold", detector.m_upperThreshold);
227  detector.m_upperThresholdRatio = j.value("upperThresholdRatio", detector.m_upperThresholdRatio);
228  }
229 
236  friend inline void to_json(json &j, const vpCannyEdgeDetection &detector)
237  {
238  std::string filteringAndGradientName = vpImageFilter::vpCannyFilteringAndGradientTypeToString(detector.m_filteringAndGradientType);
239  j = json {
240  {"filteringAndGradientType", filteringAndGradientName},
241  {"gaussianSize", detector.m_gaussianKernelSize},
242  {"gaussianStdev", detector.m_gaussianStdev},
243  {"lowerThreshold", detector.m_lowerThreshold},
244  {"lowerThresholdRatio", detector.m_lowerThresholdRatio},
245  {"gradientFilterKernelSize", detector.m_gradientFilterKernelSize},
246  {"upperThreshold", detector.m_upperThreshold},
247  {"upperThresholdRatio", detector.m_upperThresholdRatio}
248  };
249  }
250 #endif
252 
255 #ifdef HAVE_OPENCV_CORE
263  vpImage<unsigned char> detect(const cv::Mat &cv_I);
264 #endif
265 
273  vpImage<unsigned char> detect(const vpImage<vpRGBa> &I_color);
274 
283 
292  {
293  m_filteringAndGradientType = type;
294  initGradientFilters();
295  }
296 
303  inline void setGradients(const vpImage<float> &dIx, const vpImage<float> &dIy)
304  {
305  m_dIx = dIx;
306  m_dIy = dIy;
307  m_areGradientAvailable = true;
308  }
309 
321  inline void setCannyThresholds(const float &lowerThresh, const float &upperThresh)
322  {
323  m_lowerThreshold = lowerThresh;
324  m_upperThreshold = upperThresh;
325  }
326 
339  inline void setCannyThresholdsRatio(const float &lowerThreshRatio, const float &upperThreshRatio)
340  {
341  m_lowerThresholdRatio = lowerThreshRatio;
342  m_upperThresholdRatio = upperThreshRatio;
343  }
344 
353  inline void setGaussianFilterParameters(const int &kernelSize, const float &stdev)
354  {
355  m_gaussianKernelSize = kernelSize;
356  m_gaussianStdev = stdev;
357  initGaussianFilters();
358  }
359 
365  inline void setGradientFilterAperture(const unsigned int &apertureSize)
366  {
367  m_gradientFilterKernelSize = apertureSize;
368  initGradientFilters();
369  }
370 
381  inline void setMask(const vpImage<bool> *p_mask)
382  {
383  mp_mask = p_mask;
384  }
386 };
387 #endif
json namespace shortcut
friend void to_json(json &j, const vpCannyEdgeDetection &detector)
Parse a vpCannyEdgeDetection object into JSON format.
void setFilteringAndGradientType(const vpImageFilter::vpCannyFilteringAndGradientType &type)
Set the Filtering And Gradient operators to apply to the image before the edge detection operation.
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....
friend void from_json(const json &j, vpCannyEdgeDetection &detector)
Read the detector configuration from JSON. All values are optional and if an argument is not present,...
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...
vpCannyFilteringAndGradientType
Canny filter and gradient operators to apply on the image before the edge detection stage.
@ CANNY_GBLUR_SOBEL_FILTERING
Apply Gaussian blur + Sobel operator on the input image.
static vpCannyFilteringAndGradientType vpCannyFilteringAndGradientTypeFromString(const std::string &name)
Cast a string into a vpImageFilter::vpCannyFilteringAndGradientType.
static std::string vpCannyFilteringAndGradientTypeToString(const vpCannyFilteringAndGradientType &type)
Cast a vpImageFilter::vpCannyFilteringAndGradientType into a string, to know its name.