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));
324 std::ostringstream oss;
325 oss <<
"Image size (" << I.
getWidth() <<
"x" << I.
getHeight() <<
") is too small for the Gaussian kernel ("
326 <<
"size=" << size <<
"), min size is " << (size-1);
330 double *fg =
new double[(size + 1) / 2];
343 void vpImageFilter::getGaussianKernel<float>(
float *filter,
unsigned int size,
float sigma,
bool normalize);
346 void vpImageFilter::getGaussianDerivativeKernel<float>(
float *filter,
unsigned int size,
float sigma,
bool normalize);
349 void vpImageFilter::getGaussianDerivativeKernel<double>(
double *filter,
unsigned int size,
double sigma,
bool normalize);
389 const float *gaussianDerivativeKernel,
unsigned int size,
const vpImage<bool> *p_mask);
393 const double *gaussianDerivativeKernel,
unsigned int size,
const vpImage<bool> *p_mask);
397 const float *gaussianDerivativeKernel,
unsigned int size,
const vpImage<bool> *p_mask);
401 const double *gaussianDerivativeKernel,
unsigned int size,
const vpImage<bool> *p_mask);
405 const float *gaussianDerivativeKernel,
unsigned int size,
const vpImage<bool> *p_mask);
409 const double *gaussianDerivativeKernel,
unsigned int size,
const vpImage<bool> *p_mask);
413 const float *gaussianDerivativeKernel,
unsigned int size,
const vpImage<bool> *p_mask);
417 const double *gaussianDerivativeKernel,
unsigned int size,
const vpImage<bool> *p_mask);
426 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC)
427 #if (VISP_HAVE_OPENCV_VERSION >= 0x030000)
428 cv::Mat imgsrc, imgdest;
430 cv::pyrDown(imgsrc, imgdest, cv::Size((
int)I.
getWidth() / 2, (
int)I.
getHeight() / 2));
433 cv::Mat imgsrc, imgdest;
435 cv::pyrDown(imgsrc, imgdest, cvSize((
int)I.
getWidth() / 2, (
int)I.
getHeight() / 2));
446 const unsigned int w = I.
getWidth() / 2;
447 const unsigned int height = I.
getHeight();
448 const unsigned int val_2 = 2;
451 for (
unsigned int i = 0; i < height; ++i) {
453 for (
unsigned int j = 1; j < (w - 1); ++j) {
456 GI[i][w - 1] = I[i][(val_2 * w) - 1];
462 const unsigned int h = I.
getHeight() / 2;
463 const unsigned int width = I.
getWidth();
464 const unsigned int val_2 = 2;
467 for (
unsigned int j = 0; j < width; ++j) {
469 for (
unsigned int i = 1; i < (h - 1); ++i) {
472 GI[h - 1][j] = I[(val_2 * h) - 1][j];
480 double vpImageFilter::getSobelKernelX<double>(
double *filter,
unsigned int size);
483 float vpImageFilter::getSobelKernelX<float>(
float *filter,
unsigned int size);
486 double vpImageFilter::getSobelKernelY<double>(
double *filter,
unsigned int size);
489 float vpImageFilter::getSobelKernelY<float>(
float *filter,
unsigned int size);
495 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC)
503 float m = (channel.rows * channel.cols) / 2.f;
508 float range[] = { 0, 256 };
509 const float *histRange = { range };
511 bool accumulate =
false;
513 cv::calcHist(&channel, 1, 0, cv::Mat(), hist, 1, &histSize, &histRange, uniform, accumulate);
516 while ((i < histSize) && (med < 0.0f)) {
517 bin += cvRound(hist.at<
float>(i));
518 if ((bin > m) && (med < 0.0f)) {
519 med =
static_cast<float>(i);
553 std::vector<cv::Mat> channels;
554 cv::split(cv_I_bgr, channels);
555 std::vector<float> meds(3);
556 const int orderMeds[] = { 2, 1, 0 };
557 const int orderCvChannels[] = { 0, 1, 2 };
558 const unsigned int val_3 = 3;
559 for (
unsigned int i = 0; i < val_3; ++i) {
560 meds[orderMeds[i]] =
median(channels[orderCvChannels[i]]);
583 cv::Mat &cv_dIx, cv::Mat &cv_dIy,
584 const bool &computeDx,
const bool &computeDy,
const bool &normalize,
585 const unsigned int &gaussianKernelSize,
const float &gaussianStdev,
586 const unsigned int &apertureGradient,
593 cv::Size gsz(gaussianKernelSize, gaussianKernelSize);
594 cv::GaussianBlur(cv_I, img_blur, gsz, gaussianStdev);
601 if (apertureGradient > 3) {
602 scale *= std::pow(1. / 2., (
static_cast<double>(apertureGradient) * 2. - 3.));
606 cv::Sobel(img_blur, cv_dIx, CV_16S, 1, 0, apertureGradient, scale, 0., cv::BORDER_REPLICATE);
609 cv::Sobel(img_blur, cv_dIy, CV_16S, 0, 1, apertureGradient, scale, 0., cv::BORDER_REPLICATE);
618 cv::Scharr(img_blur, cv_dIx, CV_16S, 1, 0, scale);
621 cv::Scharr(img_blur, cv_dIy, CV_16S, 0, 1, scale);
634 const bool &computeDx,
const bool &computeDy,
const bool &normalize,
635 const unsigned int &gaussianKernelSize,
const float &gaussianStdev,
636 const unsigned int &apertureGradient,
637 const vpCannyFilteringAndGradientType &filteringType,
638 const vpCannyBackendType &backend,
const vpImage<bool> *p_mask);
643 const bool &computeDx,
const bool &computeDy,
const bool &normalize,
644 const unsigned int &gaussianKernelSize,
const double &gaussianStdev,
645 const unsigned int &apertureGradient,
646 const vpCannyFilteringAndGradientType &filteringType,
647 const vpCannyBackendType &backend,
const vpImage<bool> *p_mask);
650 void vpImageFilter::computePartialDerivatives<float, float>(
const vpImage<float> &I,
652 const bool &computeDx,
const bool &computeDy,
const bool &normalize,
653 const unsigned int &gaussianKernelSize,
const float &gaussianStdev,
654 const unsigned int &apertureGradient,
655 const vpCannyFilteringAndGradientType &filteringType,
656 const vpCannyBackendType &backend,
const vpImage<bool> *p_mask);
659 void vpImageFilter::computePartialDerivatives<float, double>(
const vpImage<float> &I,
661 const bool &computeDx,
const bool &computeDy,
const bool &normalize,
662 const unsigned int &gaussianKernelSize,
const double &gaussianStdev,
663 const unsigned int &apertureGradient,
664 const vpCannyFilteringAndGradientType &filteringType,
665 const vpCannyBackendType &backend,
const vpImage<bool> *p_mask);
668 void vpImageFilter::computePartialDerivatives<double, float>(
const vpImage<double> &I,
670 const bool &computeDx,
const bool &computeDy,
const bool &normalize,
671 const unsigned int &gaussianKernelSize,
const float &gaussianStdev,
672 const unsigned int &apertureGradient,
673 const vpCannyFilteringAndGradientType &filteringType,
674 const vpCannyBackendType &backend,
const vpImage<bool> *p_mask);
677 void vpImageFilter::computePartialDerivatives<double, double>(
const vpImage<double> &I,
679 const bool &computeDx,
const bool &computeDy,
const bool &normalize,
680 const unsigned int &gaussianKernelSize,
const double &gaussianStdev,
681 const unsigned int &apertureGradient,
682 const vpCannyFilteringAndGradientType &filteringType,
683 const vpCannyBackendType &backend,
const vpImage<bool> *p_mask);
688 const unsigned int &gaussianKernelSize,
689 const double &gaussianStdev,
const unsigned int &apertureGradient,
690 const float &lowerThresholdRatio,
const float &upperThresholdRatio,
697 const unsigned int &gaussianKernelSize,
698 const float &gaussianStdev,
const unsigned int &apertureGradient,
699 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.
error that can be emitted by ViSP classes.
@ dimensionError
Bad dimension.
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