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();
133 const unsigned int widthI = I.getWidth(), heightI = I.getHeight();
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];
182#if (VISP_CXX_STANDARD < VISP_CXX_STANDARD_11)
186 const unsigned int heightI = I.getHeight(), widthI = I.getWidth();
187 const unsigned int stop1J = (size - 1) / 2;
188 const unsigned int stop2J = widthI - ((size - 1) / 2);
189 resizeAndInitializeIfNeeded(p_mask, heightI, widthI, dIx);
191 for (
unsigned int i = 0; i < heightI; ++i) {
192 for (
unsigned int j = 0; j < stop1J; ++j) {
195 bool computeVal = checkBooleanMask(p_mask, i, j);
197 dIx[i][j].R =
static_cast<unsigned char>(vpImageFilter::filterXLeftBorderR(I, i, j,
filter, size));
198 dIx[i][j].G =
static_cast<unsigned char>(vpImageFilter::filterXLeftBorderG(I, i, j,
filter, size));
199 dIx[i][j].B =
static_cast<unsigned char>(vpImageFilter::filterXLeftBorderB(I, i, j,
filter, size));
202 for (
unsigned int j = stop1J;
j < stop2J; ++
j) {
205 bool computeVal = checkBooleanMask(p_mask, i, j);
207 dIx[
i][
j].R =
static_cast<unsigned char>(vpImageFilter::filterXR(I, i, j,
filter, size));
208 dIx[
i][
j].G =
static_cast<unsigned char>(vpImageFilter::filterXG(I, i, j,
filter, size));
209 dIx[
i][
j].B =
static_cast<unsigned char>(vpImageFilter::filterXB(I, i, j,
filter, size));
212 for (
unsigned int j = stop2J;
j < widthI; ++
j) {
215 bool computeVal = checkBooleanMask(p_mask, i, j);
217 dIx[
i][
j].R =
static_cast<unsigned char>(vpImageFilter::filterXRightBorderR(I, i, j,
filter, size));
218 dIx[
i][
j].G =
static_cast<unsigned char>(vpImageFilter::filterXRightBorderG(I, i, j,
filter, size));
219 dIx[
i][
j].B =
static_cast<unsigned char>(vpImageFilter::filterXRightBorderB(I, i, j,
filter, size));
246#if (VISP_CXX_STANDARD < VISP_CXX_STANDARD_11)
251 const unsigned int stop1I = (size - 1) / 2;
252 const unsigned int stop2I = heightI - ((size - 1) / 2);
253 resizeAndInitializeIfNeeded(p_mask, heightI, widthI, dIy);
255 for (
unsigned int i = 0;
i < stop1I; ++
i) {
256 for (
unsigned int j = 0;
j < widthI; ++
j) {
259 bool computeVal = checkBooleanMask(p_mask, i, j);
261 dIy[
i][
j].R =
static_cast<unsigned char>(vpImageFilter::filterYTopBorderR(I, i, j,
filter, size));
262 dIy[
i][
j].G =
static_cast<unsigned char>(vpImageFilter::filterYTopBorderG(I, i, j,
filter, size));
263 dIy[
i][
j].B =
static_cast<unsigned char>(vpImageFilter::filterYTopBorderB(I, i, j,
filter, size));
267 for (
unsigned int i = stop1I;
i < stop2I; ++
i) {
268 for (
unsigned int j = 0;
j < widthI; ++
j) {
271 bool computeVal = checkBooleanMask(p_mask, i, j);
273 dIy[
i][
j].R =
static_cast<unsigned char>(vpImageFilter::filterYR(I, i, j,
filter, size));
274 dIy[
i][
j].G =
static_cast<unsigned char>(vpImageFilter::filterYG(I, i, j,
filter, size));
275 dIy[
i][
j].B =
static_cast<unsigned char>(vpImageFilter::filterYB(I, i, j,
filter, size));
279 for (
unsigned int i = stop2I;
i < heightI; ++
i) {
280 for (
unsigned int j = 0;
j < widthI; ++
j) {
283 bool computeVal = checkBooleanMask(p_mask, i, j);
285 dIy[
i][
j].R =
static_cast<unsigned char>(vpImageFilter::filterYBottomBorderR(I, i, j,
filter, size));
286 dIy[
i][
j].G =
static_cast<unsigned char>(vpImageFilter::filterYBottomBorderG(I, i, j,
filter, size));
287 dIy[
i][
j].B =
static_cast<unsigned char>(vpImageFilter::filterYBottomBorderB(I, i, j,
filter, size));
312#if (VISP_CXX_STANDARD < VISP_CXX_STANDARD_11)
329 std::ostringstream oss;
330 oss <<
"Image size (" << I.
getWidth() <<
"x" << I.
getHeight() <<
") is too small for the Gaussian kernel ("
331 <<
"size=" << size <<
"), min size is " << (size-1);
335 double *fg =
new double[(size + 1) / 2];
395 const float *gaussianDerivativeKernel,
unsigned int size,
const vpImage<bool> *p_mask);
399 const double *gaussianDerivativeKernel,
unsigned int size,
const vpImage<bool> *p_mask);
403 const float *gaussianDerivativeKernel,
unsigned int size,
const vpImage<bool> *p_mask);
407 const double *gaussianDerivativeKernel,
unsigned int size,
const vpImage<bool> *p_mask);
411 const float *gaussianDerivativeKernel,
unsigned int size,
const vpImage<bool> *p_mask);
415 const double *gaussianDerivativeKernel,
unsigned int size,
const vpImage<bool> *p_mask);
419 const float *gaussianDerivativeKernel,
unsigned int size,
const vpImage<bool> *p_mask);
423 const double *gaussianDerivativeKernel,
unsigned int size,
const vpImage<bool> *p_mask);
432#if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC)
433#if (VISP_HAVE_OPENCV_VERSION >= 0x030000)
434 cv::Mat imgsrc, imgdest;
436 cv::pyrDown(imgsrc, imgdest, cv::Size(
static_cast<int>(I.getWidth()) / 2,
static_cast<int>(I.getHeight()) / 2));
439 cv::Mat imgsrc, imgdest;
441 cv::pyrDown(imgsrc, imgdest, cvSize(
static_cast<int>(I.getWidth()) / 2,
static_cast<int>(I.getHeight()) / 2));
452 const unsigned int w = I.getWidth() / 2;
453 const unsigned int height = I.getHeight();
454 const unsigned int val_2 = 2;
457 for (
unsigned int i = 0; i < height; ++i) {
459 for (
unsigned int j = 1; j < (w - 1); ++j) {
462 GI[i][w - 1] = I[i][(val_2 * w) - 1];
468 const unsigned int h = I.getHeight() / 2;
469 const unsigned int width = I.getWidth();
470 const unsigned int val_2 = 2;
473 for (
unsigned int j = 0; j < width; ++j) {
475 for (
unsigned int i = 1; i < (h - 1); ++i) {
478 GI[h - 1][j] = I[(val_2 * h) - 1][j];
501#if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC)
509 float m = (channel.rows * channel.cols) / 2.f;
514 float range[] = { 0, 256 };
515 const float *histRange = { range };
517 bool accumulate =
false;
519 cv::calcHist(&channel, 1, 0, cv::Mat(), hist, 1, &histSize, &histRange, uniform, accumulate);
522 while ((i < histSize) && (med < 0.0f)) {
523 bin += cvRound(hist.at<
float>(i));
524 if ((bin > m) && (med < 0.0f)) {
525 med =
static_cast<float>(i);
559 std::vector<cv::Mat> channels;
560 cv::split(cv_I_bgr, channels);
561 std::vector<float> meds(3);
562 const int orderMeds[] = { 2, 1, 0 };
563 const int orderCvChannels[] = { 0, 1, 2 };
564 const unsigned int val_3 = 3;
565 for (
unsigned int i = 0; i < val_3; ++i) {
566 meds[orderMeds[i]] =
median(channels[orderCvChannels[i]]);
589 cv::Mat &cv_dIx, cv::Mat &cv_dIy,
590 const bool &computeDx,
const bool &computeDy,
const bool &normalize,
591 const unsigned int &gaussianKernelSize,
const float &gaussianStdev,
592 const unsigned int &apertureGradient,
599 cv::Size gsz(gaussianKernelSize, gaussianKernelSize);
600 cv::GaussianBlur(cv_I, img_blur, gsz, gaussianStdev);
607 if (apertureGradient > 3) {
608 scale *= std::pow(1. / 2., (
static_cast<double>(apertureGradient) * 2. - 3.));
612 cv::Sobel(img_blur, cv_dIx, CV_16S, 1, 0, apertureGradient, scale, 0., cv::BORDER_REPLICATE);
615 cv::Sobel(img_blur, cv_dIy, CV_16S, 0, 1, apertureGradient, scale, 0., cv::BORDER_REPLICATE);
624 cv::Scharr(img_blur, cv_dIx, CV_16S, 1, 0, scale);
627 cv::Scharr(img_blur, cv_dIy, CV_16S, 0, 1, scale);
640 const bool &computeDx,
const bool &computeDy,
const bool &normalize,
641 const unsigned int &gaussianKernelSize,
const float &gaussianStdev,
642 const unsigned int &apertureGradient,
643 const vpCannyFilteringAndGradientType &filteringType,
644 const vpCannyBackendType &backend,
const vpImage<bool> *p_mask);
649 const bool &computeDx,
const bool &computeDy,
const bool &normalize,
650 const unsigned int &gaussianKernelSize,
const double &gaussianStdev,
651 const unsigned int &apertureGradient,
652 const vpCannyFilteringAndGradientType &filteringType,
653 const vpCannyBackendType &backend,
const vpImage<bool> *p_mask);
658 const bool &computeDx,
const bool &computeDy,
const bool &normalize,
659 const unsigned int &gaussianKernelSize,
const float &gaussianStdev,
660 const unsigned int &apertureGradient,
661 const vpCannyFilteringAndGradientType &filteringType,
662 const vpCannyBackendType &backend,
const vpImage<bool> *p_mask);
667 const bool &computeDx,
const bool &computeDy,
const bool &normalize,
668 const unsigned int &gaussianKernelSize,
const double &gaussianStdev,
669 const unsigned int &apertureGradient,
670 const vpCannyFilteringAndGradientType &filteringType,
671 const vpCannyBackendType &backend,
const vpImage<bool> *p_mask);
676 const bool &computeDx,
const bool &computeDy,
const bool &normalize,
677 const unsigned int &gaussianKernelSize,
const float &gaussianStdev,
678 const unsigned int &apertureGradient,
679 const vpCannyFilteringAndGradientType &filteringType,
680 const vpCannyBackendType &backend,
const vpImage<bool> *p_mask);
685 const bool &computeDx,
const bool &computeDy,
const bool &normalize,
686 const unsigned int &gaussianKernelSize,
const double &gaussianStdev,
687 const unsigned int &apertureGradient,
688 const vpCannyFilteringAndGradientType &filteringType,
689 const vpCannyBackendType &backend,
const vpImage<bool> *p_mask);
694 const unsigned int &gaussianKernelSize,
695 const double &gaussianStdev,
const unsigned int &apertureGradient,
696 const float &lowerThresholdRatio,
const float &upperThresholdRatio,
703 const unsigned int &gaussianKernelSize,
704 const float &gaussianStdev,
const unsigned int &apertureGradient,
705 const float &lowerThresholdRatio,
const float &upperThresholdRatio,
Implementation of a generic 2D array used as base class for matrices and vectors.
unsigned int size() const
Return the number of elements of the 2D array.
Implementation of column vector and the associated operations.
@ 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)
static void filterY(const vpImage< ImageType > &I, vpImage< OutputType > &dIy, const FilterType *filter, unsigned int size, const vpImage< bool > *p_mask=nullptr)
Filter along the vertical direction.
static void getGradX(const vpImage< unsigned char > &I, vpImage< FilterType > &dIx, const vpImage< bool > *p_mask=nullptr)
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 FilterType getSobelKernelX(FilterType *filter, unsigned int size)
static void getGradXGauss2D(const vpImage< ImageType > &I, vpImage< FilterType > &dIx, const FilterType *gaussianKernel, const FilterType *gaussianDerivativeKernel, unsigned int size, const vpImage< bool > *p_mask=nullptr)
static void filterX(const vpImage< ImageType > &I, vpImage< OutputType > &dIx, const FilterType *filter, unsigned int size, const vpImage< bool > *p_mask=nullptr)
Filter along the horizontal direction.
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 getGaussianDerivativeKernel(FilterType *filter, unsigned int size, FilterType sigma=0., bool normalize=true)
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 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 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 FilterType getSobelKernelY(FilterType *filter, unsigned int size)
static void getGradYGauss2D(const vpImage< ImageType > &I, vpImage< FilterType > &dIy, const FilterType *gaussianKernel, const FilterType *gaussianDerivativeKernel, unsigned int size, const vpImage< bool > *p_mask=nullptr)
static void getGradY(const vpImage< unsigned char > &I, vpImage< FilterType > &dIy, 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.
Definition of the vpImage class member functions.
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