Visual Servoing Platform  version 3.6.1 under development (2024-04-20)
perfImageResize.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  * Benchmark image resize.
33  *
34 *****************************************************************************/
35 
36 #include <visp3/core/vpConfig.h>
37 
38 #if defined(VISP_HAVE_CATCH2) && defined(VISP_HAVE_THREADS)
39 #define CATCH_CONFIG_ENABLE_BENCHMARKING
40 #define CATCH_CONFIG_RUNNER
41 #include <catch.hpp>
42 
43 #include "common.hpp"
44 #include <thread>
45 #include <visp3/core/vpImageTools.h>
46 #include <visp3/core/vpIoTools.h>
47 #include <visp3/io/vpImageIo.h>
48 
49 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGCODECS) && defined(HAVE_OPENCV_IMGPROC)
50 #include <opencv2/imgcodecs.hpp>
51 #include <opencv2/imgproc/imgproc.hpp>
52 #endif
53 
54 static const std::string ipath = vpIoTools::getViSPImagesDataPath();
55 static std::string imagePathColor = vpIoTools::createFilePath(ipath, "Klimt/Klimt.ppm");
56 static std::string imagePathGray = vpIoTools::createFilePath(ipath, "Klimt/Klimt.pgm");
57 static unsigned int g_resize_width = 293;
58 static unsigned int g_resize_height = 137;
59 
60 TEST_CASE("Nearest Neighbor image resize (naive code)", "[benchmark]")
61 {
62  SECTION("unsigned char")
63  {
64  vpImage<unsigned char> I, Iresize(g_resize_height, g_resize_width);
65  vpImageIo::read(I, imagePathGray);
66 
67  BENCHMARK("Benchmark Nearest Neighbor uchar image resize (naive code)")
68  {
69  common_tools::resizeRef(I, Iresize, common_tools::g_nearest_neighbor);
70  return Iresize;
71  };
72  }
73 
74  SECTION("vpRGBa")
75  {
76  vpImage<vpRGBa> I, Iresize(g_resize_height, g_resize_width);
77  vpImageIo::read(I, imagePathColor);
78 
79  BENCHMARK("Benchmark Nearest Neighbor RGBa image resize (naive code)")
80  {
81  common_tools::resizeRef(I, Iresize, common_tools::g_nearest_neighbor);
82  return Iresize;
83  };
84  }
85 }
86 
87 TEST_CASE("Nearest Neighbor image resize (ViSP)", "[benchmark]")
88 {
89  SECTION("unsigned char")
90  {
91  vpImage<unsigned char> I, Iresize(g_resize_height, g_resize_width);
92  vpImageIo::read(I, imagePathGray);
93 
94  BENCHMARK("Benchmark Nearest Neighbor uchar image resize (ViSP) (1 thread)")
95  {
97  return Iresize;
98  };
99 
100  const unsigned int nThreads = std::thread::hardware_concurrency();
101  std::stringstream buffer;
102  buffer << "Benchmark Nearest Neighbor uchar image resize (ViSP) (" << nThreads << "threads)";
103  BENCHMARK(buffer.str().c_str())
104  {
106  return Iresize;
107  };
108  }
109 
110  SECTION("vpRGBa")
111  {
112  vpImage<vpRGBa> I, Iresize(g_resize_height, g_resize_width);
113  vpImageIo::read(I, imagePathColor);
114 
115  BENCHMARK("Benchmark Nearest Neighbor RGBa image resize (ViSP) (1 thread)")
116  {
118  return Iresize;
119  };
120 
121  const unsigned int nThreads = std::thread::hardware_concurrency();
122  std::stringstream buffer;
123  buffer << "Benchmark Nearest Neighbor RGBa image resize (ViSP) (" << nThreads << " threads)";
124  BENCHMARK(buffer.str().c_str())
125  {
127  return Iresize;
128  };
129  }
130 }
131 
132 TEST_CASE("Bilinear image resize (naive code)", "[benchmark]")
133 {
134  SECTION("unsigned char")
135  {
136  vpImage<unsigned char> I, Iresize(g_resize_height, g_resize_width);
137  vpImageIo::read(I, imagePathGray);
138 
139  BENCHMARK("Benchmark Bilinear uchar image resize (naive code)")
140  {
141  common_tools::resizeRef(I, Iresize, common_tools::g_bilinear);
142  return Iresize;
143  };
144  }
145 
146  SECTION("vpRGBa")
147  {
148  vpImage<vpRGBa> I, Iresize(g_resize_height, g_resize_width);
149  vpImageIo::read(I, imagePathColor);
150 
151  BENCHMARK("Benchmark Bilinear RGBa image resize (naive code)")
152  {
153  common_tools::resizeRef(I, Iresize, common_tools::g_bilinear);
154  return Iresize;
155  };
156  }
157 }
158 
159 TEST_CASE("Bilinear image resize (ViSP)", "[benchmark]")
160 {
161  SECTION("unsigned char")
162  {
163  vpImage<unsigned char> I, Iresize(g_resize_height, g_resize_width);
164  vpImageIo::read(I, imagePathGray);
165 
166  BENCHMARK("Benchmark Bilinear uchar image resize (ViSP)")
167  {
169  return Iresize;
170  };
171  }
172 
173  SECTION("vpRGBa")
174  {
175  vpImage<vpRGBa> I, Iresize(g_resize_height, g_resize_width);
176  vpImageIo::read(I, imagePathColor);
177 
178  BENCHMARK("Benchmark Bilinear RGBa image resize (ViSP)")
179  {
181  return Iresize;
182  };
183  }
184 }
185 
186 TEST_CASE("Area image resize (ViSP)", "[benchmark]")
187 {
188  SECTION("unsigned char")
189  {
190  vpImage<unsigned char> I, Iresize(g_resize_height, g_resize_width);
191  vpImageIo::read(I, imagePathGray);
192 
193  BENCHMARK("Benchmark Area uchar image resize (ViSP)")
194  {
196  return Iresize;
197  };
198  }
199 
200  SECTION("vpRGBa")
201  {
202  vpImage<vpRGBa> I, Iresize(g_resize_height, g_resize_width);
203  vpImageIo::read(I, imagePathColor);
204 
205  BENCHMARK("Benchmark Area RGBa image resize (ViSP)")
206  {
208  return Iresize;
209  };
210  }
211 }
212 
213 TEST_CASE("Bicubic image resize (ViSP)", "[benchmark]")
214 {
215  SECTION("unsigned char")
216  {
217  vpImage<unsigned char> I, Iresize(g_resize_height, g_resize_width);
218  vpImageIo::read(I, imagePathGray);
219 
220  BENCHMARK("Benchmark Bicubic uchar image resize (ViSP) (1 thread)")
221  {
223  return Iresize;
224  };
225 
226  const unsigned int nThreads = std::thread::hardware_concurrency();
227  std::stringstream buffer;
228  buffer << "Benchmark Bicubic uchar image resize (ViSP) (" << nThreads << " threads)";
229  BENCHMARK(buffer.str().c_str())
230  {
232  return Iresize;
233  };
234  }
235 
236  SECTION("vpRGBa")
237  {
238  vpImage<vpRGBa> I, Iresize(g_resize_height, g_resize_width);
239  vpImageIo::read(I, imagePathColor);
240 
241  BENCHMARK("Benchmark Bicubic RGBa image resize (ViSP) (1 thread)")
242  {
244  return Iresize;
245  };
246 
247  const unsigned int nThreads = std::thread::hardware_concurrency();
248  std::stringstream buffer;
249  buffer << "Benchmark Bicubic RGBa image resize (ViSP) (" << nThreads << " threads)";
250  BENCHMARK(buffer.str().c_str())
251  {
253  return Iresize;
254  };
255  }
256 }
257 
258 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGCODECS) && defined(HAVE_OPENCV_IMGPROC)
259 TEST_CASE("Nearest Neighbor image resize (OpenCV)", "[benchmark]")
260 {
261  SECTION("unsigned char")
262  {
263  cv::Mat img, img_resize;
264  img = cv::imread(imagePathGray, cv::IMREAD_GRAYSCALE);
265 
266  BENCHMARK("Benchmark Nearest Neighbor uchar image resize (OpenCV)")
267  {
268  cv::resize(img, img_resize, cv::Size(g_resize_width, g_resize_height), 0, 0, cv::INTER_NEAREST);
269  return img_resize;
270  };
271  }
272 
273  SECTION("BGR")
274  {
275  cv::Mat img, img_resize;
276  img = cv::imread(imagePathColor, cv::IMREAD_COLOR);
277 
278  BENCHMARK("Benchmark Nearest Neighbor BGR image resize (OpenCV)")
279  {
280  cv::resize(img, img_resize, cv::Size(g_resize_width, g_resize_height), 0, 0, cv::INTER_NEAREST);
281  return img_resize;
282  };
283  }
284 }
285 
286 TEST_CASE("Bilinear image resize (OpenCV)", "[benchmark]")
287 {
288  SECTION("unsigned char")
289  {
290  cv::Mat img, img_resize;
291  img = cv::imread(imagePathGray, cv::IMREAD_GRAYSCALE);
292 
293  BENCHMARK("Benchmark Bilinear uchar image resize (OpenCV)")
294  {
295  cv::resize(img, img_resize, cv::Size(g_resize_width, g_resize_height), 0, 0, cv::INTER_LINEAR);
296  return img_resize;
297  };
298  }
299 
300  SECTION("BGR")
301  {
302  cv::Mat img, img_resize;
303  img = cv::imread(imagePathColor, cv::IMREAD_COLOR);
304 
305  BENCHMARK("Benchmark Bilinear BGR image resize (OpenCV)")
306  {
307  cv::resize(img, img_resize, cv::Size(g_resize_width, g_resize_height), 0, 0, cv::INTER_LINEAR);
308  return img_resize;
309  };
310  }
311 }
312 
313 TEST_CASE("Area image resize (OpenCV)", "[benchmark]")
314 {
315  SECTION("unsigned char")
316  {
317  cv::Mat img, img_resize;
318  img = cv::imread(imagePathGray, cv::IMREAD_GRAYSCALE);
319 
320  BENCHMARK("Benchmark Area uchar image resize (OpenCV)")
321  {
322  cv::resize(img, img_resize, cv::Size(g_resize_width, g_resize_height), 0, 0, cv::INTER_AREA);
323  return img_resize;
324  };
325  }
326 
327  SECTION("BGR")
328  {
329  cv::Mat img, img_resize;
330  img = cv::imread(imagePathColor, cv::IMREAD_COLOR);
331 
332  BENCHMARK("Benchmark Area BGR image resize (OpenCV)")
333  {
334  cv::resize(img, img_resize, cv::Size(g_resize_width, g_resize_height), 0, 0, cv::INTER_AREA);
335  return img_resize;
336  };
337  }
338 }
339 
340 TEST_CASE("Bicubic image resize (OpenCV)", "[benchmark]")
341 {
342  SECTION("unsigned char")
343  {
344  cv::Mat img, img_resize;
345  img = cv::imread(imagePathGray, cv::IMREAD_GRAYSCALE);
346 
347  BENCHMARK("Benchmark Bicubic uchar image resize (OpenCV)")
348  {
349  cv::resize(img, img_resize, cv::Size(g_resize_width, g_resize_height), 0, 0, cv::INTER_CUBIC);
350  return img_resize;
351  };
352  }
353 
354  SECTION("BGR")
355  {
356  cv::Mat img, img_resize;
357  img = cv::imread(imagePathColor, cv::IMREAD_COLOR);
358 
359  BENCHMARK("Benchmark Bicubic BGR image resize (OpenCV)")
360  {
361  cv::resize(img, img_resize, cv::Size(g_resize_width, g_resize_height), 0, 0, cv::INTER_CUBIC);
362  return img_resize;
363  };
364  }
365 }
366 #endif
367 
368 int main(int argc, char *argv[])
369 {
370  Catch::Session session; // There must be exactly one instance
371 
372  bool runBenchmark = false;
373  // Build a new parser on top of Catch's
374  using namespace Catch::clara;
375  auto cli = session.cli() // Get Catch's composite command line parser
376  | Opt(runBenchmark) // bind variable to a new option, with a hint string
377  ["--benchmark"] // the option names it will respond to
378  ("run benchmark?") // description string for the help output
379  | Opt(imagePathColor, "imagePathColor")["--imagePathColor"]("Path to color image") |
380  Opt(imagePathGray, "imagePathColor")["--imagePathGray"] |
381  Opt(g_resize_width, "g_resize_width")["--width"]("Resize width") |
382  Opt(g_resize_height, "g_resize_height")["--height"]("Resize height");
383 
384 // Now pass the new composite back to Catch so it uses that
385  session.cli(cli);
386 
387  // Let Catch (using Clara) parse the command line
388  session.applyCommandLine(argc, argv);
389 
390  if (runBenchmark) {
391  vpImage<vpRGBa> I_color;
392  vpImageIo::read(I_color, imagePathColor);
393  std::cout << "imagePathColor:\n\t" << imagePathColor << "\n\t" << I_color.getWidth() << "x" << I_color.getHeight()
394  << std::endl;
395 
396  vpImage<unsigned char> I_gray;
397  vpImageIo::read(I_gray, imagePathGray);
398  std::cout << "imagePathGray:\n\t" << imagePathGray << "\n\t" << I_gray.getWidth() << "x" << I_gray.getHeight()
399  << std::endl;
400  std::cout << "Resize to: " << g_resize_width << "x" << g_resize_height << std::endl;
401 
402  int numFailed = session.run();
403 
404  // numFailed is clamped to 255 as some unices only use the lower 8 bits.
405  // This clamping has already been applied, so just return it here
406  // You can also do any post run clean-up here
407  return numFailed;
408  }
409 
410  return EXIT_SUCCESS;
411 }
412 #else
413 #include <iostream>
414 
415 int main() { return EXIT_SUCCESS; }
416 #endif
static void read(vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Definition: vpImageIo.cpp:143
static void resize(const vpImage< Type > &I, vpImage< Type > &Ires, unsigned int width, unsigned int height, const vpImageInterpolationType &method=INTERPOLATION_NEAREST, unsigned int nThreads=0)
@ INTERPOLATION_LINEAR
Definition: vpImageTools.h:80
@ INTERPOLATION_NEAREST
Definition: vpImageTools.h:79
unsigned int getWidth() const
Definition: vpImage.h:245
unsigned int getHeight() const
Definition: vpImage.h:184
static std::string getViSPImagesDataPath()
Definition: vpIoTools.cpp:1832
static std::string createFilePath(const std::string &parent, const std::string &child)
Definition: vpIoTools.cpp:2195