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";
82 return "unknown-backend";
100 while ((i < count) && notFound) {
120 const std::string &suf)
122 std::string list(pref);
145 name =
"gaussianblur+sobel-filtering";
148 name =
"gaussianblur+scharr-filtering";
152 return "unknown-filtering";
168 bool notFound =
true;
170 while ((i < count) && notFound) {
181 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC)
201 float &lowerThresh,
const unsigned int &gaussianKernelSize,
202 const float &gaussianStdev,
const unsigned int &apertureGradient,
203 const float &lowerThresholdRatio,
const float &upperThresholdRatio,
206 if ((lowerThresholdRatio <= 0.f) || (lowerThresholdRatio >= 1.f)) {
207 std::stringstream errMsg;
208 errMsg <<
"Lower ratio (" << lowerThresholdRatio <<
") " << (lowerThresholdRatio < 0.f ?
"should be greater than 0 !" :
"should be lower than 1 !");
212 if ((upperThresholdRatio <= 0.f) || (upperThresholdRatio >= 1.f)) {
213 std::stringstream errMsg;
214 errMsg <<
"Upper ratio (" << upperThresholdRatio <<
") " << (upperThresholdRatio < 0.f ?
"should be greater than 0 !" :
"should be lower than 1 !");
218 if (lowerThresholdRatio >= upperThresholdRatio) {
219 std::stringstream errMsg;
220 errMsg <<
"Lower ratio (" << lowerThresholdRatio <<
") should be lower than the upper ratio (" << upperThresholdRatio <<
")";
224 double w = cv_I.cols;
225 double h = cv_I.rows;
227 cv::Mat dI, dIx, dIy, dIx_abs, dIy_abs;
229 if ((p_cv_dIx ==
nullptr) || (p_cv_dIy ==
nullptr)) {
239 cv::convertScaleAbs(dIx, dIx_abs);
240 cv::convertScaleAbs(dIy, dIy_abs);
241 cv::addWeighted(dIx_abs, 1, dIy_abs, 1, 0, dI);
242 dI.convertTo(dI, CV_8U);
246 const float range[] = { 0.f, 256.f };
247 const float *ranges[] = { range };
248 int channels[] = { 0 };
250 int histSize[] = { bins };
252 bool accumulate =
false;
253 cv::calcHist(&dI, 1, channels, cv::Mat(), hist, dims, histSize, ranges, uniform, accumulate);
255 float t =
static_cast<float>(upperThresholdRatio * w * h);
258 bool notFound =
true;
259 while ((i < bins) && notFound) {
260 float tf = hist.at<
float>(i);
263 bon =
static_cast<float>(i);
269 std::stringstream errMsg;
270 errMsg <<
"Could not find a bin for which " << upperThresholdRatio * 100.f <<
" percents of the pixels had a gradient lower than the upper threshold.";
273 float upperThresh = std::max<float>(bon, 1.f);
274 lowerThresh = lowerThresholdRatio * bon;
323 const unsigned int &gaussianFilterSize,
const float &thresholdCanny,
324 const unsigned int &apertureSobel)
326 vpImageFilter::canny(Isrc, Ires, gaussianFilterSize, thresholdCanny / 3.f, thresholdCanny, apertureSobel);
377 const unsigned int &gaussianFilterSize,
378 const float &lowerThreshold,
const float &upperThreshold,
379 const unsigned int &apertureSobel)
381 const float gaussianStdev = 2.f;
382 const float upperThresholdRatio = 0.8f;
383 const float lowerThresholdRatio = 0.6f;
384 #if defined(HAVE_OPENCV_IMGPROC)
390 canny(Isrc, Ires, gaussianFilterSize, lowerThreshold, upperThreshold, apertureSobel,
391 gaussianStdev, lowerThresholdRatio, upperThresholdRatio,
false, cannyBackend, cannyFilteringSteps);
463 const unsigned int &gaussianFilterSize,
464 const float &lowerThreshold,
const float &upperThreshold,
const unsigned int &apertureGradient,
465 const float &gaussianStdev,
const float &lowerThresholdRatio,
const float &upperThresholdRatio,
466 const bool &normalizeGradients,
471 #if defined(HAVE_OPENCV_IMGPROC)
472 cv::Mat img_cvmat, cv_dx, cv_dy, edges_cvmat;
475 gaussianStdev, apertureGradient, cannyFilteringSteps);
476 float upperCannyThresh = upperThreshold;
477 float lowerCannyThresh = lowerThreshold;
478 if (upperCannyThresh < 0.f) {
479 upperCannyThresh =
computeCannyThreshold(img_cvmat, &cv_dx, &cv_dy, lowerCannyThresh, gaussianFilterSize,
480 gaussianStdev, apertureGradient, lowerThresholdRatio, upperThresholdRatio,
481 cannyFilteringSteps);
483 else if (lowerCannyThresh < 0.f) {
484 lowerCannyThresh = upperCannyThresh / 3.f;
486 #if (VISP_HAVE_OPENCV_VERSION >= 0x030200)
487 cv::Canny(cv_dx, cv_dy, edges_cvmat, lowerCannyThresh, upperCannyThresh,
false);
489 cv::GaussianBlur(img_cvmat, img_cvmat, cv::Size((
int)gaussianFilterSize, (
int)gaussianFilterSize),
490 gaussianStdev, gaussianStdev);
491 cv::Canny(img_cvmat, edges_cvmat, lowerCannyThresh, upperCannyThresh);
495 std::string errMsg(
"[vpImageFilter::canny]You asked for CANNY_OPENCV_BACKEND but ViSP has not been compiled with OpenCV");
500 float upperCannyThresh = upperThreshold;
501 float lowerCannyThresh = lowerThreshold;
505 gaussianStdev, apertureGradient, cannyFilteringSteps, cannyBackend, p_mask);
507 if (upperCannyThresh < 0.f) {
508 upperCannyThresh =
computeCannyThreshold(Isrc, lowerCannyThresh, &dIx, &dIy, gaussianFilterSize, gaussianStdev,
509 apertureGradient, lowerThresholdRatio, upperThresholdRatio,
510 cannyFilteringSteps, p_mask);
512 else if (lowerCannyThresh < 0.f) {
513 lowerCannyThresh = upperCannyThresh / 3.f;
515 vpCannyEdgeDetection edgeDetector(gaussianFilterSize, gaussianStdev, apertureGradient, lowerCannyThresh, upperCannyThresh,
516 lowerThresholdRatio, upperThresholdRatio, cannyFilteringSteps);
519 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 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 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.6, const float &upperThresholdRatio=0.8, const vpCannyFilteringAndGradientType &filteringType=CANNY_GBLUR_SOBEL_FILTERING)
Compute the upper Canny edge filter threshold, using Gaussian blur + Sobel or + Scharr operators to c...
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.