31#ifndef VP_CANNY_EDGE_DETECTION_H
32#define VP_CANNY_EDGE_DETECTION_H
38#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
39#include <sys/resource.h>
43#include <visp3/core/vpConfig.h>
44#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
45#include <visp3/core/vpHSV.h>
47#include <visp3/core/vpImage.h>
48#include <visp3/core/vpImageFilter.h>
49#include <visp3/core/vpRGBa.h>
52#ifdef VISP_HAVE_NLOHMANN_JSON
53#include VISP_NLOHMANN_JSON(json.hpp)
100 vpCannyEdgeDetection(
const int &gaussianKernelSize,
const float &gaussianStdev,
const unsigned int &sobelAperture,
101 const float &lowerThreshold = -1.f,
const float &upperThreshold = -1.f,
102 const float &lowerThresholdRatio = 0.6f,
const float &upperThresholdRatio = 0.8f,
104 const bool &storeEdgePoints =
false,
const int &nbThread = -1);
118#ifdef VISP_HAVE_NLOHMANN_JSON
156#ifdef HAVE_OPENCV_CORE
180#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
181 template <
typename ArithmeticType,
bool useFullScale>
185 if (!m_areGradientAvailable) {
190 m_areGradientAvailable =
false;
193 float upperThreshold = m_upperThreshold;
194 float lowerThreshold = m_lowerThreshold;
195 if (upperThreshold < 0) {
197 m_gaussianStdev, m_lowerThresholdRatio,
198 m_upperThresholdRatio, m_filteringAndGradientType, mp_mask);
200 else if (m_lowerThreshold < 0) {
202 lowerThreshold = m_upperThreshold / 3.f;
205 lowerThreshold = std::max<float>(lowerThreshold, std::numeric_limits<float>::epsilon());
207 step3to5(Ihsv.getHeight(), Ihsv.getWidth(), lowerThreshold, upperThreshold);
232 m_filteringAndGradientType = type;
233 initGradientFilters();
246 m_areGradientAvailable =
true;
262 m_lowerThreshold = lowerThresh;
263 m_upperThreshold = upperThresh;
280 m_lowerThresholdRatio = lowerThreshRatio;
281 m_upperThresholdRatio = upperThreshRatio;
294 m_gaussianKernelSize = kernelSize;
295 m_gaussianStdev = stdev;
296 initGaussianFilters();
306 m_gradientFilterKernelSize = apertureSize;
307 initGradientFilters();
340#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
343 m_minStackSize = requiredStackSize;
346 inline void setMinimumStackSize(
const unsigned int &requiredStackSize)
348 (void)requiredStackSize;
349 static bool hasNotBeenDisplayed =
true;
350 if (hasNotBeenDisplayed) {
351 std::cerr <<
"vpCannyEdgeDetection::setStackSize() has no effect on non-POSIX systems. The stack size is defined during compilation." << std::endl;
352 hasNotBeenDisplayed =
false;
359#ifdef VISP_HAVE_OPENMP
360 int nbThread = maxNbThread;
362 nbThread = omp_get_max_threads();
364 m_nbThread = nbThread;
368 std::cout <<
"[WARNING] OpenMP is not available, setting the number of threads is ignored." << std::endl;
379 m_storeListEdgePoints = storeEdgePoints;
392 if (!m_storeListEdgePoints) {
395 return m_edgePointsList;
406#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
409 return m_minStackSize;
412 inline unsigned int getMinimumStackSize()
const
414 const unsigned int limit = 65532000;
451 typedef enum EdgeType
466 int m_gaussianKernelSize;
467 float m_gaussianStdev;
468 vpArray2D<float> m_fg;
471 bool m_areGradientAvailable;
472 unsigned int m_gradientFilterKernelSize;
473 vpArray2D<float> m_gradientFilterX;
474 vpArray2D<float> m_gradientFilterY;
475 vpImage<float> m_dIx;
476 vpImage<float> m_dIy;
479 std::vector<std::pair<unsigned int, float> > m_edgeCandidateAndGradient;
482 float m_lowerThreshold;
484 float m_lowerThresholdRatio;
486 float m_upperThreshold;
487 float m_upperThresholdRatio;
491#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
492 rlim_t m_minStackSize;
494 bool m_storeListEdgePoints;
495 std::vector<unsigned int> m_activeEdgeCandidates;
496 vpImage<EdgeType> m_edgePointsCandidates;
498 vpImage<unsigned char> m_edgeMap;
499 std::vector<vpImagePoint> m_edgePointsList;
500 const vpImage<bool> *mp_mask;
502 float getGradientOrientation(
const vpImage<float> &dIx,
const vpImage<float> &dIy,
const int &iter);
504 void getInterpolWeightsAndOffsets(
const float &gradientOrientation,
float &alpha,
float &beta,
const int &nbCols,
505 int &dRowGradAlpha,
int &dRowGradBeta,
int &dColGradAlpha,
int &dColGradBeta);
507 float getManhattanGradient(
const vpImage<float> &dIx,
const vpImage<float> &dIy,
const int &iter);
514 void initGaussianFilters();
519 void initGradientFilters();
529 void computeFilteringAndGradient(
const vpImage<unsigned char> &I);
540 void step3to5(
const unsigned int &height,
const unsigned int &width,
const float &lowerThreshold,
const float &upperThreshold);
549 void performEdgeThinning(
const float &lowerThreshold);
564 void performHysteresisThresholding(
const float &lowerThreshold,
const float &upperThreshold);
573 bool recursiveSearchForStrongEdge(
const unsigned int &coordinates);
581 void performEdgeTracking();
585#ifdef VISP_HAVE_NLOHMANN_JSON
589 filteringAndGradientName = j.value(
"filteringAndGradientType", filteringAndGradientName);
591 detector.m_gaussianKernelSize = j.value(
"gaussianSize", detector.m_gaussianKernelSize);
592 detector.m_gaussianStdev = j.value(
"gaussianStdev", detector.m_gaussianStdev);
593 detector.m_lowerThreshold = j.value(
"lowerThreshold", detector.m_lowerThreshold);
594 detector.m_lowerThresholdRatio = j.value(
"lowerThresholdRatio", detector.m_lowerThresholdRatio);
595 detector.m_gradientFilterKernelSize = j.value(
"gradientFilterKernelSize", detector.m_gradientFilterKernelSize);
596 detector.m_upperThreshold = j.value(
"upperThreshold", detector.m_upperThreshold);
597 detector.m_upperThresholdRatio = j.value(
"upperThresholdRatio", detector.m_upperThresholdRatio);
598 detector.m_nbThread = j.value(
"nbThread", detector.m_nbThread);
606 {
"filteringAndGradientType", filteringAndGradientName},
607 {
"gaussianSize", detector.m_gaussianKernelSize},
608 {
"gaussianStdev", detector.m_gaussianStdev},
609 {
"lowerThreshold", detector.m_lowerThreshold},
610 {
"lowerThresholdRatio", detector.m_lowerThresholdRatio},
611 {
"gradientFilterKernelSize", detector.m_gradientFilterKernelSize},
612 {
"upperThreshold", detector.m_upperThreshold},
613 {
"upperThresholdRatio", detector.m_upperThresholdRatio},
614 {
"nbThread", detector.m_nbThread}
vpCannyEdgeDetection()
Default constructor of the vpCannyEdgeDetection class. The thresholds used during the hysteresis thre...
vpImage< unsigned char > detect(const vpImage< vpRGBa > &I_color)
Detect the edges in an image. Convert the color image into a gray-scale image.
rlim_t getMinimumStackSize() const
Get the minimum stack size used by the algorithm.
void setMinimumStackSize(const rlim_t &requiredStackSize)
Set the minimum stack size, expressed in bytes, due to the recursive algorithm. If not called,...
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.
const std::vector< vpImagePoint > & getEdgePointsList() const
Get the list of edge-points that have been detected.
void reinit()
Reinitialize the detector:
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,...
vpImage< unsigned char > detect(const vpImage< vpHSV< ArithmeticType, useFullScale > > &Ihsv)
void initFromJSON(const std::string &jsonPath)
Initialize all the algorithm parameters using the JSON file whose path is jsonPath....
void setNbThread(const int &maxNbThread)
const vpImage< float > & getGIx() const
Get the horizontal gradient.
const vpImage< float > & getGIy() const
Get the vertical gradient.
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.
const vpImage< unsigned char > & getEdgeMap() const
Get the final edge-map.
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.
Class implementing the HSV pixel format.
static float computeCannyThreshold(const cv::Mat &cv_I, const cv::Mat *p_cv_dIx, const cv::Mat *p_cv_dIy, float &lowerThresh, const unsigned int &gaussianKernelSize=5, const float &gaussianStdev=2.f, const unsigned int &apertureGradient=3, const float &lowerThresholdRatio=0.6f, const float &upperThresholdRatio=0.8f, const vpCannyFilteringAndGradientType &filteringType=CANNY_GBLUR_SOBEL_FILTERING)
Compute the upper Canny edge filter threshold, using Gaussian blur + Sobel or + Scharr operators to c...
static std::string vpCannyFiltAndGradTypeToStr(const vpCannyFilteringAndGradientType &type)
Cast a vpImageFilter::vpCannyFilteringAndGradientType into a string, to know its name.
static void gradientFilter(const vpImage< vpHSV< ArithmeticType, useFullScale > > &I, vpImage< FilterType > &GIx, vpImage< FilterType > &GIy, const int &nbThread=-1, const vpImage< bool > *p_mask=nullptr, const vpImageFilter::vpCannyFilteringAndGradientType &type=CANNY_GBLUR_SCHARR_FILTERING)
Compute the horizontal and vertical gradients for HSV images.
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 void gaussianBlur(const vpImage< ImageType > &I, vpImage< OutputType > &GI, unsigned int size=7, FilterType sigma=0., bool normalize=true, const vpImage< bool > *p_mask=nullptr)
static vpCannyFilteringAndGradientType vpCannyFiltAndGradTypeFromStr(const std::string &name)
Cast a string into a vpImageFilter::vpCannyFilteringAndGradientType.
Definition of the vpImage class member functions.