34 #ifndef _vpImageFilter_h_
35 #define _vpImageFilter_h_
47 #include <visp3/core/vpException.h>
48 #include <visp3/core/vpHistogram.h>
49 #include <visp3/core/vpImage.h>
50 #include <visp3/core/vpImageConvert.h>
51 #include <visp3/core/vpImageException.h>
52 #include <visp3/core/vpMath.h>
53 #include <visp3/core/vpMatrix.h>
54 #include <visp3/core/vpRGBa.h>
56 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC)
57 #include <opencv2/imgproc/imgproc.hpp>
58 #include <opencv2/imgproc/imgproc_c.h>
74 CANNY_OPENCV_BACKEND = 0,
75 CANNY_VISP_BACKEND = 1,
76 CANNY_COUNT_BACKEND = 2
79 static std::string vpCannyBackendTypeList(
const std::string &pref =
"<",
const std::string &sep =
" , ",
80 const std::string &suf =
">");
82 static std::string vpCannyBackendTypeToString(
const vpCannyBackendType &type);
84 static vpCannyBackendType vpCannyBackendTypeFromString(
const std::string &name);
89 CANNY_GBLUR_SOBEL_FILTERING = 0,
90 CANNY_GBLUR_SCHARR_FILTERING = 1,
91 CANNY_COUNT_FILTERING = 2
92 } vpCannyFilteringAndGradientType;
94 static std::string vpCannyFilteringAndGradientTypeList(
const std::string &pref =
"<",
const std::string &sep =
" , ",
95 const std::string &suf =
">");
97 static std::string vpCannyFilteringAndGradientTypeToString(
const vpCannyFilteringAndGradientType &type);
99 static vpCannyFilteringAndGradientType vpCannyFilteringAndGradientTypeFromString(
const std::string &name);
102 const float &thresholdCanny,
const unsigned int &apertureSobel);
105 const float &lowerThresholdCanny,
const float &higherThresholdCanny,
106 const unsigned int &apertureSobel);
109 const float &lowerThresholdCanny,
const float &higherThresholdCanny,
110 const unsigned int &apertureSobel,
const float &gaussianStdev,
const float &lowerThresholdRatio,
111 const float &upperThresholdRatio,
const bool &normalizeGradients,
112 const vpCannyBackendType &cannyBackend,
const vpCannyFilteringAndGradientType &cannyFilteringSteps);
114 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC)
115 static float computeCannyThreshold(
const cv::Mat &cv_I,
const cv::Mat *p_cv_dIx,
const cv::Mat *p_cv_dIy,
116 float &lowerThresh,
const unsigned int &gaussianKernelSize = 5,
117 const float &gaussianStdev = 2.f,
const unsigned int &apertureGradient = 3,
118 const float &lowerThresholdRatio = 0.6,
const float &upperThresholdRatio = 0.8,
119 const vpCannyFilteringAndGradientType &filteringType = CANNY_GBLUR_SOBEL_FILTERING);
121 static void computePartialDerivatives(
const cv::Mat &cv_I,
122 cv::Mat &cv_dIx, cv::Mat &cv_dIy,
123 const bool &computeDx =
true,
const bool &computeDy =
true,
const bool &normalize =
true,
124 const unsigned int &gaussianKernelSize = 5,
const float &gaussianStdev = 2.f,
125 const unsigned int &apertureGradient = 3,
126 const vpCannyFilteringAndGradientType &filteringType = CANNY_GBLUR_SOBEL_FILTERING);
148 template <
typename ImageType,
typename FilterType>
151 const bool &computeDx =
true,
const bool &computeDy =
true,
const bool &normalize =
true,
152 const unsigned int &gaussianKernelSize = 5,
const FilterType &gaussianStdev = 2.f,
153 const unsigned int &apertureGradient = 3,
157 if (backend == CANNY_OPENCV_BACKEND) {
158 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC)
159 cv::Mat cv_I, cv_dIx, cv_dIy;
161 computePartialDerivatives(cv_I, cv_dIx, cv_dIy, computeDx, computeDy, normalize, gaussianKernelSize,
162 gaussianStdev, apertureGradient, filteringType);
174 if (filteringType == CANNY_GBLUR_SCHARR_FILTERING || filteringType == CANNY_GBLUR_SOBEL_FILTERING) {
187 for (
unsigned int r = 0; r < filter.
getRows(); r++) {
188 for (
unsigned int c = 0; c < filter.
getCols(); c++) {
189 filter[r][c] = filter[r][c] * scale;
198 if (filteringType == CANNY_GBLUR_SOBEL_FILTERING) {
206 else if (filteringType == CANNY_GBLUR_SCHARR_FILTERING) {
218 scaleFilter(gradientFilterX, scaleX);
221 scaleFilter(gradientFilterY, scaleY);
235 std::string errMsg =
"[vpImageFilter::computePartialDerivatives] Filtering + gradient method \"";
236 errMsg += vpCannyFilteringAndGradientTypeToString(filteringType);
237 errMsg +=
"\" is not implemented yet\n";
243 template <
typename FilterType>
246 const bool &computeDx =
true,
const bool &computeDy =
true,
const bool &normalize =
true,
247 const unsigned int &gaussianKernelSize = 5,
const FilterType &gaussianStdev = 2.f,
248 const unsigned int &apertureGradient = 3,
252 template <
typename ImageType>
255 const bool &computeDx =
true,
const bool &computeDy =
true,
const bool &normalize =
true,
256 const unsigned int &gaussianKernelSize = 5,
const unsigned char &gaussianStdev = 2.f,
257 const unsigned int &apertureGradient = 3,
261 template <
typename ImageType>
264 const bool &computeDx =
true,
const bool &computeDy =
true,
const bool &normalize =
true,
265 const unsigned int gaussianKernelSize = 5,
const vpRGBa gaussianStdev =
vpRGBa(),
266 const unsigned int apertureGradient = 3,
289 template<
typename OutType>
292 const unsigned int &gaussianKernelSize = 5,
293 const OutType &gaussianStdev = 2.f,
const unsigned int &apertureGradient = 3,
294 const float &lowerThresholdRatio = 0.6,
const float &upperThresholdRatio = 0.8,
302 if (p_dIx !=
nullptr && p_dIy !=
nullptr) {
307 computePartialDerivatives(I, dIx, dIy,
true,
true,
true, gaussianKernelSize, gaussianStdev,
308 apertureGradient, filteringType);
312 for (
unsigned int r = 0; r < h; r++) {
313 for (
unsigned int c = 0; c < w; c++) {
314 float dx = (float)dIx[r][c];
315 float dy = (float)dIy[r][c];
316 float gradient = std::abs(dx) + std::abs(dy);
317 float gradientClamped = std::min(gradient, (
float)std::numeric_limits<unsigned char>::max());
318 dI[r][c] = gradientClamped;
324 const unsigned int nbBins = 256;
327 float t = (float)(upperThresholdRatio * w * h);
329 for (
unsigned int i = 0; i < nbBins; i++) {
337 float upperThresh = std::max(bon, 1.f);
338 lowerThresh = lowerThresholdRatio * bon;
351 return (2047.0 * (I[r][c + 1] - I[r][c - 1]) + 913.0 * (I[r][c + 2] - I[r][c - 2]) +
352 112.0 * (I[r][c + 3] - I[r][c - 3])) / 8418.0;
364 return (2047.0 * (I[r + 1][c] - I[r - 1][c]) + 913.0 * (I[r + 2][c] - I[r - 2][c]) +
365 112.0 * (I[r + 3][c] - I[r - 3][c])) / 8418.0;
381 template <
class ImageType,
typename FilterType>
389 for (i = 1; i <= (size - 1) / 2; i++) {
390 result += filter[i] * (I[r][c + i] - I[r][c - i]);
408 template <
class ImageType,
typename FilterType>
416 for (i = 1; i <= (size - 1) / 2; i++) {
417 result += filter[i] * (I[r + i][c] - I[r - i][c]);
450 template <
typename ImageType,
typename FilterType>
454 unsigned int half_size_y = size_y / 2, half_size_x = size_x / 2;
459 for (
unsigned int i = half_size_y; i < I.
getHeight() - half_size_y; i++) {
460 for (
unsigned int j = half_size_x; j < I.
getWidth() - half_size_x; j++) {
463 for (
unsigned int a = 0; a < size_y; a++) {
464 for (
unsigned int b = 0; b < size_x; b++) {
465 FilterType val = I[i + half_size_y - a][j + half_size_x - b];
466 conv += M[a][b] * val;
474 for (
unsigned int i = half_size_y; i < I.
getHeight() - half_size_y; i++) {
475 for (
unsigned int j = half_size_x; j < I.
getWidth() - half_size_x; j++) {
478 for (
unsigned int a = 0; a < size_y; a++) {
479 for (
unsigned int b = 0; b < size_x; b++) {
480 FilterType val = I[i - half_size_y + a][j - half_size_x + b];
481 corr += M[a][b] * val;
490 template <
typename FilterType>
505 template <
typename ImageType,
typename FilterType>
507 bool convolve =
false)
509 unsigned int size = M.
getRows();
510 unsigned int half_size = size / 2;
516 for (
unsigned int v = half_size; v < I.
getHeight() - half_size; v++) {
517 for (
unsigned int u = half_size; u < I.
getWidth() - half_size; u++) {
518 FilterType conv_u = 0;
519 FilterType conv_v = 0;
521 for (
unsigned int a = 0; a < size; a++) {
522 for (
unsigned int b = 0; b < size; b++) {
523 FilterType val = I[v + half_size - a][u + half_size - b];
524 conv_u += M[a][b] * val;
525 conv_v += M[b][a] * val;
534 for (
unsigned int v = half_size; v < I.
getHeight() - half_size; v++) {
535 for (
unsigned int u = half_size; u < I.
getWidth() - half_size; u++) {
536 FilterType conv_u = 0;
537 FilterType conv_v = 0;
539 for (
unsigned int a = 0; a < size; a++) {
540 for (
unsigned int b = 0; b < size; b++) {
541 FilterType val = I[v - half_size + a][u - half_size + b];
542 conv_u += M[a][b] * val;
543 conv_v += M[b][a] * val;
553 template<
typename FilterType>
556 template<
typename ImageType>
569 template <
typename ImageType,
typename FilterType>
573 filterX<ImageType, FilterType>(I, GIx, filter, size);
574 filterY<FilterType, FilterType>(GIx, GI, filter, size);
580 return (
unsigned char)((1. * I[i][j - 2] + 4. * I[i][j - 1] + 6. * I[i][j] + 4. * I[i][j + 1] + 1. * I[i][j + 2]) / 16.);
584 return (
unsigned char)((1. * I[i - 2][j] + 4. * I[i - 1][j] + 6. * I[i][j] + 4. * I[i + 1][j] + 1. * I[i + 2][j]) / 16.);
587 template <
typename ImageType,
typename FilterType>
591 for (
unsigned int i = 0; i < I.
getHeight(); i++) {
592 for (
unsigned int j = 0; j < (size - 1) / 2; j++) {
593 dIx[i][j] = vpImageFilter::filterXLeftBorder<ImageType, FilterType>(I, i, j, filter, size);
595 for (
unsigned int j = (size - 1) / 2; j < I.
getWidth() - (size - 1) / 2; j++) {
596 dIx[i][j] = vpImageFilter::filterX<ImageType, FilterType>(I, i, j, filter, size);
598 for (
unsigned int j = I.
getWidth() - (size - 1) / 2; j < I.
getWidth(); j++) {
599 dIx[i][j] = vpImageFilter::filterXRightBorder<ImageType, FilterType>(I, i, j, filter, size);
609 template<
typename ImageType,
typename FilterType>
610 static inline FilterType
filterX(
const vpImage<ImageType> &I,
unsigned int r,
unsigned int c,
const FilterType *filter,
unsigned int size)
616 for (
unsigned int i = 1; i <= (size - 1) / 2; i++) {
617 result += filter[i] * (I[r][c + i] + I[r][c - i]);
619 return result + filter[0] * I[r][c];
622 static inline double filterXR(
const vpImage<vpRGBa> &I,
unsigned int r,
unsigned int c,
const double *filter,
unsigned int size)
628 for (
unsigned int i = 1; i <= (size - 1) / 2; i++) {
629 result += filter[i] * (I[r][c + i].R + I[r][c - i].R);
631 return result + filter[0] * I[r][c].R;
634 static inline double filterXG(
const vpImage<vpRGBa> &I,
unsigned int r,
unsigned int c,
const double *filter,
unsigned int size)
640 for (
unsigned int i = 1; i <= (size - 1) / 2; i++) {
641 result += filter[i] * (I[r][c + i].G + I[r][c - i].G);
643 return result + filter[0] * I[r][c].G;
646 static inline double filterXB(
const vpImage<vpRGBa> &I,
unsigned int r,
unsigned int c,
const double *filter,
unsigned int size)
652 for (
unsigned int i = 1; i <= (size - 1) / 2; i++) {
653 result += filter[i] * (I[r][c + i].B + I[r][c - i].B);
655 return result + filter[0] * I[r][c].B;
658 template <
typename ImageType,
typename FilterType>
660 const FilterType *filter,
unsigned int size)
666 for (
unsigned int i = 1; i <= (size - 1) / 2; i++) {
668 result += filter[i] * (I[r][c + i] + I[r][c - i]);
670 result += filter[i] * (I[r][c + i] + I[r][i - c]);
672 return result + filter[0] * I[r][c];
676 const double *filter,
unsigned int size)
682 for (
unsigned int i = 1; i <= (size - 1) / 2; i++) {
684 result += filter[i] * (I[r][c + i].R + I[r][c - i].R);
686 result += filter[i] * (I[r][c + i].R + I[r][i - c].R);
688 return result + filter[0] * I[r][c].R;
692 const double *filter,
unsigned int size)
698 for (
unsigned int i = 1; i <= (size - 1) / 2; i++) {
700 result += filter[i] * (I[r][c + i].G + I[r][c - i].G);
702 result += filter[i] * (I[r][c + i].G + I[r][i - c].G);
704 return result + filter[0] * I[r][c].G;
708 const double *filter,
unsigned int size)
714 for (
unsigned int i = 1; i <= (size - 1) / 2; i++) {
716 result += filter[i] * (I[r][c + i].B + I[r][c - i].B);
718 result += filter[i] * (I[r][c + i].B + I[r][i - c].B);
720 return result + filter[0] * I[r][c].B;
723 template <
typename ImageType,
typename FilterType>
725 const FilterType *filter,
unsigned int size)
731 for (
unsigned int i = 1; i <= (size - 1) / 2; i++) {
733 result += filter[i] * (I[r][c + i] + I[r][c - i]);
735 result += filter[i] * (I[r][2 * I.
getWidth() - c - i - 1] + I[r][c - i]);
737 return result + filter[0] * I[r][c];
741 const double *filter,
unsigned int size)
747 for (
unsigned int i = 1; i <= (size - 1) / 2; i++) {
749 result += filter[i] * (I[r][c + i].R + I[r][c - i].R);
751 result += filter[i] * (I[r][2 * I.
getWidth() - c - i - 1].R + I[r][c - i].R);
753 return result + filter[0] * I[r][c].R;
757 const double *filter,
unsigned int size)
763 for (
unsigned int i = 1; i <= (size - 1) / 2; i++) {
765 result += filter[i] * (I[r][c + i].G + I[r][c - i].G);
767 result += filter[i] * (I[r][2 * I.
getWidth() - c - i - 1].G + I[r][c - i].G);
769 return result + filter[0] * I[r][c].G;
773 const double *filter,
unsigned int size)
779 for (
unsigned int i = 1; i <= (size - 1) / 2; i++) {
781 result += filter[i] * (I[r][c + i].B + I[r][c - i].B);
783 result += filter[i] * (I[r][2 * I.
getWidth() - c - i - 1].B + I[r][c - i].B);
785 return result + filter[0] * I[r][c].B;
793 template<
typename ImageType,
typename FilterType>
797 for (
unsigned int i = 0; i < (size - 1) / 2; i++) {
798 for (
unsigned int j = 0; j < I.
getWidth(); j++) {
799 dIy[i][j] = vpImageFilter::filterYTopBorder<ImageType, FilterType>(I, i, j, filter, size);
802 for (
unsigned int i = (size - 1) / 2; i < I.
getHeight() - (size - 1) / 2; i++) {
803 for (
unsigned int j = 0; j < I.
getWidth(); j++) {
804 dIy[i][j] = vpImageFilter::filterY<ImageType, FilterType>(I, i, j, filter, size);
808 for (
unsigned int j = 0; j < I.
getWidth(); j++) {
809 dIy[i][j] = vpImageFilter::filterYBottomBorder<ImageType, FilterType>(I, i, j, filter, size);
814 template<
typename ImageType,
typename FilterType>
815 static inline FilterType
filterY(
const vpImage<ImageType> &I,
unsigned int r,
unsigned int c,
const FilterType *filter,
unsigned int size)
821 for (
unsigned int i = 1; i <= (size - 1) / 2; i++) {
822 result += filter[i] * (I[r + i][c] + I[r - i][c]);
824 return result + filter[0] * I[r][c];
827 static inline double filterYR(
const vpImage<vpRGBa> &I,
unsigned int r,
unsigned int c,
const double *filter,
unsigned int size)
833 for (
unsigned int i = 1; i <= (size - 1) / 2; i++) {
834 result += filter[i] * (I[r + i][c].R + I[r - i][c].R);
836 return result + filter[0] * I[r][c].R;
838 static inline double filterYG(
const vpImage<vpRGBa> &I,
unsigned int r,
unsigned int c,
const double *filter,
unsigned int size)
844 for (
unsigned int i = 1; i <= (size - 1) / 2; i++) {
845 result += filter[i] * (I[r + i][c].G + I[r - i][c].G);
847 return result + filter[0] * I[r][c].G;
850 static inline double filterYB(
const vpImage<vpRGBa> &I,
unsigned int r,
unsigned int c,
const double *filter,
unsigned int size)
856 for (
unsigned int i = 1; i <= (size - 1) / 2; i++) {
857 result += filter[i] * (I[r + i][c].B + I[r - i][c].B);
859 return result + filter[0] * I[r][c].B;
862 template<
typename ImageType,
typename FilterType>
864 const FilterType *filter,
unsigned int size)
870 for (
unsigned int i = 1; i <= (size - 1) / 2; i++) {
872 result += filter[i] * (I[r + i][c] + I[r - i][c]);
874 result += filter[i] * (I[r + i][c] + I[i - r][c]);
876 return result + filter[0] * I[r][c];
885 for (
unsigned int i = 1; i <= (size - 1) / 2; i++) {
887 result += filter[i] * (I[r + i][c].R + I[r - i][c].R);
889 result += filter[i] * (I[r + i][c].R + I[i - r][c].R);
891 return result + filter[0] * I[r][c].R;
900 for (
unsigned int i = 1; i <= (size - 1) / 2; i++) {
902 result += filter[i] * (I[r + i][c].G + I[r - i][c].G);
904 result += filter[i] * (I[r + i][c].G + I[i - r][c].G);
906 return result + filter[0] * I[r][c].G;
915 for (
unsigned int i = 1; i <= (size - 1) / 2; i++) {
917 result += filter[i] * (I[r + i][c].B + I[r - i][c].B);
919 result += filter[i] * (I[r + i][c].B + I[i - r][c].B);
921 return result + filter[0] * I[r][c].B;
924 template<
typename ImageType,
typename FilterType>
926 const FilterType *filter,
unsigned int size)
932 for (
unsigned int i = 1; i <= (size - 1) / 2; i++) {
934 result += filter[i] * (I[r + i][c] + I[r - i][c]);
936 result += filter[i] * (I[2 * I.
getHeight() - r - i - 1][c] + I[r - i][c]);
938 return result + filter[0] * I[r][c];
942 const double *filter,
unsigned int size)
948 for (
unsigned int i = 1; i <= (size - 1) / 2; i++) {
950 result += filter[i] * (I[r + i][c].R + I[r - i][c].R);
952 result += filter[i] * (I[2 * I.
getHeight() - r - i - 1][c].R + I[r - i][c].R);
954 return result + filter[0] * I[r][c].R;
958 const double *filter,
unsigned int size)
964 for (
unsigned int i = 1; i <= (size - 1) / 2; i++) {
966 result += filter[i] * (I[r + i][c].G + I[r - i][c].G);
968 result += filter[i] * (I[2 * I.
getHeight() - r - i - 1][c].G + I[r - i][c].G);
970 return result + filter[0] * I[r][c].G;
974 const double *filter,
unsigned int size)
980 for (
unsigned int i = 1; i <= (size - 1) / 2; i++) {
982 result += filter[i] * (I[r + i][c].B + I[r - i][c].B);
984 result += filter[i] * (I[2 * I.
getHeight() - r - i - 1][c].B + I[r - i][c].B);
986 return result + filter[0] * I[r][c].B;
1001 template <
typename ImageType,
typename FilterType>
1004 FilterType *fg =
new FilterType[(size + 1) / 2];
1005 vpImageFilter::getGaussianKernel<FilterType>(fg, size, sigma, normalize);
1007 vpImageFilter::filterX<ImageType, FilterType>(I, GIx, fg, size);
1008 vpImageFilter::filterY<FilterType, FilterType>(GIx, GI, fg, size);
1024 return (15.0 * fr[r][c] + 12.0 * (fr[r - 1][c] + fr[r][c - 1] + fr[r + 1][c] + fr[r][c + 1]) +
1025 9.0 * (fr[r - 1][c - 1] + fr[r + 1][c - 1] + fr[r - 1][c + 1] + fr[r + 1][c + 1]) +
1026 5.0 * (fr[r - 2][c] + fr[r][c - 2] + fr[r + 2][c] + fr[r][c + 2]) +
1027 4.0 * (fr[r - 2][c + 1] + fr[r - 2][c - 1] + fr[r - 1][c - 2] + fr[r + 1][c - 2] + fr[r + 2][c - 1] +
1028 fr[r + 2][c + 1] + fr[r - 1][c + 2] + fr[r + 1][c + 2]) +
1029 2.0 * (fr[r - 2][c - 2] + fr[r + 2][c - 2] + fr[r - 2][c + 2] + fr[r + 2][c + 2])) / 159.0;
1052 template<
typename FilterType>
1053 static void getGaussianKernel(FilterType *filter,
unsigned int size, FilterType sigma = 0.,
bool normalize =
true)
1059 sigma =
static_cast<FilterType
>((size - 1) / 6.0);
1061 int middle = (int)(size - 1) / 2;
1062 FilterType sigma2 =
static_cast<FilterType
>(
vpMath::sqr(sigma));
1063 FilterType coef1 =
static_cast<FilterType
>(1. / (sigma * sqrt(2. * M_PI)));
1064 FilterType _2_sigma2 =
static_cast<FilterType
>(2. * sigma2);
1065 for (
int i = 0; i <= middle; i++) {
1066 filter[i] = coef1 * exp(-(i * i) / _2_sigma2);
1071 for (
int i = 1; i <= middle; i++) {
1072 sum += 2 * filter[i];
1076 for (
int i = 0; i <= middle; i++) {
1077 filter[i] = filter[i] / sum;
1096 template <
typename FilterType>
1103 sigma =
static_cast<FilterType
>((size - 1) / 6.0);
1105 int middle = (int)(size - 1) / 2;
1106 FilterType sigma2 =
static_cast<FilterType
>(
vpMath::sqr(sigma));
1107 FilterType coef_1 =
static_cast<FilterType
>(1. / (sigma * sqrt(2. * M_PI)));
1108 FilterType coef_1_over_2 = coef_1 /
static_cast<FilterType
>(2.);
1109 FilterType _2_coef_1 =
static_cast<FilterType
>(2.) * coef_1;
1110 FilterType _2_sigma2 =
static_cast<FilterType
>(2. * sigma2);
1112 for (
int i = 1; i <= middle; i++) {
1113 filter[i] = -coef_1_over_2 * (
static_cast<FilterType
>(exp(-((i + 1) * (i + 1)) / _2_sigma2)) -
static_cast<FilterType
>(exp(-((i - 1) * (i - 1)) / _2_sigma2)));
1118 for (
int i = 1; i <= middle; i++) {
1119 sum += _2_coef_1 *
static_cast<FilterType
>(exp(-(i * i) / _2_sigma2));
1123 for (
int i = 1; i <= middle; i++) {
1124 filter[i] = filter[i] / sum;
1130 template<
typename FilterType>
1135 for (
unsigned int i = 0; i < I.
getHeight(); i++) {
1136 for (
unsigned int j = 0; j < 3; j++) {
1139 for (
unsigned int j = 3; j < I.
getWidth() - 3; j++) {
1148 template <
typename ImageType,
typename FilterType>
1152 for (
unsigned int i = 0; i < I.
getHeight(); i++) {
1153 for (
unsigned int j = 0; j < (size - 1) / 2; j++) {
1156 for (
unsigned int j = (size - 1) / 2; j < I.
getWidth() - (size - 1) / 2; j++) {
1157 dIx[i][j] = vpImageFilter::derivativeFilterX<ImageType, FilterType>(I, i, j, filter, size);
1159 for (
unsigned int j = I.
getWidth() - (size - 1) / 2; j < I.
getWidth(); j++) {
1175 template <
typename ImageType,
typename FilterType>
1177 const FilterType *gaussianDerivativeKernel,
unsigned int size)
1180 vpImageFilter::filterY<ImageType, FilterType>(I, GIy, gaussianKernel, size);
1181 vpImageFilter::getGradX<FilterType, FilterType>(GIy, dIx, gaussianDerivativeKernel, size);
1185 template <
typename FilterType>
1189 for (
unsigned int i = 0; i < 3; i++) {
1190 for (
unsigned int j = 0; j < I.
getWidth(); j++) {
1194 for (
unsigned int i = 3; i < I.
getHeight() - 3; i++) {
1195 for (
unsigned int j = 0; j < I.
getWidth(); j++) {
1200 for (
unsigned int j = 0; j < I.
getWidth(); j++) {
1206 template <
typename ImageType,
typename FilterType>
1210 for (
unsigned int i = 0; i < (size - 1) / 2; i++) {
1211 for (
unsigned int j = 0; j < I.
getWidth(); j++) {
1215 for (
unsigned int i = (size - 1) / 2; i < I.
getHeight() - (size - 1) / 2; i++) {
1216 for (
unsigned int j = 0; j < I.
getWidth(); j++) {
1217 dIy[i][j] = vpImageFilter::derivativeFilterY<ImageType, FilterType>(I, i, j, filter, size);
1221 for (
unsigned int j = 0; j < I.
getWidth(); j++) {
1237 template <
typename ImageType,
typename FilterType>
1239 const FilterType *gaussianDerivativeKernel,
unsigned int size)
1242 vpImageFilter::filterX<ImageType, FilterType>(I, GIx, gaussianKernel, size);
1243 vpImageFilter::getGradY<FilterType, FilterType>(GIx, dIy, gaussianDerivativeKernel, size);
1253 template <
typename FilterType>
1258 std::string errMsg =
"Cannot get Scharr kernel of size " + std::to_string(size * 2 + 1) +
" != 3";
1263 FilterType norm = getScharrKernelY<FilterType>(ScharrY.
data, size);
1264 memcpy(filter, ScharrY.
t().data, ScharrY.
getRows() * ScharrY.
getCols() *
sizeof(FilterType));
1275 template <
typename FilterType>
1279 static const FilterType ScharrY3x3[9] = { -3.0, -10.0, -3.0, 0.0, 0.0, 0.0, 3.0, 10.0, 3.0 };
1283 std::string errMsg =
"Cannot get Scharr kernel of size " + std::to_string(size * 2 + 1) +
" != 3";
1287 const unsigned int kernel_size = size * 2 + 1;
1288 if (kernel_size == 3) {
1289 memcpy(filter, ScharrY3x3, kernel_size * kernel_size *
sizeof(FilterType));
1303 template <
typename FilterType>
1312 FilterType norm = getSobelKernelY<FilterType>(SobelY.
data, size);
1313 memcpy(filter, SobelY.
t().data, SobelY.
getRows() * SobelY.
getCols() *
sizeof(FilterType));
1324 template <
typename FilterType>
1328 static const FilterType SobelY3x3[9] = { -1.0, -2.0, -1.0, 0.0, 0.0, 0.0, 1.0, 2.0, 1.0 };
1329 static const FilterType SobelY5x5[25] = { -1.0, -4.0, -6.0, -4.0, -1.0, -2.0, -8.0, -12.0, -8.0, -2.0, 0.0, 0.0, 0.0,
1330 0.0, 0.0, 2.0, 8.0, 12.0, 8.0, 2.0, 1.0, 4.0, 6.0, 4.0, 1.0 };
1331 static const FilterType SobelY7x7[49] = { -1, -6, -15, -20, -15, -6, -1, -4, -24, -60, -80, -60, -24, -4, -5, -30, -75,
1332 -100, -75, -30, -5, 0, 0, 0, 0, 0, 0, 0, 5, 30, 75, 100, 75, 30,
1333 5, 4, 24, 60, 80, 60, 24, 4, 1, 6, 15, 20, 15, 6, 1 };
1335 smoothingKernel[0][0] = 1.0;
1336 smoothingKernel[0][1] = 2.0;
1337 smoothingKernel[0][2] = 1.0;
1338 smoothingKernel[1][0] = 2.0;
1339 smoothingKernel[1][1] = 4.0;
1340 smoothingKernel[1][2] = 2.0;
1341 smoothingKernel[2][0] = 1.0;
1342 smoothingKernel[2][1] = 2.0;
1343 smoothingKernel[2][2] = 1.0;
1350 const unsigned int kernel_size = size * 2 + 1;
1351 double scale = (1. / 8.);
1352 if (kernel_size == 3) {
1353 memcpy(filter, SobelY3x3, kernel_size * kernel_size *
sizeof(FilterType));
1357 if (kernel_size == 5) {
1358 memcpy(filter, SobelY5x5, kernel_size * kernel_size *
sizeof(FilterType));
1362 if (kernel_size == 7) {
1363 memcpy(filter, SobelY7x7, kernel_size * kernel_size *
sizeof(FilterType));
1368 memcpy(sobelY.
data, SobelY7x7, sobelY.
getRows() * sobelY.
getCols() *
sizeof(FilterType));
1369 for (
unsigned int i = 4; i <= size; i++) {
1375 memcpy(filter, sobelY.
data, sobelY.
getRows() * sobelY.
getCols() *
sizeof(FilterType));
1380 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC)
1381 static float median(
const cv::Mat &cv_I);
Implementation of a generic 2D array used as base class for matrices and vectors.
unsigned int getCols() const
Type * data
Address of the first element of the data array.
static vpArray2D< Type > conv2(const vpArray2D< Type > &M, const vpArray2D< Type > &kernel, const std::string &mode)
vpArray2D< Type > t() const
Compute the transpose of the array.
unsigned int getRows() const
Implementation of column vector and the associated operations.
error that can be emitted by ViSP classes.
@ badValue
Used to indicate that a value is not in the allowed range.
@ dimensionError
Bad dimension.
@ notImplementedError
Not implemented.
Class to compute a gray level image histogram.
void calculate(const vpImage< unsigned char > &I, unsigned int nbins=256, unsigned int nbThreads=1)
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
Error that can be emitted by the vpImage class and its derivatives.
@ incorrectInitializationError
Wrong image initialization.
Various image filter, convolution, etc...
static unsigned char filterGaussXPyramidal(const vpImage< unsigned char > &I, unsigned int i, unsigned int j)
static FilterType filterX(const vpImage< ImageType > &I, unsigned int r, unsigned int c, const FilterType *filter, unsigned int size)
static double derivativeFilterX(const vpImage< ImageType > &I, unsigned int r, unsigned int c)
static double filterXG(const vpImage< vpRGBa > &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
static FilterType filterYBottomBorder(const vpImage< ImageType > &I, unsigned int r, unsigned int c, const FilterType *filter, unsigned int size)
static double filterYTopBorderG(const vpImage< vpRGBa > &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
static void filterYB(const vpImage< vpRGBa > &I, vpImage< vpRGBa > &dIx, const double *filter, unsigned int size)
static double filterYBottomBorderB(const vpImage< vpRGBa > &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
static void getGradYGauss2D(const vpImage< ImageType > &I, vpImage< FilterType > &dIy, const FilterType *gaussianKernel, const FilterType *gaussianDerivativeKernel, unsigned int size)
static FilterType getSobelKernelX(FilterType *filter, unsigned int size)
static double filterXRightBorderB(const vpImage< vpRGBa > &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
static void filter(const vpImage< ImageType > &I, vpImage< FilterType > &If, const vpArray2D< FilterType > &M, bool convolve=false)
static double filterYBottomBorderR(const vpImage< vpRGBa > &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
static double filterYTopBorderB(const vpImage< vpRGBa > &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
static void filterXB(const vpImage< vpRGBa > &I, vpImage< vpRGBa > &dIx, const double *filter, unsigned int size)
static double filterYR(const vpImage< vpRGBa > &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
static FilterType filterY(const vpImage< ImageType > &I, unsigned int r, unsigned int c, const FilterType *filter, unsigned int size)
static void getGradXGauss2D(const vpImage< ImageType > &I, vpImage< FilterType > &dIx, const FilterType *gaussianKernel, const FilterType *gaussianDerivativeKernel, unsigned int size)
static FilterType filterYTopBorder(const vpImage< ImageType > &I, unsigned int r, unsigned int c, const FilterType *filter, unsigned int size)
static double filterXLeftBorderB(const vpImage< vpRGBa > &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
static void filterYR(const vpImage< vpRGBa > &I, vpImage< vpRGBa > &dIx, const double *filter, unsigned int size)
static void computePartialDerivatives(const vpImage< ImageType > &I, vpImage< vpRGBa > &dIx, vpImage< vpRGBa > &dIy, const bool &computeDx=true, const bool &computeDy=true, const bool &normalize=true, const unsigned int gaussianKernelSize=5, const vpRGBa gaussianStdev=vpRGBa(), const unsigned int apertureGradient=3, const vpCannyFilteringAndGradientType &filteringType=CANNY_GBLUR_SOBEL_FILTERING, const vpCannyBackendType &backend=CANNY_VISP_BACKEND)=delete
static void computePartialDerivatives(const vpImage< ImageType > &I, vpImage< FilterType > &dIx, vpImage< FilterType > &dIy, const bool &computeDx=true, const bool &computeDy=true, const bool &normalize=true, const unsigned int &gaussianKernelSize=5, const FilterType &gaussianStdev=2.f, const unsigned int &apertureGradient=3, const vpCannyFilteringAndGradientType &filteringType=CANNY_GBLUR_SOBEL_FILTERING, const vpCannyBackendType &backend=CANNY_VISP_BACKEND)
Compute the partial derivatives (i.e. horizontal and vertical gradients) of the input image.
static double filterXB(const vpImage< vpRGBa > &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
static void filter(const vpImage< ImageType > &I, vpImage< ImageType > &Iu, vpImage< ImageType > &Iv, const vpArray2D< vpRGBa > &M, bool convolve)=delete
static double filterXR(const vpImage< vpRGBa > &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
static void filter(const vpImage< vpRGBa > &I, vpImage< FilterType > &Iu, vpImage< FilterType > &Iv, const vpArray2D< FilterType > &M, bool convolve)=delete
vpCannyFilteringAndGradientType
Canny filter and gradient operators to apply on the image before the edge detection stage.
static void getGaussianDerivativeKernel(FilterType *filter, unsigned int size, FilterType sigma=0., bool normalize=true)
static float computeCannyThreshold(const vpImage< unsigned char > &I, float &lowerThresh, const vpImage< OutType > *p_dIx=nullptr, const vpImage< OutType > *p_dIy=nullptr, const unsigned int &gaussianKernelSize=5, const OutType &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 void filter(const vpImage< ImageType > &I, vpImage< FilterType > &GI, const FilterType *filter, unsigned int size)
vpCannyBackendType
Canny filter backends for the edge detection operations.
static double filterXLeftBorderR(const vpImage< vpRGBa > &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
static FilterType filterXRightBorder(const vpImage< ImageType > &I, unsigned int r, unsigned int c, const FilterType *filter, unsigned int size)
static FilterType derivativeFilterY(const vpImage< ImageType > &I, unsigned int r, unsigned int c, const FilterType *filter, unsigned int size)
static double filterXLeftBorderG(const vpImage< vpRGBa > &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
static double filterXRightBorderR(const vpImage< vpRGBa > &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
static void getGradX(const vpImage< unsigned char > &I, vpImage< FilterType > &dIx)
static void filterXR(const vpImage< vpRGBa > &I, vpImage< vpRGBa > &dIx, const double *filter, unsigned int size)
static double derivativeFilterY(const vpImage< ImageType > &I, unsigned int r, unsigned int c)
static void computePartialDerivatives(const vpImage< ImageType > &I, vpImage< unsigned char > &dIx, vpImage< unsigned char > &dIy, const bool &computeDx=true, const bool &computeDy=true, const bool &normalize=true, const unsigned int &gaussianKernelSize=5, const unsigned char &gaussianStdev=2.f, const unsigned int &apertureGradient=3, const vpCannyFilteringAndGradientType &filteringType=CANNY_GBLUR_SOBEL_FILTERING, const vpCannyBackendType &backend=CANNY_VISP_BACKEND)=delete
static void getGaussianKernel(FilterType *filter, unsigned int size, FilterType sigma=0., bool normalize=true)
static double filterYTopBorderR(const vpImage< vpRGBa > &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
static void getGradX(const vpImage< ImageType > &I, vpImage< FilterType > &dIx, const FilterType *filter, unsigned int size)
static void computePartialDerivatives(const vpImage< vpRGBa > &I, vpImage< FilterType > &dIx, vpImage< FilterType > &dIy, const bool &computeDx=true, const bool &computeDy=true, const bool &normalize=true, const unsigned int &gaussianKernelSize=5, const FilterType &gaussianStdev=2.f, const unsigned int &apertureGradient=3, const vpCannyFilteringAndGradientType &filteringType=CANNY_GBLUR_SOBEL_FILTERING, const vpCannyBackendType &backend=CANNY_VISP_BACKEND)=delete
static void filterYG(const vpImage< vpRGBa > &I, vpImage< vpRGBa > &dIx, const double *filter, unsigned int size)
static FilterType getScharrKernelY(FilterType *filter, unsigned int size)
static void filter(const vpImage< ImageType > &I, vpImage< FilterType > &Iu, vpImage< FilterType > &Iv, const vpArray2D< FilterType > &M, bool convolve=false)
static FilterType filterXLeftBorder(const vpImage< ImageType > &I, unsigned int r, unsigned int c, const FilterType *filter, unsigned int size)
static double filterXRightBorderG(const vpImage< vpRGBa > &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
static void filterX(const vpImage< ImageType > &I, vpImage< FilterType > &dIx, const FilterType *filter, unsigned int size)
static FilterType getSobelKernelY(FilterType *filter, unsigned int size)
static void getGradY(const vpImage< ImageType > &I, vpImage< FilterType > &dIy, const FilterType *filter, unsigned int size)
static FilterType getScharrKernelX(FilterType *filter, unsigned int size)
static void filterXG(const vpImage< vpRGBa > &I, vpImage< vpRGBa > &dIx, const double *filter, unsigned int size)
static double filterYG(const vpImage< vpRGBa > &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
static void filterY(const vpImage< ImageType > &I, vpImage< FilterType > &dIy, const FilterType *filter, unsigned int size)
static double filterYBottomBorderG(const vpImage< vpRGBa > &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
static double filterYB(const vpImage< vpRGBa > &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
static unsigned char filterGaussYPyramidal(const vpImage< unsigned char > &I, unsigned int i, unsigned int j)
static void gaussianBlur(const vpImage< ImageType > &I, vpImage< FilterType > &GI, unsigned int size=7, FilterType sigma=0., bool normalize=true)
static double gaussianFilter(const vpImage< T > &fr, unsigned int r, unsigned int c)
static void filter(const vpImage< vpRGBa > &I, vpImage< FilterType > &If, const vpArray2D< FilterType > &M, bool convolve=false)=delete
static FilterType derivativeFilterX(const vpImage< ImageType > &I, unsigned int r, unsigned int c, const FilterType *filter, unsigned int size)
static void getGradY(const vpImage< unsigned char > &I, vpImage< FilterType > &dIy)
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
static double sqr(double x)