Visual Servoing Platform version 3.6.0
Loading...
Searching...
No Matches
testImageWarp.cpp
1/****************************************************************************
2 *
3 * ViSP, open source Visual Servoing Platform software.
4 * Copyright (C) 2005 - 2023 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 https://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) && (VISP_HAVE_DATASET_VERSION >= 0x030300)
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} // namespace
112
113TEST_CASE("Affine warp on grayscale", "[warp_image]")
114{
115 const std::string imgPath = vpIoTools::createFilePath(vpIoTools::getViSPImagesDataPath(), "Klimt/Klimt.pgm");
116 REQUIRE(vpIoTools::checkFilename(imgPath));
117
119 vpImageIo::read(I, imgPath);
120 REQUIRE(I.getSize() > 0);
121
122 SECTION("Identity")
123 {
124 vpMatrix M(2, 3);
125 M.eye();
126
127 for (size_t i = 0; i < interp_methods.size(); i++) {
128 SECTION(interp_names[i])
129 {
130 SECTION("Empty destination")
131 {
132 vpImage<unsigned char> I_affine;
133 vpImageTools::warpImage(I, M, I_affine, interp_methods[i]);
134 CHECK((I == I_affine));
135 }
136
137 SECTION("Initialized destination")
138 {
139 vpImage<unsigned char> I_affine(I.getHeight(), I.getWidth(), 0);
140 vpImageTools::warpImage(I, M, I_affine, interp_methods[i]);
141 CHECK((I == I_affine));
142 }
143 }
144 }
145 }
146
147 SECTION("Rotation 45 deg")
148 {
149 vpMatrix M(2, 3);
150 M.eye();
151
152 const double theta = vpMath::rad(45);
153 M[0][0] = cos(theta);
154 M[0][1] = -sin(theta);
155 M[0][2] = I.getWidth() / 2.0;
156 M[1][0] = sin(theta);
157 M[1][1] = cos(theta);
158 M[1][2] = I.getHeight() / 2.0;
159
160 for (size_t i = 0; i < interp_methods.size(); i++) {
161 SECTION(interp_names[i])
162 {
163 SECTION("Against reference implementation")
164 {
166 vpImageTools::warpImage(I, M, I_ref, interp_methods[i], false);
167
168 vpImage<unsigned char> I_affine;
169 vpImageTools::warpImage(I, M, I_affine, interp_methods[i]);
170
171 double percentage = 0.0;
172 bool equal = almostEqual(I_ref, I_affine, g_threshold_value, g_threshold_percentage, percentage);
173 std::cout << "Percentage valid pixels (45 deg " << interp_names[i] << " Ref): " << percentage << std::endl;
174 CHECK(equal);
175 }
176
177 SECTION("Against OpenCV")
178 {
179 const std::string refImgPath = vpIoTools::createFilePath(
180 vpIoTools::getViSPImagesDataPath(), std::string("warp/cv_warp_affine_rot_45_gray" + suffixes[i]));
181 REQUIRE(vpIoTools::checkFilename(refImgPath));
182 vpImage<unsigned char> I_ref_opencv;
183 vpImageIo::read(I_ref_opencv, refImgPath);
184
185 vpImage<unsigned char> I_affine;
186 vpImageTools::warpImage(I, M, I_affine, interp_methods[i]);
187
188 double percentage = 0.0;
189 bool equal = almostEqual(I_ref_opencv, I_affine, g_threshold_value,
190 (i == 0) ? g_threshold_percentage : g_threshold_percentage_bilinear, percentage);
191 std::cout << "Percentage valid pixels (45 deg " << interp_names[i] << " OpenCV): " << percentage << std::endl;
192 CHECK(equal);
193 }
194
195 SECTION("Against PIL")
196 {
197 const std::string refImgPath = vpIoTools::createFilePath(
198 vpIoTools::getViSPImagesDataPath(), std::string("warp/pil_warp_affine_rot_45_gray" + suffixes[i]));
199 REQUIRE(vpIoTools::checkFilename(refImgPath));
200 vpImage<unsigned char> I_ref_pil;
201 vpImageIo::read(I_ref_pil, refImgPath);
202
203 vpImage<unsigned char> I_affine;
204 vpImageTools::warpImage(I, M, I_affine, interp_methods[i], false, true);
205
206 double percentage = 0.0;
207 bool equal = almostEqual(I_ref_pil, I_affine, g_threshold_value,
208 (i == 0) ? g_threshold_percentage : g_threshold_percentage_bilinear, percentage);
209 std::cout << "Percentage valid pixels (45 deg " << interp_names[i] << " PIL): " << percentage << std::endl;
210 CHECK(equal);
211 }
212 }
213 }
214 }
215
216 SECTION("SRT")
217 {
218 vpMatrix M(2, 3);
219 M.eye();
220
221 const double theta = vpMath::rad(-67);
222 const double scale = 0.83;
223 M[0][0] = scale * cos(theta);
224 M[0][1] = -scale * sin(theta);
225 M[0][2] = I.getWidth() / 2.0 + 17;
226 M[1][0] = scale * sin(theta);
227 M[1][1] = scale * cos(theta);
228 M[1][2] = I.getHeight() / 2.0 - 23;
229
230 for (size_t i = 0; i < interp_methods.size(); i++) {
231 SECTION(interp_names[i])
232 {
233 SECTION("Against reference implementation")
234 {
236 vpImageTools::warpImage(I, M, I_ref, interp_methods[i], false);
237
238 vpImage<unsigned char> I_affine;
239 vpImageTools::warpImage(I, M, I_affine, interp_methods[i]);
240
241 double percentage = 0.0;
242 bool equal = almostEqual(I_ref, I_affine, g_threshold_value, g_threshold_percentage, percentage);
243 std::cout << "Percentage valid pixels (SRT " << interp_names[i] << " Ref): " << percentage << std::endl;
244 CHECK(equal);
245 }
246
247 SECTION("Against OpenCV")
248 {
249 const std::string refImgPath = vpIoTools::createFilePath(
250 vpIoTools::getViSPImagesDataPath(), std::string("warp/cv_warp_affine_SRT_gray" + suffixes[i]));
251 REQUIRE(vpIoTools::checkFilename(refImgPath));
252 vpImage<unsigned char> I_ref_opencv;
253 vpImageIo::read(I_ref_opencv, refImgPath);
254
255 vpImage<unsigned char> I_affine;
256 vpImageTools::warpImage(I, M, I_affine, interp_methods[i]);
257
258 double percentage = 0.0;
259 bool equal = almostEqual(I_ref_opencv, I_affine, g_threshold_value,
260 (i == 0) ? g_threshold_percentage : g_threshold_percentage_bilinear, percentage);
261 std::cout << "Percentage valid pixels (SRT " << interp_names[i] << " OpenCV): " << percentage << std::endl;
262 CHECK(equal);
263 }
264
265 SECTION("Against PIL")
266 {
267 const std::string refImgPath = vpIoTools::createFilePath(
268 vpIoTools::getViSPImagesDataPath(), std::string("warp/pil_warp_affine_SRT_gray" + suffixes[i]));
269 REQUIRE(vpIoTools::checkFilename(refImgPath));
270 vpImage<unsigned char> I_ref_pil;
271 vpImageIo::read(I_ref_pil, refImgPath);
272
273 vpImage<unsigned char> I_affine;
274 vpImageTools::warpImage(I, M, I_affine, interp_methods[i], false, true);
275
276 double percentage = 0.0;
277 bool equal = almostEqual(I_ref_pil, I_affine, g_threshold_value,
278 (i == 0) ? g_threshold_percentage : g_threshold_percentage_bilinear, percentage);
279 std::cout << "Percentage valid pixels (SRT " << interp_names[i] << " PIL): " << percentage << std::endl;
280 CHECK(equal);
281 }
282 }
283 }
284 }
285}
286
287TEST_CASE("Affine warp on color", "[warp_image]")
288{
289 const std::string imgPath = vpIoTools::createFilePath(vpIoTools::getViSPImagesDataPath(), "Klimt/Klimt.ppm");
290 REQUIRE(vpIoTools::checkFilename(imgPath));
291
293 vpImageIo::read(I, imgPath);
294 REQUIRE(I.getSize() > 0);
295
296 SECTION("Identity")
297 {
298 vpMatrix M(2, 3);
299 M.eye();
300
301 for (size_t i = 0; i < interp_methods.size(); i++) {
302 SECTION(interp_names[i])
303 {
304 SECTION("Empty destination")
305 {
306 vpImage<vpRGBa> I_affine;
307 vpImageTools::warpImage(I, M, I_affine, interp_methods[i]);
308 CHECK((I == I_affine));
309 }
310
311 SECTION("Initialized destination")
312 {
313 vpImage<vpRGBa> I_affine(I.getHeight(), I.getWidth(), vpRGBa(0));
314 vpImageTools::warpImage(I, M, I_affine, interp_methods[i]);
315 CHECK((I == I_affine));
316 }
317 }
318 }
319 }
320
321 SECTION("Rotation 45 deg")
322 {
323 vpMatrix M(2, 3);
324 M.eye();
325
326 const double theta = vpMath::rad(45);
327 M[0][0] = cos(theta);
328 M[0][1] = -sin(theta);
329 M[0][2] = I.getWidth() / 2.0;
330 M[1][0] = sin(theta);
331 M[1][1] = cos(theta);
332 M[1][2] = I.getHeight() / 2.0;
333
334 for (size_t i = 0; i < interp_methods.size(); i++) {
335 SECTION(interp_names[i])
336 {
337 SECTION("Against reference implementation")
338 {
339 vpImage<vpRGBa> I_ref;
340 vpImageTools::warpImage(I, M, I_ref, interp_methods[i], false);
341
342 vpImage<vpRGBa> I_affine;
343 vpImageTools::warpImage(I, M, I_affine, interp_methods[i]);
344
345 double percentage = 0.0;
346 bool equal = almostEqual(I_ref, I_affine, g_threshold_value, g_threshold_percentage, percentage);
347 std::cout << "Percentage valid pixels (45 deg " << interp_names[i] << " Ref): " << percentage << std::endl;
348 CHECK(equal);
349 }
350
351 SECTION("Against OpenCV")
352 {
353 const std::string refImgPath = vpIoTools::createFilePath(
354 vpIoTools::getViSPImagesDataPath(), std::string("warp/cv_warp_affine_rot_45_color" + suffixes[i]));
355 REQUIRE(vpIoTools::checkFilename(refImgPath));
356 vpImage<vpRGBa> I_ref_opencv;
357 vpImageIo::read(I_ref_opencv, refImgPath);
358
359 vpImage<vpRGBa> I_affine;
360 vpImageTools::warpImage(I, M, I_affine, interp_methods[i]);
361
362 double percentage = 0.0;
363 bool equal = almostEqual(I_ref_opencv, I_affine, g_threshold_value,
364 (i == 0) ? g_threshold_percentage : g_threshold_percentage_bilinear, percentage);
365 std::cout << "Percentage valid pixels (45 deg " << interp_names[i] << " OpenCV): " << percentage << std::endl;
366 CHECK(equal);
367 }
368
369 SECTION("Against PIL")
370 {
371 const std::string refImgPath = vpIoTools::createFilePath(
372 vpIoTools::getViSPImagesDataPath(), std::string("warp/pil_warp_affine_rot_45_color" + suffixes[i]));
373 REQUIRE(vpIoTools::checkFilename(refImgPath));
374 vpImage<vpRGBa> I_ref_pil;
375 vpImageIo::read(I_ref_pil, refImgPath);
376
377 vpImage<vpRGBa> I_affine;
378 vpImageTools::warpImage(I, M, I_affine, interp_methods[i], false, true);
379
380 double percentage = 0.0;
381 bool equal = almostEqual(I_ref_pil, I_affine, g_threshold_value,
382 (i == 0) ? g_threshold_percentage : g_threshold_percentage_bilinear, percentage);
383 std::cout << "Percentage valid pixels (45 deg " << interp_names[i] << " PIL): " << percentage << std::endl;
384 CHECK(equal);
385 }
386 }
387 }
388 }
389
390 SECTION("SRT")
391 {
392 vpMatrix M(2, 3);
393 M.eye();
394
395 const double theta = vpMath::rad(-67);
396 const double scale = 0.83;
397 M[0][0] = scale * cos(theta);
398 M[0][1] = -scale * sin(theta);
399 M[0][2] = I.getWidth() / 2.0 + 17;
400 M[1][0] = scale * sin(theta);
401 M[1][1] = scale * cos(theta);
402 M[1][2] = I.getHeight() / 2.0 - 23;
403
404 for (size_t i = 0; i < interp_methods.size(); i++) {
405 SECTION(interp_names[i])
406 {
407 SECTION("Against reference implementation")
408 {
409 vpImage<vpRGBa> I_ref;
410 vpImageTools::warpImage(I, M, I_ref, interp_methods[i], false);
411
412 vpImage<vpRGBa> I_affine;
413 vpImageTools::warpImage(I, M, I_affine, interp_methods[i]);
414
415 double percentage = 0.0;
416 bool equal = almostEqual(I_ref, I_affine, g_threshold_value,
417 (i == 0) ? g_threshold_percentage : g_threshold_percentage_bilinear, percentage);
418 std::cout << "Percentage valid pixels (SRT " << interp_names[i] << " Ref): " << percentage << std::endl;
419 CHECK(equal);
420 }
421
422 SECTION("Against OpenCV")
423 {
424 const std::string refImgPath = vpIoTools::createFilePath(
425 vpIoTools::getViSPImagesDataPath(), std::string("warp/cv_warp_affine_SRT_color" + suffixes[i]));
426 REQUIRE(vpIoTools::checkFilename(refImgPath));
427 vpImage<vpRGBa> I_ref_opencv;
428 vpImageIo::read(I_ref_opencv, refImgPath);
429
430 vpImage<vpRGBa> I_affine;
431 vpImageTools::warpImage(I, M, I_affine, interp_methods[i]);
432
433 double percentage = 0.0;
434 bool equal = almostEqual(I_ref_opencv, I_affine, g_threshold_value,
435 (i == 0) ? g_threshold_percentage : g_threshold_percentage_bilinear, percentage);
436 std::cout << "Percentage valid pixels (SRT " << interp_names[i] << " OpenCV): " << percentage << std::endl;
437 CHECK(equal);
438 }
439
440 SECTION("Against PIL")
441 {
442 const std::string refImgPath = vpIoTools::createFilePath(
443 vpIoTools::getViSPImagesDataPath(), std::string("warp/pil_warp_affine_SRT_color" + suffixes[i]));
444 REQUIRE(vpIoTools::checkFilename(refImgPath));
445 vpImage<vpRGBa> I_ref_pil;
446 vpImageIo::read(I_ref_pil, refImgPath);
447
448 vpImage<vpRGBa> I_affine;
449 vpImageTools::warpImage(I, M, I_affine, interp_methods[i], false, true);
450
451 double percentage = 0.0;
452 bool equal = almostEqual(I_ref_pil, I_affine, g_threshold_value,
453 (i == 0) ? g_threshold_percentage : g_threshold_percentage_bilinear, percentage);
454 std::cout << "Percentage valid pixels (SRT " << interp_names[i] << " PIL): " << percentage << std::endl;
455 CHECK(equal);
456 }
457 }
458 }
459 }
460}
461
462TEST_CASE("Perspective warp on grayscale", "[warp_image]")
463{
464 const std::string imgPath = vpIoTools::createFilePath(vpIoTools::getViSPImagesDataPath(), "Klimt/Klimt.pgm");
465 REQUIRE(vpIoTools::checkFilename(imgPath));
466
468 vpImageIo::read(I, imgPath);
469 REQUIRE(I.getSize() > 0);
470
471 SECTION("Identity")
472 {
473 vpMatrix M(3, 3);
474 M.eye();
475
476 for (size_t i = 0; i < interp_methods.size(); i++) {
477 SECTION(interp_names[i])
478 {
479 SECTION("Empty destination")
480 {
481 vpImage<unsigned char> I_perspective;
482 vpImageTools::warpImage(I, M, I_perspective, interp_methods[i]);
483 CHECK((I == I_perspective));
484 }
485
486 SECTION("Initialized destination")
487 {
488 vpImage<unsigned char> I_perspective(I.getHeight(), I.getWidth(), 0);
489 vpImageTools::warpImage(I, M, I_perspective, interp_methods[i]);
490 CHECK((I == I_perspective));
491 }
492 }
493 }
494 }
495
496 SECTION("Rotation 45 deg")
497 {
498 vpMatrix M(3, 3);
499 M.eye();
500
501 const double theta = vpMath::rad(45);
502 M[0][0] = cos(theta);
503 M[0][1] = -sin(theta);
504 M[0][2] = I.getWidth() / 2.0;
505 M[1][0] = sin(theta);
506 M[1][1] = cos(theta);
507 M[1][2] = I.getHeight() / 2.0;
508
509 SECTION("Nearest Neighbor")
510 {
513
514 vpImage<unsigned char> I_perspective;
516
517 double percentage = 0.0;
518 bool equal = almostEqual(I_ref, I_perspective, g_threshold_value, g_threshold_percentage, percentage);
519 std::cout << "Percentage valid pixels (persp 45 deg): " << percentage << std::endl;
520 CHECK(equal);
521 }
522 }
523
524 SECTION("Homography")
525 {
526 vpMatrix M(3, 3);
527 M.eye();
528
529 M[0][0] = 1.8548;
530 M[0][1] = -0.0402;
531 M[0][2] = 114.9;
532 M[1][0] = 1.1209;
533 M[1][1] = 4.0106;
534 M[1][2] = 111;
535 M[2][0] = 0.0022;
536 M[2][1] = 0.0064;
537
538 for (size_t i = 0; i < interp_methods.size(); i++) {
539 SECTION(interp_names[i])
540 {
541 SECTION("Against reference implementation")
542 {
544 vpImageTools::warpImage(I, M, I_ref, interp_methods[i], false);
545
546 vpImage<unsigned char> I_perspective;
547 vpImageTools::warpImage(I, M, I_perspective, interp_methods[i]);
548
549 double percentage = 0.0;
550 bool equal =
551 almostEqual(I_ref, I_perspective, g_threshold_value,
552 (i == 0) ? g_threshold_percentage_pers : g_threshold_percentage_pers_bilinear, percentage);
553 std::cout << "Percentage valid pixels (Homography " << interp_names[i] << " Ref): " << percentage
554 << std::endl;
555 CHECK(equal);
556 }
557
558 SECTION("Against OpenCV")
559 {
560 const std::string refImgPath = vpIoTools::createFilePath(
561 vpIoTools::getViSPImagesDataPath(), std::string("warp/cv_warp_perspective_gray" + suffixes[i]));
562 REQUIRE(vpIoTools::checkFilename(refImgPath));
563 vpImage<unsigned char> I_ref_opencv;
564 vpImageIo::read(I_ref_opencv, refImgPath);
565
566 vpImage<unsigned char> I_perspective;
567 vpImageTools::warpImage(I, M, I_perspective, interp_methods[i]);
568
569 double percentage = 0.0;
570 bool equal =
571 almostEqual(I_ref_opencv, I_perspective, g_threshold_value,
572 (i == 0) ? g_threshold_percentage_pers : g_threshold_percentage_pers_bilinear, percentage);
573 std::cout << "Percentage valid pixels (Homography " << interp_names[i] << " OpenCV): " << percentage
574 << std::endl;
575 CHECK(equal);
576 }
577
578 SECTION("Against PIL")
579 {
580 const std::string refImgPath = vpIoTools::createFilePath(
581 vpIoTools::getViSPImagesDataPath(), std::string("warp/pil_warp_perspective_gray" + suffixes[i]));
582 REQUIRE(vpIoTools::checkFilename(refImgPath));
583 vpImage<unsigned char> I_ref_pil;
584 vpImageIo::read(I_ref_pil, refImgPath);
585
586 vpImage<unsigned char> I_perspective;
587 vpImageTools::warpImage(I, M, I_perspective, interp_methods[i], false, true);
588
589 double percentage = 0.0;
590 bool equal =
591 almostEqual(I_ref_pil, I_perspective, g_threshold_value,
592 (i == 0) ? g_threshold_percentage_pers : g_threshold_percentage_pers_bilinear, percentage);
593 std::cout << "Percentage valid pixels (Homography " << interp_names[i] << " PIL): " << percentage
594 << std::endl;
595 CHECK(equal);
596 }
597 }
598 }
599 }
600}
601
602TEST_CASE("Perspective warp on color", "[warp_image]")
603{
604 const std::string imgPath = vpIoTools::createFilePath(vpIoTools::getViSPImagesDataPath(), "Klimt/Klimt.ppm");
605 REQUIRE(vpIoTools::checkFilename(imgPath));
606
608 vpImageIo::read(I, imgPath);
609 REQUIRE(I.getSize() > 0);
610
611 SECTION("Identity")
612 {
613 vpMatrix M(3, 3);
614 M.eye();
615
616 for (size_t i = 0; i < interp_methods.size(); i++) {
617 SECTION(interp_names[i])
618 {
619 SECTION("Empty destination")
620 {
621 vpImage<vpRGBa> I_perspective;
622 vpImageTools::warpImage(I, M, I_perspective, interp_methods[i]);
623 CHECK((I == I_perspective));
624 }
625
626 SECTION("Initialized destination")
627 {
628 vpImage<vpRGBa> I_perspective(I.getHeight(), I.getWidth(), vpRGBa(0));
629 vpImageTools::warpImage(I, M, I_perspective, interp_methods[i]);
630 CHECK((I == I_perspective));
631 }
632 }
633 }
634 }
635
636 SECTION("Homography")
637 {
638 vpMatrix M(3, 3);
639 M.eye();
640
641 M[0][0] = 1.8548;
642 M[0][1] = -0.0402;
643 M[0][2] = 114.9;
644 M[1][0] = 1.1209;
645 M[1][1] = 4.0106;
646 M[1][2] = 111;
647 M[2][0] = 0.0022;
648 M[2][1] = 0.0064;
649
650 for (size_t i = 0; i < interp_methods.size(); i++) {
651 SECTION(interp_names[i])
652 {
653 SECTION("Against reference implementation")
654 {
655 vpImage<vpRGBa> I_ref;
656 vpImageTools::warpImage(I, M, I_ref, interp_methods[i], false);
657
658 vpImage<vpRGBa> I_perspective;
659 vpImageTools::warpImage(I, M, I_perspective, interp_methods[i]);
660
661 double percentage = 0.0;
662 bool equal =
663 almostEqual(I_ref, I_perspective, g_threshold_value,
664 (i == 0) ? g_threshold_percentage_pers : g_threshold_percentage_pers_bilinear, percentage);
665 std::cout << "Percentage valid pixels (Homography " << interp_names[i] << " Ref): " << percentage
666 << std::endl;
667 CHECK(equal);
668 }
669
670 SECTION("Against OpenCV")
671 {
672 const std::string refImgPath = vpIoTools::createFilePath(
673 vpIoTools::getViSPImagesDataPath(), std::string("warp/cv_warp_perspective_color" + suffixes[i]));
674 REQUIRE(vpIoTools::checkFilename(refImgPath));
675 vpImage<vpRGBa> I_ref_opencv;
676 vpImageIo::read(I_ref_opencv, refImgPath);
677
678 vpImage<vpRGBa> I_perspective;
679 vpImageTools::warpImage(I, M, I_perspective, interp_methods[i]);
680
681 double percentage = 0.0;
682 bool equal =
683 almostEqual(I_ref_opencv, I_perspective, g_threshold_value,
684 (i == 0) ? g_threshold_percentage_pers : g_threshold_percentage_pers_bilinear, percentage);
685 std::cout << "Percentage valid pixels (Homography " << interp_names[i] << " OpenCV): " << percentage
686 << std::endl;
687 CHECK(equal);
688 }
689
690 SECTION("Against PIL")
691 {
692 const std::string refImgPath = vpIoTools::createFilePath(
693 vpIoTools::getViSPImagesDataPath(), std::string("warp/pil_warp_perspective_color" + suffixes[i]));
694 REQUIRE(vpIoTools::checkFilename(refImgPath));
695 vpImage<vpRGBa> I_ref_pil;
696 vpImageIo::read(I_ref_pil, refImgPath);
697
698 vpImage<vpRGBa> I_perspective;
699 vpImageTools::warpImage(I, M, I_perspective, interp_methods[i], false, true);
700
701 double percentage = 0.0;
702 bool equal =
703 almostEqual(I_ref_pil, I_perspective, g_threshold_value,
704 (i == 0) ? g_threshold_percentage_pers : g_threshold_percentage_pers_bilinear, percentage);
705 std::cout << "Percentage valid pixels (Homography " << interp_names[i] << " PIL): " << percentage
706 << std::endl;
707 CHECK(equal);
708 }
709 }
710 }
711 }
712}
713
714int main(int argc, char *argv[])
715{
716 Catch::Session session; // There must be exactly one instance
717
718 // Let Catch (using Clara) parse the command line
719 session.applyCommandLine(argc, argv);
720
721 int numFailed = session.run();
722
723 // numFailed is clamped to 255 as some unices only use the lower 8 bits.
724 // This clamping has already been applied, so just return it here
725 // You can also do any post run clean-up here
726 return numFailed;
727}
728#else
729int main() { return EXIT_SUCCESS; }
730#endif
static void read(vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
static void warpImage(const vpImage< Type > &src, const vpMatrix &T, vpImage< Type > &dst, const vpImageInterpolationType &interpolation=INTERPOLATION_NEAREST, bool fixedPointArithmetic=true, bool pixelCenter=false)
Definition of the vpImage class member functions.
Definition vpImage.h:135
unsigned int getWidth() const
Definition vpImage.h:242
unsigned int getSize() const
Definition vpImage.h:223
unsigned int getHeight() const
Definition vpImage.h:184
static std::string getViSPImagesDataPath()
static bool checkFilename(const std::string &filename)
static std::string createFilePath(const std::string &parent, const std::string &child)
static double rad(double deg)
Definition vpMath.h:116
static Type abs(const Type &x)
Definition vpMath.h:187
Implementation of a matrix and operations on matrices.
Definition vpMatrix.h:152