Visual Servoing Platform  version 3.5.0 under development (2022-02-15)
perfImageLoadSave.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2022 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  * Benchmark color image conversion.
33  *
34  *****************************************************************************/
35 
36 #include <visp3/core/vpConfig.h>
37 
38 #ifdef VISP_HAVE_CATCH2
39 #define CATCH_CONFIG_ENABLE_BENCHMARKING
40 #define CATCH_CONFIG_RUNNER
41 #include <catch.hpp>
42 
43 #include <thread>
44 #include <visp3/core/vpIoTools.h>
45 #include <visp3/io/vpImageIo.h>
46 
47 static std::string ipath = vpIoTools::getViSPImagesDataPath();
48 static std::vector<std::string> paths {
49  ipath + "/Solvay/Solvay_conference_1927_Version2_640x440",
50  ipath + "/Solvay/Solvay_conference_1927_Version2_1024x705",
51  ipath + "/Solvay/Solvay_conference_1927_Version2_1280x881",
52  ipath + "/Solvay/Solvay_conference_1927_Version2_2126x1463",
53 };
54 static std::vector<std::string> names {
55  "Solvay (640x440)", "Solvay (1024x705)", "Solvay (1280x881)", "Solvay (2126x1463)"
56 };
57 static std::vector<vpImageIo::vpImageIoBackendType> backends {
58 #if defined(VISP_HAVE_JPEG) && defined(VISP_HAVE_PNG)
60 #endif
61 #if defined(VISP_HAVE_OPENCV)
63 #endif
66 };
67 static std::vector<std::string> backendNamesJpeg {
68  "libjpeg", "OpenCV", "simd", "stb"
69 };
70 static std::vector<std::string> backendNamesPng {
71  "libpng", "OpenCV", "simd", "stb"
72 };
73 static int nThreads = 0;
74 
75 TEST_CASE("Benchmark grayscale JPEG image loading", "[benchmark]") {
76  for (size_t i = 0; i < paths.size(); i++) {
77  SECTION(names[i]) {
78  for (size_t j = 0; j < backends.size(); j++) {
80 
81  BENCHMARK(backendNamesJpeg[j] + " backend") {
82  vpImageIo::read(I, paths[i] + ".jpg", backends[j]);
83  return I;
84  };
85  }
86  }
87  }
88 }
89 
90 TEST_CASE("Benchmark RGBA JPEG image loading", "[benchmark]") {
91  for (size_t i = 0; i < paths.size(); i++) {
92  SECTION(names[i]) {
93  for (size_t j = 0; j < backends.size(); j++) {
95 
96  BENCHMARK(backendNamesJpeg[j] + " backend") {
97  vpImageIo::read(I, paths[i] + ".jpg", backends[j]);
98  return I;
99  };
100  }
101  }
102  }
103 }
104 
105 TEST_CASE("Benchmark grayscale PNG image loading", "[benchmark]") {
106  for (size_t i = 0; i < paths.size(); i++) {
107  SECTION(names[i]) {
108  for (size_t j = 0; j < backends.size(); j++) {
109  vpImage<vpRGBa> I;
110 
111  BENCHMARK(backendNamesPng[j] + " backend") {
112  vpImageIo::read(I, paths[i] + ".png", backends[j]);
113  return I;
114  };
115  }
116  }
117  }
118 }
119 
120 TEST_CASE("Benchmark RGBA PNG image loading", "[benchmark]") {
121  for (size_t i = 0; i < paths.size(); i++) {
122  SECTION(names[i]) {
123  for (size_t j = 0; j < backends.size(); j++) {
125 
126  BENCHMARK(backendNamesPng[j] + " backend") {
127  vpImageIo::read(I, paths[i] + ".png", backends[j]);
128  return I;
129  };
130  }
131  }
132  }
133 }
134 
135 TEST_CASE("Benchmark grayscale JPEG image saving", "[benchmark]") {
136  std::string tmp_dir = vpIoTools::makeTempDirectory( vpIoTools::getTempPath() );
137  std::string directory_filename_tmp = tmp_dir + "/vpIoTools_perfImageLoadSave_" + vpTime::getDateTime("%Y-%m-%d_%H.%M.%S");
138  vpIoTools::makeDirectory(directory_filename_tmp);
139  REQUIRE(vpIoTools::checkDirectory(directory_filename_tmp));
140 
141  for (size_t i = 0; i < paths.size(); i++) {
143  vpImageIo::read(I, paths[i] + ".png");
144 
145  SECTION(names[i]) {
146  for (size_t j = 0; j < backends.size(); j++) {
147  BENCHMARK(backendNamesJpeg[j] + " backend") {
148  vpImageIo::write(I, directory_filename_tmp + "/ViSP_tmp_perf_write.jpg", backends[j]);
149  return I;
150  };
151  }
152  }
153  }
154 
155  REQUIRE(vpIoTools::remove(directory_filename_tmp));
156 }
157 
158 TEST_CASE("Benchmark RGBA JPEG image saving", "[benchmark]") {
159  std::string tmp_dir = vpIoTools::makeTempDirectory( vpIoTools::getTempPath() );
160  std::string directory_filename_tmp = tmp_dir + "/vpIoTools_perfImageLoadSave_" + vpTime::getDateTime("%Y-%m-%d_%H.%M.%S");
161  vpIoTools::makeDirectory(directory_filename_tmp);
162  REQUIRE(vpIoTools::checkDirectory(directory_filename_tmp));
163 
164  for (size_t i = 0; i < paths.size(); i++) {
165  vpImage<vpRGBa> I;
166  vpImageIo::read(I, paths[i] + ".png");
167 
168  SECTION(names[i]) {
169  for (size_t j = 0; j < backends.size(); j++) {
170  BENCHMARK(backendNamesJpeg[j] + " backend") {
171  vpImageIo::write(I, directory_filename_tmp + "/ViSP_tmp_perf_write.jpg", backends[j]);
172  return I;
173  };
174  }
175  }
176  }
177 
178  REQUIRE(vpIoTools::remove(directory_filename_tmp));
179 }
180 
181 TEST_CASE("Benchmark grayscale PNG image saving", "[benchmark]") {
182  std::string tmp_dir = vpIoTools::makeTempDirectory( vpIoTools::getTempPath() );
183  std::string directory_filename_tmp = tmp_dir + "/vpIoTools_perfImageLoadSave_" + vpTime::getDateTime("%Y-%m-%d_%H.%M.%S");
184  vpIoTools::makeDirectory(directory_filename_tmp);
185  REQUIRE(vpIoTools::checkDirectory(directory_filename_tmp));
186 
187  for (size_t i = 0; i < paths.size(); i++) {
189  vpImageIo::read(I, paths[i] + ".png");
190 
191  SECTION(names[i]) {
192  for (size_t j = 0; j < backends.size(); j++) {
193  BENCHMARK(backendNamesPng[j] + " backend") {
194  vpImageIo::write(I, directory_filename_tmp + "/ViSP_tmp_perf_write.png", backends[j]);
195  return I;
196  };
197  }
198  }
199  }
200 
201  REQUIRE(vpIoTools::remove(directory_filename_tmp));
202 }
203 
204 TEST_CASE("Benchmark RGBA PNG image saving", "[benchmark]") {
205  std::string tmp_dir = vpIoTools::makeTempDirectory( vpIoTools::getTempPath() );
206  std::string directory_filename_tmp = tmp_dir + "/vpIoTools_perfImageLoadSave_" + vpTime::getDateTime("%Y-%m-%d_%H.%M.%S");
207  vpIoTools::makeDirectory(directory_filename_tmp);
208  REQUIRE(vpIoTools::checkDirectory(directory_filename_tmp));
209 
210  for (size_t i = 0; i < paths.size(); i++) {
211  vpImage<vpRGBa> I;
212  vpImageIo::read(I, paths[i] + ".png");
213 
214  SECTION(names[i]) {
215  for (size_t j = 0; j < backends.size(); j++) {
216  BENCHMARK(backendNamesPng[j] + " backend") {
217  vpImageIo::write(I, directory_filename_tmp + "/ViSP_tmp_perf_write.png", backends[j]);
218  return I;
219  };
220  }
221  }
222  }
223 
224  REQUIRE(vpIoTools::remove(directory_filename_tmp));
225 }
226 
227 int main(int argc, char *argv[])
228 {
229  Catch::Session session; // There must be exactly one instance
230 
231  bool runBenchmark = false;
232  // Build a new parser on top of Catch's
233  using namespace Catch::clara;
234  auto cli = session.cli() // Get Catch's composite command line parser
235  | Opt(runBenchmark) // bind variable to a new option, with a hint string
236  ["--benchmark"] // the option names it will respond to
237  ("Run benchmark")
238  | Opt(nThreads, "nThreads")
239  ["--nThreads"]
240  ("Number of threads");
241 
242  // Now pass the new composite back to Catch so it uses that
243  session.cli(cli);
244 
245  // Let Catch (using Clara) parse the command line
246  session.applyCommandLine(argc, argv);
247 
248  if (runBenchmark) {
249  std::cout << "nThreads: " << nThreads << " / available threads: " << std::thread::hardware_concurrency() << std::endl;
250 
251  int numFailed = session.run();
252 
253  // numFailed is clamped to 255 as some unices only use the lower 8 bits.
254  // This clamping has already been applied, so just return it here
255  // You can also do any post run clean-up here
256  return numFailed;
257  }
258 
259  return EXIT_SUCCESS;
260 }
261 #else
262 #include <iostream>
263 
264 int main()
265 {
266  return 0;
267 }
268 #endif
static void read(vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Definition: vpImageIo.cpp:149
static void makeDirectory(const std::string &dirname)
Definition: vpIoTools.cpp:570
Use embedded simd library.
Definition: vpImageIo.h:131
static std::string getViSPImagesDataPath()
Definition: vpIoTools.cpp:1365
Use system libraries like libpng or libjpeg.
Definition: vpImageIo.h:129
Use embedded stb_image library.
Definition: vpImageIo.h:132
static void write(const vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Definition: vpImageIo.cpp:293
VISP_EXPORT std::string getDateTime(const std::string &format="%Y/%m/%d %H:%M:%S")
Definition: vpTime.cpp:358
static bool checkDirectory(const std::string &dirname)
Definition: vpIoTools.cpp:420
static std::string getTempPath()
Definition: vpIoTools.cpp:194
static bool remove(const std::string &filename)
Definition: vpIoTools.cpp:929
static std::string makeTempDirectory(const std::string &dirname)
Definition: vpIoTools.cpp:728