Visual Servoing Platform  version 3.6.1 under development (2024-07-27)
perfImageWarp.cpp
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2024 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  * Benchmark image warping.
32  */
33 
38 #include <visp3/core/vpConfig.h>
39 
40 #ifdef VISP_HAVE_CATCH2
41 #define CATCH_CONFIG_ENABLE_BENCHMARKING
42 #define CATCH_CONFIG_RUNNER
43 #include <catch.hpp>
44 
45 #include <visp3/core/vpImageTools.h>
46 #include <visp3/core/vpIoTools.h>
47 #include <visp3/io/vpImageIo.h>
48 
49 #ifdef ENABLE_VISP_NAMESPACE
50 using namespace VISP_NAMESPACE_NAME;
51 #endif
52 namespace
53 {
54 static std::string ipath = vpIoTools::getViSPImagesDataPath();
55 }
56 
57 TEST_CASE("Benchmark affine warp on grayscale image", "[benchmark]")
58 {
59  std::string imgPath = vpIoTools::createFilePath(ipath, "Klimt/Klimt.pgm");
60  REQUIRE(vpIoTools::checkFilename(imgPath));
61 
63  vpImageIo::read(I, imgPath);
64  REQUIRE(I.getSize() > 0);
65  vpImage<unsigned char> I_affine(I.getHeight(), I.getWidth());
66 
67  vpMatrix M(2, 3);
68  M.eye();
69 
70  const double theta = vpMath::rad(45);
71  M[0][0] = cos(theta);
72  M[0][1] = -sin(theta);
73  M[0][2] = I.getWidth() / 2;
74  M[1][0] = sin(theta);
75  M[1][1] = cos(theta);
76  M[1][2] = I.getHeight() / 2;
77 
78  BENCHMARK("Benchmark affine warp (ref code) (NN)")
79  {
81  return I_affine;
82  };
83 
84  BENCHMARK("Benchmark affine warp (fixed-point) (NN)")
85  {
87  return I_affine;
88  };
89 
90  BENCHMARK("Benchmark affine warp (ref code) (bilinear)")
91  {
93  return I_affine;
94  };
95 
96  BENCHMARK("Benchmark affine warp (fixed-point) (bilinear)")
97  {
99  return I_affine;
100  };
101 
102 #if (VISP_HAVE_OPENCV_VERSION >= 0x030000) && defined(HAVE_OPENCV_IMGPROC)
103  cv::Mat img, img_affine;
104  vpImageConvert::convert(I, img);
105  vpImageConvert::convert(I, img_affine);
106 
107  cv::Mat M_cv(2, 3, CV_64FC1);
108  for (unsigned int i = 0; i < M.getRows(); i++) {
109  for (unsigned int j = 0; j < M.getCols(); j++) {
110  M_cv.at<double>(i, j) = M[i][j];
111  }
112  }
113 
114  BENCHMARK("Benchmark affine warp (OpenCV) (NN)")
115  {
116  cv::warpAffine(img, img_affine, M_cv, img.size(), cv::INTER_NEAREST);
117  return img_affine;
118  };
119 
120  BENCHMARK("Benchmark affine warp (OpenCV) (bilinear)")
121  {
122  cv::warpAffine(img, img_affine, M_cv, img.size(), cv::INTER_LINEAR);
123  return img_affine;
124  };
125 #endif
126 }
127 
128 TEST_CASE("Benchmark affine warp on color image", "[benchmark]")
129 {
130  std::string imgPath = vpIoTools::createFilePath(ipath, "Klimt/Klimt.ppm");
131  REQUIRE(vpIoTools::checkFilename(imgPath));
132 
133  vpImage<vpRGBa> I;
134  vpImageIo::read(I, imgPath);
135  REQUIRE(I.getSize() > 0);
136  vpImage<vpRGBa> I_affine(I.getHeight(), I.getWidth());
137 
138  vpMatrix M(2, 3);
139  M.eye();
140 
141  const double theta = vpMath::rad(45);
142  M[0][0] = cos(theta);
143  M[0][1] = -sin(theta);
144  M[0][2] = I.getWidth() / 2;
145  M[1][0] = sin(theta);
146  M[1][1] = cos(theta);
147  M[1][2] = I.getHeight() / 2;
148 
149  BENCHMARK("Benchmark affine warp (ref code) (NN)")
150  {
152  return I_affine;
153  };
154 
155  BENCHMARK("Benchmark affine warp (fixed-point) (NN)")
156  {
158  return I_affine;
159  };
160 
161  BENCHMARK("Benchmark affine warp (ref code) (bilinear)")
162  {
164  return I_affine;
165  };
166 
167  BENCHMARK("Benchmark affine warp (fixed-point) (bilinear)")
168  {
170  return I_affine;
171  };
172 
173 #if (VISP_HAVE_OPENCV_VERSION >= 0x030000) && defined(HAVE_OPENCV_IMGPROC)
174  cv::Mat img, img_affine;
175  vpImageConvert::convert(I, img);
176  vpImageConvert::convert(I, img_affine);
177 
178  cv::Mat M_cv(2, 3, CV_64FC1);
179  for (unsigned int i = 0; i < M.getRows(); i++) {
180  for (unsigned int j = 0; j < M.getCols(); j++) {
181  M_cv.at<double>(i, j) = M[i][j];
182  }
183  }
184 
185  BENCHMARK("Benchmark affine warp (OpenCV) (NN)")
186  {
187  cv::warpAffine(img, img_affine, M_cv, img.size(), cv::INTER_NEAREST);
188  return img_affine;
189  };
190 
191  BENCHMARK("Benchmark affine warp (OpenCV) (bilinear)")
192  {
193  cv::warpAffine(img, img_affine, M_cv, img.size(), cv::INTER_LINEAR);
194  return img_affine;
195  };
196 #endif
197 }
198 
199 TEST_CASE("Benchmark perspective warp on grayscale image", "[benchmark]")
200 {
201  std::string imgPath = vpIoTools::createFilePath(ipath, "Klimt/Klimt.pgm");
202  REQUIRE(vpIoTools::checkFilename(imgPath));
203 
205  vpImageIo::read(I, imgPath);
206  REQUIRE(I.getSize() > 0);
207  vpImage<unsigned char> I_perspective(I.getHeight(), I.getWidth());
208 
209  vpMatrix M(3, 3);
210  M.eye();
211 
212  const double theta = vpMath::rad(45);
213  M[0][0] = cos(theta);
214  M[0][1] = -sin(theta);
215  M[0][2] = I.getWidth() / 2;
216  M[1][0] = sin(theta);
217  M[1][1] = cos(theta);
218  M[1][2] = I.getHeight() / 2;
219 
220  BENCHMARK("Benchmark perspective warp (ref code) (NN)")
221  {
223  return I_perspective;
224  };
225 
226  BENCHMARK("Benchmark perspective warp (fixed-point) (NN)")
227  {
229  return I_perspective;
230  };
231 
232  BENCHMARK("Benchmark perspective warp (ref code) (bilinear)")
233  {
234  vpImageTools::warpImage(I, M, I_perspective, vpImageTools::INTERPOLATION_LINEAR, false);
235  return I_perspective;
236  };
237 
238  BENCHMARK("Benchmark perspective warp (fixed-point) (bilinear)")
239  {
241  return I_perspective;
242  };
243 
244 #if (VISP_HAVE_OPENCV_VERSION >= 0x030000) && defined(HAVE_OPENCV_IMGPROC)
245  cv::Mat img, img_perspective;
246  vpImageConvert::convert(I, img);
247  vpImageConvert::convert(I, img_perspective);
248 
249  cv::Mat M_cv(3, 3, CV_64FC1);
250  for (unsigned int i = 0; i < M.getRows(); i++) {
251  for (unsigned int j = 0; j < M.getCols(); j++) {
252  M_cv.at<double>(i, j) = M[i][j];
253  }
254  }
255 
256  BENCHMARK("Benchmark perspective warp (OpenCV) (NN)")
257  {
258  cv::warpPerspective(img, img_perspective, M_cv, img.size(), cv::INTER_NEAREST);
259  return img_perspective;
260  };
261 
262  BENCHMARK("Benchmark perspective warp (OpenCV) (bilinear)")
263  {
264  cv::warpPerspective(img, img_perspective, M_cv, img.size(), cv::INTER_LINEAR);
265  return img_perspective;
266  };
267 #endif
268 }
269 
270 TEST_CASE("Benchmark perspective warp on color image", "[benchmark]")
271 {
272  std::string imgPath = vpIoTools::createFilePath(ipath, "Klimt/Klimt.ppm");
273  REQUIRE(vpIoTools::checkFilename(imgPath));
274 
275  vpImage<vpRGBa> I;
276  vpImageIo::read(I, imgPath);
277  REQUIRE(I.getSize() > 0);
278  vpImage<vpRGBa> I_perspective(I.getHeight(), I.getWidth());
279 
280  vpMatrix M(3, 3);
281  M.eye();
282 
283  const double theta = vpMath::rad(45);
284  M[0][0] = cos(theta);
285  M[0][1] = -sin(theta);
286  M[0][2] = I.getWidth() / 2;
287  M[1][0] = sin(theta);
288  M[1][1] = cos(theta);
289  M[1][2] = I.getHeight() / 2;
290 
291  BENCHMARK("Benchmark perspective warp (ref code) (NN)")
292  {
294  return I_perspective;
295  };
296 
297  BENCHMARK("Benchmark perspective warp (fixed-point) (NN)")
298  {
300  return I_perspective;
301  };
302 
303  BENCHMARK("Benchmark perspective warp (ref code) (bilinear)")
304  {
305  vpImageTools::warpImage(I, M, I_perspective, vpImageTools::INTERPOLATION_LINEAR, false);
306  return I_perspective;
307  };
308 
309  BENCHMARK("Benchmark perspective warp (fixed-point) (bilinear)")
310  {
312  return I_perspective;
313  };
314 
315 #if (VISP_HAVE_OPENCV_VERSION >= 0x030000) && defined(HAVE_OPENCV_IMGPROC)
316  cv::Mat img, img_perspective;
317  vpImageConvert::convert(I, img);
318  vpImageConvert::convert(I, img_perspective);
319 
320  cv::Mat M_cv(3, 3, CV_64FC1);
321  for (unsigned int i = 0; i < M.getRows(); i++) {
322  for (unsigned int j = 0; j < M.getCols(); j++) {
323  M_cv.at<double>(i, j) = M[i][j];
324  }
325  }
326 
327  BENCHMARK("Benchmark perspective warp (OpenCV) (NN)")
328  {
329  cv::warpPerspective(img, img_perspective, M_cv, img.size(), cv::INTER_NEAREST);
330  return img_perspective;
331  };
332 
333  BENCHMARK("Benchmark perspective warp (OpenCV) (bilinear)")
334  {
335  cv::warpPerspective(img, img_perspective, M_cv, img.size(), cv::INTER_LINEAR);
336  return img_perspective;
337  };
338 #endif
339 }
340 
341 int main(int argc, char *argv[])
342 {
343  Catch::Session session; // There must be exactly one instance
344 
345  bool runBenchmark = false;
346  // Build a new parser on top of Catch's
347  using namespace Catch::clara;
348  auto cli = session.cli() // Get Catch's composite command line parser
349  | Opt(runBenchmark) // bind variable to a new option, with a hint string
350  ["--benchmark"] // the option names it will respond to
351  ("run benchmark?"); // description string for the help output
352 
353 // Now pass the new composite back to Catch so it uses that
354  session.cli(cli);
355 
356  // Let Catch (using Clara) parse the command line
357  session.applyCommandLine(argc, argv);
358 
359  if (runBenchmark) {
360  int numFailed = session.run();
361 
362  // numFailed is clamped to 255 as some unices only use the lower 8 bits.
363  // This clamping has already been applied, so just return it here
364  // You can also do any post run clean-up here
365  return numFailed;
366  }
367 
368  return EXIT_SUCCESS;
369 }
370 #else
371 #include <iostream>
372 
373 int main() { return EXIT_SUCCESS; }
374 #endif
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
static void read(vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Definition: vpImageIo.cpp:147
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:81
@ INTERPOLATION_NEAREST
Definition: vpImageTools.h:80
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()
Definition: vpIoTools.cpp:1053
static bool checkFilename(const std::string &filename)
Definition: vpIoTools.cpp:786
static std::string createFilePath(const std::string &parent, const std::string &child)
Definition: vpIoTools.cpp:1427
static double rad(double deg)
Definition: vpMath.h:129
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:169