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