40#include <visp3/core/vpColorGetter.h>
41#include <visp3/core/vpImage.h>
43#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
47#ifndef DOXYGEN_SHOULD_SKIP_THIS
59inline typename std::enable_if<std::is_arithmetic<T>::value,
double>::type
error(
const T &a,
const T &b)
61 return std::abs(a - b);
73template<
typename Tp,
int I = 0>
74inline typename std::enable_if<I == Tp::nbChannels, double>::type
error(
const Tp &t1,
const Tp &t2)
90template<
typename Tp,
int I = 0>
91inline typename std::enable_if<I < Tp::nbChannels, double>::type
error(
const Tp &t1,
const Tp &t2)
95 const double den = 1. / Tp::nbChannels;
96 double err = den * std::abs(val1 - val2) + error<Tp, I + 1>(t1, t2);
111bool areAlmostEqual(
const vpImage<T> &I1,
const std::string &nameI1,
const vpImage<T> &I2,
const std::string &nameI2,
const double &thresh = 1e-3)
113 bool areEqual =
true;
115 std::cerr <<
"ERROR: Image width differ." << std::endl;
119 std::cerr <<
"ERROR: Image height differ." << std::endl;
123 for (
unsigned int r = 0; (
r <
height) && areEqual; ++
r) {
124 for (
unsigned int c = 0; (c <
width) && areEqual; ++c) {
125 double err =
error(I1[r][c], I2[r][c]);
127 std::cerr <<
"ERROR: Error (" << err <<
") > thresh (" << thresh <<
")" << std::endl;
128 std::cerr <<
"\t" << nameI1 <<
"[" <<
r <<
"][" << c <<
"] = (" << I1[
r][c] <<
") , " << nameI2 <<
"[" <<
r <<
"][" << c <<
"] = (" << I2[
r][c] <<
")" << std::endl;
143template<
typename ArithmeticType,
bool useFullScale>
144void print(
const vpImage<vpHSV<ArithmeticType, useFullScale>> &I,
const std::string &name)
146 std::cout << name <<
" = " << std::endl;
148 for (
unsigned int r = 0;
r < nbRows; ++
r) {
149 for (
unsigned int c = 0; c < nbCols; ++c) {
150 std::string character;
155 double val =
static_cast<double>(I[
r][c].H);
156 if (val > 0 && val < 1.) {
159 character = std::to_string(
static_cast<unsigned int>(val));
161 std::cout << character <<
" ";
163 std::cout << std::endl;
165 std::cout << std::endl;
174template<
typename ArithmeticType>
175void print(
const vpImage<ArithmeticType> &I,
const std::string &name)
177 std::cout << name <<
" = " << std::endl;
179 for (
unsigned int r = 0;
r < nbRows; ++
r) {
180 for (
unsigned int c = 0; c < nbCols; ++c) {
185 else if (I[r][c] > 0) {
191 std::cout << character <<
" ";
193 std::cout << std::endl;
195 std::cout << std::endl << std::flush;
203void print(
const vpImage<unsigned char> &I,
const std::string &name)
205 std::cout << name <<
" = " << std::endl;
207 for (
unsigned int r = 0;
r < nbRows; ++
r) {
208 for (
unsigned int c = 0; c < nbCols; ++c) {
209 std::cout << std::to_string(I[r][c]) <<
" ";
211 std::cout << std::endl;
213 std::cout << std::endl << std::flush;
216template <
typename ImageType>
219 std::string m_errorMsg;
220 vpImage<ImageType> m_I;
222 vpInputImage(
const std::string &errMsg =
"",
const vpImage<ImageType> &I = vpImage<ImageType>())
228typedef struct vpInputDataset
230 std::vector<std::pair<std::string, vpInputImage<unsigned char>>> m_ucImages;
231 std::vector<std::pair<std::string, vpInputImage<vpHSV<unsigned char, true>>>> m_hsvUCtrue;
232 std::vector<std::pair<std::string, vpInputImage<vpHSV<unsigned char, false>>>> m_hsvUCfalse;
233 std::vector<std::pair<std::string, vpInputImage<vpHSV<double>>>> m_hsvDouble;
234 vpImage<bool> m_Imask;
238 vpImage<vpHSV<unsigned char, true>> Ihsv_uc_true_square(11, 11, vpHSV<unsigned char, true>(0U, 0U, 0U));
239 vpImage<vpHSV<unsigned char, true>> Ihsv_uc_true_inversed = Ihsv_uc_true_square;
240 vpImage<vpHSV<unsigned char, true>> Ihsv_uc_true_horizontal = Ihsv_uc_true_square;
241 vpImage<vpHSV<unsigned char, true>> Ihsv_uc_true_vertical = Ihsv_uc_true_square;
242 vpImage<vpHSV<unsigned char, true>> Ihsv_uc_true_pyramid = Ihsv_uc_true_square;
244 vpImage<vpHSV<unsigned char, false>> Ihsv_uc_false_square(11, 11, vpHSV<unsigned char, false>(0U, 0U, 0U));
245 vpImage<vpHSV<unsigned char, false>> Ihsv_uc_false_inversed = Ihsv_uc_false_square;
246 vpImage<vpHSV<unsigned char, false>> Ihsv_uc_false_horizontal = Ihsv_uc_false_square;
247 vpImage<vpHSV<unsigned char, false>> Ihsv_uc_false_vertical = Ihsv_uc_false_square;
248 vpImage<vpHSV<unsigned char, false>> Ihsv_uc_false_pyramid = Ihsv_uc_false_square;
250 vpImage<vpHSV<double>> Ihsv_square(11, 11, vpHSV<double>(0., 0., 0.));
251 vpImage<vpHSV<double>> Ihsv_square_inversed = Ihsv_square;
252 vpImage<vpHSV<double>> Ihsv_square_horizontal = Ihsv_square;
253 vpImage<vpHSV<double>> Ihsv_square_vertical = Ihsv_square;
254 vpImage<vpHSV<double>> Ihsv_pyramid = Ihsv_square;
256 vpImage<unsigned char> Iuc_square(11, 11, 0);
257 vpImage<unsigned char> Iuc_square_inversed = Iuc_square;
258 vpImage<unsigned char> Iuc_square_horizontal = Iuc_square;
259 vpImage<unsigned char> Iuc_square_vertical = Iuc_square;
260 vpImage<unsigned char> Iuc_pyramid = Iuc_square;
262 m_Imask.
resize(11, 11,
false);
264 for (
unsigned int r = 2;
r <=8; ++
r) {
265 for (
unsigned int c = 2; c <= 8; ++c) {
266 if ((r == 2) || (r == 3) || (r==7) || (r == 8)) {
267 m_Imask[
r][c] =
true;
269 if ((c == 2) || (c == 3) || (c==7) || (c == 8)) {
270 m_Imask[
r][c] =
true;
272 double val = 0., val_inversed = 0., val_pyramid = 0.;
273 unsigned char val_c = 0, val_c_inversed = 0, val_c_pyramid = 0;
275 val = 0.1 *
static_cast<double>(c - 1);
276 val_inversed = 0.1 *
static_cast<double>(6 - c);
278 val_c_inversed = 6 - c;
281 val = 0.1 *
static_cast<double>(9 - c);
282 val_inversed = 0.1 *
static_cast<double>(c - 4);
284 val_c_inversed = c - 4;
287 val_pyramid = val + 0.1 * (
r - 2);
288 val_c_pyramid = val_c +
r - 2;
291 val_pyramid = val + 0.1 * (8 -
r);
292 val_c_pyramid = val_c + 8 -
r;
294 if ((r == 2) || (r == 8) ) {
296 Ihsv_square[
r][c] = vpHSV<double>(val, val, val);
297 Ihsv_square_inversed[
r][c] = vpHSV<double>(val_inversed, val_inversed, val_inversed);
298 Ihsv_square[c][
r] = vpHSV<double>(val, val, val);
299 Ihsv_square_inversed[c][
r] = vpHSV<double>(val_inversed, val_inversed, val_inversed);
301 Ihsv_uc_false_square[
r][c] = vpHSV<unsigned char, false>(val_c, val_c, val_c);
302 Ihsv_uc_false_inversed[
r][c] = vpHSV<unsigned char, false>(val_c_inversed, val_c_inversed, val_c_inversed);
303 Ihsv_uc_false_square[c][
r] = vpHSV<unsigned char, false>(val_c, val_c, val_c);
304 Ihsv_uc_false_inversed[c][
r] = vpHSV<unsigned char, false>(val_c_inversed, val_c_inversed, val_c_inversed);
306 Ihsv_uc_true_square[
r][c] = vpHSV<unsigned char, true>(val_c, val_c, val_c);
307 Ihsv_uc_true_inversed[
r][c] = vpHSV<unsigned char, true>(val_c_inversed, val_c_inversed, val_c_inversed);
308 Ihsv_uc_true_square[c][
r] = vpHSV<unsigned char, true>(val_c, val_c, val_c);
309 Ihsv_uc_true_inversed[c][
r] = vpHSV<unsigned char, true>(val_c_inversed, val_c_inversed, val_c_inversed);
311 Iuc_square[
r][c] = val_c;
312 Iuc_square_inversed[
r][c] = val_c_inversed;
313 Iuc_square[c][
r] = val_c;
314 Iuc_square_inversed[c][
r] = val_c_inversed;
316 Ihsv_square_horizontal[
r][c] = vpHSV<double>(val, val, val);
317 Ihsv_uc_true_horizontal[
r][c] = vpHSV<unsigned char, true>(val_c, val_c, val_c);
318 Ihsv_uc_false_horizontal[
r][c] = vpHSV<unsigned char, false>(val_c, val_c, val_c);
319 Iuc_square_horizontal[
r][c] = val_c;
321 Ihsv_square_vertical[c][
r] = vpHSV<double>(val, val, val);
322 Ihsv_uc_true_vertical[c][
r] = vpHSV<unsigned char, true>(val_c, val_c, val_c);
323 Ihsv_uc_false_vertical[c][
r] = vpHSV<unsigned char, false>(val_c, val_c, val_c);
324 Iuc_square_vertical[c][
r] = val_c;
326 Ihsv_pyramid[
r][c] = vpHSV<double>(val_pyramid, val_pyramid, val_pyramid);
327 Ihsv_uc_true_pyramid[
r][c] = vpHSV<unsigned char, true>(val_c_pyramid, val_c_pyramid, val_c_pyramid);
328 Ihsv_uc_false_pyramid[
r][c] = vpHSV<unsigned char, false>(val_c_pyramid, val_c_pyramid, val_c_pyramid);
329 Iuc_pyramid[
r][c] = val_c_pyramid;
332 m_ucImages.emplace_back(
"Iuc_square", vpInputImage<unsigned char>(
"", Iuc_square));
333 m_ucImages.emplace_back(
"Iuc_square_inversed", vpInputImage<unsigned char>(
"", Iuc_square_inversed));
334 m_ucImages.emplace_back(
"Iuc_square_horizontal", vpInputImage<unsigned char>(
"GX is expected to have values on the whole surface of the square, GY only on the borders", Iuc_square_horizontal));
335 m_ucImages.emplace_back(
"Iuc_square_vertical", vpInputImage<unsigned char>(
"GY is expected to have values on the whole surface of the square, GX only on the borders", Iuc_square_vertical));
336 m_ucImages.emplace_back(
"Iuc_pyramid", vpInputImage<unsigned char>(
"GX and GY are expected to have values on the whole square", Iuc_pyramid));
338 m_hsvUCtrue.emplace_back(
"Ihsv_uc_true_square", vpInputImage<vpHSV<unsigned char, true>>(
"", Ihsv_uc_true_square));
339 m_hsvUCtrue.emplace_back(
"Ihsv_uc_true_inversed", vpInputImage<vpHSV<unsigned char, true>>(
"", Ihsv_uc_true_inversed));
340 m_hsvUCtrue.emplace_back(
"Ihsv_uc_true_horizontal", vpInputImage<vpHSV<unsigned char, true>>(
"GX is expected to have values on the whole surface of the square, GY only on the borders", Ihsv_uc_true_horizontal));
341 m_hsvUCtrue.emplace_back(
"Ihsv_uc_true_vertical", vpInputImage<vpHSV<unsigned char, true>>(
"GY is expected to have values on the whole surface of the square, GX only on the borders", Ihsv_uc_true_vertical));
342 m_hsvUCtrue.emplace_back(
"Ihsv_uc_true_pyramid", vpInputImage<vpHSV<unsigned char, true>>(
"GX and GY are expected to have values on the whole square", Ihsv_uc_true_pyramid));
344 m_hsvUCfalse.emplace_back(
"Ihsv_uc_false_square", vpInputImage<vpHSV<unsigned char, false>>(
"", Ihsv_uc_false_square));
345 m_hsvUCfalse.emplace_back(
"Ihsv_uc_false_inversed", vpInputImage<vpHSV<unsigned char, false>>(
"", Ihsv_uc_false_inversed));
346 m_hsvUCfalse.emplace_back(
"Ihsv_uc_false_horizontal", vpInputImage<vpHSV<unsigned char, false>>(
"GX is expected to have values on the whole surface of the square, GY only on the borders", Ihsv_uc_false_horizontal));
347 m_hsvUCfalse.emplace_back(
"Ihsv_uc_false_vertical", vpInputImage<vpHSV<unsigned char, false>>(
"GY is expected to have values on the whole surface of the square, GX only on the borders", Ihsv_uc_false_vertical));
348 m_hsvUCfalse.emplace_back(
"Ihsv_uc_false_pyramid", vpInputImage<vpHSV<unsigned char, false>>(
"GX and GY are expected to have values on the whole square", Ihsv_uc_false_pyramid));
350 m_hsvDouble.emplace_back(
"I_hsv_double_square", vpInputImage<vpHSV<double>>(
"", Ihsv_square));
351 m_hsvDouble.emplace_back(
"Ihsv_double_square_inversed", vpInputImage<vpHSV<double>>(
"", Ihsv_square_inversed));
352 m_hsvDouble.emplace_back(
"Ihsv_double_horizontal", vpInputImage<vpHSV<double>>(
"GX is expected to have values on the whole surface of the square, GY only on the borders", Ihsv_square_horizontal));
353 m_hsvDouble.emplace_back(
"Ihsv_double_vertical", vpInputImage<vpHSV<double>>(
"GY is expected to have values on the whole surface of the square, GX only on the borders", Ihsv_square_vertical));
354 m_hsvDouble.emplace_back(
"Ihsv_double_pyramid", vpInputImage<vpHSV<double>>(
"GX and GY are expected to have values on the whole square", Ihsv_pyramid));
static ArithmeticType & get(vpHSV< ArithmeticType, useFullScale > &col)
Setter for a channel of a HSV pixel.
unsigned int getWidth() const
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
unsigned int getCols() const
unsigned int getHeight() const
unsigned int getRows() const
static bool nul(double x, double threshold=0.001)