Visual Servoing Platform  version 3.6.1 under development (2024-07-27)
vpImageFilter.cpp
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2024 by Inria. All rights reserved.
4  *
5  * This software is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See https://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * Various image tools, convolution, ...
32  */
33 
34 #include <visp3/core/vpImageFilter.h>
35 #include <visp3/core/vpIoTools.h>
36 #include <visp3/core/vpRGBa.h>
37 
39 
43 template
44 void vpImageFilter::filter<unsigned char, float>(const vpImage<unsigned char> &I, vpImage<float> &If,
45  const vpArray2D<float> &M, bool convolve, const vpImage<bool> *p_mask);
46 
47 template
48 void vpImageFilter::filter<unsigned char, double>(const vpImage<unsigned char> &I, vpImage<double> &If,
49  const vpArray2D<double> &M, bool convolve, const vpImage<bool> *p_mask);
50 
51 template
52 void vpImageFilter::filter<float, float>(const vpImage<float> &I, vpImage<float> &Iu, vpImage<float> &Iv,
53  const vpArray2D<float> &M, bool convolve, const vpImage<bool> *p_mask);
54 
55 template
56 void vpImageFilter::filter<double, double>(const vpImage<double> &I, vpImage<double> &Iu, vpImage<double> &Iv,
57  const vpArray2D<double> &M, bool convolve, const vpImage<bool> *p_mask);
58 
59 template
60 void vpImageFilter::filter<unsigned char, float>(const vpImage<unsigned char> &I, vpImage<float> &GI, const float *filter,
61  unsigned int size, const vpImage<bool> *p_mask);
62 
63 template
64 void vpImageFilter::filter<unsigned char, double>(const vpImage<unsigned char> &I, vpImage<double> &GI, const double *filter,
65  unsigned int size, const vpImage<bool> *p_mask);
66 
67 template
68 void vpImageFilter::filter<float, float>(const vpImage<float> &I, vpImage<float> &GI, const float *filter,
69  unsigned int size, const vpImage<bool> *p_mask);
70 
71 template
72 void vpImageFilter::filter<double, double>(const vpImage<double> &I, vpImage<double> &GI, const double *filter,
73  unsigned int size, const vpImage<bool> *p_mask);
130  const vpColVector &kernelV)
131 {
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;
135 
136  If.resize(heightI, widthI, 0.0);
137  vpImage<double> I_filter(heightI, widthI, 0.0);
138 
139  for (unsigned int i = 0; i < heightI; ++i) {
140  for (unsigned int j = half_size; j < (widthI - half_size); ++j) {
141  double conv = 0.0;
142  for (unsigned int a = 0; a < size; ++a) {
143  conv += kernelH[a] * static_cast<double>(I[i][(j + half_size) - a]);
144  }
145 
146  I_filter[i][j] = conv;
147  }
148  }
149 
150  for (unsigned int i = half_size; i < (heightI - half_size); ++i) {
151  for (unsigned int j = 0; j < widthI; ++j) {
152  double conv = 0.0;
153  for (unsigned int a = 0; a < sizeV; ++a) {
154  conv += kernelV[a] * I_filter[(i + half_size) - a][j];
155  }
156 
157  If[i][j] = conv;
158  }
159  }
160 }
161 
165 template
166 void vpImageFilter::filterX<unsigned char, float>(const vpImage<unsigned char> &I, vpImage<float> &dIx, const float *filter,
167  unsigned int size, const vpImage<bool> *p_mask);
168 
169 template
170 void vpImageFilter::filterX<unsigned char, double>(const vpImage<unsigned char> &I, vpImage<double> &dIx, const double *filter,
171  unsigned int size, const vpImage<bool> *p_mask);
172 
173 template
174 void vpImageFilter::filterX<float, float>(const vpImage<float> &I, vpImage<float> &dIx, const float *filter, unsigned int size, const vpImage<bool> *p_mask);
175 
176 template
177 void vpImageFilter::filterX<double, double>(const vpImage<double> &I, vpImage<double> &dIx, const double *filter, unsigned int size, const vpImage<bool> *p_mask);
182 void vpImageFilter::filterX(const vpImage<vpRGBa> &I, vpImage<vpRGBa> &dIx, const double *filter, unsigned int size,
183  const vpImage<bool> *p_mask)
184 {
185  const unsigned int heightI = I.getHeight(), widthI = I.getWidth();
186  const unsigned int stop1J = (size - 1) / 2;
187  const unsigned int stop2J = widthI - ((size - 1) / 2);
188  resizeAndInitializeIfNeeded(p_mask, heightI, widthI, dIx);
189 
190  for (unsigned int i = 0; i < heightI; ++i) {
191  for (unsigned int j = 0; j < stop1J; ++j) {
192  // We have to compute the value for each pixel if we don't have a mask or for
193  // pixels for which the mask is true otherwise
194  bool computeVal = checkBooleanMask(p_mask, i, j);
195  if (computeVal) {
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));
199  }
200  }
201  for (unsigned int j = stop1J; j < stop2J; ++j) {
202  // We have to compute the value for each pixel if we don't have a mask or for
203  // pixels for which the mask is true otherwise
204  bool computeVal = checkBooleanMask(p_mask, i, j);
205  if (computeVal) {
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));
209  }
210  }
211  for (unsigned int j = stop2J; j < widthI; ++j) {
212  // We have to compute the value for each pixel if we don't have a mask or for
213  // pixels for which the mask is true otherwise
214  bool computeVal = checkBooleanMask(p_mask, i, j);
215  if (computeVal) {
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));
219  }
220  }
221  }
222 }
223 
227 template
228 void vpImageFilter::filterY<unsigned char, float>(const vpImage<unsigned char> &I, vpImage<float> &dIy, const float *filter,
229  unsigned int size, const vpImage<bool> *p_mask);
230 
231 template
232 void vpImageFilter::filterY<unsigned char, double>(const vpImage<unsigned char> &I, vpImage<double> &dIy, const double *filter,
233  unsigned int size, const vpImage<bool> *p_mask);
234 
235 template
236 void vpImageFilter::filterY<float, float>(const vpImage<float> &I, vpImage<float> &dIy, const float *filter, unsigned int size, const vpImage<bool> *p_mask);
237 
238 template
239 void vpImageFilter::filterY<double, double>(const vpImage<double> &I, vpImage<double> &dIy, const double *filter, unsigned int size, const vpImage<bool> *p_mask);
244 void vpImageFilter::filterY(const vpImage<vpRGBa> &I, vpImage<vpRGBa> &dIy, const double *filter, unsigned int size,
245  const vpImage<bool> *p_mask)
246 {
247  const unsigned int heightI = I.getHeight(), widthI = I.getWidth();
248  const unsigned int stop1I = (size - 1) / 2;
249  const unsigned int stop2I = heightI - ((size - 1) / 2);
250  resizeAndInitializeIfNeeded(p_mask, heightI, widthI, dIy);
251 
252  for (unsigned int i = 0; i < stop1I; ++i) {
253  for (unsigned int j = 0; j < widthI; ++j) {
254  // We have to compute the value for each pixel if we don't have a mask or for
255  // pixels for which the mask is true otherwise
256  bool computeVal = checkBooleanMask(p_mask, i, j);
257  if (computeVal) {
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));
261  }
262  }
263  }
264  for (unsigned int i = stop1I; i < stop2I; ++i) {
265  for (unsigned int j = 0; j < widthI; ++j) {
266  // We have to compute the value for each pixel if we don't have a mask or for
267  // pixels for which the mask is true otherwise
268  bool computeVal = checkBooleanMask(p_mask, i, j);
269  if (computeVal) {
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));
273  }
274  }
275  }
276  for (unsigned int i = stop2I; i < heightI; ++i) {
277  for (unsigned int j = 0; j < widthI; ++j) {
278  // We have to compute the value for each pixel if we don't have a mask or for
279  // pixels for which the mask is true otherwise
280  bool computeVal = checkBooleanMask(p_mask, i, j);
281  if (computeVal) {
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));
285  }
286  }
287  }
288 }
289 
293 template
294 void vpImageFilter::gaussianBlur<unsigned char, float>(const vpImage<unsigned char> &I, vpImage<float> &GI, unsigned int size, float sigma, bool normalize, const vpImage<bool> *p_mask);
295 
296 template
297 void vpImageFilter::gaussianBlur<unsigned char, double>(const vpImage<unsigned char> &I, vpImage<double> &GI, unsigned int size, double sigma, bool normalize, const vpImage<bool> *p_mask);
298 
299 template
300 void vpImageFilter::gaussianBlur<float, float>(const vpImage<float> &I, vpImage<float> &GI, unsigned int size, float sigma, bool normalize, const vpImage<bool> *p_mask);
301 
302 template
303 void vpImageFilter::gaussianBlur<double, double>(const vpImage<double> &I, vpImage<double> &GI, unsigned int size, double sigma, bool normalize, const vpImage<bool> *p_mask);
320 void vpImageFilter::gaussianBlur(const vpImage<vpRGBa> &I, vpImage<vpRGBa> &GI, unsigned int size, double sigma, bool normalize,
321  const vpImage<bool> *p_mask)
322 {
323  double *fg = new double[(size + 1) / 2];
324  vpImageFilter::getGaussianKernel(fg, size, sigma, normalize);
325  vpImage<vpRGBa> GIx;
326  vpImageFilter::filterX(I, GIx, fg, size, p_mask);
327  vpImageFilter::filterY(GIx, GI, fg, size, p_mask);
328  GIx.destroy();
329  delete[] fg;
330 }
331 
335 template
336 void vpImageFilter::getGaussianKernel<float>(float *filter, unsigned int size, float sigma, bool normalize);
337 
338 template
339 void vpImageFilter::getGaussianDerivativeKernel<float>(float *filter, unsigned int size, float sigma, bool normalize);
340 
341 template
342 void vpImageFilter::getGaussianDerivativeKernel<double>(double *filter, unsigned int size, double sigma, bool normalize);
343 
344 template
345 void vpImageFilter::getGradX<float>(const vpImage<unsigned char> &I, vpImage<float> &dIx, const vpImage<bool> *p_mask);
346 
347 template
348 void vpImageFilter::getGradX<double>(const vpImage<unsigned char> &I, vpImage<double> &dIx, const vpImage<bool> *p_mask);
349 
350 template
351 void vpImageFilter::getGradY<float>(const vpImage<unsigned char> &I, vpImage<float> &dIy, const vpImage<bool> *p_mask);
352 
353 template
354 void vpImageFilter::getGradY<double>(const vpImage<unsigned char> &I, vpImage<double> &dIy, const vpImage<bool> *p_mask);
355 
356 template
357 void vpImageFilter::getGradX<unsigned char, float>(const vpImage<unsigned char> &I, vpImage<float> &dIx, const float *filter, unsigned int size, const vpImage<bool> *p_mask);
358 
359 template
360 void vpImageFilter::getGradX<unsigned char, double>(const vpImage<unsigned char> &I, vpImage<double> &dIx, const double *filter, unsigned int size, const vpImage<bool> *p_mask);
361 
362 template
363 void vpImageFilter::getGradX<float, float>(const vpImage<float> &I, vpImage<float> &dIx, const float *filter, unsigned int size, const vpImage<bool> *p_mask);
364 
365 template
366 void vpImageFilter::getGradX<double, double>(const vpImage<double> &I, vpImage<double> &dIx, const double *filter, unsigned int size, const vpImage<bool> *p_mask);
367 
368 template
369 void vpImageFilter::getGradY<unsigned char, float>(const vpImage<unsigned char> &I, vpImage<float> &dIy, const float *filter, unsigned int size, const vpImage<bool> *p_mask);
370 
371 template
372 void vpImageFilter::getGradY<unsigned char, double>(const vpImage<unsigned char> &I, vpImage<double> &dIy, const double *filter, unsigned int size, const vpImage<bool> *p_mask);
373 
374 template
375 void vpImageFilter::getGradY<float, float>(const vpImage<float> &I, vpImage<float> &dIy, const float *filter, unsigned int size, const vpImage<bool> *p_mask);
376 
377 template
378 void vpImageFilter::getGradY<double, double>(const vpImage<double> &I, vpImage<double> &dIy, const double *filter, unsigned int size, const vpImage<bool> *p_mask);
379 
380 template
381 void vpImageFilter::getGradXGauss2D<unsigned char, float>(const vpImage<unsigned char> &I, vpImage<float> &dIx, const float *gaussianKernel,
382  const float *gaussianDerivativeKernel, unsigned int size, const vpImage<bool> *p_mask);
383 
384 template
385 void vpImageFilter::getGradXGauss2D<unsigned char, double>(const vpImage<unsigned char> &I, vpImage<double> &dIx, const double *gaussianKernel,
386  const double *gaussianDerivativeKernel, unsigned int size, const vpImage<bool> *p_mask);
387 
388 template
389 void vpImageFilter::getGradXGauss2D<float, float>(const vpImage<float> &I, vpImage<float> &dIx, const float *gaussianKernel,
390  const float *gaussianDerivativeKernel, unsigned int size, const vpImage<bool> *p_mask);
391 
392 template
393 void vpImageFilter::getGradXGauss2D<double, double>(const vpImage<double> &I, vpImage<double> &dIx, const double *gaussianKernel,
394  const double *gaussianDerivativeKernel, unsigned int size, const vpImage<bool> *p_mask);
395 
396 template
397 void vpImageFilter::getGradYGauss2D<unsigned char, float>(const vpImage<unsigned char> &I, vpImage<float> &dIy, const float *gaussianKernel,
398  const float *gaussianDerivativeKernel, unsigned int size, const vpImage<bool> *p_mask);
399 
400 template
401 void vpImageFilter::getGradYGauss2D<unsigned char, double>(const vpImage<unsigned char> &I, vpImage<double> &dIy, const double *gaussianKernel,
402  const double *gaussianDerivativeKernel, unsigned int size, const vpImage<bool> *p_mask);
403 
404 template
405 void vpImageFilter::getGradYGauss2D<float, float>(const vpImage<float> &I, vpImage<float> &dIy, const float *gaussianKernel,
406  const float *gaussianDerivativeKernel, unsigned int size, const vpImage<bool> *p_mask);
407 
408 template
409 void vpImageFilter::getGradYGauss2D<double, double>(const vpImage<double> &I, vpImage<double> &dIy, const double *gaussianKernel,
410  const double *gaussianDerivativeKernel, unsigned int size, const vpImage<bool> *p_mask);
415  // Operation for Gaussian pyramid
417 {
419 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC)
420 #if (VISP_HAVE_OPENCV_VERSION >= 0x030000)
421  cv::Mat imgsrc, imgdest;
422  vpImageConvert::convert(I, imgsrc);
423  cv::pyrDown(imgsrc, imgdest, cv::Size((int)I.getWidth() / 2, (int)I.getHeight() / 2));
424  vpImageConvert::convert(imgdest, GI);
425 #else
426  cv::Mat imgsrc, imgdest;
427  vpImageConvert::convert(I, imgsrc);
428  cv::pyrDown(imgsrc, imgdest, cvSize((int)I.getWidth() / 2, (int)I.getHeight() / 2));
429  vpImageConvert::convert(imgdest, GI);
430 #endif
431 #else
434 #endif
435 }
436 
438 {
439  const unsigned int w = I.getWidth() / 2;
440  const unsigned int height = I.getHeight();
441  const unsigned int val_2 = 2;
442 
443  GI.resize(height, w);
444  for (unsigned int i = 0; i < height; ++i) {
445  GI[i][0] = I[i][0];
446  for (unsigned int j = 1; j < (w - 1); ++j) {
447  GI[i][j] = vpImageFilter::filterGaussXPyramidal(I, i, val_2 * j);
448  }
449  GI[i][w - 1] = I[i][(val_2 * w) - 1];
450  }
451 }
452 
454 {
455  const unsigned int h = I.getHeight() / 2;
456  const unsigned int width = I.getWidth();
457  const unsigned int val_2 = 2;
458 
459  GI.resize(h, width);
460  for (unsigned int j = 0; j < width; ++j) {
461  GI[0][j] = I[0][j];
462  for (unsigned int i = 1; i < (h - 1); ++i) {
463  GI[i][j] = vpImageFilter::filterGaussYPyramidal(I, val_2 * i, j);
464  }
465  GI[h - 1][j] = I[(val_2 * h) - 1][j];
466  }
467 }
468 
472 template
473 double vpImageFilter::getSobelKernelX<double>(double *filter, unsigned int size);
474 
475 template
476 float vpImageFilter::getSobelKernelX<float>(float *filter, unsigned int size);
477 
478 template
479 double vpImageFilter::getSobelKernelY<double>(double *filter, unsigned int size);
480 
481 template
482 float vpImageFilter::getSobelKernelY<float>(float *filter, unsigned int size);
488 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC)
494 float vpImageFilter::median(const cv::Mat &channel)
495 {
496  float m = (channel.rows * channel.cols) / 2.f;
497  int bin = 0;
498  float med = -1.0f;
499 
500  int histSize = 256;
501  float range[] = { 0, 256 };
502  const float *histRange = { range };
503  bool uniform = true;
504  bool accumulate = false;
505  cv::Mat hist;
506  cv::calcHist(&channel, 1, 0, cv::Mat(), hist, 1, &histSize, &histRange, uniform, accumulate);
507 
508  int i = 0;
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);
513  }
514  ++i;
515  }
516 
517  return med;
518 }
519 
528 {
529  cv::Mat cv_I;
530  vpImageConvert::convert(Isrc, cv_I);
531  return median(cv_I);
532 }
533 
542 std::vector<float> vpImageFilter::median(const vpImage<vpRGBa> &Isrc)
543 {
544  cv::Mat cv_I_bgr;
545  vpImageConvert::convert(Isrc, cv_I_bgr);
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 }; // To keep the order R, G, B
550  const int orderCvChannels[] = { 0, 1, 2 }; // Because the order of the cv::Mat is B, G, R
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]]);
554  }
555  return meds;
556 }
557 
558 
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,
581 {
582  if ((filteringType == vpImageFilter::CANNY_GBLUR_SCHARR_FILTERING)
583  || (filteringType == vpImageFilter::CANNY_GBLUR_SOBEL_FILTERING)) {
584  cv::Mat img_blur;
585  // Apply Gaussian blur to the image
586  cv::Size gsz(gaussianKernelSize, gaussianKernelSize);
587  cv::GaussianBlur(cv_I, img_blur, gsz, gaussianStdev);
588 
589  // Compute the gradient of the blurred image
590  if (filteringType == vpImageFilter::CANNY_GBLUR_SOBEL_FILTERING) {
591  double scale = 1.;
592  if (normalize) {
593  scale = 1. / 8.;
594  if (apertureGradient > 3) {
595  scale *= std::pow(1. / 2., (static_cast<double>(apertureGradient) * 2. - 3.)); // 1 / 2^(2 x ksize - dx - dy -2) with ksize =apertureGradient and dx xor dy = 1
596  }
597  }
598  if (computeDx) {
599  cv::Sobel(img_blur, cv_dIx, CV_16S, 1, 0, apertureGradient, scale, 0., cv::BORDER_REPLICATE);
600  }
601  if (computeDy) {
602  cv::Sobel(img_blur, cv_dIy, CV_16S, 0, 1, apertureGradient, scale, 0., cv::BORDER_REPLICATE);
603  }
604  }
605  else if (filteringType == vpImageFilter::CANNY_GBLUR_SCHARR_FILTERING) {
606  double scale = 1.;
607  if (normalize) {
608  scale = 1. / 32.;
609  }
610  if (computeDx) {
611  cv::Scharr(img_blur, cv_dIx, CV_16S, 1, 0, scale);
612  }
613  if (computeDy) {
614  cv::Scharr(img_blur, cv_dIy, CV_16S, 0, 1, scale);
615  }
616  }
617  }
618 }
619 #endif
620 
624 template
625 void vpImageFilter::computePartialDerivatives<unsigned char, float>(const vpImage<unsigned char> &I,
626  vpImage<float> &dIx, vpImage<float> &dIy,
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);
632 
633 template
634 void vpImageFilter::computePartialDerivatives<unsigned char, double>(const vpImage<unsigned char> &I,
635  vpImage<double> &dIx, vpImage<double> &dIy,
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);
641 
642 template
643 void vpImageFilter::computePartialDerivatives<float, float>(const vpImage<float> &I,
644  vpImage<float> &dIx, vpImage<float> &dIy,
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);
650 
651 template
652 void vpImageFilter::computePartialDerivatives<float, double>(const vpImage<float> &I,
653  vpImage<double> &dIx, vpImage<double> &dIy,
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);
659 
660 template
661 void vpImageFilter::computePartialDerivatives<double, float>(const vpImage<double> &I,
662  vpImage<float> &dIx, vpImage<float> &dIy,
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);
668 
669 template
670 void vpImageFilter::computePartialDerivatives<double, double>(const vpImage<double> &I,
671  vpImage<double> &dIx, vpImage<double> &dIy,
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);
677 
678 template
679 float vpImageFilter::computeCannyThreshold<double>(const vpImage<unsigned char> &I, float &lowerThresh,
680  const vpImage<double> *p_dIx, const vpImage<double> *p_dIy,
681  const unsigned int &gaussianKernelSize,
682  const double &gaussianStdev, const unsigned int &apertureGradient,
683  const float &lowerThresholdRatio, const float &upperThresholdRatio,
685  const vpImage<bool> *p_mask);
686 
687 template
688 float vpImageFilter::computeCannyThreshold<float>(const vpImage<unsigned char> &I, float &lowerThresh,
689  const vpImage<float> *p_dIx, const vpImage<float> *p_dIy,
690  const unsigned int &gaussianKernelSize,
691  const float &gaussianStdev, const unsigned int &apertureGradient,
692  const float &lowerThresholdRatio, const float &upperThresholdRatio,
694  const vpImage<bool> *p_mask);
699 END_VISP_NAMESPACE
unsigned int size() const
Return the number of elements of the 2D array.
Definition: vpArray2D.h:349
Implementation of column vector and the associated operations.
Definition: vpColVector.h:191
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.
Definition: vpImageFilter.h:90
@ CANNY_GBLUR_SOBEL_FILTERING
Apply Gaussian blur + Sobel operator on the input image.
Definition: vpImageFilter.h:91
@ CANNY_GBLUR_SCHARR_FILTERING
Apply Gaussian blur + Scharr operator on the input image.
Definition: vpImageFilter.h:92
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.
Definition: vpImage.h:567
unsigned int getWidth() const
Definition: vpImage.h:242
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:538
unsigned int getHeight() const
Definition: vpImage.h:181