Visual Servoing Platform  version 3.4.0
testImageWarp.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2019 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See http://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description:
32  * Test image warping.
33  *
34  *****************************************************************************/
35 
42 #include <visp3/core/vpConfig.h>
43 
44 #if defined(VISP_HAVE_CATCH2)
45 #define CATCH_CONFIG_RUNNER
46 #include <catch.hpp>
47 
48 #include <iostream>
49 #include <visp3/core/vpImageTools.h>
50 #include <visp3/core/vpIoTools.h>
51 #include <visp3/io/vpImageIo.h>
52 
53 namespace
54 {
55 static const double g_threshold_value = 0.5;
56 static const double g_threshold_percentage = 0.9;
57 static const double g_threshold_percentage_bilinear = 0.75;
58 static const double g_threshold_percentage_pers = 0.75;
59 static const double g_threshold_percentage_pers_bilinear = 0.65;
60 
61 static const std::vector<vpImageTools::vpImageInterpolationType> interp_methods = {vpImageTools::INTERPOLATION_NEAREST,
63 static const std::vector<std::string> interp_names = {"Nearest Neighbor", "Bilinear"};
64 static const std::vector<std::string> suffixes = { "_NN.png", "_bilinear.png" };
65 
66 bool almostEqual(const vpImage<unsigned char>& I1, const vpImage<unsigned char>& I2, double threshold_val,
67  double threshold_percentage, double& percentage)
68 {
69  double nb_valid = 0;
70 
71  if (I1.getHeight() != I2.getHeight() || I1.getWidth() != I2.getWidth()) {
72  return false;
73  }
74 
75  for (unsigned int i = 0; i < I1.getHeight(); i++) {
76  for (unsigned int j = 0; j < I1.getWidth(); j++) {
77  nb_valid += vpMath::abs(I1[i][j] - I2[i][j]) < threshold_val ? 1 : 0;
78  }
79  }
80 
81  percentage = nb_valid / I1.getSize();
82  return percentage >= threshold_percentage;
83 }
84 
85 bool almostEqual(const vpImage<vpRGBa>& I1, const vpImage<vpRGBa>& I2, double threshold_val,
86  double threshold_percentage, double& percentage)
87 {
88  double nb_valid = 0;
89 
90  if (I1.getHeight() != I2.getHeight() || I1.getWidth() != I2.getWidth()) {
91  return false;
92  }
93 
94  for (unsigned int i = 0; i < I1.getHeight(); i++) {
95  for (unsigned int j = 0; j < I1.getWidth(); j++) {
96  if (vpMath::abs(I1[i][j].R - I2[i][j].R) < threshold_val) {
97  nb_valid++;
98  }
99  if (vpMath::abs(I1[i][j].G - I2[i][j].G) < threshold_val) {
100  nb_valid++;
101  }
102  if (vpMath::abs(I1[i][j].B - I2[i][j].B) < threshold_val) {
103  nb_valid++;
104  }
105  }
106  }
107 
108  percentage = nb_valid / (3*I1.getSize());
109  return percentage >= threshold_percentage;
110 }
111 }
112 
113 TEST_CASE("Affine warp on grayscale", "[warp_image]") {
114  const std::string imgPath = vpIoTools::createFilePath(vpIoTools::getViSPImagesDataPath(), "Klimt/Klimt.pgm");
115  REQUIRE(vpIoTools::checkFilename(imgPath));
116 
118  vpImageIo::read(I, imgPath);
119  REQUIRE(I.getSize() > 0);
120 
121  SECTION("Identity")
122  {
123  vpMatrix M(2, 3);
124  M.eye();
125 
126  for (size_t i = 0; i < interp_methods.size(); i++) {
127  SECTION(interp_names[i])
128  {
129  SECTION("Empty destination")
130  {
131  vpImage<unsigned char> I_affine;
132  vpImageTools::warpImage(I, M, I_affine, interp_methods[i]);
133  CHECK((I == I_affine));
134  }
135 
136  SECTION("Initialized destination")
137  {
138  vpImage<unsigned char> I_affine(I.getHeight(), I.getWidth(), 0);
139  vpImageTools::warpImage(I, M, I_affine, interp_methods[i]);
140  CHECK((I == I_affine));
141  }
142  }
143  }
144  }
145 
146  SECTION("Rotation 45 deg")
147  {
148  vpMatrix M(2, 3);
149  M.eye();
150 
151  const double theta = vpMath::rad(45);
152  M[0][0] = cos(theta); M[0][1] = -sin(theta); M[0][2] = I.getWidth() / 2.0;
153  M[1][0] = sin(theta); M[1][1] = cos(theta); M[1][2] = I.getHeight() / 2.0;
154 
155  for (size_t i = 0; i < interp_methods.size(); i++) {
156  SECTION(interp_names[i])
157  {
158  SECTION("Against reference implementation")
159  {
161  vpImageTools::warpImage(I, M, I_ref, interp_methods[i], false);
162 
163  vpImage<unsigned char> I_affine;
164  vpImageTools::warpImage(I, M, I_affine, interp_methods[i]);
165 
166  double percentage = 0.0;
167  bool equal = almostEqual(I_ref, I_affine, g_threshold_value, g_threshold_percentage, percentage);
168  std::cout << "Percentage valid pixels (45 deg " << interp_names[i] << " Ref): " << percentage << std::endl;
169  CHECK(equal);
170  }
171 
172  SECTION("Against OpenCV")
173  {
174  const std::string refImgPath = vpIoTools::createFilePath(vpIoTools::getViSPImagesDataPath(),
175  std::string("warp/cv_warp_affine_rot_45_gray" + suffixes[i]));
176  REQUIRE(vpIoTools::checkFilename(refImgPath));
177  vpImage<unsigned char> I_ref_opencv;
178  vpImageIo::read(I_ref_opencv, refImgPath);
179 
180  vpImage<unsigned char> I_affine;
181  vpImageTools::warpImage(I, M, I_affine, interp_methods[i]);
182 
183  double percentage = 0.0;
184  bool equal = almostEqual(I_ref_opencv, I_affine, g_threshold_value, (i == 0) ? g_threshold_percentage : g_threshold_percentage_bilinear, percentage);
185  std::cout << "Percentage valid pixels (45 deg " << interp_names[i] << " OpenCV): " << percentage << std::endl;
186  CHECK(equal);
187  }
188 
189  SECTION("Against PIL")
190  {
191  const std::string refImgPath = vpIoTools::createFilePath(vpIoTools::getViSPImagesDataPath(),
192  std::string("warp/pil_warp_affine_rot_45_gray" + suffixes[i]));
193  REQUIRE(vpIoTools::checkFilename(refImgPath));
194  vpImage<unsigned char> I_ref_pil;
195  vpImageIo::read(I_ref_pil, refImgPath);
196 
197  vpImage<unsigned char> I_affine;
198  vpImageTools::warpImage(I, M, I_affine, interp_methods[i], false, true);
199 
200  double percentage = 0.0;
201  bool equal = almostEqual(I_ref_pil, I_affine, g_threshold_value, (i == 0) ? g_threshold_percentage : g_threshold_percentage_bilinear, percentage);
202  std::cout << "Percentage valid pixels (45 deg " << interp_names[i] << " PIL): " << percentage << std::endl;
203  CHECK(equal);
204  }
205  }
206  }
207  }
208 
209  SECTION("SRT")
210  {
211  vpMatrix M(2, 3);
212  M.eye();
213 
214  const double theta = vpMath::rad(-67);
215  const double scale = 0.83;
216  M[0][0] = scale*cos(theta); M[0][1] = -scale*sin(theta); M[0][2] = I.getWidth() / 2.0 + 17;
217  M[1][0] = scale*sin(theta); M[1][1] = scale*cos(theta); M[1][2] = I.getHeight() / 2.0 - 23;
218 
219  for (size_t i = 0; i < interp_methods.size(); i++) {
220  SECTION(interp_names[i])
221  {
222  SECTION("Against reference implementation")
223  {
225  vpImageTools::warpImage(I, M, I_ref, interp_methods[i], false);
226 
227  vpImage<unsigned char> I_affine;
228  vpImageTools::warpImage(I, M, I_affine, interp_methods[i]);
229 
230  double percentage = 0.0;
231  bool equal = almostEqual(I_ref, I_affine, g_threshold_value, g_threshold_percentage, percentage);
232  std::cout << "Percentage valid pixels (SRT " << interp_names[i] << " Ref): " << percentage << std::endl;
233  CHECK(equal);
234  }
235 
236  SECTION("Against OpenCV")
237  {
238  const std::string refImgPath = vpIoTools::createFilePath(vpIoTools::getViSPImagesDataPath(),
239  std::string("warp/cv_warp_affine_SRT_gray" + suffixes[i]));
240  REQUIRE(vpIoTools::checkFilename(refImgPath));
241  vpImage<unsigned char> I_ref_opencv;
242  vpImageIo::read(I_ref_opencv, refImgPath);
243 
244  vpImage<unsigned char> I_affine;
245  vpImageTools::warpImage(I, M, I_affine, interp_methods[i]);
246 
247  double percentage = 0.0;
248  bool equal = almostEqual(I_ref_opencv, I_affine, g_threshold_value, (i == 0) ? g_threshold_percentage : g_threshold_percentage_bilinear, percentage);
249  std::cout << "Percentage valid pixels (SRT " << interp_names[i] << " OpenCV): " << percentage << std::endl;
250  CHECK(equal);
251  }
252 
253  SECTION("Against PIL")
254  {
255  const std::string refImgPath = vpIoTools::createFilePath(vpIoTools::getViSPImagesDataPath(),
256  std::string("warp/pil_warp_affine_SRT_gray" + suffixes[i]));
257  REQUIRE(vpIoTools::checkFilename(refImgPath));
258  vpImage<unsigned char> I_ref_pil;
259  vpImageIo::read(I_ref_pil, refImgPath);
260 
261  vpImage<unsigned char> I_affine;
262  vpImageTools::warpImage(I, M, I_affine, interp_methods[i], false, true);
263 
264  double percentage = 0.0;
265  bool equal = almostEqual(I_ref_pil, I_affine, g_threshold_value, (i == 0) ? g_threshold_percentage : g_threshold_percentage_bilinear, percentage);
266  std::cout << "Percentage valid pixels (SRT " << interp_names[i] << " PIL): " << percentage << std::endl;
267  CHECK(equal);
268  }
269  }
270  }
271  }
272 }
273 
274 TEST_CASE("Affine warp on color", "[warp_image]") {
275  const std::string imgPath = vpIoTools::createFilePath(vpIoTools::getViSPImagesDataPath(), "Klimt/Klimt.ppm");
276  REQUIRE(vpIoTools::checkFilename(imgPath));
277 
278  vpImage<vpRGBa> I;
279  vpImageIo::read(I, imgPath);
280  REQUIRE(I.getSize() > 0);
281 
282  SECTION("Identity")
283  {
284  vpMatrix M(2, 3);
285  M.eye();
286 
287  for (size_t i = 0; i < interp_methods.size(); i++) {
288  SECTION(interp_names[i])
289  {
290  SECTION("Empty destination")
291  {
292  vpImage<vpRGBa> I_affine;
293  vpImageTools::warpImage(I, M, I_affine, interp_methods[i]);
294  CHECK((I == I_affine));
295  }
296 
297  SECTION("Initialized destination")
298  {
299  vpImage<vpRGBa> I_affine(I.getHeight(), I.getWidth(), vpRGBa(0));
300  vpImageTools::warpImage(I, M, I_affine, interp_methods[i]);
301  CHECK((I == I_affine));
302  }
303  }
304  }
305  }
306 
307  SECTION("Rotation 45 deg")
308  {
309  vpMatrix M(2, 3);
310  M.eye();
311 
312  const double theta = vpMath::rad(45);
313  M[0][0] = cos(theta); M[0][1] = -sin(theta); M[0][2] = I.getWidth() / 2.0;
314  M[1][0] = sin(theta); M[1][1] = cos(theta); M[1][2] = I.getHeight() / 2.0;
315 
316  for (size_t i = 0; i < interp_methods.size(); i++) {
317  SECTION(interp_names[i])
318  {
319  SECTION("Against reference implementation")
320  {
321  vpImage<vpRGBa> I_ref;
322  vpImageTools::warpImage(I, M, I_ref, interp_methods[i], false);
323 
324  vpImage<vpRGBa> I_affine;
325  vpImageTools::warpImage(I, M, I_affine, interp_methods[i]);
326 
327  double percentage = 0.0;
328  bool equal = almostEqual(I_ref, I_affine, g_threshold_value, g_threshold_percentage, percentage);
329  std::cout << "Percentage valid pixels (45 deg " << interp_names[i] << " Ref): " << percentage << std::endl;
330  CHECK(equal);
331  }
332 
333  SECTION("Against OpenCV")
334  {
335  const std::string refImgPath = vpIoTools::createFilePath(vpIoTools::getViSPImagesDataPath(),
336  std::string("warp/cv_warp_affine_rot_45_color" + suffixes[i]));
337  REQUIRE(vpIoTools::checkFilename(refImgPath));
338  vpImage<vpRGBa> I_ref_opencv;
339  vpImageIo::read(I_ref_opencv, refImgPath);
340 
341  vpImage<vpRGBa> I_affine;
342  vpImageTools::warpImage(I, M, I_affine, interp_methods[i]);
343 
344  double percentage = 0.0;
345  bool equal = almostEqual(I_ref_opencv, I_affine, g_threshold_value, (i == 0) ? g_threshold_percentage : g_threshold_percentage_bilinear, percentage);
346  std::cout << "Percentage valid pixels (45 deg " << interp_names[i] << " OpenCV): " << percentage << std::endl;
347  CHECK(equal);
348  }
349 
350  SECTION("Against PIL")
351  {
352  const std::string refImgPath = vpIoTools::createFilePath(vpIoTools::getViSPImagesDataPath(),
353  std::string("warp/pil_warp_affine_rot_45_color" + suffixes[i]));
354  REQUIRE(vpIoTools::checkFilename(refImgPath));
355  vpImage<vpRGBa> I_ref_pil;
356  vpImageIo::read(I_ref_pil, refImgPath);
357 
358  vpImage<vpRGBa> I_affine;
359  vpImageTools::warpImage(I, M, I_affine, interp_methods[i], false, true);
360 
361  double percentage = 0.0;
362  bool equal = almostEqual(I_ref_pil, I_affine, g_threshold_value, (i == 0) ? g_threshold_percentage : g_threshold_percentage_bilinear, percentage);
363  std::cout << "Percentage valid pixels (45 deg " << interp_names[i] << " PIL): " << percentage << std::endl;
364  CHECK(equal);
365  }
366  }
367  }
368  }
369 
370  SECTION("SRT")
371  {
372  vpMatrix M(2, 3);
373  M.eye();
374 
375  const double theta = vpMath::rad(-67);
376  const double scale = 0.83;
377  M[0][0] = scale * cos(theta); M[0][1] = -scale * sin(theta); M[0][2] = I.getWidth() / 2.0 + 17;
378  M[1][0] = scale * sin(theta); M[1][1] = scale * cos(theta); M[1][2] = I.getHeight() / 2.0 - 23;
379 
380  for (size_t i = 0; i < interp_methods.size(); i++) {
381  SECTION(interp_names[i])
382  {
383  SECTION("Against reference implementation")
384  {
385  vpImage<vpRGBa> I_ref;
386  vpImageTools::warpImage(I, M, I_ref, interp_methods[i], false);
387 
388  vpImage<vpRGBa> I_affine;
389  vpImageTools::warpImage(I, M, I_affine, interp_methods[i]);
390 
391  double percentage = 0.0;
392  bool equal = almostEqual(I_ref, I_affine, g_threshold_value, (i == 0) ? g_threshold_percentage : g_threshold_percentage_bilinear, percentage);
393  std::cout << "Percentage valid pixels (SRT " << interp_names[i] << " Ref): " << percentage << std::endl;
394  CHECK(equal);
395  }
396 
397  SECTION("Against OpenCV")
398  {
399  const std::string refImgPath = vpIoTools::createFilePath(vpIoTools::getViSPImagesDataPath(),
400  std::string("warp/cv_warp_affine_SRT_color" + suffixes[i]));
401  REQUIRE(vpIoTools::checkFilename(refImgPath));
402  vpImage<vpRGBa> I_ref_opencv;
403  vpImageIo::read(I_ref_opencv, refImgPath);
404 
405  vpImage<vpRGBa> I_affine;
406  vpImageTools::warpImage(I, M, I_affine, interp_methods[i]);
407 
408  double percentage = 0.0;
409  bool equal = almostEqual(I_ref_opencv, I_affine, g_threshold_value, (i == 0) ? g_threshold_percentage : g_threshold_percentage_bilinear, percentage);
410  std::cout << "Percentage valid pixels (SRT " << interp_names[i] << " OpenCV): " << percentage << std::endl;
411  CHECK(equal);
412  }
413 
414  SECTION("Against PIL")
415  {
416  const std::string refImgPath = vpIoTools::createFilePath(vpIoTools::getViSPImagesDataPath(),
417  std::string("warp/pil_warp_affine_SRT_color" + suffixes[i]));
418  REQUIRE(vpIoTools::checkFilename(refImgPath));
419  vpImage<vpRGBa> I_ref_pil;
420  vpImageIo::read(I_ref_pil, refImgPath);
421 
422  vpImage<vpRGBa> I_affine;
423  vpImageTools::warpImage(I, M, I_affine, interp_methods[i], false, true);
424 
425  double percentage = 0.0;
426  bool equal = almostEqual(I_ref_pil, I_affine, g_threshold_value, (i == 0) ? g_threshold_percentage : g_threshold_percentage_bilinear, percentage);
427  std::cout << "Percentage valid pixels (SRT " << interp_names[i] << " PIL): " << percentage << std::endl;
428  CHECK(equal);
429  }
430  }
431  }
432  }
433 }
434 
435 TEST_CASE("Perspective warp on grayscale", "[warp_image]") {
436  const std::string imgPath = vpIoTools::createFilePath(vpIoTools::getViSPImagesDataPath(), "Klimt/Klimt.pgm");
437  REQUIRE(vpIoTools::checkFilename(imgPath));
438 
440  vpImageIo::read(I, imgPath);
441  REQUIRE(I.getSize() > 0);
442 
443  SECTION("Identity")
444  {
445  vpMatrix M(3, 3);
446  M.eye();
447 
448  for (size_t i = 0; i < interp_methods.size(); i++) {
449  SECTION(interp_names[i])
450  {
451  SECTION("Empty destination")
452  {
453  vpImage<unsigned char> I_perspective;
454  vpImageTools::warpImage(I, M, I_perspective, interp_methods[i]);
455  CHECK((I == I_perspective));
456  }
457 
458  SECTION("Initialized destination")
459  {
460  vpImage<unsigned char> I_perspective(I.getHeight(), I.getWidth(), 0);
461  vpImageTools::warpImage(I, M, I_perspective, interp_methods[i]);
462  CHECK((I == I_perspective));
463  }
464  }
465  }
466  }
467 
468  SECTION("Rotation 45 deg")
469  {
470  vpMatrix M(3, 3);
471  M.eye();
472 
473  const double theta = vpMath::rad(45);
474  M[0][0] = cos(theta); M[0][1] = -sin(theta); M[0][2] = I.getWidth() / 2.0;
475  M[1][0] = sin(theta); M[1][1] = cos(theta); M[1][2] = I.getHeight() / 2.0;
476 
477  SECTION("Nearest Neighbor")
478  {
481 
482  vpImage<unsigned char> I_perspective;
484 
485  double percentage = 0.0;
486  bool equal = almostEqual(I_ref, I_perspective, g_threshold_value, g_threshold_percentage, percentage);
487  std::cout << "Percentage valid pixels (persp 45 deg): " << percentage << std::endl;
488  CHECK(equal);
489  }
490  }
491 
492  SECTION("Homography")
493  {
494  vpMatrix M(3, 3);
495  M.eye();
496 
497  M[0][0] = 1.8548; M[0][1] = -0.0402; M[0][2] = 114.9;
498  M[1][0] = 1.1209; M[1][1] = 4.0106; M[1][2] = 111;
499  M[2][0] = 0.0022; M[2][1] = 0.0064;
500 
501  for (size_t i = 0; i < interp_methods.size(); i++) {
502  SECTION(interp_names[i])
503  {
504  SECTION("Against reference implementation")
505  {
507  vpImageTools::warpImage(I, M, I_ref, interp_methods[i], false);
508 
509  vpImage<unsigned char> I_perspective;
510  vpImageTools::warpImage(I, M, I_perspective, interp_methods[i]);
511 
512  double percentage = 0.0;
513  bool equal = almostEqual(I_ref, I_perspective, g_threshold_value,
514  (i == 0) ? g_threshold_percentage_pers : g_threshold_percentage_pers_bilinear, percentage);
515  std::cout << "Percentage valid pixels (Homography " << interp_names[i] << " Ref): " << percentage << std::endl;
516  CHECK(equal);
517  }
518 
519  SECTION("Against OpenCV")
520  {
521  const std::string refImgPath = vpIoTools::createFilePath(vpIoTools::getViSPImagesDataPath(),
522  std::string("warp/cv_warp_perspective_gray" + suffixes[i]));
523  REQUIRE(vpIoTools::checkFilename(refImgPath));
524  vpImage<unsigned char> I_ref_opencv;
525  vpImageIo::read(I_ref_opencv, refImgPath);
526 
527  vpImage<unsigned char> I_perspective;
528  vpImageTools::warpImage(I, M, I_perspective, interp_methods[i]);
529 
530  double percentage = 0.0;
531  bool equal = almostEqual(I_ref_opencv, I_perspective, g_threshold_value,
532  (i == 0) ? g_threshold_percentage_pers : g_threshold_percentage_pers_bilinear, percentage);
533  std::cout << "Percentage valid pixels (Homography " << interp_names[i] << " OpenCV): " << percentage << std::endl;
534  CHECK(equal);
535  }
536 
537  SECTION("Against PIL")
538  {
539  const std::string refImgPath = vpIoTools::createFilePath(vpIoTools::getViSPImagesDataPath(),
540  std::string("warp/pil_warp_perspective_gray" + suffixes[i]));
541  REQUIRE(vpIoTools::checkFilename(refImgPath));
542  vpImage<unsigned char> I_ref_pil;
543  vpImageIo::read(I_ref_pil, refImgPath);
544 
545  vpImage<unsigned char> I_perspective;
546  vpImageTools::warpImage(I, M, I_perspective, interp_methods[i], false, true);
547 
548  double percentage = 0.0;
549  bool equal = almostEqual(I_ref_pil, I_perspective, g_threshold_value,
550  (i == 0) ? g_threshold_percentage_pers : g_threshold_percentage_pers_bilinear, percentage);
551  std::cout << "Percentage valid pixels (Homography " << interp_names[i] << " PIL): " << percentage << std::endl;
552  CHECK(equal);
553  }
554  }
555  }
556  }
557 }
558 
559 TEST_CASE("Perspective warp on color", "[warp_image]") {
560  const std::string imgPath = vpIoTools::createFilePath(vpIoTools::getViSPImagesDataPath(), "Klimt/Klimt.ppm");
561  REQUIRE(vpIoTools::checkFilename(imgPath));
562 
563  vpImage<vpRGBa> I;
564  vpImageIo::read(I, imgPath);
565  REQUIRE(I.getSize() > 0);
566 
567  SECTION("Identity")
568  {
569  vpMatrix M(3, 3);
570  M.eye();
571 
572  for (size_t i = 0; i < interp_methods.size(); i++) {
573  SECTION(interp_names[i])
574  {
575  SECTION("Empty destination")
576  {
577  vpImage<vpRGBa> I_perspective;
578  vpImageTools::warpImage(I, M, I_perspective, interp_methods[i]);
579  CHECK((I == I_perspective));
580  }
581 
582  SECTION("Initialized destination")
583  {
584  vpImage<vpRGBa> I_perspective(I.getHeight(), I.getWidth(), vpRGBa(0));
585  vpImageTools::warpImage(I, M, I_perspective, interp_methods[i]);
586  CHECK((I == I_perspective));
587  }
588  }
589  }
590  }
591 
592  SECTION("Homography")
593  {
594  vpMatrix M(3, 3);
595  M.eye();
596 
597  M[0][0] = 1.8548; M[0][1] = -0.0402; M[0][2] = 114.9;
598  M[1][0] = 1.1209; M[1][1] = 4.0106; M[1][2] = 111;
599  M[2][0] = 0.0022; M[2][1] = 0.0064;
600 
601  for (size_t i = 0; i < interp_methods.size(); i++) {
602  SECTION(interp_names[i])
603  {
604  SECTION("Against reference implementation")
605  {
606  vpImage<vpRGBa> I_ref;
607  vpImageTools::warpImage(I, M, I_ref, interp_methods[i], false);
608 
609  vpImage<vpRGBa> I_perspective;
610  vpImageTools::warpImage(I, M, I_perspective, interp_methods[i]);
611 
612  double percentage = 0.0;
613  bool equal = almostEqual(I_ref, I_perspective, g_threshold_value,
614  (i == 0) ? g_threshold_percentage_pers : g_threshold_percentage_pers_bilinear, percentage);
615  std::cout << "Percentage valid pixels (Homography " << interp_names[i] << " Ref): " << percentage << std::endl;
616  CHECK(equal);
617  }
618 
619  SECTION("Against OpenCV")
620  {
621  const std::string refImgPath = vpIoTools::createFilePath(vpIoTools::getViSPImagesDataPath(),
622  std::string("warp/cv_warp_perspective_color" + suffixes[i]));
623  REQUIRE(vpIoTools::checkFilename(refImgPath));
624  vpImage<vpRGBa> I_ref_opencv;
625  vpImageIo::read(I_ref_opencv, refImgPath);
626 
627  vpImage<vpRGBa> I_perspective;
628  vpImageTools::warpImage(I, M, I_perspective, interp_methods[i]);
629 
630  double percentage = 0.0;
631  bool equal = almostEqual(I_ref_opencv, I_perspective, g_threshold_value,
632  (i == 0) ? g_threshold_percentage_pers : g_threshold_percentage_pers_bilinear, percentage);
633  std::cout << "Percentage valid pixels (Homography " << interp_names[i] << " OpenCV): " << percentage << std::endl;
634  CHECK(equal);
635  }
636 
637  SECTION("Against PIL")
638  {
639  const std::string refImgPath = vpIoTools::createFilePath(vpIoTools::getViSPImagesDataPath(),
640  std::string("warp/pil_warp_perspective_color" + suffixes[i]));
641  REQUIRE(vpIoTools::checkFilename(refImgPath));
642  vpImage<vpRGBa> I_ref_pil;
643  vpImageIo::read(I_ref_pil, refImgPath);
644 
645  vpImage<vpRGBa> I_perspective;
646  vpImageTools::warpImage(I, M, I_perspective, interp_methods[i], false, true);
647 
648  double percentage = 0.0;
649  bool equal = almostEqual(I_ref_pil, I_perspective, g_threshold_value,
650  (i == 0) ? g_threshold_percentage_pers : g_threshold_percentage_pers_bilinear, percentage);
651  std::cout << "Percentage valid pixels (Homography " << interp_names[i] << " PIL): " << percentage << std::endl;
652  CHECK(equal);
653  }
654  }
655  }
656  }
657 }
658 
659 int main(int argc, char *argv[])
660 {
661  Catch::Session session; // There must be exactly one instance
662 
663  // Let Catch (using Clara) parse the command line
664  session.applyCommandLine(argc, argv);
665 
666  int numFailed = session.run();
667 
668  // numFailed is clamped to 255 as some unices only use the lower 8 bits.
669  // This clamping has already been applied, so just return it here
670  // You can also do any post run clean-up here
671  return numFailed;
672 }
673 #else
674 int main()
675 {
676  return 0;
677 }
678 #endif
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:153
static std::string getViSPImagesDataPath()
Definition: vpIoTools.cpp:1202
unsigned int getWidth() const
Definition: vpImage.h:246
Definition: vpRGBa.h:66
static Type abs(const Type &x)
Definition: vpMath.h:160
static std::string createFilePath(const std::string &parent, const std::string &child)
Definition: vpIoTools.cpp:1446
unsigned int getSize() const
Definition: vpImage.h:227
static double rad(double deg)
Definition: vpMath.h:110
static void warpImage(const vpImage< Type > &src, const vpMatrix &T, vpImage< Type > &dst, const vpImageInterpolationType &interpolation=INTERPOLATION_NEAREST, bool fixedPointArithmetic=true, bool pixelCenter=false)
static void read(vpImage< unsigned char > &I, const std::string &filename)
Definition: vpImageIo.cpp:244
static bool checkFilename(const std::string &filename)
Definition: vpIoTools.cpp:640
unsigned int getHeight() const
Definition: vpImage.h:188