Visual Servoing Platform  version 3.6.1 under development (2025-01-21)
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 
38 BEGIN_VISP_NAMESPACE
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  if (size-1 > I.getWidth() || size-1 > I.getHeight()) {
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);
327  throw vpException(vpException::dimensionError, oss.str());
328  }
329 
330  double *fg = new double[(size + 1) / 2];
331  vpImageFilter::getGaussianKernel(fg, size, sigma, normalize);
332  vpImage<vpRGBa> GIx;
333  vpImageFilter::filterX(I, GIx, fg, size, p_mask);
334  vpImageFilter::filterY(GIx, GI, fg, size, p_mask);
335  GIx.destroy();
336  delete[] fg;
337 }
338 
342 template
343 void vpImageFilter::getGaussianKernel<float>(float *filter, unsigned int size, float sigma, bool normalize);
344 
345 template
346 void vpImageFilter::getGaussianDerivativeKernel<float>(float *filter, unsigned int size, float sigma, bool normalize);
347 
348 template
349 void vpImageFilter::getGaussianDerivativeKernel<double>(double *filter, unsigned int size, double sigma, bool normalize);
350 
351 template
352 void vpImageFilter::getGradX<float>(const vpImage<unsigned char> &I, vpImage<float> &dIx, const vpImage<bool> *p_mask);
353 
354 template
355 void vpImageFilter::getGradX<double>(const vpImage<unsigned char> &I, vpImage<double> &dIx, const vpImage<bool> *p_mask);
356 
357 template
358 void vpImageFilter::getGradY<float>(const vpImage<unsigned char> &I, vpImage<float> &dIy, const vpImage<bool> *p_mask);
359 
360 template
361 void vpImageFilter::getGradY<double>(const vpImage<unsigned char> &I, vpImage<double> &dIy, const vpImage<bool> *p_mask);
362 
363 template
364 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);
365 
366 template
367 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);
368 
369 template
370 void vpImageFilter::getGradX<float, float>(const vpImage<float> &I, vpImage<float> &dIx, const float *filter, unsigned int size, const vpImage<bool> *p_mask);
371 
372 template
373 void vpImageFilter::getGradX<double, double>(const vpImage<double> &I, vpImage<double> &dIx, const double *filter, unsigned int size, const vpImage<bool> *p_mask);
374 
375 template
376 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);
377 
378 template
379 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);
380 
381 template
382 void vpImageFilter::getGradY<float, float>(const vpImage<float> &I, vpImage<float> &dIy, const float *filter, unsigned int size, const vpImage<bool> *p_mask);
383 
384 template
385 void vpImageFilter::getGradY<double, double>(const vpImage<double> &I, vpImage<double> &dIy, const double *filter, unsigned int size, const vpImage<bool> *p_mask);
386 
387 template
388 void vpImageFilter::getGradXGauss2D<unsigned char, float>(const vpImage<unsigned char> &I, vpImage<float> &dIx, const float *gaussianKernel,
389  const float *gaussianDerivativeKernel, unsigned int size, const vpImage<bool> *p_mask);
390 
391 template
392 void vpImageFilter::getGradXGauss2D<unsigned char, double>(const vpImage<unsigned char> &I, vpImage<double> &dIx, const double *gaussianKernel,
393  const double *gaussianDerivativeKernel, unsigned int size, const vpImage<bool> *p_mask);
394 
395 template
396 void vpImageFilter::getGradXGauss2D<float, float>(const vpImage<float> &I, vpImage<float> &dIx, const float *gaussianKernel,
397  const float *gaussianDerivativeKernel, unsigned int size, const vpImage<bool> *p_mask);
398 
399 template
400 void vpImageFilter::getGradXGauss2D<double, double>(const vpImage<double> &I, vpImage<double> &dIx, const double *gaussianKernel,
401  const double *gaussianDerivativeKernel, unsigned int size, const vpImage<bool> *p_mask);
402 
403 template
404 void vpImageFilter::getGradYGauss2D<unsigned char, float>(const vpImage<unsigned char> &I, vpImage<float> &dIy, const float *gaussianKernel,
405  const float *gaussianDerivativeKernel, unsigned int size, const vpImage<bool> *p_mask);
406 
407 template
408 void vpImageFilter::getGradYGauss2D<unsigned char, double>(const vpImage<unsigned char> &I, vpImage<double> &dIy, const double *gaussianKernel,
409  const double *gaussianDerivativeKernel, unsigned int size, const vpImage<bool> *p_mask);
410 
411 template
412 void vpImageFilter::getGradYGauss2D<float, float>(const vpImage<float> &I, vpImage<float> &dIy, const float *gaussianKernel,
413  const float *gaussianDerivativeKernel, unsigned int size, const vpImage<bool> *p_mask);
414 
415 template
416 void vpImageFilter::getGradYGauss2D<double, double>(const vpImage<double> &I, vpImage<double> &dIy, const double *gaussianKernel,
417  const double *gaussianDerivativeKernel, unsigned int size, const vpImage<bool> *p_mask);
422  // Operation for Gaussian pyramid
424 {
426 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC)
427 #if (VISP_HAVE_OPENCV_VERSION >= 0x030000)
428  cv::Mat imgsrc, imgdest;
429  vpImageConvert::convert(I, imgsrc);
430  cv::pyrDown(imgsrc, imgdest, cv::Size((int)I.getWidth() / 2, (int)I.getHeight() / 2));
431  vpImageConvert::convert(imgdest, GI);
432 #else
433  cv::Mat imgsrc, imgdest;
434  vpImageConvert::convert(I, imgsrc);
435  cv::pyrDown(imgsrc, imgdest, cvSize((int)I.getWidth() / 2, (int)I.getHeight() / 2));
436  vpImageConvert::convert(imgdest, GI);
437 #endif
438 #else
441 #endif
442 }
443 
445 {
446  const unsigned int w = I.getWidth() / 2;
447  const unsigned int height = I.getHeight();
448  const unsigned int val_2 = 2;
449 
450  GI.resize(height, w);
451  for (unsigned int i = 0; i < height; ++i) {
452  GI[i][0] = I[i][0];
453  for (unsigned int j = 1; j < (w - 1); ++j) {
454  GI[i][j] = vpImageFilter::filterGaussXPyramidal(I, i, val_2 * j);
455  }
456  GI[i][w - 1] = I[i][(val_2 * w) - 1];
457  }
458 }
459 
461 {
462  const unsigned int h = I.getHeight() / 2;
463  const unsigned int width = I.getWidth();
464  const unsigned int val_2 = 2;
465 
466  GI.resize(h, width);
467  for (unsigned int j = 0; j < width; ++j) {
468  GI[0][j] = I[0][j];
469  for (unsigned int i = 1; i < (h - 1); ++i) {
470  GI[i][j] = vpImageFilter::filterGaussYPyramidal(I, val_2 * i, j);
471  }
472  GI[h - 1][j] = I[(val_2 * h) - 1][j];
473  }
474 }
475 
479 template
480 double vpImageFilter::getSobelKernelX<double>(double *filter, unsigned int size);
481 
482 template
483 float vpImageFilter::getSobelKernelX<float>(float *filter, unsigned int size);
484 
485 template
486 double vpImageFilter::getSobelKernelY<double>(double *filter, unsigned int size);
487 
488 template
489 float vpImageFilter::getSobelKernelY<float>(float *filter, unsigned int size);
495 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC)
501 float vpImageFilter::median(const cv::Mat &channel)
502 {
503  float m = (channel.rows * channel.cols) / 2.f;
504  int bin = 0;
505  float med = -1.0f;
506 
507  int histSize = 256;
508  float range[] = { 0, 256 };
509  const float *histRange = { range };
510  bool uniform = true;
511  bool accumulate = false;
512  cv::Mat hist;
513  cv::calcHist(&channel, 1, 0, cv::Mat(), hist, 1, &histSize, &histRange, uniform, accumulate);
514 
515  int i = 0;
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);
520  }
521  ++i;
522  }
523 
524  return med;
525 }
526 
535 {
536  cv::Mat cv_I;
537  vpImageConvert::convert(Isrc, cv_I);
538  return median(cv_I);
539 }
540 
549 std::vector<float> vpImageFilter::median(const vpImage<vpRGBa> &Isrc)
550 {
551  cv::Mat cv_I_bgr;
552  vpImageConvert::convert(Isrc, cv_I_bgr);
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 }; // To keep the order R, G, B
557  const int orderCvChannels[] = { 0, 1, 2 }; // Because the order of the cv::Mat is B, G, R
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]]);
561  }
562  return meds;
563 }
564 
565 
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,
588 {
589  if ((filteringType == vpImageFilter::CANNY_GBLUR_SCHARR_FILTERING)
590  || (filteringType == vpImageFilter::CANNY_GBLUR_SOBEL_FILTERING)) {
591  cv::Mat img_blur;
592  // Apply Gaussian blur to the image
593  cv::Size gsz(gaussianKernelSize, gaussianKernelSize);
594  cv::GaussianBlur(cv_I, img_blur, gsz, gaussianStdev);
595 
596  // Compute the gradient of the blurred image
597  if (filteringType == vpImageFilter::CANNY_GBLUR_SOBEL_FILTERING) {
598  double scale = 1.;
599  if (normalize) {
600  scale = 1. / 8.;
601  if (apertureGradient > 3) {
602  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
603  }
604  }
605  if (computeDx) {
606  cv::Sobel(img_blur, cv_dIx, CV_16S, 1, 0, apertureGradient, scale, 0., cv::BORDER_REPLICATE);
607  }
608  if (computeDy) {
609  cv::Sobel(img_blur, cv_dIy, CV_16S, 0, 1, apertureGradient, scale, 0., cv::BORDER_REPLICATE);
610  }
611  }
612  else if (filteringType == vpImageFilter::CANNY_GBLUR_SCHARR_FILTERING) {
613  double scale = 1.;
614  if (normalize) {
615  scale = 1. / 32.;
616  }
617  if (computeDx) {
618  cv::Scharr(img_blur, cv_dIx, CV_16S, 1, 0, scale);
619  }
620  if (computeDy) {
621  cv::Scharr(img_blur, cv_dIy, CV_16S, 0, 1, scale);
622  }
623  }
624  }
625 }
626 #endif
627 
631 template
632 void vpImageFilter::computePartialDerivatives<unsigned char, float>(const vpImage<unsigned char> &I,
633  vpImage<float> &dIx, vpImage<float> &dIy,
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);
639 
640 template
641 void vpImageFilter::computePartialDerivatives<unsigned char, double>(const vpImage<unsigned char> &I,
642  vpImage<double> &dIx, vpImage<double> &dIy,
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);
648 
649 template
650 void vpImageFilter::computePartialDerivatives<float, float>(const vpImage<float> &I,
651  vpImage<float> &dIx, vpImage<float> &dIy,
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);
657 
658 template
659 void vpImageFilter::computePartialDerivatives<float, double>(const vpImage<float> &I,
660  vpImage<double> &dIx, vpImage<double> &dIy,
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);
666 
667 template
668 void vpImageFilter::computePartialDerivatives<double, float>(const vpImage<double> &I,
669  vpImage<float> &dIx, vpImage<float> &dIy,
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);
675 
676 template
677 void vpImageFilter::computePartialDerivatives<double, double>(const vpImage<double> &I,
678  vpImage<double> &dIx, vpImage<double> &dIy,
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);
684 
685 template
686 float vpImageFilter::computeCannyThreshold<double>(const vpImage<unsigned char> &I, float &lowerThresh,
687  const vpImage<double> *p_dIx, const vpImage<double> *p_dIy,
688  const unsigned int &gaussianKernelSize,
689  const double &gaussianStdev, const unsigned int &apertureGradient,
690  const float &lowerThresholdRatio, const float &upperThresholdRatio,
692  const vpImage<bool> *p_mask);
693 
694 template
695 float vpImageFilter::computeCannyThreshold<float>(const vpImage<unsigned char> &I, float &lowerThresh,
696  const vpImage<float> *p_dIx, const vpImage<float> *p_dIy,
697  const unsigned int &gaussianKernelSize,
698  const float &gaussianStdev, const unsigned int &apertureGradient,
699  const float &lowerThresholdRatio, const float &upperThresholdRatio,
701  const vpImage<bool> *p_mask);
706 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
error that can be emitted by ViSP classes.
Definition: vpException.h:60
@ dimensionError
Bad dimension.
Definition: vpException.h:71
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:92
@ CANNY_GBLUR_SOBEL_FILTERING
Apply Gaussian blur + Sobel operator on the input image.
Definition: vpImageFilter.h:93
@ CANNY_GBLUR_SCHARR_FILTERING
Apply Gaussian blur + Scharr operator on the input image.
Definition: vpImageFilter.h:94
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:573
unsigned int getWidth() const
Definition: vpImage.h:242
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:544
unsigned int getHeight() const
Definition: vpImage.h:181