Visual Servoing Platform  version 3.5.1 under development (2023-09-22)
vpImageFilter.h
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2023 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 #ifndef _vpImageFilter_h_
35 #define _vpImageFilter_h_
36 
43 #include <fstream>
44 #include <iostream>
45 #include <math.h>
46 #include <string.h>
47 
48 #include <visp3/core/vpImage.h>
49 #include <visp3/core/vpImageException.h>
50 #include <visp3/core/vpMath.h>
51 #include <visp3/core/vpMatrix.h>
52 #include <visp3/core/vpRGBa.h>
53 
54 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC)
55 #include <opencv2/imgproc/imgproc.hpp>
56 #include <opencv2/imgproc/imgproc_c.h>
57 #endif
58 
67 class VISP_EXPORT vpImageFilter
68 {
69 public:
70  static void canny(const vpImage<unsigned char> &I, vpImage<unsigned char> &Ic, unsigned int gaussianFilterSize,
71  float thresholdCanny, unsigned int apertureSobel);
72 
73  static void canny(const vpImage<unsigned char> &I, vpImage<unsigned char> &Ic, unsigned int gaussianFilterSize,
74  float lowerThresholdCanny, float higherThresholdCanny, unsigned int apertureSobel);
75 
83  template <class T> static double derivativeFilterX(const vpImage<T> &I, unsigned int r, unsigned int c)
84  {
85  return (2047.0 * (I[r][c + 1] - I[r][c - 1]) + 913.0 * (I[r][c + 2] - I[r][c - 2]) +
86  112.0 * (I[r][c + 3] - I[r][c - 3])) / 8418.0;
87  }
88 
96  template <class T> static double derivativeFilterY(const vpImage<T> &I, unsigned int r, unsigned int c)
97  {
98  return (2047.0 * (I[r + 1][c] - I[r - 1][c]) + 913.0 * (I[r + 2][c] - I[r - 2][c]) +
99  112.0 * (I[r + 3][c] - I[r - 3][c])) / 8418.0;
100  }
101 
115  template <class T, typename FilterType>
116  static FilterType derivativeFilterX(const vpImage<T> &I, unsigned int r, unsigned int c, const FilterType *filter, unsigned int size)
117  {
118  unsigned int i;
119  FilterType result;
120 
121  result = 0;
122 
123  for (i = 1; i <= (size - 1) / 2; i++) {
124  result += filter[i] * (I[r][c + i] - I[r][c - i]);
125  }
126  return result;
127  }
128 
142  template <class T, typename FilterType>
143  static FilterType derivativeFilterY(const vpImage<T> &I, unsigned int r, unsigned int c, const FilterType *filter, unsigned int size)
144  {
145  unsigned int i;
146  FilterType result;
147 
148  result = 0;
149 
150  for (i = 1; i <= (size - 1) / 2; i++) {
151  result += filter[i] * (I[r + i][c] - I[r - i][c]);
152  }
153  return result;
154  }
155 
184  template <typename FilterType>
185  static void filter(const vpImage<unsigned char> &I, vpImage<FilterType> &If, const vpArray2D<FilterType> &M, bool convolve = false)
186  {
187  unsigned int size_y = M.getRows(), size_x = M.getCols();
188  unsigned int half_size_y = size_y / 2, half_size_x = size_x / 2;
189 
190  If.resize(I.getHeight(), I.getWidth(), 0.0);
191 
192  if (convolve) {
193  for (unsigned int i = half_size_y; i < I.getHeight() - half_size_y; i++) {
194  for (unsigned int j = half_size_x; j < I.getWidth() - half_size_x; j++) {
195  FilterType conv = 0;
196 
197  for (unsigned int a = 0; a < size_y; a++) {
198  for (unsigned int b = 0; b < size_x; b++) {
199  FilterType val = I[i + half_size_y - a][j + half_size_x - b]; // Convolution
200  conv += M[a][b] * val;
201  }
202  }
203  If[i][j] = conv;
204  }
205  }
206  }
207  else {
208  for (unsigned int i = half_size_y; i < I.getHeight() - half_size_y; i++) {
209  for (unsigned int j = half_size_x; j < I.getWidth() - half_size_x; j++) {
210  FilterType corr = 0;
211 
212  for (unsigned int a = 0; a < size_y; a++) {
213  for (unsigned int b = 0; b < size_x; b++) {
214  FilterType val = I[i - half_size_y + a][j - half_size_x + b]; // Correlation
215  corr += M[a][b] * val;
216  }
217  }
218  If[i][j] = corr;
219  }
220  }
221  }
222  }
223 
236  template <typename FilterType>
238  bool convolve = false)
239  {
240  unsigned int size = M.getRows();
241  unsigned int half_size = size / 2;
242 
243  Iu.resize(I.getHeight(), I.getWidth(), 0.0);
244  Iv.resize(I.getHeight(), I.getWidth(), 0.0);
245 
246  if (convolve) {
247  for (unsigned int v = half_size; v < I.getHeight() - half_size; v++) {
248  for (unsigned int u = half_size; u < I.getWidth() - half_size; u++) {
249  FilterType conv_u = 0;
250  FilterType conv_v = 0;
251 
252  for (unsigned int a = 0; a < size; a++) {
253  for (unsigned int b = 0; b < size; b++) {
254  FilterType val = I[v + half_size - a][u + half_size - b]; // Convolution
255  conv_u += M[a][b] * val;
256  conv_v += M[b][a] * val;
257  }
258  }
259  Iu[v][u] = conv_u;
260  Iv[v][u] = conv_v;
261  }
262  }
263  }
264  else {
265  for (unsigned int v = half_size; v < I.getHeight() - half_size; v++) {
266  for (unsigned int u = half_size; u < I.getWidth() - half_size; u++) {
267  FilterType conv_u = 0;
268  FilterType conv_v = 0;
269 
270  for (unsigned int a = 0; a < size; a++) {
271  for (unsigned int b = 0; b < size; b++) {
272  FilterType val = I[v - half_size + a][u - half_size + b]; // Correlation
273  conv_u += M[a][b] * val;
274  conv_v += M[b][a] * val;
275  }
276  }
277  Iu[v][u] = conv_u;
278  Iv[v][u] = conv_v;
279  }
280  }
281  }
282  }
283 
284  static void sepFilter(const vpImage<unsigned char> &I, vpImage<double> &If, const vpColVector &kernelH, const vpColVector &kernelV);
285 
294  template <typename FilterType>
295  static void filter(const vpImage<unsigned char> &I, vpImage<FilterType> &GI, const FilterType *filter, unsigned int size)
296  {
298  filterX<FilterType>(I, GIx, filter, size);
299  filterY<FilterType>(GIx, GI, filter, size);
300  GIx.destroy();
301  }
302 
311  template <typename FilterType>
312  static void filter(const vpImage<FilterType> &I, vpImage<FilterType> &GI, const FilterType *filter, unsigned int size)
313  {
315  filterX<FilterType>(I, GIx, filter, size);
316  filterY<FilterType>(GIx, GI, filter, size);
317  GIx.destroy();
318  }
319 
320  static inline unsigned char filterGaussXPyramidal(const vpImage<unsigned char> &I, unsigned int i, unsigned int j)
321  {
322  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.);
323  }
324  static inline unsigned char filterGaussYPyramidal(const vpImage<unsigned char> &I, unsigned int i, unsigned int j)
325  {
326  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.);
327  }
328 
329  template <typename FilterType>
330  static void filterX(const vpImage<unsigned char> &I, vpImage<FilterType> &dIx, const FilterType *filter, unsigned int size)
331  {
332  dIx.resize(I.getHeight(), I.getWidth());
333  for (unsigned int i = 0; i < I.getHeight(); i++) {
334  for (unsigned int j = 0; j < (size - 1) / 2; j++) {
335  dIx[i][j] = vpImageFilter::filterXLeftBorder<FilterType>(I, i, j, filter, size);
336  }
337  for (unsigned int j = (size - 1) / 2; j < I.getWidth() - (size - 1) / 2; j++) {
338  dIx[i][j] = vpImageFilter::filterX<FilterType>(I, i, j, filter, size);
339  }
340  for (unsigned int j = I.getWidth() - (size - 1) / 2; j < I.getWidth(); j++) {
341  dIx[i][j] = vpImageFilter::filterXRightBorder<FilterType>(I, i, j, filter, size);
342  }
343  }
344  }
345 
346  template<typename FilterType>
347  static void filterX(const vpImage<FilterType> &I, vpImage<FilterType> &dIx, const FilterType *filter, unsigned int size)
348  {
349  dIx.resize(I.getHeight(), I.getWidth());
350  for (unsigned int i = 0; i < I.getHeight(); i++) {
351  for (unsigned int j = 0; j < (size - 1) / 2; j++) {
352  dIx[i][j] = vpImageFilter::filterXLeftBorder<FilterType>(I, i, j, filter, size);
353  }
354  for (unsigned int j = (size - 1) / 2; j < I.getWidth() - (size - 1) / 2; j++) {
355  dIx[i][j] = vpImageFilter::filterX<FilterType>(I, i, j, filter, size);
356  }
357  for (unsigned int j = I.getWidth() - (size - 1) / 2; j < I.getWidth(); j++) {
358  dIx[i][j] = vpImageFilter::filterXRightBorder<FilterType>(I, i, j, filter, size);
359  }
360  }
361  }
362 
363  static void filterX(const vpImage<vpRGBa> &I, vpImage<vpRGBa> &dIx, const double *filter, unsigned int size);
364  static void filterXR(const vpImage<vpRGBa> &I, vpImage<vpRGBa> &dIx, const double *filter, unsigned int size);
365  static void filterXG(const vpImage<vpRGBa> &I, vpImage<vpRGBa> &dIx, const double *filter, unsigned int size);
366  static void filterXB(const vpImage<vpRGBa> &I, vpImage<vpRGBa> &dIx, const double *filter, unsigned int size);
367 
368  template<typename FilterType>
369  static inline FilterType filterX(const vpImage<unsigned char> &I, unsigned int r, unsigned int c, const FilterType *filter, unsigned int size)
370  {
371  FilterType result;
372 
373  result = 0;
374 
375  for (unsigned int i = 1; i <= (size - 1) / 2; i++) {
376  result += filter[i] * (I[r][c + i] + I[r][c - i]);
377  }
378  return result + filter[0] * I[r][c];
379  }
380 
381  static inline double filterXR(const vpImage<vpRGBa> &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
382  {
383  double result;
384 
385  result = 0;
386 
387  for (unsigned int i = 1; i <= (size - 1) / 2; i++) {
388  result += filter[i] * (I[r][c + i].R + I[r][c - i].R);
389  }
390  return result + filter[0] * I[r][c].R;
391  }
392 
393  static inline double filterXG(const vpImage<vpRGBa> &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
394  {
395  double result;
396 
397  result = 0;
398 
399  for (unsigned int i = 1; i <= (size - 1) / 2; i++) {
400  result += filter[i] * (I[r][c + i].G + I[r][c - i].G);
401  }
402  return result + filter[0] * I[r][c].G;
403  }
404 
405  static inline double filterXB(const vpImage<vpRGBa> &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
406  {
407  double result;
408 
409  result = 0;
410 
411  for (unsigned int i = 1; i <= (size - 1) / 2; i++) {
412  result += filter[i] * (I[r][c + i].B + I[r][c - i].B);
413  }
414  return result + filter[0] * I[r][c].B;
415  }
416 
417  template <typename FilterType>
418  static inline FilterType filterXLeftBorder(const vpImage<unsigned char> &I, unsigned int r, unsigned int c,
419  const FilterType *filter, unsigned int size)
420  {
421  FilterType result;
422 
423  result = 0;
424 
425  for (unsigned int i = 1; i <= (size - 1) / 2; i++) {
426  if (c > i)
427  result += filter[i] * (I[r][c + i] + I[r][c - i]);
428  else
429  result += filter[i] * (I[r][c + i] + I[r][i - c]);
430  }
431  return result + filter[0] * I[r][c];
432  }
433 
434  static inline double filterXLeftBorderR(const vpImage<vpRGBa> &I, unsigned int r, unsigned int c,
435  const double *filter, unsigned int size)
436  {
437  double result;
438 
439  result = 0;
440 
441  for (unsigned int i = 1; i <= (size - 1) / 2; i++) {
442  if (c > i)
443  result += filter[i] * (I[r][c + i].R + I[r][c - i].R);
444  else
445  result += filter[i] * (I[r][c + i].R + I[r][i - c].R);
446  }
447  return result + filter[0] * I[r][c].R;
448  }
449 
450  static inline double filterXLeftBorderG(const vpImage<vpRGBa> &I, unsigned int r, unsigned int c,
451  const double *filter, unsigned int size)
452  {
453  double result;
454 
455  result = 0;
456 
457  for (unsigned int i = 1; i <= (size - 1) / 2; i++) {
458  if (c > i)
459  result += filter[i] * (I[r][c + i].G + I[r][c - i].G);
460  else
461  result += filter[i] * (I[r][c + i].G + I[r][i - c].G);
462  }
463  return result + filter[0] * I[r][c].G;
464  }
465 
466  static inline double filterXLeftBorderB(const vpImage<vpRGBa> &I, unsigned int r, unsigned int c,
467  const double *filter, unsigned int size)
468  {
469  double result;
470 
471  result = 0;
472 
473  for (unsigned int i = 1; i <= (size - 1) / 2; i++) {
474  if (c > i)
475  result += filter[i] * (I[r][c + i].B + I[r][c - i].B);
476  else
477  result += filter[i] * (I[r][c + i].B + I[r][i - c].B);
478  }
479  return result + filter[0] * I[r][c].B;
480  }
481 
482  template <typename FilterType>
483  static inline FilterType filterXRightBorder(const vpImage<unsigned char> &I, unsigned int r, unsigned int c,
484  const FilterType *filter, unsigned int size)
485  {
486  FilterType result;
487 
488  result = 0;
489 
490  for (unsigned int i = 1; i <= (size - 1) / 2; i++) {
491  if (c + i < I.getWidth())
492  result += filter[i] * (I[r][c + i] + I[r][c - i]);
493  else
494  result += filter[i] * (I[r][2 * I.getWidth() - c - i - 1] + I[r][c - i]);
495  }
496  return result + filter[0] * I[r][c];
497  }
498 
499  static inline double filterXRightBorderR(const vpImage<vpRGBa> &I, unsigned int r, unsigned int c,
500  const double *filter, unsigned int size)
501  {
502  double result;
503 
504  result = 0;
505 
506  for (unsigned int i = 1; i <= (size - 1) / 2; i++) {
507  if (c + i < I.getWidth())
508  result += filter[i] * (I[r][c + i].R + I[r][c - i].R);
509  else
510  result += filter[i] * (I[r][2 * I.getWidth() - c - i - 1].R + I[r][c - i].R);
511  }
512  return result + filter[0] * I[r][c].R;
513  }
514 
515  static inline double filterXRightBorderG(const vpImage<vpRGBa> &I, unsigned int r, unsigned int c,
516  const double *filter, unsigned int size)
517  {
518  double result;
519 
520  result = 0;
521 
522  for (unsigned int i = 1; i <= (size - 1) / 2; i++) {
523  if (c + i < I.getWidth())
524  result += filter[i] * (I[r][c + i].G + I[r][c - i].G);
525  else
526  result += filter[i] * (I[r][2 * I.getWidth() - c - i - 1].G + I[r][c - i].G);
527  }
528  return result + filter[0] * I[r][c].G;
529  }
530 
531  static inline double filterXRightBorderB(const vpImage<vpRGBa> &I, unsigned int r, unsigned int c,
532  const double *filter, unsigned int size)
533  {
534  double result;
535 
536  result = 0;
537 
538  for (unsigned int i = 1; i <= (size - 1) / 2; i++) {
539  if (c + i < I.getWidth())
540  result += filter[i] * (I[r][c + i].B + I[r][c - i].B);
541  else
542  result += filter[i] * (I[r][2 * I.getWidth() - c - i - 1].B + I[r][c - i].B);
543  }
544  return result + filter[0] * I[r][c].B;
545  }
546 
547  template <typename FilterType>
548  static inline FilterType filterX(const vpImage<FilterType> &I, unsigned int r, unsigned int c,
549  const FilterType *filter, unsigned int size)
550  {
551  FilterType result;
552 
553  result = 0;
554 
555  for (unsigned int i = 1; i <= (size - 1) / 2; i++) {
556  result += filter[i] * (I[r][c + i] + I[r][c - i]);
557  }
558  return result + filter[0] * I[r][c];
559  }
560 
561  template <typename FilterType>
562  static inline FilterType filterXLeftBorder(const vpImage<FilterType> &I, unsigned int r, unsigned int c,
563  const FilterType *filter, unsigned int size)
564  {
565  FilterType result;
566 
567  result = 0;
568 
569  for (unsigned int i = 1; i <= (size - 1) / 2; i++) {
570  if (c > i)
571  result += filter[i] * (I[r][c + i] + I[r][c - i]);
572  else
573  result += filter[i] * (I[r][c + i] + I[r][i - c]);
574  }
575  return result + filter[0] * I[r][c];
576  }
577 
578  template <typename FilterType>
579  static inline FilterType filterXRightBorder(const vpImage<FilterType> &I, unsigned int r, unsigned int c,
580  const FilterType *filter, unsigned int size)
581  {
582  FilterType result;
583 
584  result = 0;
585 
586  for (unsigned int i = 1; i <= (size - 1) / 2; i++) {
587  if (c + i < I.getWidth())
588  result += filter[i] * (I[r][c + i] + I[r][c - i]);
589  else
590  result += filter[i] * (I[r][2 * I.getWidth() - c - i - 1] + I[r][c - i]);
591  }
592  return result + filter[0] * I[r][c];
593  }
594 
595  template <typename FilterType>
596  static void filterY(const vpImage<unsigned char> &I, vpImage<FilterType> &dIy, const FilterType *filter, unsigned int size)
597  {
598  dIy.resize(I.getHeight(), I.getWidth());
599  for (unsigned int i = 0; i < (size - 1) / 2; i++) {
600  for (unsigned int j = 0; j < I.getWidth(); j++) {
601  dIy[i][j] = vpImageFilter::filterYTopBorder<FilterType>(I, i, j, filter, size);
602  }
603  }
604  for (unsigned int i = (size - 1) / 2; i < I.getHeight() - (size - 1) / 2; i++) {
605  for (unsigned int j = 0; j < I.getWidth(); j++) {
606  dIy[i][j] = vpImageFilter::filterY<FilterType>(I, i, j, filter, size);
607  }
608  }
609  for (unsigned int i = I.getHeight() - (size - 1) / 2; i < I.getHeight(); i++) {
610  for (unsigned int j = 0; j < I.getWidth(); j++) {
611  dIy[i][j] = vpImageFilter::filterYBottomBorder<FilterType>(I, i, j, filter, size);
612  }
613  }
614  }
615 
616  static void filterY(const vpImage<vpRGBa> &I, vpImage<vpRGBa> &dIx, const double *filter, unsigned int size);
617  static void filterYR(const vpImage<vpRGBa> &I, vpImage<vpRGBa> &dIx, const double *filter, unsigned int size);
618  static void filterYG(const vpImage<vpRGBa> &I, vpImage<vpRGBa> &dIx, const double *filter, unsigned int size);
619  static void filterYB(const vpImage<vpRGBa> &I, vpImage<vpRGBa> &dIx, const double *filter, unsigned int size);
620 
621  template<typename FilterType>
622  static void filterY(const vpImage<FilterType> &I, vpImage<FilterType> &dIy, const FilterType *filter, unsigned int size)
623  {
624  dIy.resize(I.getHeight(), I.getWidth());
625  for (unsigned int i = 0; i < (size - 1) / 2; i++) {
626  for (unsigned int j = 0; j < I.getWidth(); j++) {
627  dIy[i][j] = vpImageFilter::filterYTopBorder<FilterType>(I, i, j, filter, size);
628  }
629  }
630  for (unsigned int i = (size - 1) / 2; i < I.getHeight() - (size - 1) / 2; i++) {
631  for (unsigned int j = 0; j < I.getWidth(); j++) {
632  dIy[i][j] = vpImageFilter::filterY<FilterType>(I, i, j, filter, size);
633  }
634  }
635  for (unsigned int i = I.getHeight() - (size - 1) / 2; i < I.getHeight(); i++) {
636  for (unsigned int j = 0; j < I.getWidth(); j++) {
637  dIy[i][j] = vpImageFilter::filterYBottomBorder<FilterType>(I, i, j, filter, size);
638  }
639  }
640  }
641 
642  template<typename FilterType>
643  static inline FilterType filterY(const vpImage<unsigned char> &I, unsigned int r, unsigned int c, const FilterType *filter, unsigned int size)
644  {
645  FilterType result;
646 
647  result = 0;
648 
649  for (unsigned int i = 1; i <= (size - 1) / 2; i++) {
650  result += filter[i] * (I[r + i][c] + I[r - i][c]);
651  }
652  return result + filter[0] * I[r][c];
653  }
654 
655  static inline double filterYR(const vpImage<vpRGBa> &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
656  {
657  double result;
658 
659  result = 0;
660 
661  for (unsigned int i = 1; i <= (size - 1) / 2; i++) {
662  result += filter[i] * (I[r + i][c].R + I[r - i][c].R);
663  }
664  return result + filter[0] * I[r][c].R;
665  }
666  static inline double filterYG(const vpImage<vpRGBa> &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
667  {
668  double result;
669 
670  result = 0;
671 
672  for (unsigned int i = 1; i <= (size - 1) / 2; i++) {
673  result += filter[i] * (I[r + i][c].G + I[r - i][c].G);
674  }
675  return result + filter[0] * I[r][c].G;
676  }
677 
678  static inline double filterYB(const vpImage<vpRGBa> &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
679  {
680  double result;
681 
682  result = 0;
683 
684  for (unsigned int i = 1; i <= (size - 1) / 2; i++) {
685  result += filter[i] * (I[r + i][c].B + I[r - i][c].B);
686  }
687  return result + filter[0] * I[r][c].B;
688  }
689 
690  template<typename FilterType>
691  static inline FilterType filterYTopBorder(const vpImage<unsigned char> &I, unsigned int r, unsigned int c,
692  const FilterType *filter, unsigned int size)
693  {
694  FilterType result;
695 
696  result = 0;
697 
698  for (unsigned int i = 1; i <= (size - 1) / 2; i++) {
699  if (r > i)
700  result += filter[i] * (I[r + i][c] + I[r - i][c]);
701  else
702  result += filter[i] * (I[r + i][c] + I[i - r][c]);
703  }
704  return result + filter[0] * I[r][c];
705  }
706 
707  double static inline filterYTopBorderR(const vpImage<vpRGBa> &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
708  {
709  double result;
710 
711  result = 0;
712 
713  for (unsigned int i = 1; i <= (size - 1) / 2; i++) {
714  if (r > i)
715  result += filter[i] * (I[r + i][c].R + I[r - i][c].R);
716  else
717  result += filter[i] * (I[r + i][c].R + I[i - r][c].R);
718  }
719  return result + filter[0] * I[r][c].R;
720  }
721 
722  double static inline filterYTopBorderG(const vpImage<vpRGBa> &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
723  {
724  double result;
725 
726  result = 0;
727 
728  for (unsigned int i = 1; i <= (size - 1) / 2; i++) {
729  if (r > i)
730  result += filter[i] * (I[r + i][c].G + I[r - i][c].G);
731  else
732  result += filter[i] * (I[r + i][c].G + I[i - r][c].G);
733  }
734  return result + filter[0] * I[r][c].G;
735  }
736 
737  double static inline filterYTopBorderB(const vpImage<vpRGBa> &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
738  {
739  double result;
740 
741  result = 0;
742 
743  for (unsigned int i = 1; i <= (size - 1) / 2; i++) {
744  if (r > i)
745  result += filter[i] * (I[r + i][c].B + I[r - i][c].B);
746  else
747  result += filter[i] * (I[r + i][c].B + I[i - r][c].B);
748  }
749  return result + filter[0] * I[r][c].B;
750  }
751 
752  template<typename FilterType>
753  static inline FilterType filterYBottomBorder(const vpImage<unsigned char> &I, unsigned int r, unsigned int c,
754  const FilterType *filter, unsigned int size)
755  {
756  FilterType result;
757 
758  result = 0;
759 
760  for (unsigned int i = 1; i <= (size - 1) / 2; i++) {
761  if (r + i < I.getHeight())
762  result += filter[i] * (I[r + i][c] + I[r - i][c]);
763  else
764  result += filter[i] * (I[2 * I.getHeight() - r - i - 1][c] + I[r - i][c]);
765  }
766  return result + filter[0] * I[r][c];
767  }
768 
769  double static inline filterYBottomBorderR(const vpImage<vpRGBa> &I, unsigned int r, unsigned int c,
770  const double *filter, unsigned int size)
771  {
772  double result;
773 
774  result = 0;
775 
776  for (unsigned int i = 1; i <= (size - 1) / 2; i++) {
777  if (r + i < I.getHeight())
778  result += filter[i] * (I[r + i][c].R + I[r - i][c].R);
779  else
780  result += filter[i] * (I[2 * I.getHeight() - r - i - 1][c].R + I[r - i][c].R);
781  }
782  return result + filter[0] * I[r][c].R;
783  }
784 
785  double static inline filterYBottomBorderG(const vpImage<vpRGBa> &I, unsigned int r, unsigned int c,
786  const double *filter, unsigned int size)
787  {
788  double result;
789 
790  result = 0;
791 
792  for (unsigned int i = 1; i <= (size - 1) / 2; i++) {
793  if (r + i < I.getHeight())
794  result += filter[i] * (I[r + i][c].G + I[r - i][c].G);
795  else
796  result += filter[i] * (I[2 * I.getHeight() - r - i - 1][c].G + I[r - i][c].G);
797  }
798  return result + filter[0] * I[r][c].G;
799  }
800 
801  double static inline filterYBottomBorderB(const vpImage<vpRGBa> &I, unsigned int r, unsigned int c,
802  const double *filter, unsigned int size)
803  {
804  double result;
805 
806  result = 0;
807 
808  for (unsigned int i = 1; i <= (size - 1) / 2; i++) {
809  if (r + i < I.getHeight())
810  result += filter[i] * (I[r + i][c].B + I[r - i][c].B);
811  else
812  result += filter[i] * (I[2 * I.getHeight() - r - i - 1][c].B + I[r - i][c].B);
813  }
814  return result + filter[0] * I[r][c].B;
815  }
816 
817  template<typename FilterType>
818  static inline FilterType filterYTopBorder(const vpImage<double> &I, unsigned int r, unsigned int c,
819  const FilterType *filter, unsigned int size)
820  {
821  FilterType result;
822 
823  result = 0;
824 
825  for (unsigned int i = 1; i <= (size - 1) / 2; i++) {
826  if (r > i)
827  result += filter[i] * (I[r + i][c] + I[r - i][c]);
828  else
829  result += filter[i] * (I[r + i][c] + I[i - r][c]);
830  }
831  return result + filter[0] * I[r][c];
832  }
833 
834  template<typename FilterType>
835  static inline FilterType filterYBottomBorder(const vpImage<double> &I, unsigned int r, unsigned int c,
836  const FilterType *filter, unsigned int size)
837  {
838  FilterType result;
839 
840  result = 0;
841 
842  for (unsigned int i = 1; i <= (size - 1) / 2; i++) {
843  if (r + i < I.getHeight())
844  result += filter[i] * (I[r + i][c] + I[r - i][c]);
845  else
846  result += filter[i] * (I[2 * I.getHeight() - r - i - 1][c] + I[r - i][c]);
847  }
848  return result + filter[0] * I[r][c];
849  }
850 
851  template<typename FilterType>
852  static inline FilterType filterY(const vpImage<double> &I, unsigned int r, unsigned int c,
853  const FilterType *filter, unsigned int size)
854  {
855  FilterType result;
856 
857  result = 0;
858 
859  for (unsigned int i = 1; i <= (size - 1) / 2; i++) {
860  result += filter[i] * (I[r + i][c] + I[r - i][c]);
861  }
862  return result + filter[0] * I[r][c];
863  }
864 
877  template <typename FilterType>
878  static void gaussianBlur(const vpImage<unsigned char> &I, vpImage<FilterType> &GI, unsigned int size = 7, FilterType sigma = 0., bool normalize = true)
879  {
880  FilterType *fg = new FilterType[(size + 1) / 2];
881  vpImageFilter::getGaussianKernel<FilterType>(fg, size, sigma, normalize);
883  vpImageFilter::filterX<FilterType>(I, GIx, fg, size);
884  vpImageFilter::filterY<FilterType>(GIx, GI, fg, size);
885  GIx.destroy();
886  delete[] fg;
887  }
888 
889  static void gaussianBlur(const vpImage<vpRGBa> &I, vpImage<vpRGBa> &GI, unsigned int size = 7, double sigma = 0., bool normalize = true);
890 
903  template <typename FilterType>
904  static void gaussianBlur(const vpImage<FilterType> &I, vpImage<FilterType> &GI, unsigned int size = 7, FilterType sigma = 0., bool normalize = true)
905  {
906  FilterType *fg = new FilterType[(size + 1) / 2];
907  vpImageFilter::getGaussianKernel<FilterType>(fg, size, sigma, normalize);
909  vpImageFilter::filterX<FilterType>(I, GIx, fg, size);
910  vpImageFilter::filterY<FilterType>(GIx, GI, fg, size);
911  GIx.destroy();
912  delete[] fg;
913  }
914 
922  template <class T> static double gaussianFilter(const vpImage<T> &fr, unsigned int r, unsigned int c)
923  {
924  return (15.0 * fr[r][c] + 12.0 * (fr[r - 1][c] + fr[r][c - 1] + fr[r + 1][c] + fr[r][c + 1]) +
925  9.0 * (fr[r - 1][c - 1] + fr[r + 1][c - 1] + fr[r - 1][c + 1] + fr[r + 1][c + 1]) +
926  5.0 * (fr[r - 2][c] + fr[r][c - 2] + fr[r + 2][c] + fr[r][c + 2]) +
927  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] +
928  fr[r + 2][c + 1] + fr[r - 1][c + 2] + fr[r + 1][c + 2]) +
929  2.0 * (fr[r - 2][c - 2] + fr[r + 2][c - 2] + fr[r - 2][c + 2] + fr[r + 2][c + 2])) / 159.0;
930  }
931  // Gaussian pyramid operation
932  static void getGaussPyramidal(const vpImage<unsigned char> &I, vpImage<unsigned char> &GI);
933  static void getGaussXPyramidal(const vpImage<unsigned char> &I, vpImage<unsigned char> &GI);
934  static void getGaussYPyramidal(const vpImage<unsigned char> &I, vpImage<unsigned char> &GI);
935 
952  template<typename FilterType>
953  static void getGaussianKernel(FilterType *filter, unsigned int size, FilterType sigma = 0., bool normalize = true)
954  {
955  if (size % 2 != 1)
956  throw(vpImageException(vpImageException::incorrectInitializationError, "Bad Gaussian filter size"));
957 
958  if (sigma <= 0)
959  sigma = static_cast<FilterType>((size - 1) / 6.0);
960 
961  int middle = (int)(size - 1) / 2;
962  FilterType sigma2 = static_cast<FilterType>(vpMath::sqr(sigma));
963  FilterType coef1 = static_cast<FilterType>(1. / (sigma * sqrt(2. * M_PI)));
964  FilterType _2_sigma2 = static_cast<FilterType>(2. * sigma2);
965  for (int i = 0; i <= middle; i++) {
966  filter[i] = coef1 * exp(-(i * i) / _2_sigma2);
967  }
968  if (normalize) {
969  // renormalization
970  FilterType sum = 0;
971  for (int i = 1; i <= middle; i++) {
972  sum += 2 * filter[i];
973  }
974  sum += filter[0];
975 
976  for (int i = 0; i <= middle; i++) {
977  filter[i] = filter[i] / sum;
978  }
979  }
980  }
981 
996  template <typename FilterType>
997  static void getGaussianDerivativeKernel(FilterType *filter, unsigned int size, FilterType sigma = 0., bool normalize = true)
998  {
999  if (size % 2 != 1)
1000  throw(vpImageException(vpImageException::incorrectInitializationError, "Bad Gaussian filter size"));
1001 
1002  if (sigma <= 0)
1003  sigma = static_cast<FilterType>((size - 1) / 6.0);
1004 
1005  int middle = (int)(size - 1) / 2;
1006  FilterType sigma2 = static_cast<FilterType>(vpMath::sqr(sigma));
1007  FilterType coef_1 = static_cast<FilterType>(1. / (sigma * sqrt(2. * M_PI)));
1008  FilterType coef_1_over_2 = coef_1 / static_cast<FilterType>(2.);
1009  FilterType _2_coef_1 = static_cast<FilterType>(2.) * coef_1;
1010  FilterType _2_sigma2 = static_cast<FilterType>(2. * sigma2);
1011  filter[0] = 0.;
1012  for (int i = 1; i <= middle; i++) {
1013  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)));
1014  }
1015 
1016  if (normalize) {
1017  FilterType sum = 0;
1018  for (int i = 1; i <= middle; i++) {
1019  sum += _2_coef_1 * static_cast<FilterType>(exp(-(i * i) / _2_sigma2));
1020  }
1021  sum += coef_1;
1022 
1023  for (int i = 1; i <= middle; i++) {
1024  filter[i] = filter[i] / sum;
1025  }
1026  }
1027  }
1028 
1029  // Gradient along X
1030  template<typename FilterType>
1032  {
1033  dIx.resize(I.getHeight(), I.getWidth());
1034  // dIx=0;
1035  for (unsigned int i = 0; i < I.getHeight(); i++) {
1036  for (unsigned int j = 0; j < 3; j++) {
1037  dIx[i][j] = 0;
1038  }
1039  for (unsigned int j = 3; j < I.getWidth() - 3; j++) {
1040  dIx[i][j] = vpImageFilter::derivativeFilterX(I, i, j);
1041  }
1042  for (unsigned int j = I.getWidth() - 3; j < I.getWidth(); j++) {
1043  dIx[i][j] = 0;
1044  }
1045  }
1046  }
1047 
1048  template <typename ImageType, typename FilterType>
1049  static void getGradX(const vpImage<ImageType> &I, vpImage<FilterType> &dIx, const FilterType *filter, unsigned int size)
1050  {
1051  dIx.resize(I.getHeight(), I.getWidth());
1052  for (unsigned int i = 0; i < I.getHeight(); i++) {
1053  for (unsigned int j = 0; j < (size - 1) / 2; j++) {
1054  dIx[i][j] = 0;
1055  }
1056  for (unsigned int j = (size - 1) / 2; j < I.getWidth() - (size - 1) / 2; j++) {
1057  dIx[i][j] = vpImageFilter::derivativeFilterX<ImageType, FilterType>(I, i, j, filter, size);
1058  }
1059  for (unsigned int j = I.getWidth() - (size - 1) / 2; j < I.getWidth(); j++) {
1060  dIx[i][j] = 0;
1061  }
1062  }
1063  }
1064 
1075  template <typename ImageType, typename FilterType>
1076  static void getGradXGauss2D(const vpImage<ImageType> &I, vpImage<FilterType> &dIx, const FilterType *gaussianKernel,
1077  const FilterType *gaussianDerivativeKernel, unsigned int size)
1078  {
1079  vpImage<FilterType> GIy;
1080  vpImageFilter::filterY<FilterType>(I, GIy, gaussianKernel, size);
1081  vpImageFilter::getGradX<FilterType, FilterType>(GIy, dIx, gaussianDerivativeKernel, size);
1082  }
1083 
1084  // Gradient along Y
1085  template <typename FilterType>
1087  {
1088  dIy.resize(I.getHeight(), I.getWidth());
1089  for (unsigned int i = 0; i < 3; i++) {
1090  for (unsigned int j = 0; j < I.getWidth(); j++) {
1091  dIy[i][j] = 0;
1092  }
1093  }
1094  for (unsigned int i = 3; i < I.getHeight() - 3; i++) {
1095  for (unsigned int j = 0; j < I.getWidth(); j++) {
1096  dIy[i][j] = vpImageFilter::derivativeFilterY(I, i, j);
1097  }
1098  }
1099  for (unsigned int i = I.getHeight() - 3; i < I.getHeight(); i++) {
1100  for (unsigned int j = 0; j < I.getWidth(); j++) {
1101  dIy[i][j] = 0;
1102  }
1103  }
1104  }
1105 
1106  template <typename ImageType, typename FilterType>
1107  static void getGradY(const vpImage<ImageType> &I, vpImage<FilterType> &dIy, const FilterType *filter, unsigned int size)
1108  {
1109  dIy.resize(I.getHeight(), I.getWidth());
1110  for (unsigned int i = 0; i < (size - 1) / 2; i++) {
1111  for (unsigned int j = 0; j < I.getWidth(); j++) {
1112  dIy[i][j] = 0;
1113  }
1114  }
1115  for (unsigned int i = (size - 1) / 2; i < I.getHeight() - (size - 1) / 2; i++) {
1116  for (unsigned int j = 0; j < I.getWidth(); j++) {
1117  dIy[i][j] = vpImageFilter::derivativeFilterY<ImageType, FilterType>(I, i, j, filter, size);
1118  }
1119  }
1120  for (unsigned int i = I.getHeight() - (size - 1) / 2; i < I.getHeight(); i++) {
1121  for (unsigned int j = 0; j < I.getWidth(); j++) {
1122  dIy[i][j] = 0;
1123  }
1124  }
1125  }
1126 
1137  template <typename ImageType, typename FilterType>
1138  static void getGradYGauss2D(const vpImage<ImageType> &I, vpImage<FilterType> &dIy, const FilterType *gaussianKernel,
1139  const FilterType *gaussianDerivativeKernel, unsigned int size)
1140  {
1141  vpImage<FilterType> GIx;
1142  vpImageFilter::filterX<FilterType>(I, GIx, gaussianKernel, size);
1143  vpImageFilter::getGradY<FilterType, FilterType>(GIx, dIy, gaussianDerivativeKernel, size);
1144  }
1145 
1153  template <typename FilterType>
1154  inline static FilterType getSobelKernelX(FilterType *filter, unsigned int size)
1155  {
1156  if (size == 0)
1157  throw vpException(vpException::dimensionError, "Cannot get Sobel kernel of size 0!");
1158  if (size > 20)
1159  throw vpException(vpException::dimensionError, "Cannot get Sobel kernel of size > 20!");
1160 
1161  vpArray2D<FilterType> SobelY(size * 2 + 1, size * 2 + 1);
1162  FilterType norm = getSobelKernelY<FilterType>(SobelY.data, size);
1163  memcpy(filter, SobelY.t().data, SobelY.getRows() * SobelY.getCols() * sizeof(FilterType));
1164  return norm;
1165  }
1166 
1174  template <typename FilterType>
1175  inline static FilterType getSobelKernelY(FilterType *filter, unsigned int size)
1176  {
1177  // Sobel kernel pre-computed for the usual size
1178  static const FilterType SobelY3x3[9] = { -1.0, -2.0, -1.0, 0.0, 0.0, 0.0, 1.0, 2.0, 1.0 };
1179  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,
1180  0.0, 0.0, 2.0, 8.0, 12.0, 8.0, 2.0, 1.0, 4.0, 6.0, 4.0, 1.0 };
1181  static const FilterType SobelY7x7[49] = { -1, -6, -15, -20, -15, -6, -1, -4, -24, -60, -80, -60, -24, -4, -5, -30, -75,
1182  -100, -75, -30, -5, 0, 0, 0, 0, 0, 0, 0, 5, 30, 75, 100, 75, 30,
1183  5, 4, 24, 60, 80, 60, 24, 4, 1, 6, 15, 20, 15, 6, 1 };
1184  const vpArray2D<FilterType> smoothingKernel(3, 3);
1185  smoothingKernel[0][0] = 1.0;
1186  smoothingKernel[0][1] = 2.0;
1187  smoothingKernel[0][2] = 1.0;
1188  smoothingKernel[1][0] = 2.0;
1189  smoothingKernel[1][1] = 4.0;
1190  smoothingKernel[1][2] = 2.0;
1191  smoothingKernel[2][0] = 1.0;
1192  smoothingKernel[2][1] = 2.0;
1193  smoothingKernel[2][2] = 1.0;
1194 
1195  if (size == 0)
1196  throw vpException(vpException::dimensionError, "Cannot get Sobel kernel of size 0!");
1197  if (size > 20)
1198  throw vpException(vpException::dimensionError, "Cannot get Sobel kernel of size > 20!");
1199 
1200  const unsigned int kernel_size = size * 2 + 1;
1201  if (kernel_size == 3) {
1202  memcpy(filter, SobelY3x3, kernel_size * kernel_size * sizeof(FilterType));
1203  return 1 / 8.0;
1204  }
1205  if (kernel_size == 5) {
1206  memcpy(filter, SobelY5x5, kernel_size * kernel_size * sizeof(FilterType));
1207  return 1 / 16.0;
1208  }
1209  if (kernel_size == 7) {
1210  memcpy(filter, SobelY7x7, kernel_size * kernel_size * sizeof(FilterType));
1211  return 1 / 16.0;
1212  }
1213 
1214  vpArray2D<FilterType> sobelY(7, 7);
1215  memcpy(sobelY.data, SobelY7x7, sobelY.getRows() * sobelY.getCols() * sizeof(FilterType));
1216  for (unsigned int i = 4; i <= size; i++) {
1217  sobelY = vpArray2D<FilterType>::conv2(sobelY, smoothingKernel, "full");
1218  }
1219 
1220  memcpy(filter, sobelY.data, sobelY.getRows() * sobelY.getCols() * sizeof(FilterType));
1221 
1222  return 1 / 16.0;
1223  }
1224 
1225 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC)
1226  static float computeCannyThreshold(const cv::Mat &cv_I, const cv::Mat *p_cv_blur, float &lowerThresh);
1227  static float computeCannyThreshold(const vpImage<unsigned char> &I, float &lowerThresh);
1228  static float median(const cv::Mat &cv_I);
1229  static float median(const vpImage<unsigned char> &Isrc);
1230  static std::vector<float> median(const vpImage<vpRGBa> &Isrc);
1231 #endif
1232 };
1233 
1234 #endif
Implementation of a generic 2D array used as base class for matrices and vectors.
Definition: vpArray2D.h:131
unsigned int getCols() const
Definition: vpArray2D.h:280
Type * data
Address of the first element of the data array.
Definition: vpArray2D.h:144
static vpArray2D< Type > conv2(const vpArray2D< Type > &M, const vpArray2D< Type > &kernel, const std::string &mode)
Definition: vpArray2D.h:1070
vpArray2D< Type > t() const
Compute the transpose of the array.
Definition: vpArray2D.h:1059
unsigned int getRows() const
Definition: vpArray2D.h:290
Implementation of column vector and the associated operations.
Definition: vpColVector.h:167
error that can be emitted by ViSP classes.
Definition: vpException.h:59
@ dimensionError
Bad dimension.
Definition: vpException.h:83
Error that can be emitted by the vpImage class and its derivatives.
@ incorrectInitializationError
Wrong image initialization.
Various image filter, convolution, etc...
Definition: vpImageFilter.h:68
static unsigned char filterGaussXPyramidal(const vpImage< unsigned char > &I, unsigned int i, unsigned int j)
static double filterXG(const vpImage< vpRGBa > &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
static double derivativeFilterY(const vpImage< T > &I, unsigned int r, unsigned int c)
Definition: vpImageFilter.h:96
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 FilterType filterXLeftBorder(const vpImage< unsigned char > &I, unsigned int r, unsigned int c, const FilterType *filter, unsigned int size)
static void gaussianBlur(const vpImage< FilterType > &I, vpImage< FilterType > &GI, unsigned int size=7, FilterType sigma=0., bool normalize=true)
static void filterX(const vpImage< unsigned char > &I, vpImage< FilterType > &dIx, const FilterType *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 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< unsigned char > &I, unsigned int r, unsigned int c, const FilterType *filter, unsigned int size)
static void filter(const vpImage< FilterType > &I, vpImage< FilterType > &Iu, vpImage< FilterType > &Iv, const vpArray2D< FilterType > &M, bool convolve=false)
static void getGradXGauss2D(const vpImage< ImageType > &I, vpImage< FilterType > &dIx, const FilterType *gaussianKernel, const FilterType *gaussianDerivativeKernel, unsigned int size)
static FilterType filterX(const vpImage< FilterType > &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 gaussianBlur(const vpImage< unsigned char > &I, vpImage< FilterType > &GI, unsigned int size=7, FilterType sigma=0., bool normalize=true)
static double filterXB(const vpImage< vpRGBa > &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
static double filterXR(const vpImage< vpRGBa > &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
static FilterType filterX(const vpImage< unsigned char > &I, unsigned int r, unsigned int c, const FilterType *filter, unsigned int size)
static void getGaussianDerivativeKernel(FilterType *filter, unsigned int size, FilterType sigma=0., bool normalize=true)
static double derivativeFilterX(const vpImage< T > &I, unsigned int r, unsigned int c)
Definition: vpImageFilter.h:83
static double filterXLeftBorderR(const vpImage< vpRGBa > &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
static FilterType filterYBottomBorder(const vpImage< unsigned char > &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 FilterType filterXRightBorder(const vpImage< FilterType > &I, unsigned int r, unsigned int c, const FilterType *filter, unsigned int size)
static FilterType derivativeFilterX(const vpImage< T > &I, unsigned int r, unsigned int c, const FilterType *filter, unsigned int size)
static void filterXR(const vpImage< vpRGBa > &I, vpImage< vpRGBa > &dIx, const double *filter, unsigned int size)
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 filterYG(const vpImage< vpRGBa > &I, vpImage< vpRGBa > &dIx, const double *filter, unsigned int size)
static FilterType filterXLeftBorder(const vpImage< FilterType > &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 filterY(const vpImage< FilterType > &I, vpImage< FilterType > &dIy, 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 filterY(const vpImage< double > &I, unsigned int r, unsigned int c, const FilterType *filter, unsigned int size)
static void filterY(const vpImage< unsigned char > &I, vpImage< FilterType > &dIy, const FilterType *filter, unsigned int size)
static void filter(const vpImage< unsigned char > &I, vpImage< FilterType > &If, const vpArray2D< FilterType > &M, bool convolve=false)
static FilterType derivativeFilterY(const vpImage< T > &I, unsigned int r, unsigned int c, const FilterType *filter, unsigned int size)
static void filterX(const vpImage< FilterType > &I, vpImage< FilterType > &dIx, const FilterType *filter, unsigned int size)
static void filterXG(const vpImage< vpRGBa > &I, vpImage< vpRGBa > &dIx, const double *filter, unsigned int size)
static FilterType filterXRightBorder(const vpImage< unsigned char > &I, unsigned int r, unsigned int c, const FilterType *filter, unsigned int size)
static double filterYG(const vpImage< vpRGBa > &I, unsigned int r, unsigned int c, const double *filter, unsigned int size)
static FilterType filterYTopBorder(const vpImage< unsigned char > &I, unsigned int r, unsigned int c, const FilterType *filter, unsigned int size)
static FilterType filterYTopBorder(const vpImage< double > &I, unsigned int r, unsigned int c, 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 FilterType filterYBottomBorder(const vpImage< double > &I, unsigned int r, unsigned int c, const FilterType *filter, unsigned int size)
static double gaussianFilter(const vpImage< T > &fr, unsigned int r, unsigned int c)
static void filter(const vpImage< unsigned char > &I, vpImage< FilterType > &GI, const FilterType *filter, unsigned int size)
static void filter(const vpImage< FilterType > &I, vpImage< FilterType > &GI, const FilterType *filter, unsigned int size)
static void getGradY(const vpImage< unsigned char > &I, vpImage< FilterType > &dIy)
void destroy()
Destructor : Memory de-allocation.
Definition: vpImage.h:824
unsigned int getWidth() const
Definition: vpImage.h:242
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:795
unsigned int getHeight() const
Definition: vpImage.h:184
static double sqr(double x)
Definition: vpMath.h:124