42#include <visp3/core/vpRGBa.h>
43#include <visp3/core/vpHSV.h>
44#include <visp3/core/vpImage.h>
45#include <visp3/core/vpImageFilter.h>
49#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
52#ifdef ENABLE_VISP_NAMESPACE
56#ifndef DOXYGEN_SHOULD_SKIP_THIS
57namespace vpOldImageFilter
69template<
typename ImageType>
70static void resizeAndInitializeIfNeeded(
const vpImage<bool> *p_mask,
const unsigned int height,
const unsigned int width, vpImage<ImageType> &I)
72 if (p_mask ==
nullptr) {
78 I.
resize(height, width,
static_cast<ImageType
>(0));
91bool checkBooleanMask(
const vpImage<bool> *p_mask,
const unsigned int &r,
const unsigned int &c)
93 bool computeVal =
true;
94#if ((__cplusplus >= 201103L) || (defined(_MSVC_LANG) && (_MSVC_LANG >= 201103L)))
95 if (p_mask !=
nullptr)
100 computeVal = (*p_mask)[
r][c];
105double filterXR(
const vpImage<vpRGBa> &I,
unsigned int r,
unsigned int c,
const double *filter,
unsigned int size)
107 const unsigned int stop = (size - 1) / 2;
109 for (
unsigned int i = 1;
i <= stop; ++
i) {
110 result += filter[
i] *
static_cast<double>(I[
r][c +
i].R + I[
r][c -
i].R);
112 return result + (filter[0] *
static_cast<double>(I[
r][c].R));
115double filterXG(
const vpImage<vpRGBa> &I,
unsigned int r,
unsigned int c,
const double *filter,
unsigned int size)
117 const unsigned int stop = (size - 1) / 2;
120 for (
unsigned int i = 1;
i <= stop; ++
i) {
121 result += filter[
i] *
static_cast<double>(I[
r][c +
i].G + I[
r][c -
i].G);
123 return result + (filter[0] *
static_cast<double>(I[
r][c].G));
126double filterXB(
const vpImage<vpRGBa> &I,
unsigned int r,
unsigned int c,
const double *filter,
unsigned int size)
128 const unsigned int stop = (size - 1) / 2;
131 for (
unsigned int i = 1;
i <= stop; ++
i) {
132 result += filter[
i] *
static_cast<double>(I[
r][c +
i].B + I[
r][c -
i].B);
134 return result + (filter[0] *
static_cast<double>(I[
r][c].B));
137double filterXLeftBorderR(
const vpImage<vpRGBa> &I,
unsigned int r,
unsigned int c,
138 const double *filter,
unsigned int size)
140 const unsigned int stop = (size - 1) / 2;
143 for (
unsigned int i = 1;
i <= stop; ++
i) {
145 result += filter[
i] *
static_cast<double>(I[
r][c +
i].R + I[
r][c -
i].R);
148 result += filter[
i] *
static_cast<double>(I[
r][c +
i].R + I[
r][
i - c].R);
151 return result + (filter[0] *
static_cast<double>(I[
r][c].R));
154double filterXLeftBorderG(
const vpImage<vpRGBa> &I,
unsigned int r,
unsigned int c,
155 const double *filter,
unsigned int size)
157 const unsigned int stop = (size - 1) / 2;
160 for (
unsigned int i = 1;
i <= stop; ++
i) {
162 result += filter[
i] *
static_cast<double>(I[
r][c +
i].G + I[
r][c -
i].G);
165 result += filter[
i] *
static_cast<double>(I[
r][c +
i].G + I[
r][
i - c].G);
168 return result + (filter[0] *
static_cast<double>(I[
r][c].G));
171double filterXLeftBorderB(
const vpImage<vpRGBa> &I,
unsigned int r,
unsigned int c,
172 const double *filter,
unsigned int size)
174 const unsigned int stop = (size - 1) / 2;
177 for (
unsigned int i = 1;
i <= stop; ++
i) {
179 result += filter[
i] *
static_cast<double>(I[
r][c +
i].B + I[
r][c -
i].B);
182 result += filter[
i] *
static_cast<double>(I[
r][c +
i].B + I[
r][
i - c].B);
185 return result + (filter[0] *
static_cast<double>(I[
r][c].B));
188double filterXRightBorderR(
const vpImage<vpRGBa> &I,
unsigned int r,
unsigned int c,
189 const double *filter,
unsigned int size)
191 const unsigned int val_2 = 2;
192 const unsigned int stop = (size - 1) / 2;
196 for (
unsigned int i = 1;
i <= stop; ++
i) {
197 if ((c + i) < width) {
198 result += filter[
i] *
static_cast<double>(I[
r][c +
i].R + I[
r][c -
i].R);
201 result += filter[
i] *
static_cast<double>(I[
r][((val_2 *
width) - c) -
i - 1].R + I[
r][c -
i].R);
204 return result + (filter[0] *
static_cast<double>(I[
r][c].R));
207double filterXRightBorderG(
const vpImage<vpRGBa> &I,
unsigned int r,
unsigned int c,
208 const double *filter,
unsigned int size)
210 const unsigned int val_2 = 2;
211 const unsigned int stop = (size - 1) / 2;
215 for (
unsigned int i = 1;
i <= stop; ++
i) {
216 if ((c + i) < width) {
217 result += filter[
i] *
static_cast<double>(I[
r][c +
i].G + I[
r][c -
i].G);
220 result += filter[
i] *
static_cast<double>(I[
r][((val_2 *
width) - c) -
i - 1].G + I[
r][c -
i].G);
223 return result + (filter[0] *
static_cast<double>(I[
r][c].G));
226double filterXRightBorderB(
const vpImage<vpRGBa> &I,
unsigned int r,
unsigned int c,
227 const double *filter,
unsigned int size)
229 const unsigned int val_2 = 2;
230 const unsigned int stop = (size - 1) / 2;
234 for (
unsigned int i = 1;
i <= stop; ++
i) {
235 if ((c + i) < width) {
236 result += filter[
i] *
static_cast<double>(I[
r][c +
i].B + I[
r][c -
i].B);
239 result += filter[
i] *
static_cast<double>(I[
r][(val_2 *
width) - c -
i - 1].B + I[
r][c -
i].B);
242 return result + (filter[0] *
static_cast<double>(I[
r][c].B));
245double filterYR(
const vpImage<vpRGBa> &I,
unsigned int r,
unsigned int c,
const double *filter,
unsigned int size)
247 const unsigned int stop = (size - 1) / 2;
250 for (
unsigned int i = 1;
i <= stop; ++
i) {
251 result += filter[
i] *
static_cast<double>(I[
r +
i][c].R + I[
r -
i][c].R);
253 return result + (filter[0] *
static_cast<double>(I[
r][c].R));
256double filterYG(
const vpImage<vpRGBa> &I,
unsigned int r,
unsigned int c,
const double *filter,
unsigned int size)
258 const unsigned int stop = (size - 1) / 2;
261 for (
unsigned int i = 1;
i <= stop; ++
i) {
262 result += filter[
i] *
static_cast<double>(I[
r +
i][c].G + I[
r -
i][c].G);
264 return result + (filter[0] *
static_cast<double>(I[
r][c].G));
267double filterYB(
const vpImage<vpRGBa> &I,
unsigned int r,
unsigned int c,
const double *filter,
unsigned int size)
269 const unsigned int stop = (size - 1) / 2;
272 for (
unsigned int i = 1;
i <= stop; ++
i) {
273 result += filter[
i] *
static_cast<double>(I[
r +
i][c].B + I[
r -
i][c].B);
275 return result + (filter[0] *
static_cast<double>(I[
r][c].B));
278double filterYTopBorderR(
const vpImage<vpRGBa> &I,
unsigned int r,
unsigned int c,
const double *filter,
unsigned int size)
280 const unsigned int stop = (size - 1) / 2;
283 for (
unsigned int i = 1;
i <= stop; ++
i) {
285 result += filter[
i] *
static_cast<double>(I[
r +
i][c].R + I[
r -
i][c].R);
288 result += filter[
i] *
static_cast<double>(I[
r +
i][c].R + I[
i -
r][c].R);
291 return result + (filter[0] *
static_cast<double>(I[
r][c].R));
294double filterYTopBorderG(
const vpImage<vpRGBa> &I,
unsigned int r,
unsigned int c,
const double *filter,
unsigned int size)
296 const unsigned int stop = (size - 1) / 2;
299 for (
unsigned int i = 1;
i <= stop; ++
i) {
301 result += filter[
i] *
static_cast<double>(I[
r +
i][c].G + I[
r -
i][c].G);
304 result += filter[
i] *
static_cast<double>(I[
r +
i][c].G + I[
i -
r][c].G);
307 return result + (filter[0] *
static_cast<double>(I[
r][c].G));
310double filterYTopBorderB(
const vpImage<vpRGBa> &I,
unsigned int r,
unsigned int c,
const double *filter,
unsigned int size)
312 const unsigned int stop = (size - 1) / 2;
315 for (
unsigned int i = 1;
i <= stop; ++
i) {
317 result += filter[
i] *
static_cast<double>(I[
r +
i][c].B + I[
r -
i][c].B);
320 result += filter[
i] *
static_cast<double>(I[
r +
i][c].B + I[
i -
r][c].B);
323 return result + (filter[0] *
static_cast<double>(I[
r][c].B));
326double filterYBottomBorderR(
const vpImage<vpRGBa> &I,
unsigned int r,
unsigned int c,
327 const double *filter,
unsigned int size)
329 const unsigned int val_2 = 2;
331 const unsigned int stop = (size - 1) / 2;
334 for (
unsigned int i = 1;
i <= stop; ++
i) {
335 if ((r + i) < height) {
336 result += filter[
i] *
static_cast<double>(I[
r +
i][c].R + I[
r -
i][c].R);
339 result += filter[
i] *
static_cast<double>(I[((val_2 *
height) -
r) -
i - 1][c].R + I[
r -
i][c].R);
342 return result + (filter[0] *
static_cast<double>(I[
r][c].R));
345double filterYBottomBorderG(
const vpImage<vpRGBa> &I,
unsigned int r,
unsigned int c,
346 const double *filter,
unsigned int size)
348 const unsigned int val_2 = 2;
350 const unsigned int stop = (size - 1) / 2;
353 for (
unsigned int i = 1;
i <= stop; ++
i) {
354 if ((r + i) < height) {
355 result += filter[
i] *
static_cast<double>(I[
r +
i][c].G + I[
r -
i][c].G);
358 result += filter[
i] *
static_cast<double>(I[((val_2 *
height) -
r) -
i - 1][c].G + I[
r -
i][c].G);
361 return result + (filter[0] *
static_cast<double>(I[
r][c].G));
364double filterYBottomBorderB(
const vpImage<vpRGBa> &I,
unsigned int r,
unsigned int c,
365 const double *filter,
unsigned int size)
367 const unsigned int val_2 = 2;
369 const unsigned int stop = (size - 1) / 2;
372 for (
unsigned int i = 1;
i <= stop; ++
i) {
373 if ((r + i) < height) {
374 result += filter[
i] *
static_cast<double>(I[
r +
i][c].B + I[
r -
i][c].B);
377 result += filter[
i] *
static_cast<double>(I[((val_2 *
height) -
r) -
i - 1][c].B + I[
r -
i][c].B);
380 return result + (filter[0] *
static_cast<double>(I[
r][c].B));
383void filterX(
const vpImage<vpRGBa> &I, vpImage<vpRGBa> &dIx,
const double *filter,
unsigned int size,
const vpImage<bool> *p_mask =
nullptr);
385template<
typename ImageType,
typename FilterType>
386inline FilterType filterX(
const vpImage<ImageType> &I,
unsigned int r,
unsigned int c,
const FilterType *filter,
unsigned int size)
388 const unsigned int stop = (size - 1) / 2;
389 FilterType result =
static_cast<FilterType
>(0.);
391 for (
unsigned int i = 1;
i <= stop; ++
i) {
392 result += filter[
i] *
static_cast<FilterType
>(I[
r][c +
i] + I[
r][c -
i]);
394 return result + (filter[0] *
static_cast<FilterType
>(I[
r][c]));
397template <
typename ImageType,
typename FilterType>
398inline FilterType filterXLeftBorder(
const vpImage<ImageType> &I,
unsigned int r,
unsigned int c,
399 const FilterType *filter,
unsigned int size)
401 const unsigned int stop = (size - 1) / 2;
402 FilterType result =
static_cast<FilterType
>(0.);
404 for (
unsigned int i = 1;
i <= stop; ++
i) {
406 result += filter[
i] *
static_cast<FilterType
>(I[
r][c +
i] + I[
r][c -
i]);
409 result += filter[
i] *
static_cast<FilterType
>(I[
r][c +
i] + I[
r][
i - c]);
412 return result + (filter[0] *
static_cast<FilterType
>(I[
r][c]));
415template <
typename ImageType,
typename FilterType>
416inline FilterType filterXRightBorder(
const vpImage<ImageType> &I,
unsigned int r,
unsigned int c,
417 const FilterType *filter,
unsigned int size)
419 const unsigned int stop = (size - 1) / 2;
421 FilterType result =
static_cast<FilterType
>(0.);
422 const unsigned int twice = 2;
424 for (
unsigned int i = 1;
i <= stop; ++
i) {
425 if ((c + i) < width) {
426 result += filter[
i] *
static_cast<FilterType
>(I[
r][c +
i] + I[
r][c -
i]);
429 result += filter[
i] *
static_cast<FilterType
>(I[
r][((twice *
width) - c) -
i - 1] + I[
r][c -
i]);
432 return result + (filter[0] *
static_cast<FilterType
>(I[
r][c]));
435template <
typename ImageType,
typename FilterType>
436void filterX(
const vpImage<ImageType> &I, vpImage<FilterType> &dIx,
const FilterType *filter,
unsigned int size,
437 const vpImage<bool> *p_mask =
nullptr)
441 const unsigned int stop1J = (size - 1) / 2;
442 const unsigned int stop2J =
width - ((size - 1) / 2);
443 resizeAndInitializeIfNeeded(p_mask, height, width, dIx);
445 for (
unsigned int i = 0;
i <
height; ++
i) {
446 for (
unsigned int j = 0;
j < stop1J; ++
j) {
449 bool computeVal = checkBooleanMask(p_mask, i, j);
451 dIx[
i][
j] = filterXLeftBorder<ImageType, FilterType>(I, i, j, filter, size);
454 for (
unsigned int j = stop1J;
j < stop2J; ++
j) {
457 bool computeVal = checkBooleanMask(p_mask, i, j);
459 dIx[
i][
j] = filterX<ImageType, FilterType>(I, i, j, filter, size);
462 for (
unsigned int j = stop2J;
j <
width; ++
j) {
465 bool computeVal = checkBooleanMask(p_mask, i, j);
467 dIx[
i][
j] = filterXRightBorder<ImageType, FilterType>(I, i, j, filter, size);
473void filterY(
const vpImage<vpRGBa> &I, vpImage<vpRGBa> &dIx,
const double *filter,
unsigned int size,
const vpImage<bool> *p_mask =
nullptr);
475template<
typename ImageType,
typename FilterType>
476inline FilterType filterY(
const vpImage<ImageType> &I,
unsigned int r,
unsigned int c,
const FilterType *filter,
unsigned int size)
478 const unsigned int stop = (size - 1) / 2;
479 FilterType result =
static_cast<FilterType
>(0.);
481 for (
unsigned int i = 1;
i <= stop; ++
i) {
482 result += filter[
i] *
static_cast<FilterType
>(I[
r +
i][c] + I[
r -
i][c]);
484 return result + (filter[0] *
static_cast<FilterType
>(I[
r][c]));
487template<
typename ImageType,
typename FilterType>
488inline FilterType filterYTopBorder(
const vpImage<ImageType> &I,
unsigned int r,
unsigned int c,
489 const FilterType *filter,
unsigned int size)
491 const unsigned int stop = (size - 1) / 2;
492 FilterType result =
static_cast<FilterType
>(0.);
494 for (
unsigned int i = 1;
i <= stop; ++
i) {
496 result += filter[
i] *
static_cast<FilterType
>(I[
r +
i][c] + I[
r -
i][c]);
499 result += filter[
i] *
static_cast<FilterType
>(I[
r +
i][c] + I[
i -
r][c]);
502 return result + (filter[0] *
static_cast<FilterType
>(I[
r][c]));
505template<
typename ImageType,
typename FilterType>
506inline FilterType filterYBottomBorder(
const vpImage<ImageType> &I,
unsigned int r,
unsigned int c,
507 const FilterType *filter,
unsigned int size)
510 const unsigned int stop = (size - 1) / 2;
511 FilterType result =
static_cast<FilterType
>(0.);
512 const unsigned int twiceHeight = 2 *
height;
513 for (
unsigned int i = 1;
i <= stop; ++
i) {
514 if ((r + i) < height) {
515 result += filter[
i] *
static_cast<FilterType
>(I[
r +
i][c] + I[
r -
i][c]);
518 result += filter[
i] *
static_cast<FilterType
>(I[(twiceHeight -
r) -
i - 1][c] + I[
r -
i][c]);
521 return result + (filter[0] *
static_cast<FilterType
>(I[
r][c]));
524template<
typename ImageType,
typename FilterType>
525void filterY(
const vpImage<ImageType> &I, vpImage<FilterType> &dIy,
const FilterType *filter,
unsigned int size,
526 const vpImage<bool> *p_mask =
nullptr)
529 const unsigned int stop1I = (size - 1) / 2;
530 const unsigned int stop2I =
height - ((size - 1) / 2);
531 resizeAndInitializeIfNeeded(p_mask, height, width, dIy);
533 for (
unsigned int i = 0;
i < stop1I; ++
i) {
534 for (
unsigned int j = 0;
j <
width; ++
j) {
537 bool computeVal = checkBooleanMask(p_mask, i, j);
539 dIy[
i][
j] = filterYTopBorder<ImageType, FilterType>(I, i, j, filter, size);
543 for (
unsigned int i = stop1I;
i < stop2I; ++
i) {
544 for (
unsigned int j = 0;
j <
width; ++
j) {
547 bool computeVal = checkBooleanMask(p_mask, i, j);
549 dIy[
i][
j] = filterY<ImageType, FilterType>(I, i, j, filter, size);
553 for (
unsigned int i = stop2I;
i <
height; ++
i) {
554 for (
unsigned int j = 0;
j <
width; ++
j) {
557 bool computeVal = checkBooleanMask(p_mask, i, j);
559 dIy[
i][
j] = filterYBottomBorder<ImageType, FilterType>(I, i, j, filter, size);
565void gaussianBlur(
const vpImage<vpRGBa> &I, vpImage<vpRGBa> &GI,
unsigned int size = 7,
double sigma = 0.,
bool normalize =
true,
566 const vpImage<bool> *p_mask =
nullptr)
569 std::ostringstream oss;
570 oss <<
"Image size (" << I.
getWidth() <<
"x" << I.
getHeight() <<
") is too small for the Gaussian kernel ("
571 <<
"size=" << size <<
"), min size is " << (size-1);
575 double *fg =
new double[(size + 1) / 2];
584template<
typename HSVType,
bool useFullScale>
585double filterXH(
const vpImage<vpHSV<HSVType, useFullScale>> &I,
unsigned int r,
unsigned int c,
const double *filter,
unsigned int size)
587 const unsigned int stop = (size - 1) / 2;
589 for (
unsigned int i = 1;
i <= stop; ++
i) {
590 result += filter[
i] *
static_cast<double>(I[
r][c +
i].H + I[
r][c -
i].H);
592 return result + (filter[0] *
static_cast<double>(I[
r][c].H));
595template<
typename HSVType,
bool useFullScale>
596double filterXS(
const vpImage<vpHSV<HSVType, useFullScale>> &I,
unsigned int r,
unsigned int c,
const double *filter,
unsigned int size)
598 const unsigned int stop = (size - 1) / 2;
601 for (
unsigned int i = 1;
i <= stop; ++
i) {
602 result += filter[
i] *
static_cast<double>(I[
r][c +
i].S + I[
r][c -
i].S);
604 return result + (filter[0] *
static_cast<double>(I[
r][c].S));
607template<
typename HSVType,
bool useFullScale>
608double filterXV(
const vpImage<vpHSV<HSVType, useFullScale>> &I,
unsigned int r,
unsigned int c,
const double *filter,
unsigned int size)
610 const unsigned int stop = (size - 1) / 2;
613 for (
unsigned int i = 1;
i <= stop; ++
i) {
614 result += filter[
i] *
static_cast<double>(I[
r][c +
i].V + I[
r][c -
i].V);
616 return result + (filter[0] *
static_cast<double>(I[
r][c].V));
619template<
typename HSVType,
bool useFullScale>
620double filterXLeftBorderH(
const vpImage<vpHSV<HSVType, useFullScale>> &I,
unsigned int r,
unsigned int c,
621 const double *filter,
unsigned int size)
623 const unsigned int stop = (size - 1) / 2;
626 for (
unsigned int i = 1;
i <= stop; ++
i) {
628 result += filter[
i] *
static_cast<double>(I[
r][c +
i].H + I[
r][c -
i].H);
631 result += filter[
i] *
static_cast<double>(I[
r][c +
i].H + I[
r][
i - c].H);
634 return result + (filter[0] *
static_cast<double>(I[
r][c].H));
637template<
typename HSVType,
bool useFullScale>
638double filterXLeftBorderS(
const vpImage<vpHSV<HSVType, useFullScale>> &I,
unsigned int r,
unsigned int c,
639 const double *filter,
unsigned int size)
641 const unsigned int stop = (size - 1) / 2;
644 for (
unsigned int i = 1;
i <= stop; ++
i) {
646 result += filter[
i] *
static_cast<double>(I[
r][c +
i].S + I[
r][c -
i].S);
649 result += filter[
i] *
static_cast<double>(I[
r][c +
i].S + I[
r][
i - c].S);
652 return result + (filter[0] *
static_cast<double>(I[
r][c].S));
655template<
typename HSVType,
bool useFullScale>
656double filterXLeftBorderV(
const vpImage<vpHSV<HSVType, useFullScale>> &I,
unsigned int r,
unsigned int c,
657 const double *filter,
unsigned int size)
659 const unsigned int stop = (size - 1) / 2;
662 for (
unsigned int i = 1;
i <= stop; ++
i) {
664 result += filter[
i] *
static_cast<double>(I[
r][c +
i].V + I[
r][c -
i].V);
667 result += filter[
i] *
static_cast<double>(I[
r][c +
i].V + I[
r][
i - c].V);
670 return result + (filter[0] *
static_cast<double>(I[
r][c].V));
673template<
typename HSVType,
bool useFullScale>
674double filterXRightBorderH(
const vpImage<vpHSV<HSVType, useFullScale>> &I,
unsigned int r,
unsigned int c,
675 const double *filter,
unsigned int size)
677 const unsigned int val_2 = 2;
678 const unsigned int stop = (size - 1) / 2;
682 for (
unsigned int i = 1;
i <= stop; ++
i) {
683 if ((c + i) < width) {
684 result += filter[
i] *
static_cast<double>(I[
r][c +
i].H + I[
r][c -
i].H);
687 result += filter[
i] *
static_cast<double>(I[
r][((val_2 *
width) - c) -
i - 1].H + I[
r][c -
i].H);
690 return result + (filter[0] *
static_cast<double>(I[
r][c].H));
693template<
typename HSVType,
bool useFullScale>
694double filterXRightBorderS(
const vpImage<vpHSV<HSVType, useFullScale>> &I,
unsigned int r,
unsigned int c,
695 const double *filter,
unsigned int size)
697 const unsigned int val_2 = 2;
698 const unsigned int stop = (size - 1) / 2;
702 for (
unsigned int i = 1;
i <= stop; ++
i) {
703 if ((c + i) < width) {
704 result += filter[
i] *
static_cast<double>(I[
r][c +
i].S + I[
r][c -
i].S);
707 result += filter[
i] *
static_cast<double>(I[
r][((val_2 *
width) - c) -
i - 1].S + I[
r][c -
i].S);
710 return result + (filter[0] *
static_cast<double>(I[
r][c].S));
713template<
typename HSVType,
bool useFullScale>
714double filterXRightBorderV(
const vpImage<vpHSV<HSVType, useFullScale>> &I,
unsigned int r,
unsigned int c,
715 const double *filter,
unsigned int size)
717 const unsigned int val_2 = 2;
718 const unsigned int stop = (size - 1) / 2;
722 for (
unsigned int i = 1;
i <= stop; ++
i) {
723 if ((c + i) < width) {
724 result += filter[
i] *
static_cast<double>(I[
r][c +
i].V + I[
r][c -
i].V);
727 result += filter[
i] *
static_cast<double>(I[
r][(val_2 *
width) - c -
i - 1].V + I[
r][c -
i].V);
730 return result + (filter[0] *
static_cast<double>(I[
r][c].V));
733template<
typename HSVType,
bool useFullScale>
734void filterX(
const vpImage<vpHSV<HSVType, useFullScale>> &I, vpImage<vpHSV<HSVType, useFullScale>> &dIx,
const double *filter,
unsigned int size,
735 const vpImage<bool> *p_mask)
738 const unsigned int stop1J = (size - 1) / 2;
739 const unsigned int stop2J = widthI - ((size - 1) / 2);
740 resizeAndInitializeIfNeeded(p_mask, heightI, widthI, dIx);
742 for (
unsigned int i = 0;
i < heightI; ++
i) {
743 for (
unsigned int j = 0;
j < stop1J; ++
j) {
746 bool computeVal = checkBooleanMask(p_mask, i, j);
748 dIx[
i][
j].H =
static_cast<HSVType
>(filterXLeftBorderH(I, i, j, filter, size));
749 dIx[
i][
j].S =
static_cast<HSVType
>(filterXLeftBorderS(I, i, j, filter, size));
750 dIx[
i][
j].V =
static_cast<HSVType
>(filterXLeftBorderV(I, i, j, filter, size));
753 for (
unsigned int j = stop1J;
j < stop2J; ++
j) {
756 bool computeVal = checkBooleanMask(p_mask, i, j);
758 dIx[
i][
j].H =
static_cast<HSVType
>(filterXH(I, i, j, filter, size));
759 dIx[
i][
j].S =
static_cast<HSVType
>(filterXS(I, i, j, filter, size));
760 dIx[
i][
j].V =
static_cast<HSVType
>(filterXV(I, i, j, filter, size));
763 for (
unsigned int j = stop2J;
j < widthI; ++
j) {
766 bool computeVal = checkBooleanMask(p_mask, i, j);
768 dIx[
i][
j].H =
static_cast<HSVType
>(filterXRightBorderH(I, i, j, filter, size));
769 dIx[
i][
j].S =
static_cast<HSVType
>(filterXRightBorderS(I, i, j, filter, size));
770 dIx[
i][
j].V =
static_cast<HSVType
>(filterXRightBorderV(I, i, j, filter, size));
778template<
typename HSVType,
bool useFullScale>
779double filterYH(
const vpImage<vpHSV<HSVType, useFullScale>> &I,
unsigned int r,
unsigned int c,
const double *filter,
unsigned int size)
781 const unsigned int stop = (size - 1) / 2;
784 for (
unsigned int i = 1;
i <= stop; ++
i) {
785 result += filter[
i] *
static_cast<double>(I[
r +
i][c].H + I[
r -
i][c].H);
787 return result + (filter[0] *
static_cast<double>(I[
r][c].H));
790template<
typename HSVType,
bool useFullScale>
791double filterYS(
const vpImage<vpHSV<HSVType, useFullScale>> &I,
unsigned int r,
unsigned int c,
const double *filter,
unsigned int size)
793 const unsigned int stop = (size - 1) / 2;
796 for (
unsigned int i = 1;
i <= stop; ++
i) {
797 result += filter[
i] *
static_cast<double>(I[
r +
i][c].S + I[
r -
i][c].S);
799 return result + (filter[0] *
static_cast<double>(I[
r][c].S));
802template<
typename HSVType,
bool useFullScale>
803double filterYV(
const vpImage<vpHSV<HSVType, useFullScale>> &I,
unsigned int r,
unsigned int c,
const double *filter,
unsigned int size)
805 const unsigned int stop = (size - 1) / 2;
808 for (
unsigned int i = 1;
i <= stop; ++
i) {
809 result += filter[
i] *
static_cast<double>(I[
r +
i][c].V + I[
r -
i][c].V);
811 return result + (filter[0] *
static_cast<double>(I[
r][c].V));
814template<
typename HSVType,
bool useFullScale>
815double filterYTopBorderH(
const vpImage<vpHSV<HSVType, useFullScale>> &I,
unsigned int r,
unsigned int c,
const double *filter,
unsigned int size)
817 const unsigned int stop = (size - 1) / 2;
820 for (
unsigned int i = 1;
i <= stop; ++
i) {
822 result += filter[
i] *
static_cast<double>(I[
r +
i][c].H + I[
r -
i][c].H);
825 result += filter[
i] *
static_cast<double>(I[
r +
i][c].H + I[
i -
r][c].H);
828 return result + (filter[0] *
static_cast<double>(I[
r][c].H));
831template<
typename HSVType,
bool useFullScale>
832double filterYTopBorderS(
const vpImage<vpHSV<HSVType, useFullScale>> &I,
unsigned int r,
unsigned int c,
const double *filter,
unsigned int size)
834 const unsigned int stop = (size - 1) / 2;
837 for (
unsigned int i = 1;
i <= stop; ++
i) {
839 result += filter[
i] *
static_cast<double>(I[
r +
i][c].S + I[
r -
i][c].S);
842 result += filter[
i] *
static_cast<double>(I[
r +
i][c].S + I[
i -
r][c].S);
845 return result + (filter[0] *
static_cast<double>(I[
r][c].S));
848template<
typename HSVType,
bool useFullScale>
849double filterYTopBorderV(
const vpImage<vpHSV<HSVType, useFullScale>> &I,
unsigned int r,
unsigned int c,
const double *filter,
unsigned int size)
851 const unsigned int stop = (size - 1) / 2;
854 for (
unsigned int i = 1;
i <= stop; ++
i) {
856 result += filter[
i] *
static_cast<double>(I[
r +
i][c].V + I[
r -
i][c].V);
859 result += filter[
i] *
static_cast<double>(I[
r +
i][c].V + I[
i -
r][c].V);
862 return result + (filter[0] *
static_cast<double>(I[
r][c].V));
865template<
typename HSVType,
bool useFullScale>
866double filterYBottomBorderH(
const vpImage<vpHSV<HSVType, useFullScale>> &I,
unsigned int r,
unsigned int c,
867 const double *filter,
unsigned int size)
869 const unsigned int val_2 = 2;
871 const unsigned int stop = (size - 1) / 2;
874 for (
unsigned int i = 1;
i <= stop; ++
i) {
875 if ((r + i) < height) {
876 result += filter[
i] *
static_cast<double>(I[
r +
i][c].H + I[
r -
i][c].H);
879 result += filter[
i] *
static_cast<double>(I[((val_2 *
height) -
r) -
i - 1][c].H + I[
r -
i][c].H);
882 return result + (filter[0] *
static_cast<double>(I[
r][c].H));
885template<
typename HSVType,
bool useFullScale>
886double filterYBottomBorderS(
const vpImage<vpHSV<HSVType, useFullScale>> &I,
unsigned int r,
unsigned int c,
887 const double *filter,
unsigned int size)
889 const unsigned int val_2 = 2;
891 const unsigned int stop = (size - 1) / 2;
894 for (
unsigned int i = 1;
i <= stop; ++
i) {
895 if ((r + i) < height) {
896 result += filter[
i] *
static_cast<double>(I[
r +
i][c].S + I[
r -
i][c].S);
899 result += filter[
i] *
static_cast<double>(I[((val_2 *
height) -
r) -
i - 1][c].S + I[
r -
i][c].S);
902 return result + (filter[0] *
static_cast<double>(I[
r][c].S));
905template<
typename HSVType,
bool useFullScale>
906double filterYBottomBorderV(
const vpImage<vpHSV<HSVType, useFullScale>> &I,
unsigned int r,
unsigned int c,
907 const double *filter,
unsigned int size)
909 const unsigned int val_2 = 2;
911 const unsigned int stop = (size - 1) / 2;
914 for (
unsigned int i = 1;
i <= stop; ++
i) {
915 if ((r + i) < height) {
916 result += filter[
i] *
static_cast<double>(I[
r +
i][c].V + I[
r -
i][c].V);
919 result += filter[
i] *
static_cast<double>(I[((val_2 *
height) -
r) -
i - 1][c].V + I[
r -
i][c].V);
922 return result + (filter[0] *
static_cast<double>(I[
r][c].V));
925template<
typename HSVType,
bool useFullScale>
926void filterY(
const vpImage<vpHSV<HSVType, useFullScale>> &I, vpImage<vpHSV<HSVType, useFullScale>> &dIy,
const double *filter,
unsigned int size,
927 const vpImage<bool> *p_mask)
930 const unsigned int stop1I = (size - 1) / 2;
931 const unsigned int stop2I = heightI - ((size - 1) / 2);
932 resizeAndInitializeIfNeeded(p_mask, heightI, widthI, dIy);
934 for (
unsigned int i = 0;
i < stop1I; ++
i) {
935 for (
unsigned int j = 0;
j < widthI; ++
j) {
938 bool computeVal = checkBooleanMask(p_mask, i, j);
940 dIy[
i][
j].H =
static_cast<HSVType
>(filterYTopBorderH(I, i, j, filter, size));
941 dIy[
i][
j].S =
static_cast<HSVType
>(filterYTopBorderS(I, i, j, filter, size));
942 dIy[
i][
j].V =
static_cast<HSVType
>(filterYTopBorderV(I, i, j, filter, size));
946 for (
unsigned int i = stop1I;
i < stop2I; ++
i) {
947 for (
unsigned int j = 0;
j < widthI; ++
j) {
950 bool computeVal = checkBooleanMask(p_mask, i, j);
952 dIy[
i][
j].H =
static_cast<HSVType
>(filterYH(I, i, j, filter, size));
953 dIy[
i][
j].S =
static_cast<HSVType
>(filterYS(I, i, j, filter, size));
954 dIy[
i][
j].V =
static_cast<HSVType
>(filterYV(I, i, j, filter, size));
958 for (
unsigned int i = stop2I;
i < heightI; ++
i) {
959 for (
unsigned int j = 0;
j < widthI; ++
j) {
962 bool computeVal = checkBooleanMask(p_mask, i, j);
964 dIy[
i][
j].H =
static_cast<HSVType
>(filterYBottomBorderH(I, i, j, filter, size));
965 dIy[
i][
j].S =
static_cast<HSVType
>(filterYBottomBorderS(I, i, j, filter, size));
966 dIy[
i][
j].V =
static_cast<HSVType
>(filterYBottomBorderV(I, i, j, filter, size));
984template<
typename HSVType,
bool useFullScale>
985void gaussianBlur(
const vpImage<vpHSV<HSVType, useFullScale>> &I, vpImage<vpHSV<HSVType, useFullScale>> &GI,
unsigned int size = 7,
double sigma = 0.,
bool normalize =
true,
986 const vpImage<bool> *p_mask =
nullptr)
988 double *fg =
new double[(size + 1) / 2];
990 vpImage<vpHSV<HSVType, useFullScale>> GIx;
997template <
typename ImageType,
typename FilterType>
998static void gaussianBlur(
const vpImage<ImageType> &I, vpImage<FilterType> &GI,
unsigned int size = 7, FilterType sigma = 0.,
bool normalize =
true,
999 const vpImage<bool> *p_mask =
nullptr)
1001 FilterType *fg =
new FilterType[(size + 1) / 2];
1003 vpImage<FilterType> GIx;
1014 bool isSuccess =
true;
1017 vpHSVTests::vpInputDataset dataset;
1026 for (
unsigned int size = 3; (size < 7) && isSuccess; size += 2) {
1027 for (
auto input: dataset.m_ucImages) {
1028 vpHSVTests::print(input.second.m_I, input.first);
1029 vpOldImageFilter::gaussianBlur(input.second.m_I, Iuc_filtered_old, size);
1031 bool ucSuccess = vpHSVTests::areAlmostEqual(Iuc_filtered_old,
"Iuc_filtered_old", Iuc_filtered_new,
"Iuc_filtered_new");
1032 isSuccess = isSuccess && ucSuccess;
1034 std::cerr <<
"ERROR: filter on uchar failed ! " << std::endl;
1038 vpOldImageFilter::gaussianBlur(Irgba, Irgba_filtered_old, size);
1040 bool rgbaSuccess = vpHSVTests::areAlmostEqual(Irgba_filtered_old,
"Irgba_filtered_old", Irgba_filtered_new,
"Irgba_filtered_new");
1041 isSuccess = isSuccess && rgbaSuccess;
1043 std::cerr <<
"ERROR: filter on RGBa failed ! " << std::endl;
1046 for (
auto input: dataset.m_hsvUCtrue) {
1047 vpHSVTests::print(input.second.m_I, input.first);
1048 vpOldImageFilter::gaussianBlur(input.second.m_I, Ihsv_uc_filtered_old_true, size);
1050 bool hsvucSuccessTrue = vpHSVTests::areAlmostEqual(Ihsv_uc_filtered_old_true,
"Ihsv_uc_filtered_old_true", Ihsv_uc_filtered_new_true,
"Ihsv_uc_filtered_new_true");
1051 isSuccess = isSuccess && hsvucSuccessTrue;
1052 if (!hsvucSuccessTrue) {
1053 std::cerr <<
"ERROR: filter on HSV<uchar, true> failed ! " << std::endl;
1057 for (
auto input: dataset.m_hsvUCfalse) {
1058 vpHSVTests::print(input.second.m_I, input.first);
1059 vpOldImageFilter::gaussianBlur(input.second.m_I, Ihsv_uc_filtered_old_false, size);
1061 bool hsvucSuccessTrue = vpHSVTests::areAlmostEqual(Ihsv_uc_filtered_old_false,
"Ihsv_uc_filtered_old_false", Ihsv_uc_filtered_new_false,
"Ihsv_uc_filtered_new_false");
1062 isSuccess = isSuccess && hsvucSuccessTrue;
1063 if (!hsvucSuccessTrue) {
1064 std::cerr <<
"ERROR: filter on HSV<uchar, false> failed ! " << std::endl;
1068 for (
auto input: dataset.m_hsvDouble) {
1069 vpHSVTests::print(input.second.m_I, input.first);
1070 vpOldImageFilter::gaussianBlur(input.second.m_I, Ihsv_double_filtered_old, size);
1072 bool hsvucSuccessTrue = vpHSVTests::areAlmostEqual(Ihsv_double_filtered_old,
"Ihsv_double_filtered_old", Ihsv_double_filtered_new,
"Ihsv_double_filtered_new");
1073 isSuccess = isSuccess && hsvucSuccessTrue;
1074 if (!hsvucSuccessTrue) {
1075 std::cerr <<
"ERROR: filter on HSV<double> failed ! " << std::endl;
1081 std::cout <<
"All tests were successful !" << std::endl;
1082 return EXIT_SUCCESS;
1084 std::cerr <<
"ERROR: Something went wrong !" << std::endl;
1085 return EXIT_FAILURE;
1091 std::cout <<
"vpHSV class is not available, please use CXX 11 standard" << std::endl;
1092 return EXIT_SUCCESS;
@ dimensionError
Bad dimension.
static void filterY(const vpImage< ImageType > &I, vpImage< OutputType > &dIy, const FilterType *filter, unsigned int size, const vpImage< bool > *p_mask=nullptr)
Filter along the vertical direction.
static void filterX(const vpImage< ImageType > &I, vpImage< OutputType > &dIx, const FilterType *filter, unsigned int size, const vpImage< bool > *p_mask=nullptr)
Filter along the horizontal direction.
static void gaussianBlur(const vpImage< ImageType > &I, vpImage< OutputType > &GI, unsigned int size=7, FilterType sigma=0., bool normalize=true, const vpImage< bool > *p_mask=nullptr)
static void getGaussianKernel(FilterType *filter, unsigned int size, FilterType sigma=0., bool normalize=true)
Definition of the vpImage class member functions.
void destroy()
Destructor : Memory de-allocation.
unsigned int getWidth() const
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
unsigned int getHeight() const