#include <iostream>
#include <limits>
#include <visp3/core/vpRGBa.h>
#include <visp3/core/vpHSV.h>
#include <visp3/core/vpImage.h>
#include <visp3/core/vpImageFilter.h>
#include "hsvUtils.h"
#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
#include <type_traits>
#ifdef ENABLE_VISP_NAMESPACE
#endif
#ifndef DOXYGEN_SHOULD_SKIP_THIS
namespace vpOldImageFilter
{
template<typename ImageType>
{
if (p_mask == nullptr) {
I.resize;
}
else {
I.resize(height, width, static_cast<ImageType>(0));
}
}
bool checkBooleanMask(
const vpImage<bool> *p_mask,
const unsigned int &r,
const unsigned int &c)
{
bool computeVal = true;
#if ((__cplusplus >= 201103L) || (defined(_MSVC_LANG) && (_MSVC_LANG >= 201103L)))
if (p_mask != nullptr)
#else
if (p_mask != NULL)
#endif
{
computeVal = (*p_mask)[r][c];
}
return computeVal;
}
double filterXR(
const vpImage<vpRGBa> &I,
unsigned int r,
unsigned int c,
const double *filter,
unsigned int size)
{
const unsigned int stop = (size - 1) / 2;
double result = 0.;
for (unsigned int i = 1; i <= stop; ++i) {
result += filter[i] * static_cast<double>(I[r][c + i].R + I[r][c - i].R);
}
return result + (filter[0] * static_cast<double>(I[r][c].R));
}
double filterXG(
const vpImage<vpRGBa> &I,
unsigned int r,
unsigned int c,
const double *filter,
unsigned int size)
{
const unsigned int stop = (size - 1) / 2;
double result = 0.;
for (unsigned int i = 1; i <= stop; ++i) {
result += filter[i] * static_cast<double>(I[r][c + i].G + I[r][c - i].G);
}
return result + (filter[0] * static_cast<double>(I[r][c].G));
}
double filterXB(
const vpImage<vpRGBa> &I,
unsigned int r,
unsigned int c,
const double *filter,
unsigned int size)
{
const unsigned int stop = (size - 1) / 2;
double result = 0.;
for (unsigned int i = 1; i <= stop; ++i) {
result += filter[i] * static_cast<double>(I[r][c + i].B + I[r][c - i].B);
}
return result + (filter[0] * static_cast<double>(I[r][c].B));
}
double filterXLeftBorderR(
const vpImage<vpRGBa> &I,
unsigned int r,
unsigned int c,
const double *filter, unsigned int size)
{
const unsigned int stop = (size - 1) / 2;
double result = 0.;
for (unsigned int i = 1; i <= stop; ++i) {
if (c > i) {
result += filter[i] * static_cast<double>(I[r][c + i].R + I[r][c - i].R);
}
else {
result += filter[i] * static_cast<double>(I[r][c + i].R + I[r][i - c].R);
}
}
return result + (filter[0] * static_cast<double>(I[r][c].R));
}
double filterXLeftBorderG(
const vpImage<vpRGBa> &I,
unsigned int r,
unsigned int c,
const double *filter, unsigned int size)
{
const unsigned int stop = (size - 1) / 2;
double result = 0.;
for (unsigned int i = 1; i <= stop; ++i) {
if (c > i) {
result += filter[i] * static_cast<double>(I[r][c + i].G + I[r][c - i].G);
}
else {
result += filter[i] * static_cast<double>(I[r][c + i].G + I[r][i - c].G);
}
}
return result + (filter[0] * static_cast<double>(I[r][c].G));
}
double filterXLeftBorderB(
const vpImage<vpRGBa> &I,
unsigned int r,
unsigned int c,
const double *filter, unsigned int size)
{
const unsigned int stop = (size - 1) / 2;
double result = 0.;
for (unsigned int i = 1; i <= stop; ++i) {
if (c > i) {
result += filter[i] * static_cast<double>(I[r][c + i].B + I[r][c - i].B);
}
else {
result += filter[i] * static_cast<double>(I[r][c + i].B + I[r][i - c].B);
}
}
return result + (filter[0] * static_cast<double>(I[r][c].B));
}
double filterXRightBorderR(
const vpImage<vpRGBa> &I,
unsigned int r,
unsigned int c,
const double *filter, unsigned int size)
{
const unsigned int val_2 = 2;
const unsigned int stop = (size - 1) / 2;
const unsigned int width = I.getWidth();
double result = 0.;
for (unsigned int i = 1; i <= stop; ++i) {
if ((c + i) < width) {
result += filter[i] * static_cast<double>(I[r][c + i].R + I[r][c - i].R);
}
else {
result += filter[i] * static_cast<double>(I[r][((val_2 * width) - c) - i - 1].R + I[r][c - i].R);
}
}
return result + (filter[0] * static_cast<double>(I[r][c].R));
}
double filterXRightBorderG(
const vpImage<vpRGBa> &I,
unsigned int r,
unsigned int c,
const double *filter, unsigned int size)
{
const unsigned int val_2 = 2;
const unsigned int stop = (size - 1) / 2;
const unsigned int width = I.getWidth();
double result = 0.;
for (unsigned int i = 1; i <= stop; ++i) {
if ((c + i) < width) {
result += filter[i] * static_cast<double>(I[r][c + i].G + I[r][c - i].G);
}
else {
result += filter[i] * static_cast<double>(I[r][((val_2 * width) - c) - i - 1].G + I[r][c - i].G);
}
}
return result + (filter[0] * static_cast<double>(I[r][c].G));
}
double filterXRightBorderB(
const vpImage<vpRGBa> &I,
unsigned int r,
unsigned int c,
const double *filter, unsigned int size)
{
const unsigned int val_2 = 2;
const unsigned int stop = (size - 1) / 2;
const unsigned int width = I.getWidth();
double result = 0.;
for (unsigned int i = 1; i <= stop; ++i) {
if ((c + i) < width) {
result += filter[i] * static_cast<double>(I[r][c + i].B + I[r][c - i].B);
}
else {
result += filter[i] * static_cast<double>(I[r][(val_2 * width) - c - i - 1].B + I[r][c - i].B);
}
}
return result + (filter[0] * static_cast<double>(I[r][c].B));
}
double filterYR(
const vpImage<vpRGBa> &I,
unsigned int r,
unsigned int c,
const double *filter,
unsigned int size)
{
const unsigned int stop = (size - 1) / 2;
double result = 0.;
for (unsigned int i = 1; i <= stop; ++i) {
result += filter[i] * static_cast<double>(I[r + i][c].R + I[r - i][c].R);
}
return result + (filter[0] * static_cast<double>(I[r][c].R));
}
double filterYG(
const vpImage<vpRGBa> &I,
unsigned int r,
unsigned int c,
const double *filter,
unsigned int size)
{
const unsigned int stop = (size - 1) / 2;
double result = 0.;
for (unsigned int i = 1; i <= stop; ++i) {
result += filter[i] * static_cast<double>(I[r + i][c].G + I[r - i][c].G);
}
return result + (filter[0] * static_cast<double>(I[r][c].G));
}
double filterYB(
const vpImage<vpRGBa> &I,
unsigned int r,
unsigned int c,
const double *filter,
unsigned int size)
{
const unsigned int stop = (size - 1) / 2;
double result = 0.;
for (unsigned int i = 1; i <= stop; ++i) {
result += filter[i] * static_cast<double>(I[r + i][c].B + I[r - i][c].B);
}
return result + (filter[0] * static_cast<double>(I[r][c].B));
}
double filterYTopBorderR(
const vpImage<vpRGBa> &I,
unsigned int r,
unsigned int c,
const double *filter,
unsigned int size)
{
const unsigned int stop = (size - 1) / 2;
double result = 0.;
for (unsigned int i = 1; i <= stop; ++i) {
if (r > i) {
result += filter[i] * static_cast<double>(I[r + i][c].R + I[r - i][c].R);
}
else {
result += filter[i] * static_cast<double>(I[r + i][c].R + I[i - r][c].R);
}
}
return result + (filter[0] * static_cast<double>(I[r][c].R));
}
double filterYTopBorderG(
const vpImage<vpRGBa> &I,
unsigned int r,
unsigned int c,
const double *filter,
unsigned int size)
{
const unsigned int stop = (size - 1) / 2;
double result = 0.;
for (unsigned int i = 1; i <= stop; ++i) {
if (r > i) {
result += filter[i] * static_cast<double>(I[r + i][c].G + I[r - i][c].G);
}
else {
result += filter[i] * static_cast<double>(I[r + i][c].G + I[i - r][c].G);
}
}
return result + (filter[0] * static_cast<double>(I[r][c].G));
}
double filterYTopBorderB(
const vpImage<vpRGBa> &I,
unsigned int r,
unsigned int c,
const double *filter,
unsigned int size)
{
const unsigned int stop = (size - 1) / 2;
double result = 0.;
for (unsigned int i = 1; i <= stop; ++i) {
if (r > i) {
result += filter[i] * static_cast<double>(I[r + i][c].B + I[r - i][c].B);
}
else {
result += filter[i] * static_cast<double>(I[r + i][c].B + I[i - r][c].B);
}
}
return result + (filter[0] * static_cast<double>(I[r][c].B));
}
double filterYBottomBorderR(
const vpImage<vpRGBa> &I,
unsigned int r,
unsigned int c,
const double *filter, unsigned int size)
{
const unsigned int val_2 = 2;
const unsigned int height = I.getHeight();
const unsigned int stop = (size - 1) / 2;
double result = 0.;
for (unsigned int i = 1; i <= stop; ++i) {
if ((r + i) < height) {
result += filter[i] * static_cast<double>(I[r + i][c].R + I[r - i][c].R);
}
else {
result += filter[i] * static_cast<double>(I[((val_2 * height) - r) - i - 1][c].R + I[r - i][c].R);
}
}
return result + (filter[0] * static_cast<double>(I[r][c].R));
}
double filterYBottomBorderG(
const vpImage<vpRGBa> &I,
unsigned int r,
unsigned int c,
const double *filter, unsigned int size)
{
const unsigned int val_2 = 2;
const unsigned int height = I.getHeight();
const unsigned int stop = (size - 1) / 2;
double result = 0.;
for (unsigned int i = 1; i <= stop; ++i) {
if ((r + i) < height) {
result += filter[i] * static_cast<double>(I[r + i][c].G + I[r - i][c].G);
}
else {
result += filter[i] * static_cast<double>(I[((val_2 * height) - r) - i - 1][c].G + I[r - i][c].G);
}
}
return result + (filter[0] * static_cast<double>(I[r][c].G));
}
double filterYBottomBorderB(
const vpImage<vpRGBa> &I,
unsigned int r,
unsigned int c,
const double *filter, unsigned int size)
{
const unsigned int val_2 = 2;
const unsigned int height = I.getHeight();
const unsigned int stop = (size - 1) / 2;
double result = 0.;
for (unsigned int i = 1; i <= stop; ++i) {
if ((r + i) < height) {
result += filter[i] * static_cast<double>(I[r + i][c].B + I[r - i][c].B);
}
else {
result += filter[i] * static_cast<double>(I[((val_2 * height) - r) - i - 1][c].B + I[r - i][c].B);
}
}
return result + (filter[0] * static_cast<double>(I[r][c].B));
}
template<typename ImageType, typename FilterType>
inline FilterType filterX(
const vpImage<ImageType> &I,
unsigned int r,
unsigned int c,
const FilterType *filter,
unsigned int size)
{
const unsigned int stop = (size - 1) / 2;
FilterType result = static_cast<FilterType>(0.);
for (unsigned int i = 1; i <= stop; ++i) {
result += filter[i] * static_cast<FilterType>(I[r][c + i] + I[r][c - i]);
}
return result + (filter[0] * static_cast<FilterType>(I[r][c]));
}
template <typename ImageType, typename FilterType>
inline FilterType filterXLeftBorder(
const vpImage<ImageType> &I,
unsigned int r,
unsigned int c,
const FilterType *filter, unsigned int size)
{
const unsigned int stop = (size - 1) / 2;
FilterType result = static_cast<FilterType>(0.);
for (unsigned int i = 1; i <= stop; ++i) {
if (c > i) {
result += filter[i] * static_cast<FilterType>(I[r][c + i] + I[r][c - i]);
}
else {
result += filter[i] * static_cast<FilterType>(I[r][c + i] + I[r][i - c]);
}
}
return result + (filter[0] * static_cast<FilterType>(I[r][c]));
}
template <typename ImageType, typename FilterType>
inline FilterType filterXRightBorder(
const vpImage<ImageType> &I,
unsigned int r,
unsigned int c,
const FilterType *filter, unsigned int size)
{
const unsigned int stop = (size - 1) / 2;
const unsigned int width = I.getWidth();
FilterType result = static_cast<FilterType>(0.);
const unsigned int twice = 2;
for (unsigned int i = 1; i <= stop; ++i) {
if ((c + i) < width) {
result += filter[i] * static_cast<FilterType>(I[r][c + i] + I[r][c - i]);
}
else {
result += filter[i] * static_cast<FilterType>(I[r][((twice * width) - c) - i - 1] + I[r][c - i]);
}
}
return result + (filter[0] * static_cast<FilterType>(I[r][c]));
}
template <typename ImageType, typename FilterType>
{
const unsigned int height = I.getHeight();
const unsigned int width = I.getWidth();
const unsigned int stop1J = (size - 1) / 2;
const unsigned int stop2J = width - ((size - 1) / 2);
resizeAndInitializeIfNeeded(p_mask, height, width, dIx);
for (unsigned int i = 0; i < height; ++i) {
for (unsigned int j = 0; j < stop1J; ++j) {
bool computeVal = checkBooleanMask(p_mask, i, j);
if (computeVal) {
dIx[i][j] = filterXLeftBorder<ImageType, FilterType>(I, i, j, filter, size);
}
}
for (unsigned int j = stop1J; j < stop2J; ++j) {
bool computeVal = checkBooleanMask(p_mask, i, j);
if (computeVal) {
dIx[i][j] = filterX<ImageType, FilterType>(I, i, j, filter, size);
}
}
for (unsigned int j = stop2J; j < width; ++j) {
bool computeVal = checkBooleanMask(p_mask, i, j);
if (computeVal) {
dIx[i][j] = filterXRightBorder<ImageType, FilterType>(I, i, j, filter, size);
}
}
}
}
template<typename ImageType, typename FilterType>
inline FilterType filterY(
const vpImage<ImageType> &I,
unsigned int r,
unsigned int c,
const FilterType *filter,
unsigned int size)
{
const unsigned int stop = (size - 1) / 2;
FilterType result = static_cast<FilterType>(0.);
for (unsigned int i = 1; i <= stop; ++i) {
result += filter[i] * static_cast<FilterType>(I[r + i][c] + I[r - i][c]);
}
return result + (filter[0] * static_cast<FilterType>(I[r][c]));
}
template<typename ImageType, typename FilterType>
inline FilterType filterYTopBorder(
const vpImage<ImageType> &I,
unsigned int r,
unsigned int c,
const FilterType *filter, unsigned int size)
{
const unsigned int stop = (size - 1) / 2;
FilterType result = static_cast<FilterType>(0.);
for (unsigned int i = 1; i <= stop; ++i) {
if (r > i) {
result += filter[i] * static_cast<FilterType>(I[r + i][c] + I[r - i][c]);
}
else {
result += filter[i] * static_cast<FilterType>(I[r + i][c] + I[i - r][c]);
}
}
return result + (filter[0] * static_cast<FilterType>(I[r][c]));
}
template<typename ImageType, typename FilterType>
inline FilterType filterYBottomBorder(
const vpImage<ImageType> &I,
unsigned int r,
unsigned int c,
const FilterType *filter, unsigned int size)
{
const unsigned int height = I.getHeight();
const unsigned int stop = (size - 1) / 2;
FilterType result = static_cast<FilterType>(0.);
const unsigned int twiceHeight = 2 * height;
for (unsigned int i = 1; i <= stop; ++i) {
if ((r + i) < height) {
result += filter[i] * static_cast<FilterType>(I[r + i][c] + I[r - i][c]);
}
else {
result += filter[i] * static_cast<FilterType>(I[(twiceHeight - r) - i - 1][c] + I[r - i][c]);
}
}
return result + (filter[0] * static_cast<FilterType>(I[r][c]));
}
template<typename ImageType, typename FilterType>
{
const unsigned int height = I.getHeight(), width = I.getWidth();
const unsigned int stop1I = (size - 1) / 2;
const unsigned int stop2I = height - ((size - 1) / 2);
resizeAndInitializeIfNeeded(p_mask, height, width, dIy);
for (unsigned int i = 0; i < stop1I; ++i) {
for (unsigned int j = 0; j < width; ++j) {
bool computeVal = checkBooleanMask(p_mask, i, j);
if (computeVal) {
dIy[i][j] = filterYTopBorder<ImageType, FilterType>(I, i, j, filter, size);
}
}
}
for (unsigned int i = stop1I; i < stop2I; ++i) {
for (unsigned int j = 0; j < width; ++j) {
bool computeVal = checkBooleanMask(p_mask, i, j);
if (computeVal) {
dIy[i][j] = filterY<ImageType, FilterType>(I, i, j, filter, size);
}
}
}
for (unsigned int i = stop2I; i < height; ++i) {
for (unsigned int j = 0; j < width; ++j) {
bool computeVal = checkBooleanMask(p_mask, i, j);
if (computeVal) {
dIy[i][j] = filterYBottomBorder<ImageType, FilterType>(I, i, j, filter, size);
}
}
}
}
{
if (size-1 > I.getWidth() || size-1 > I.getHeight()) {
std::ostringstream oss;
oss << "Image size (" << I.getWidth() << "x" << I.getHeight() << ") is too small for the Gaussian kernel ("
<< "size=" << size << "), min size is " << (size-1);
}
double *fg = new double[(size + 1) / 2];
delete[] fg;
}
template<typename HSVType, bool useFullScale>
{
const unsigned int stop = (size - 1) / 2;
double result = 0.;
for (unsigned int i = 1; i <= stop; ++i) {
result += filter[i] * static_cast<double>(I[r][c + i].H + I[r][c - i].H);
}
return result + (filter[0] * static_cast<double>(I[r][c].H));
}
template<typename HSVType, bool useFullScale>
{
const unsigned int stop = (size - 1) / 2;
double result = 0.;
for (unsigned int i = 1; i <= stop; ++i) {
result += filter[i] * static_cast<double>(I[r][c + i].S + I[r][c - i].S);
}
return result + (filter[0] * static_cast<double>(I[r][c].S));
}
template<typename HSVType, bool useFullScale>
{
const unsigned int stop = (size - 1) / 2;
double result = 0.;
for (unsigned int i = 1; i <= stop; ++i) {
result += filter[i] * static_cast<double>(I[r][c + i].V + I[r][c - i].V);
}
return result + (filter[0] * static_cast<double>(I[r][c].V));
}
template<typename HSVType, bool useFullScale>
const double *filter, unsigned int size)
{
const unsigned int stop = (size - 1) / 2;
double result = 0.;
for (unsigned int i = 1; i <= stop; ++i) {
if (c > i) {
result += filter[i] * static_cast<double>(I[r][c + i].H + I[r][c - i].H);
}
else {
result += filter[i] * static_cast<double>(I[r][c + i].H + I[r][i - c].H);
}
}
return result + (filter[0] * static_cast<double>(I[r][c].H));
}
template<typename HSVType, bool useFullScale>
const double *filter, unsigned int size)
{
const unsigned int stop = (size - 1) / 2;
double result = 0.;
for (unsigned int i = 1; i <= stop; ++i) {
if (c > i) {
result += filter[i] * static_cast<double>(I[r][c + i].S + I[r][c - i].S);
}
else {
result += filter[i] * static_cast<double>(I[r][c + i].S + I[r][i - c].S);
}
}
return result + (filter[0] * static_cast<double>(I[r][c].S));
}
template<typename HSVType, bool useFullScale>
const double *filter, unsigned int size)
{
const unsigned int stop = (size - 1) / 2;
double result = 0.;
for (unsigned int i = 1; i <= stop; ++i) {
if (c > i) {
result += filter[i] * static_cast<double>(I[r][c + i].V + I[r][c - i].V);
}
else {
result += filter[i] * static_cast<double>(I[r][c + i].V + I[r][i - c].V);
}
}
return result + (filter[0] * static_cast<double>(I[r][c].V));
}
template<typename HSVType, bool useFullScale>
const double *filter, unsigned int size)
{
const unsigned int val_2 = 2;
const unsigned int stop = (size - 1) / 2;
const unsigned int width = I.getWidth();
double result = 0.;
for (unsigned int i = 1; i <= stop; ++i) {
if ((c + i) < width) {
result += filter[i] * static_cast<double>(I[r][c + i].H + I[r][c - i].H);
}
else {
result += filter[i] * static_cast<double>(I[r][((val_2 * width) - c) - i - 1].H + I[r][c - i].H);
}
}
return result + (filter[0] * static_cast<double>(I[r][c].H));
}
template<typename HSVType, bool useFullScale>
const double *filter, unsigned int size)
{
const unsigned int val_2 = 2;
const unsigned int stop = (size - 1) / 2;
const unsigned int width = I.getWidth();
double result = 0.;
for (unsigned int i = 1; i <= stop; ++i) {
if ((c + i) < width) {
result += filter[i] * static_cast<double>(I[r][c + i].S + I[r][c - i].S);
}
else {
result += filter[i] * static_cast<double>(I[r][((val_2 * width) - c) - i - 1].S + I[r][c - i].S);
}
}
return result + (filter[0] * static_cast<double>(I[r][c].S));
}
template<typename HSVType, bool useFullScale>
const double *filter, unsigned int size)
{
const unsigned int val_2 = 2;
const unsigned int stop = (size - 1) / 2;
const unsigned int width = I.getWidth();
double result = 0.;
for (unsigned int i = 1; i <= stop; ++i) {
if ((c + i) < width) {
result += filter[i] * static_cast<double>(I[r][c + i].V + I[r][c - i].V);
}
else {
result += filter[i] * static_cast<double>(I[r][(val_2 * width) - c - i - 1].V + I[r][c - i].V);
}
}
return result + (filter[0] * static_cast<double>(I[r][c].V));
}
template<typename HSVType, bool useFullScale>
{
const unsigned int heightI = I.getHeight(), widthI = I.getWidth();
const unsigned int stop1J = (size - 1) / 2;
const unsigned int stop2J = widthI - ((size - 1) / 2);
resizeAndInitializeIfNeeded(p_mask, heightI, widthI, dIx);
for (unsigned int i = 0; i < heightI; ++i) {
for (unsigned int j = 0; j < stop1J; ++j) {
bool computeVal = checkBooleanMask(p_mask, i, j);
if (computeVal) {
dIx[i][j].H = static_cast<HSVType>(filterXLeftBorderH(I, i, j, filter, size));
dIx[i][j].S = static_cast<HSVType>(filterXLeftBorderS(I, i, j, filter, size));
dIx[i][j].V = static_cast<HSVType>(filterXLeftBorderV(I, i, j, filter, size));
}
}
for (unsigned int j = stop1J; j < stop2J; ++j) {
bool computeVal = checkBooleanMask(p_mask, i, j);
if (computeVal) {
dIx[i][j].H = static_cast<HSVType>(filterXH(I, i, j, filter, size));
dIx[i][j].S = static_cast<HSVType>(filterXS(I, i, j, filter, size));
dIx[i][j].V = static_cast<HSVType>(filterXV(I, i, j, filter, size));
}
}
for (unsigned int j = stop2J; j < widthI; ++j) {
bool computeVal = checkBooleanMask(p_mask, i, j);
if (computeVal) {
dIx[i][j].H = static_cast<HSVType>(filterXRightBorderH(I, i, j, filter, size));
dIx[i][j].S = static_cast<HSVType>(filterXRightBorderS(I, i, j, filter, size));
dIx[i][j].V = static_cast<HSVType>(filterXRightBorderV(I, i, j, filter, size));
}
}
}
}
template<typename HSVType, bool useFullScale>
{
const unsigned int stop = (size - 1) / 2;
double result = 0.;
for (unsigned int i = 1; i <= stop; ++i) {
result += filter[i] * static_cast<double>(I[r + i][c].H + I[r - i][c].H);
}
return result + (filter[0] * static_cast<double>(I[r][c].H));
}
template<typename HSVType, bool useFullScale>
{
const unsigned int stop = (size - 1) / 2;
double result = 0.;
for (unsigned int i = 1; i <= stop; ++i) {
result += filter[i] * static_cast<double>(I[r + i][c].S + I[r - i][c].S);
}
return result + (filter[0] * static_cast<double>(I[r][c].S));
}
template<typename HSVType, bool useFullScale>
{
const unsigned int stop = (size - 1) / 2;
double result = 0.;
for (unsigned int i = 1; i <= stop; ++i) {
result += filter[i] * static_cast<double>(I[r + i][c].V + I[r - i][c].V);
}
return result + (filter[0] * static_cast<double>(I[r][c].V));
}
template<typename HSVType, bool useFullScale>
{
const unsigned int stop = (size - 1) / 2;
double result = 0.;
for (unsigned int i = 1; i <= stop; ++i) {
if (r > i) {
result += filter[i] * static_cast<double>(I[r + i][c].H + I[r - i][c].H);
}
else {
result += filter[i] * static_cast<double>(I[r + i][c].H + I[i - r][c].H);
}
}
return result + (filter[0] * static_cast<double>(I[r][c].H));
}
template<typename HSVType, bool useFullScale>
{
const unsigned int stop = (size - 1) / 2;
double result = 0.;
for (unsigned int i = 1; i <= stop; ++i) {
if (r > i) {
result += filter[i] * static_cast<double>(I[r + i][c].S + I[r - i][c].S);
}
else {
result += filter[i] * static_cast<double>(I[r + i][c].S + I[i - r][c].S);
}
}
return result + (filter[0] * static_cast<double>(I[r][c].S));
}
template<typename HSVType, bool useFullScale>
{
const unsigned int stop = (size - 1) / 2;
double result = 0.;
for (unsigned int i = 1; i <= stop; ++i) {
if (r > i) {
result += filter[i] * static_cast<double>(I[r + i][c].V + I[r - i][c].V);
}
else {
result += filter[i] * static_cast<double>(I[r + i][c].V + I[i - r][c].V);
}
}
return result + (filter[0] * static_cast<double>(I[r][c].V));
}
template<typename HSVType, bool useFullScale>
const double *filter, unsigned int size)
{
const unsigned int val_2 = 2;
const unsigned int height = I.getHeight();
const unsigned int stop = (size - 1) / 2;
double result = 0.;
for (unsigned int i = 1; i <= stop; ++i) {
if ((r + i) < height) {
result += filter[i] * static_cast<double>(I[r + i][c].H + I[r - i][c].H);
}
else {
result += filter[i] * static_cast<double>(I[((val_2 * height) - r) - i - 1][c].H + I[r - i][c].H);
}
}
return result + (filter[0] * static_cast<double>(I[r][c].H));
}
template<typename HSVType, bool useFullScale>
const double *filter, unsigned int size)
{
const unsigned int val_2 = 2;
const unsigned int height = I.getHeight();
const unsigned int stop = (size - 1) / 2;
double result = 0.;
for (unsigned int i = 1; i <= stop; ++i) {
if ((r + i) < height) {
result += filter[i] * static_cast<double>(I[r + i][c].S + I[r - i][c].S);
}
else {
result += filter[i] * static_cast<double>(I[((val_2 * height) - r) - i - 1][c].S + I[r - i][c].S);
}
}
return result + (filter[0] * static_cast<double>(I[r][c].S));
}
template<typename HSVType, bool useFullScale>
const double *filter, unsigned int size)
{
const unsigned int val_2 = 2;
const unsigned int height = I.getHeight();
const unsigned int stop = (size - 1) / 2;
double result = 0.;
for (unsigned int i = 1; i <= stop; ++i) {
if ((r + i) < height) {
result += filter[i] * static_cast<double>(I[r + i][c].V + I[r - i][c].V);
}
else {
result += filter[i] * static_cast<double>(I[((val_2 * height) - r) - i - 1][c].V + I[r - i][c].V);
}
}
return result + (filter[0] * static_cast<double>(I[r][c].V));
}
template<typename HSVType, bool useFullScale>
{
const unsigned int heightI = I.getHeight(), widthI = I.getWidth();
const unsigned int stop1I = (size - 1) / 2;
const unsigned int stop2I = heightI - ((size - 1) / 2);
resizeAndInitializeIfNeeded(p_mask, heightI, widthI, dIy);
for (unsigned int i = 0; i < stop1I; ++i) {
for (unsigned int j = 0; j < widthI; ++j) {
bool computeVal = checkBooleanMask(p_mask, i, j);
if (computeVal) {
dIy[i][j].H = static_cast<HSVType>(filterYTopBorderH(I, i, j, filter, size));
dIy[i][j].S = static_cast<HSVType>(filterYTopBorderS(I, i, j, filter, size));
dIy[i][j].V = static_cast<HSVType>(filterYTopBorderV(I, i, j, filter, size));
}
}
}
for (unsigned int i = stop1I; i < stop2I; ++i) {
for (unsigned int j = 0; j < widthI; ++j) {
bool computeVal = checkBooleanMask(p_mask, i, j);
if (computeVal) {
dIy[i][j].H = static_cast<HSVType>(filterYH(I, i, j, filter, size));
dIy[i][j].S = static_cast<HSVType>(filterYS(I, i, j, filter, size));
dIy[i][j].V = static_cast<HSVType>(filterYV(I, i, j, filter, size));
}
}
}
for (unsigned int i = stop2I; i < heightI; ++i) {
for (unsigned int j = 0; j < widthI; ++j) {
bool computeVal = checkBooleanMask(p_mask, i, j);
if (computeVal) {
dIy[i][j].H = static_cast<HSVType>(filterYBottomBorderH(I, i, j, filter, size));
dIy[i][j].S = static_cast<HSVType>(filterYBottomBorderS(I, i, j, filter, size));
dIy[i][j].V = static_cast<HSVType>(filterYBottomBorderV(I, i, j, filter, size));
}
}
}
}
template<typename HSVType, bool useFullScale>
{
double *fg = new double[(size + 1) / 2];
delete[] fg;
}
template <typename ImageType, typename FilterType>
{
FilterType *fg = new FilterType[(size + 1) / 2];
delete[] fg;
}
}
#endif
int main()
{
bool isSuccess = true;
vpHSVTests::vpInputDataset dataset;
for (unsigned int size = 3; (size < 7) && isSuccess; size += 2) {
for (auto input: dataset.m_ucImages) {
vpHSVTests::print(input.second.m_I, input.first);
vpOldImageFilter::gaussianBlur(input.second.m_I, Iuc_filtered_old, size);
bool ucSuccess = vpHSVTests::areAlmostEqual(Iuc_filtered_old, "Iuc_filtered_old", Iuc_filtered_new, "Iuc_filtered_new");
isSuccess = isSuccess && ucSuccess;
if (!isSuccess) {
std::cerr << "ERROR: filter on uchar failed ! " << std::endl;
}
}
vpOldImageFilter::gaussianBlur(Irgba, Irgba_filtered_old, size);
bool rgbaSuccess = vpHSVTests::areAlmostEqual(Irgba_filtered_old, "Irgba_filtered_old", Irgba_filtered_new, "Irgba_filtered_new");
isSuccess = isSuccess && rgbaSuccess;
if (!rgbaSuccess) {
std::cerr << "ERROR: filter on RGBa failed ! " << std::endl;
}
for (auto input: dataset.m_hsvUCtrue) {
vpHSVTests::print(input.second.m_I, input.first);
vpOldImageFilter::gaussianBlur(input.second.m_I, Ihsv_uc_filtered_old_true, size);
bool hsvucSuccessTrue = vpHSVTests::areAlmostEqual(Ihsv_uc_filtered_old_true, "Ihsv_uc_filtered_old_true", Ihsv_uc_filtered_new_true, "Ihsv_uc_filtered_new_true");
isSuccess = isSuccess && hsvucSuccessTrue;
if (!hsvucSuccessTrue) {
std::cerr << "ERROR: filter on HSV<uchar, true> failed ! " << std::endl;
}
}
for (auto input: dataset.m_hsvUCfalse) {
vpHSVTests::print(input.second.m_I, input.first);
vpOldImageFilter::gaussianBlur(input.second.m_I, Ihsv_uc_filtered_old_false, size);
bool hsvucSuccessTrue = vpHSVTests::areAlmostEqual(Ihsv_uc_filtered_old_false, "Ihsv_uc_filtered_old_false", Ihsv_uc_filtered_new_false, "Ihsv_uc_filtered_new_false");
isSuccess = isSuccess && hsvucSuccessTrue;
if (!hsvucSuccessTrue) {
std::cerr << "ERROR: filter on HSV<uchar, false> failed ! " << std::endl;
}
}
for (auto input: dataset.m_hsvDouble) {
vpHSVTests::print(input.second.m_I, input.first);
vpOldImageFilter::gaussianBlur(input.second.m_I, Ihsv_double_filtered_old, size);
bool hsvucSuccessTrue = vpHSVTests::areAlmostEqual(Ihsv_double_filtered_old, "Ihsv_double_filtered_old", Ihsv_double_filtered_new, "Ihsv_double_filtered_new");
isSuccess = isSuccess && hsvucSuccessTrue;
if (!hsvucSuccessTrue) {
std::cerr << "ERROR: filter on HSV<double> failed ! " << std::endl;
}
}
}
if (isSuccess) {
std::cout << "All tests were successful !" << std::endl;
return EXIT_SUCCESS;
}
std::cerr << "ERROR: Something went wrong !" << std::endl;
return EXIT_FAILURE;
}
#else
int main()
{
std::cout << "vpHSV class is not available, please use CXX 11 standard" << std::endl;
return EXIT_SUCCESS;
}
#endif
error that can be emitted by ViSP classes.
@ dimensionError
Bad dimension.
Class implementing the HSV pixel format.
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.