34 #include <visp3/core/vpImageFilter.h>
35 #include <visp3/core/vpIoTools.h>
36 #include <visp3/core/vpRGBa.h>
132 const unsigned int size = kernelH.
size(), sizeV = kernelV.
size();
134 const unsigned int half_size = size / 2;
136 If.
resize(heightI, widthI, 0.0);
139 for (
unsigned int i = 0; i < heightI; ++i) {
140 for (
unsigned int j = half_size; j < (widthI - half_size); ++j) {
142 for (
unsigned int a = 0; a < size; ++a) {
143 conv += kernelH[a] *
static_cast<double>(I[i][(j + half_size) - a]);
146 I_filter[i][j] = conv;
150 for (
unsigned int i = half_size; i < (heightI - half_size); ++i) {
151 for (
unsigned int j = 0; j < widthI; ++j) {
153 for (
unsigned int a = 0; a < sizeV; ++a) {
154 conv += kernelV[a] * I_filter[(i + half_size) - a][j];
186 const unsigned int stop1J = (size - 1) / 2;
187 const unsigned int stop2J = widthI - ((size - 1) / 2);
188 resizeAndInitializeIfNeeded(p_mask, heightI, widthI, dIx);
190 for (
unsigned int i = 0; i < heightI; ++i) {
191 for (
unsigned int j = 0; j < stop1J; ++j) {
194 bool computeVal = checkBooleanMask(p_mask, i, j);
196 dIx[i][j].R =
static_cast<unsigned char>(vpImageFilter::filterXLeftBorderR(I, i, j,
filter, size));
197 dIx[i][j].G =
static_cast<unsigned char>(vpImageFilter::filterXLeftBorderG(I, i, j,
filter, size));
198 dIx[i][j].B =
static_cast<unsigned char>(vpImageFilter::filterXLeftBorderB(I, i, j,
filter, size));
201 for (
unsigned int j = stop1J; j < stop2J; ++j) {
204 bool computeVal = checkBooleanMask(p_mask, i, j);
206 dIx[i][j].R =
static_cast<unsigned char>(vpImageFilter::filterXR(I, i, j,
filter, size));
207 dIx[i][j].G =
static_cast<unsigned char>(vpImageFilter::filterXG(I, i, j,
filter, size));
208 dIx[i][j].B =
static_cast<unsigned char>(vpImageFilter::filterXB(I, i, j,
filter, size));
211 for (
unsigned int j = stop2J; j < widthI; ++j) {
214 bool computeVal = checkBooleanMask(p_mask, i, j);
216 dIx[i][j].R =
static_cast<unsigned char>(vpImageFilter::filterXRightBorderR(I, i, j,
filter, size));
217 dIx[i][j].G =
static_cast<unsigned char>(vpImageFilter::filterXRightBorderG(I, i, j,
filter, size));
218 dIx[i][j].B =
static_cast<unsigned char>(vpImageFilter::filterXRightBorderB(I, i, j,
filter, size));
248 const unsigned int stop1I = (size - 1) / 2;
249 const unsigned int stop2I = heightI - ((size - 1) / 2);
250 resizeAndInitializeIfNeeded(p_mask, heightI, widthI, dIy);
252 for (
unsigned int i = 0; i < stop1I; ++i) {
253 for (
unsigned int j = 0; j < widthI; ++j) {
256 bool computeVal = checkBooleanMask(p_mask, i, j);
258 dIy[i][j].R =
static_cast<unsigned char>(vpImageFilter::filterYTopBorderR(I, i, j,
filter, size));
259 dIy[i][j].G =
static_cast<unsigned char>(vpImageFilter::filterYTopBorderG(I, i, j,
filter, size));
260 dIy[i][j].B =
static_cast<unsigned char>(vpImageFilter::filterYTopBorderB(I, i, j,
filter, size));
264 for (
unsigned int i = stop1I; i < stop2I; ++i) {
265 for (
unsigned int j = 0; j < widthI; ++j) {
268 bool computeVal = checkBooleanMask(p_mask, i, j);
270 dIy[i][j].R =
static_cast<unsigned char>(vpImageFilter::filterYR(I, i, j,
filter, size));
271 dIy[i][j].G =
static_cast<unsigned char>(vpImageFilter::filterYG(I, i, j,
filter, size));
272 dIy[i][j].B =
static_cast<unsigned char>(vpImageFilter::filterYB(I, i, j,
filter, size));
276 for (
unsigned int i = stop2I; i < heightI; ++i) {
277 for (
unsigned int j = 0; j < widthI; ++j) {
280 bool computeVal = checkBooleanMask(p_mask, i, j);
282 dIy[i][j].R =
static_cast<unsigned char>(vpImageFilter::filterYBottomBorderR(I, i, j,
filter, size));
283 dIy[i][j].G =
static_cast<unsigned char>(vpImageFilter::filterYBottomBorderG(I, i, j,
filter, size));
284 dIy[i][j].B =
static_cast<unsigned char>(vpImageFilter::filterYBottomBorderB(I, i, j,
filter, size));
323 double *fg =
new double[(size + 1) / 2];
336 void vpImageFilter::getGaussianKernel<float>(
float *filter,
unsigned int size,
float sigma,
bool normalize);
339 void vpImageFilter::getGaussianDerivativeKernel<float>(
float *filter,
unsigned int size,
float sigma,
bool normalize);
342 void vpImageFilter::getGaussianDerivativeKernel<double>(
double *filter,
unsigned int size,
double sigma,
bool normalize);
382 const float *gaussianDerivativeKernel,
unsigned int size,
const vpImage<bool> *p_mask);
386 const double *gaussianDerivativeKernel,
unsigned int size,
const vpImage<bool> *p_mask);
390 const float *gaussianDerivativeKernel,
unsigned int size,
const vpImage<bool> *p_mask);
394 const double *gaussianDerivativeKernel,
unsigned int size,
const vpImage<bool> *p_mask);
398 const float *gaussianDerivativeKernel,
unsigned int size,
const vpImage<bool> *p_mask);
402 const double *gaussianDerivativeKernel,
unsigned int size,
const vpImage<bool> *p_mask);
406 const float *gaussianDerivativeKernel,
unsigned int size,
const vpImage<bool> *p_mask);
410 const double *gaussianDerivativeKernel,
unsigned int size,
const vpImage<bool> *p_mask);
419 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC)
420 #if (VISP_HAVE_OPENCV_VERSION >= 0x030000)
421 cv::Mat imgsrc, imgdest;
423 cv::pyrDown(imgsrc, imgdest, cv::Size((
int)I.
getWidth() / 2, (
int)I.
getHeight() / 2));
426 cv::Mat imgsrc, imgdest;
428 cv::pyrDown(imgsrc, imgdest, cvSize((
int)I.
getWidth() / 2, (
int)I.
getHeight() / 2));
439 const unsigned int w = I.
getWidth() / 2;
440 const unsigned int height = I.
getHeight();
441 const unsigned int val_2 = 2;
444 for (
unsigned int i = 0; i < height; ++i) {
446 for (
unsigned int j = 1; j < (w - 1); ++j) {
449 GI[i][w - 1] = I[i][(val_2 * w) - 1];
455 const unsigned int h = I.
getHeight() / 2;
456 const unsigned int width = I.
getWidth();
457 const unsigned int val_2 = 2;
460 for (
unsigned int j = 0; j < width; ++j) {
462 for (
unsigned int i = 1; i < (h - 1); ++i) {
465 GI[h - 1][j] = I[(val_2 * h) - 1][j];
473 double vpImageFilter::getSobelKernelX<double>(
double *filter,
unsigned int size);
476 float vpImageFilter::getSobelKernelX<float>(
float *filter,
unsigned int size);
479 double vpImageFilter::getSobelKernelY<double>(
double *filter,
unsigned int size);
482 float vpImageFilter::getSobelKernelY<float>(
float *filter,
unsigned int size);
488 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC)
496 float m = (channel.rows * channel.cols) / 2.f;
501 float range[] = { 0, 256 };
502 const float *histRange = { range };
504 bool accumulate =
false;
506 cv::calcHist(&channel, 1, 0, cv::Mat(), hist, 1, &histSize, &histRange, uniform, accumulate);
509 while ((i < histSize) && (med < 0.0f)) {
510 bin += cvRound(hist.at<
float>(i));
511 if ((bin > m) && (med < 0.0f)) {
512 med =
static_cast<float>(i);
546 std::vector<cv::Mat> channels;
547 cv::split(cv_I_bgr, channels);
548 std::vector<float> meds(3);
549 const int orderMeds[] = { 2, 1, 0 };
550 const int orderCvChannels[] = { 0, 1, 2 };
551 const unsigned int val_3 = 3;
552 for (
unsigned int i = 0; i < val_3; ++i) {
553 meds[orderMeds[i]] =
median(channels[orderCvChannels[i]]);
576 cv::Mat &cv_dIx, cv::Mat &cv_dIy,
577 const bool &computeDx,
const bool &computeDy,
const bool &normalize,
578 const unsigned int &gaussianKernelSize,
const float &gaussianStdev,
579 const unsigned int &apertureGradient,
586 cv::Size gsz(gaussianKernelSize, gaussianKernelSize);
587 cv::GaussianBlur(cv_I, img_blur, gsz, gaussianStdev);
594 if (apertureGradient > 3) {
595 scale *= std::pow(1. / 2., (
static_cast<double>(apertureGradient) * 2. - 3.));
599 cv::Sobel(img_blur, cv_dIx, CV_16S, 1, 0, apertureGradient, scale, 0., cv::BORDER_REPLICATE);
602 cv::Sobel(img_blur, cv_dIy, CV_16S, 0, 1, apertureGradient, scale, 0., cv::BORDER_REPLICATE);
611 cv::Scharr(img_blur, cv_dIx, CV_16S, 1, 0, scale);
614 cv::Scharr(img_blur, cv_dIy, CV_16S, 0, 1, scale);
627 const bool &computeDx,
const bool &computeDy,
const bool &normalize,
628 const unsigned int &gaussianKernelSize,
const float &gaussianStdev,
629 const unsigned int &apertureGradient,
630 const vpCannyFilteringAndGradientType &filteringType,
631 const vpCannyBackendType &backend,
const vpImage<bool> *p_mask);
636 const bool &computeDx,
const bool &computeDy,
const bool &normalize,
637 const unsigned int &gaussianKernelSize,
const double &gaussianStdev,
638 const unsigned int &apertureGradient,
639 const vpCannyFilteringAndGradientType &filteringType,
640 const vpCannyBackendType &backend,
const vpImage<bool> *p_mask);
643 void vpImageFilter::computePartialDerivatives<float, float>(
const vpImage<float> &I,
645 const bool &computeDx,
const bool &computeDy,
const bool &normalize,
646 const unsigned int &gaussianKernelSize,
const float &gaussianStdev,
647 const unsigned int &apertureGradient,
648 const vpCannyFilteringAndGradientType &filteringType,
649 const vpCannyBackendType &backend,
const vpImage<bool> *p_mask);
652 void vpImageFilter::computePartialDerivatives<float, double>(
const vpImage<float> &I,
654 const bool &computeDx,
const bool &computeDy,
const bool &normalize,
655 const unsigned int &gaussianKernelSize,
const double &gaussianStdev,
656 const unsigned int &apertureGradient,
657 const vpCannyFilteringAndGradientType &filteringType,
658 const vpCannyBackendType &backend,
const vpImage<bool> *p_mask);
661 void vpImageFilter::computePartialDerivatives<double, float>(
const vpImage<double> &I,
663 const bool &computeDx,
const bool &computeDy,
const bool &normalize,
664 const unsigned int &gaussianKernelSize,
const float &gaussianStdev,
665 const unsigned int &apertureGradient,
666 const vpCannyFilteringAndGradientType &filteringType,
667 const vpCannyBackendType &backend,
const vpImage<bool> *p_mask);
670 void vpImageFilter::computePartialDerivatives<double, double>(
const vpImage<double> &I,
672 const bool &computeDx,
const bool &computeDy,
const bool &normalize,
673 const unsigned int &gaussianKernelSize,
const double &gaussianStdev,
674 const unsigned int &apertureGradient,
675 const vpCannyFilteringAndGradientType &filteringType,
676 const vpCannyBackendType &backend,
const vpImage<bool> *p_mask);
681 const unsigned int &gaussianKernelSize,
682 const double &gaussianStdev,
const unsigned int &apertureGradient,
683 const float &lowerThresholdRatio,
const float &upperThresholdRatio,
690 const unsigned int &gaussianKernelSize,
691 const float &gaussianStdev,
const unsigned int &apertureGradient,
692 const float &lowerThresholdRatio,
const float &upperThresholdRatio,
unsigned int size() const
Return the number of elements of the 2D array.
Implementation of column vector and the associated operations.
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
static unsigned char filterGaussXPyramidal(const vpImage< unsigned char > &I, unsigned int i, unsigned int j)
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.
static void gaussianBlur(const vpImage< ImageType > &I, vpImage< FilterType > &GI, unsigned int size=7, FilterType sigma=0., bool normalize=true, const vpImage< bool > *p_mask=nullptr)
static void filter(const vpImage< ImageType > &I, vpImage< FilterType > &If, const vpArray2D< FilterType > &M, bool convolve=false, const vpImage< bool > *p_mask=nullptr)
static void sepFilter(const vpImage< unsigned char > &I, vpImage< double > &If, const vpColVector &kernelH, const vpColVector &kernelV)
static void getGaussXPyramidal(const vpImage< unsigned char > &I, vpImage< unsigned char > &GI)
static void getGaussianKernel(FilterType *filter, unsigned int size, FilterType sigma=0., bool normalize=true)
static void getGaussYPyramidal(const vpImage< unsigned char > &I, vpImage< unsigned char > &GI)
static float median(const cv::Mat &cv_I)
Calculates the median value of a single channel. The algorithm is based on based on https://github....
static void filterY(const vpImage< vpRGBa > &I, vpImage< vpRGBa > &dIx, const double *filter, unsigned int size, const vpImage< bool > *p_mask=nullptr)
static void filterX(const vpImage< ImageType > &I, vpImage< FilterType > &dIx, const FilterType *filter, unsigned int size, const vpImage< bool > *p_mask=nullptr)
static unsigned char filterGaussYPyramidal(const vpImage< unsigned char > &I, unsigned int i, unsigned int j)
static void getGaussPyramidal(const vpImage< unsigned char > &I, vpImage< unsigned char > &GI)
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.
void destroy()
Destructor : Memory de-allocation.
unsigned int getWidth() const
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
unsigned int getHeight() const