Visual Servoing Platform  version 3.6.1 under development (2024-05-02)
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 #endif
47 
48 class VISP_EXPORT vpCannyEdgeDetection
49 {
50 private:
51  typedef enum EdgeType
52  {
53  STRONG_EDGE,
54  WEAK_EDGE,
55  ON_CHECK
56  } EdgeType;
57 
58  // Filtering + gradient methods choice
59  vpImageFilter::vpCannyFilteringAndGradientType m_filteringAndGradientType;
62  // // Gaussian smoothing attributes
63  int m_gaussianKernelSize;
64  float m_gaussianStdev;
65  vpArray2D<float> m_fg;
67  // // Gradient computation attributes
68  bool m_areGradientAvailable;
69  unsigned int m_gradientFilterKernelSize;
70  vpArray2D<float> m_gradientFilterX;
71  vpArray2D<float> m_gradientFilterY;
72  vpImage<float> m_dIx;
73  vpImage<float> m_dIy;
75  // // Edge thining attributes
76  std::map<std::pair<unsigned int, unsigned int>, float> m_edgeCandidateAndGradient;
78  // // Hysteresis thresholding attributes
79  float m_lowerThreshold;
81  float m_lowerThresholdRatio;
83  float m_upperThreshold;
84  float m_upperThresholdRatio;
87  // // Edge tracking attributes
88  std::map<std::pair<unsigned int, unsigned int>, EdgeType> m_edgePointsCandidates;
90  vpImage<unsigned char> m_edgeMap;
91  const vpImage<bool> *mp_mask;
98  void initGaussianFilters();
99 
103  void initGradientFilters();
105 
113  void performFilteringAndGradientComputation(const vpImage<unsigned char> &I);
114 
122  void performEdgeThinning(const float &lowerThreshold);
123 
137  void performHysteresisThresholding(const float &lowerThreshold, const float &upperThreshold);
138 
146  bool recursiveSearchForStrongEdge(const std::pair<unsigned int, unsigned int> &coordinates);
147 
154  void performEdgeTracking();
156 
157 public:
165 
185  vpCannyEdgeDetection(const int &gaussianKernelSize, const float &gaussianStdev, const unsigned int &sobelAperture,
186  const float &lowerThreshold = -1.f, const float &upperThreshold = -1.f,
187  const float &lowerThresholdRatio = 0.6f, const float &upperThresholdRatio = 0.8f,
189 
190  // // Configuration from files
191 #ifdef VISP_HAVE_NLOHMANN_JSON
197  vpCannyEdgeDetection(const std::string &jsonPath);
198 
206  void initFromJSON(const std::string &jsonPath);
207 
215  friend inline void from_json(const nlohmann::json &j, vpCannyEdgeDetection &detector)
216  {
217  std::string filteringAndGradientName = vpImageFilter::vpCannyFilteringAndGradientTypeToString(detector.m_filteringAndGradientType);
218  filteringAndGradientName = j.value("filteringAndGradientType", filteringAndGradientName);
219  detector.m_filteringAndGradientType = vpImageFilter::vpCannyFilteringAndGradientTypeFromString(filteringAndGradientName);
220  detector.m_gaussianKernelSize = j.value("gaussianSize", detector.m_gaussianKernelSize);
221  detector.m_gaussianStdev = j.value("gaussianStdev", detector.m_gaussianStdev);
222  detector.m_lowerThreshold = j.value("lowerThreshold", detector.m_lowerThreshold);
223  detector.m_lowerThresholdRatio = j.value("lowerThresholdRatio", detector.m_lowerThresholdRatio);
224  detector.m_gradientFilterKernelSize = j.value("gradientFilterKernelSize", detector.m_gradientFilterKernelSize);
225  detector.m_upperThreshold = j.value("upperThreshold", detector.m_upperThreshold);
226  detector.m_upperThresholdRatio = j.value("upperThresholdRatio", detector.m_upperThresholdRatio);
227  }
228 
235  friend inline void to_json(nlohmann::json &j, const vpCannyEdgeDetection &detector)
236  {
237  std::string filteringAndGradientName = vpImageFilter::vpCannyFilteringAndGradientTypeToString(detector.m_filteringAndGradientType);
238  j = nlohmann::json {
239  {"filteringAndGradientType", filteringAndGradientName},
240  {"gaussianSize", detector.m_gaussianKernelSize},
241  {"gaussianStdev", detector.m_gaussianStdev},
242  {"lowerThreshold", detector.m_lowerThreshold},
243  {"lowerThresholdRatio", detector.m_lowerThresholdRatio},
244  {"gradientFilterKernelSize", detector.m_gradientFilterKernelSize},
245  {"upperThreshold", detector.m_upperThreshold},
246  {"upperThresholdRatio", detector.m_upperThresholdRatio}
247  };
248  }
249 #endif
251 
254 #ifdef HAVE_OPENCV_CORE
262  vpImage<unsigned char> detect(const cv::Mat &cv_I);
263 #endif
264 
272  vpImage<unsigned char> detect(const vpImage<vpRGBa> &I_color);
273 
282 
291  {
292  m_filteringAndGradientType = type;
293  initGradientFilters();
294  }
295 
302  inline void setGradients(const vpImage<float> &dIx, const vpImage<float> &dIy)
303  {
304  m_dIx = dIx;
305  m_dIy = dIy;
306  m_areGradientAvailable = true;
307  }
308 
320  inline void setCannyThresholds(const float &lowerThresh, const float &upperThresh)
321  {
322  m_lowerThreshold = lowerThresh;
323  m_upperThreshold = upperThresh;
324  }
325 
338  inline void setCannyThresholdsRatio(const float &lowerThreshRatio, const float &upperThreshRatio)
339  {
340  m_lowerThresholdRatio = lowerThreshRatio;
341  m_upperThresholdRatio = upperThreshRatio;
342  }
343 
352  inline void setGaussianFilterParameters(const int &kernelSize, const float &stdev)
353  {
354  m_gaussianKernelSize = kernelSize;
355  m_gaussianStdev = stdev;
356  initGaussianFilters();
357  }
358 
364  inline void setGradientFilterAperture(const unsigned int &apertureSize)
365  {
366  m_gradientFilterKernelSize = apertureSize;
367  initGradientFilters();
368  }
369 
380  inline void setMask(const vpImage<bool> *p_mask)
381  {
382  mp_mask = p_mask;
383  }
385 };
386 #endif
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 nlohmann::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.
friend void to_json(nlohmann::json &j, const vpCannyEdgeDetection &detector)
Parse a vpCannyEdgeDetection object into JSON format.
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.