34#include <visp3/core/vpConfig.h>
35#include <visp3/core/vpImageFilter.h>
36#include <visp3/core/vpIoTools.h>
37#include <visp3/core/vpCannyEdgeDetection.h>
50 const std::string &suf)
52 std::string list(pref);
75 name =
"opencv-backend";
78 name =
"visp-backend";
81 return "unknown-backend";
100 bool notFound =
true;
102 while ((i < count) && notFound) {
122 const std::string &suf)
124 std::string list(pref);
147 name =
"gaussianblur+sobel-filtering";
150 name =
"gaussianblur+scharr-filtering";
153 return "unknown-filtering";
172 bool notFound =
true;
174 while ((i < count) && notFound) {
185#if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC)
205 float &lowerThresh,
const unsigned int &gaussianKernelSize,
206 const float &gaussianStdev,
const unsigned int &apertureGradient,
207 const float &lowerThresholdRatio,
const float &upperThresholdRatio,
210 if ((lowerThresholdRatio <= 0.f) || (lowerThresholdRatio >= 1.f)) {
211 std::stringstream errMsg;
212 errMsg <<
"Lower ratio (" << lowerThresholdRatio <<
") " << (lowerThresholdRatio < 0.f ?
"should be greater than 0 !" :
"should be lower than 1 !");
216 if ((upperThresholdRatio <= 0.f) || (upperThresholdRatio >= 1.f)) {
217 std::stringstream errMsg;
218 errMsg <<
"Upper ratio (" << upperThresholdRatio <<
") " << (upperThresholdRatio < 0.f ?
"should be greater than 0 !" :
"should be lower than 1 !");
222 if (lowerThresholdRatio >= upperThresholdRatio) {
223 std::stringstream errMsg;
224 errMsg <<
"Lower ratio (" << lowerThresholdRatio <<
") should be lower than the upper ratio (" << upperThresholdRatio <<
")";
228 double w = cv_I.cols;
229 double h = cv_I.rows;
231 cv::Mat dI, dIx, dIy, dIx_abs, dIy_abs;
233 if ((p_cv_dIx ==
nullptr) || (p_cv_dIy ==
nullptr)) {
243 cv::convertScaleAbs(dIx, dIx_abs);
244 cv::convertScaleAbs(dIy, dIy_abs);
245 cv::addWeighted(dIx_abs, 1, dIy_abs, 1, 0, dI);
246 dI.convertTo(dI, CV_8U);
250 const float range[] = { 0.f, 256.f };
251 const float *ranges[] = { range };
252 int channels[] = { 0 };
254 int histSize[] = { bins };
256 bool accumulate =
false;
257 cv::calcHist(&dI, 1, channels, cv::Mat(), hist, dims, histSize, ranges, uniform, accumulate);
259 float t =
static_cast<float>(upperThresholdRatio * w * h);
260 float tLow =
static_cast<float>(lowerThresholdRatio * w * h);
263 bool notFound =
true, notFoundLower =
true;
264 while ((i < bins) && notFound) {
265 float tf = hist.at<
float>(i);
267 if ((accu > tLow) && notFoundLower) {
268 lowerThresh =
static_cast<float>(i);
269 notFoundLower =
false;
272 bon =
static_cast<float>(i);
278 std::stringstream errMsg;
279 errMsg <<
"Could not find a bin for which " << upperThresholdRatio * 100.f <<
" percents of the pixels had a gradient lower than the upper threshold.";
282 float upperThresh = std::max<float>(bon, 1.f);
331 const unsigned int &gaussianFilterSize,
const float &thresholdCanny,
332 const unsigned int &apertureSobel)
334 vpImageFilter::canny(Isrc, Ires, gaussianFilterSize, thresholdCanny / 3.f, thresholdCanny, apertureSobel);
385 const unsigned int &gaussianFilterSize,
386 const float &lowerThreshold,
const float &upperThreshold,
387 const unsigned int &apertureSobel)
389 const float gaussianStdev = 2.f;
390 const float upperThresholdRatio = 0.8f;
391 const float lowerThresholdRatio = 0.6f;
392#if defined(HAVE_OPENCV_IMGPROC)
398 canny(Isrc, Ires, gaussianFilterSize, lowerThreshold, upperThreshold, apertureSobel,
399 gaussianStdev, lowerThresholdRatio, upperThresholdRatio,
false, cannyBackend, cannyFilteringSteps);
471 const unsigned int &gaussianFilterSize,
472 const float &lowerThreshold,
const float &upperThreshold,
const unsigned int &apertureGradient,
473 const float &gaussianStdev,
const float &lowerThresholdRatio,
const float &upperThresholdRatio,
474 const bool &normalizeGradients,
479#if defined(HAVE_OPENCV_IMGPROC)
480 cv::Mat img_cvmat, cv_dx, cv_dy, edges_cvmat;
483 gaussianStdev, apertureGradient, cannyFilteringSteps);
484 float upperCannyThresh = upperThreshold;
485 float lowerCannyThresh = lowerThreshold;
486 if (upperCannyThresh < 0.f) {
487 upperCannyThresh =
computeCannyThreshold(img_cvmat, &cv_dx, &cv_dy, lowerCannyThresh, gaussianFilterSize,
488 gaussianStdev, apertureGradient, lowerThresholdRatio, upperThresholdRatio,
489 cannyFilteringSteps);
491 else if (lowerCannyThresh < 0.f) {
492 lowerCannyThresh = upperCannyThresh / 3.f;
494#if (VISP_HAVE_OPENCV_VERSION >= 0x030200)
495 cv::Canny(cv_dx, cv_dy, edges_cvmat, lowerCannyThresh, upperCannyThresh,
false);
497 cv::GaussianBlur(img_cvmat, img_cvmat, cv::Size(
static_cast<int>(gaussianFilterSize),
static_cast<int>(gaussianFilterSize)),
498 gaussianStdev, gaussianStdev);
499 cv::Canny(img_cvmat, edges_cvmat, lowerCannyThresh, upperCannyThresh);
503 std::string errMsg(
"[vpImageFilter::canny]You asked for CANNY_OPENCV_BACKEND but ViSP has not been compiled with OpenCV");
508 float upperCannyThresh = upperThreshold;
509 float lowerCannyThresh = lowerThreshold;
513 gaussianStdev, apertureGradient, cannyFilteringSteps, cannyBackend, p_mask);
515 if (upperCannyThresh < 0.f) {
516 upperCannyThresh =
computeCannyThreshold(Isrc, lowerCannyThresh, &dIx, &dIy, gaussianFilterSize, gaussianStdev,
517 apertureGradient, lowerThresholdRatio, upperThresholdRatio,
518 cannyFilteringSteps, p_mask);
520 else if (lowerCannyThresh < 0.f) {
521 lowerCannyThresh = upperCannyThresh / 3.f;
523 vpCannyEdgeDetection edgeDetector(gaussianFilterSize, gaussianStdev, apertureGradient, lowerCannyThresh, upperCannyThresh,
524 lowerThresholdRatio, upperThresholdRatio, cannyFilteringSteps);
527 Ires = edgeDetector.
detect(Isrc);
Class that implements the Canny's edge detector. It is possible to use a boolean mask to ignore some ...
vpImage< unsigned char > detect(const vpImage< vpRGBa > &I_color)
Detect the edges in an image. Convert the color image into a gray-scale image.
void setMask(const vpImage< bool > *p_mask)
Set a mask to ignore pixels for which the mask is false.
void setGradients(const vpImage< float > &dIx, const vpImage< float > &dIy)
Set the Gradients of the image that will be processed.
error that can be emitted by ViSP classes.
@ badValue
Used to indicate that a value is not in the allowed range.
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
static std::string vpCannyBackendTypeToString(const vpCannyBackendType &type)
Cast a vpImageFilter::vpCannyBackendTypeToString into a string, to know its name.
static void canny(const vpImage< unsigned char > &I, vpImage< unsigned char > &Ic, const unsigned int &gaussianFilterSize, const float &thresholdCanny, const unsigned int &apertureSobel)
static std::string vpCannyBackendTypeList(const std::string &pref="<", const std::string &sep=" , ", const std::string &suf=">")
Get the list of available vpCannyBackendType.
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.
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.
@ CANNY_GBLUR_SCHARR_FILTERING
Apply Gaussian blur + Scharr operator on the input image.
vpCannyBackendType
Canny filter backends for the edge detection operations.
@ CANNY_VISP_BACKEND
Use ViSP.
@ CANNY_OPENCV_BACKEND
Use OpenCV.
static vpCannyFilteringAndGradientType vpCannyFiltAndGradTypeFromStr(const std::string &name)
Cast a string into a vpImageFilter::vpCannyFilteringAndGradientType.
static vpCannyBackendType vpCannyBackendTypeFromString(const std::string &name)
Cast a string into a vpImageFilter::vpCannyBackendTypeToString.
static std::string vpGetCannyFiltAndGradTypes(const std::string &pref="<", const std::string &sep=" , ", const std::string &suf=">")
Get the list of available vpCannyFilteringAndGradientType.
static void computePartialDerivatives(const cv::Mat &cv_I, cv::Mat &cv_dIx, cv::Mat &cv_dIy, const bool &computeDx=true, const bool &computeDy=true, const bool &normalize=true, const unsigned int &gaussianKernelSize=5, const float &gaussianStdev=2.f, const unsigned int &apertureGradient=3, const vpCannyFilteringAndGradientType &filteringType=CANNY_GBLUR_SOBEL_FILTERING)
Compute the partial derivatives (i.e. horizontal and vertical gradients) of the input image.
Definition of the vpImage class member functions.