Visual Servoing Platform version 3.5.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
53namespace
54{
55static const double g_threshold_value = 0.5;
56static const double g_threshold_percentage = 0.9;
57static const double g_threshold_percentage_bilinear = 0.75;
58static const double g_threshold_percentage_pers = 0.75;
59static const double g_threshold_percentage_pers_bilinear = 0.65;
60
61static const std::vector<vpImageTools::vpImageInterpolationType> interp_methods = {vpImageTools::INTERPOLATION_NEAREST,
63static const std::vector<std::string> interp_names = {"Nearest Neighbor", "Bilinear"};
64static const std::vector<std::string> suffixes = { "_NN.png", "_bilinear.png" };
65
66bool 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
85bool 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
113TEST_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
274TEST_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
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
435TEST_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
559TEST_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
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
659int 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
674int main()
675{
676 return 0;
677}
678#endif
static void read(vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Definition: vpImageIo.cpp:149
static void warpImage(const vpImage< Type > &src, const vpMatrix &T, vpImage< Type > &dst, const vpImageInterpolationType &interpolation=INTERPOLATION_NEAREST, bool fixedPointArithmetic=true, bool pixelCenter=false)
@ INTERPOLATION_LINEAR
Definition: vpImageTools.h:83
@ INTERPOLATION_NEAREST
Definition: vpImageTools.h:82
unsigned int getWidth() const
Definition: vpImage.h:246
unsigned int getSize() const
Definition: vpImage.h:227
unsigned int getHeight() const
Definition: vpImage.h:188
static std::string getViSPImagesDataPath()
Definition: vpIoTools.cpp:1365
static bool checkFilename(const std::string &filename)
Definition: vpIoTools.cpp:802
static std::string createFilePath(const std::string &parent, const std::string &child)
Definition: vpIoTools.cpp:1670
static double rad(double deg)
Definition: vpMath.h:110
static Type abs(const Type &x)
Definition: vpMath.h:160
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:154
Definition: vpRGBa.h:67