Visual Servoing Platform  version 3.6.1 under development (2024-04-26)
perfColorConversion.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 color image conversion.
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/vpIoTools.h>
46 #include <visp3/io/vpImageIo.h>
47 
48 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGCODECS) && defined(HAVE_OPENCV_IMGPROC)
49 #include <opencv2/imgcodecs.hpp>
50 #include <opencv2/imgproc/imgproc.hpp>
51 #endif
52 
53 static std::string ipath = vpIoTools::getViSPImagesDataPath();
54 static std::string imagePathColor = vpIoTools::createFilePath(ipath, "Klimt/Klimt.ppm");
55 static std::string imagePathGray = vpIoTools::createFilePath(ipath, "Klimt/Klimt.pgm");
56 static int nThreads = 0;
57 
58 TEST_CASE("Benchmark rgba to grayscale (naive code)", "[benchmark]")
59 {
61  vpImageIo::read(I, imagePathColor);
62 
63  vpImage<unsigned char> I_gray(I.getHeight(), I.getWidth());
64 
65  BENCHMARK("Benchmark rgba to grayscale (naive code)")
66  {
67  common_tools::RGBaToGrayRef(reinterpret_cast<unsigned char *>(I.bitmap), I_gray.bitmap, I.getSize());
68  return I_gray;
69  };
70 }
71 
72 TEST_CASE("Benchmark rgba to grayscale (ViSP)", "[benchmark]")
73 {
75  vpImageIo::read(I, imagePathColor);
76 
77  vpImage<unsigned char> I_gray(I.getHeight(), I.getWidth());
78 
79  BENCHMARK("Benchmark rgba to grayscale (ViSP)")
80  {
81  vpImageConvert::convert(I, I_gray, nThreads);
82  return I_gray;
83  };
84 }
85 
86 TEST_CASE("Benchmark grayscale to rgba (naive code)", "[benchmark]")
87 {
89  vpImageIo::read(I, imagePathGray);
90 
91  vpImage<vpRGBa> I_color(I.getHeight(), I.getWidth());
92 
93  BENCHMARK("Benchmark grayscale to rgba (naive code)")
94  {
95  common_tools::grayToRGBaRef(I.bitmap, reinterpret_cast<unsigned char *>(I_color.bitmap), I.getSize());
96  return I_color;
97  };
98 }
99 
100 TEST_CASE("Benchmark grayscale to rgba (ViSP)", "[benchmark]")
101 {
103  vpImageIo::read(I, imagePathGray);
104 
105  vpImage<vpRGBa> I_color(I.getHeight(), I.getWidth());
106 
107  BENCHMARK("Benchmark grayscale to rgba (ViSP)")
108  {
109  vpImageConvert::convert(I, I_color);
110  return I_color;
111  };
112 }
113 
114 TEST_CASE("Benchmark split RGBa (ViSP)", "[benchmark]")
115 {
116  vpImage<vpRGBa> I;
117  vpImageIo::read(I, imagePathColor);
118 
119  vpImage<unsigned char> R, G, B, A;
120  BENCHMARK("Benchmark split RGBa (ViSP)")
121  {
122  vpImageConvert::split(I, &R, &G, &B, &A);
123  return R;
124  };
125 }
126 
127 TEST_CASE("Benchmark merge to RGBa (ViSP)", "[benchmark]")
128 {
129  vpImage<vpRGBa> I;
130  vpImageIo::read(I, imagePathColor);
131 
132  vpImage<unsigned char> R, G, B, A;
133  vpImageConvert::split(I, &R, &G, &B, &A);
134 
135  vpImage<vpRGBa> I_merge(I.getHeight(), I.getWidth());
136  BENCHMARK("Benchmark merge to RGBa (ViSP)")
137  {
138  vpImageConvert::merge(&R, &G, &B, &A, I_merge);
139  return I_merge;
140  };
141 }
142 
143 TEST_CASE("Benchmark bgr to grayscale (naive code)", "[benchmark]")
144 {
145  vpImage<vpRGBa> I;
146  vpImageIo::read(I, imagePathColor);
147 
148  std::vector<unsigned char> bgr;
149  common_tools::RGBaToBGR(I, bgr);
150 
151  vpImage<unsigned char> I_gray(I.getHeight(), I.getWidth());
152 
153  BENCHMARK("Benchmark bgr to grayscale (naive code)")
154  {
155  common_tools::BGRToGrayRef(bgr.data(), reinterpret_cast<unsigned char *>(I_gray.bitmap), I_gray.getWidth(),
156  I_gray.getHeight(), false);
157  return I_gray;
158  };
159 }
160 
161 TEST_CASE("Benchmark bgr to grayscale (ViSP)", "[benchmark]")
162 {
163  vpImage<vpRGBa> I;
164  vpImageIo::read(I, imagePathColor);
165 
166  std::vector<unsigned char> bgr;
167  common_tools::RGBaToBGR(I, bgr);
168 
169  vpImage<unsigned char> I_gray(I.getHeight(), I.getWidth());
170 
171  BENCHMARK("Benchmark bgr to grayscale (ViSP)")
172  {
173  vpImageConvert::BGRToGrey(bgr.data(), I_gray.bitmap, I.getWidth(), I.getHeight(), false, nThreads);
174  return I_gray;
175  };
176 
177 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_HIGHGUI) && defined(HAVE_OPENCV_IMGPROC)
178 
179  SECTION("OpenCV Mat type")
180  {
181  cv::Mat img;
182  vpImageConvert::convert(I, img);
183 
184  BENCHMARK("Benchmark bgr to grayscale (ViSP + OpenCV Mat type)")
185  {
186  vpImageConvert::convert(img, I_gray, false, nThreads);
187  return I_gray;
188  };
189  }
190 #endif
191 }
192 
193 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGCODECS) && defined(HAVE_OPENCV_IMGPROC)
194 TEST_CASE("Benchmark bgr to grayscale (OpenCV)", "[benchmark]")
195 {
196  cv::Mat img = cv::imread(imagePathColor);
197  cv::Mat img_gray(img.size(), CV_8UC1);
198 
199  BENCHMARK("Benchmark bgr to grayscale (OpenCV)")
200  {
201  cv::cvtColor(img, img_gray, cv::COLOR_BGR2GRAY);
202  return img_gray;
203  };
204 }
205 #endif
206 
207 TEST_CASE("Benchmark bgr to rgba (naive code)", "[benchmark]")
208 {
209  vpImage<vpRGBa> I;
210  vpImageIo::read(I, imagePathColor);
211 
212  std::vector<unsigned char> bgr;
213  common_tools::RGBaToBGR(I, bgr);
214 
215  vpImage<vpRGBa> I_bench(I.getHeight(), I.getWidth());
216  BENCHMARK("Benchmark bgr to rgba (naive code)")
217  {
218  common_tools::BGRToRGBaRef(bgr.data(), reinterpret_cast<unsigned char *>(I_bench.bitmap), I.getWidth(),
219  I.getHeight(), false);
220  return I_bench;
221  };
222 }
223 
224 TEST_CASE("Benchmark bgr to rgba (ViSP)", "[benchmark]")
225 {
226  vpImage<vpRGBa> I;
227  vpImageIo::read(I, imagePathColor);
228 
229  std::vector<unsigned char> bgr;
230  common_tools::RGBaToBGR(I, bgr);
231 
232  SECTION("Check BGR to RGBa conversion")
233  {
234  vpImage<vpRGBa> ref(I.getHeight(), I.getWidth());
235  common_tools::BGRToRGBaRef(bgr.data(), reinterpret_cast<unsigned char *>(ref.bitmap), I.getWidth(), I.getHeight(),
236  false);
237  vpImage<vpRGBa> rgba(I.getHeight(), I.getWidth());
238  vpImageConvert::BGRToRGBa(bgr.data(), reinterpret_cast<unsigned char *>(rgba.bitmap), I.getWidth(), I.getHeight(),
239  false);
240 
241  CHECK((rgba == ref));
242  }
243 
244  vpImage<vpRGBa> I_rgba(I.getHeight(), I.getWidth());
245  BENCHMARK("Benchmark bgr to rgba (ViSP)")
246  {
247  vpImageConvert::BGRToRGBa(bgr.data(), reinterpret_cast<unsigned char *>(I_rgba.bitmap), I.getWidth(), I.getHeight(),
248  false);
249  return I_rgba;
250  };
251 
252 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_HIGHGUI) && defined(HAVE_OPENCV_IMGPROC)
253  SECTION("OpenCV Mat type")
254  {
255  cv::Mat img;
256  vpImageConvert::convert(I, img);
257 
258  BENCHMARK("Benchmark bgr to rgba (ViSP + OpenCV Mat type)")
259  {
260  vpImageConvert::convert(img, I_rgba);
261  return I_rgba;
262  };
263  }
264 #endif
265 }
266 
267 TEST_CASE("Benchmark bgra to rgba (naive code)", "[benchmark]")
268 {
269  vpImage<vpRGBa> I;
270  vpImageIo::read(I, imagePathColor);
271 
272  std::vector<unsigned char> bgra;
273  common_tools::RGBaToBGRa(I, bgra);
274 
275  vpImage<vpRGBa> I_bench(I.getHeight(), I.getWidth());
276  BENCHMARK("Benchmark bgra to rgba (naive code)")
277  {
278  common_tools::BGRaToRGBaRef(bgra.data(), reinterpret_cast<unsigned char *>(I_bench.bitmap), I.getWidth(),
279  I.getHeight(), false);
280  return I_bench;
281  };
282 }
283 
284 TEST_CASE("Benchmark bgra to rgba (ViSP)", "[benchmark]")
285 {
286  vpImage<vpRGBa> I;
287  vpImageIo::read(I, imagePathColor);
288 
289  std::vector<unsigned char> bgra;
290  common_tools::RGBaToBGRa(I, bgra);
291 
292  SECTION("Check BGRa to RGBa conversion")
293  {
294  vpImage<vpRGBa> ref(I.getHeight(), I.getWidth());
295  common_tools::BGRaToRGBaRef(bgra.data(), reinterpret_cast<unsigned char *>(ref.bitmap), I.getWidth(), I.getHeight(),
296  false);
297  vpImage<vpRGBa> rgba(I.getHeight(), I.getWidth());
298  vpImageConvert::BGRaToRGBa(bgra.data(), reinterpret_cast<unsigned char *>(rgba.bitmap), I.getWidth(), I.getHeight(),
299  false);
300 
301  CHECK((rgba == ref));
302  }
303  vpImage<vpRGBa> I_rgba(I.getHeight(), I.getWidth());
304  BENCHMARK("Benchmark bgra to rgba (ViSP)")
305  {
306  vpImageConvert::BGRaToRGBa(bgra.data(), reinterpret_cast<unsigned char *>(I_rgba.bitmap), I.getWidth(),
307  I.getHeight(), false);
308  return I_rgba;
309  };
310 }
311 
312 int main(int argc, char *argv[])
313 {
314  Catch::Session session; // There must be exactly one instance
315 
316  bool runBenchmark = false;
317  // Build a new parser on top of Catch's
318  using namespace Catch::clara;
319  auto cli = session.cli() // Get Catch's composite command line parser
320  | Opt(runBenchmark) // bind variable to a new option, with a hint string
321  ["--benchmark"] // the option names it will respond to
322  ("run benchmark?") // description string for the help output
323  | Opt(imagePathColor, "imagePathColor")["--imagePathColor"]("Path to color image") |
324  Opt(imagePathGray, "imagePathColor")["--imagePathGray"]("Path to gray image") |
325  Opt(nThreads, "nThreads")["--nThreads"]("Number of threads");
326 
327 // Now pass the new composite back to Catch so it uses that
328  session.cli(cli);
329 
330  // Let Catch (using Clara) parse the command line
331  session.applyCommandLine(argc, argv);
332 
333  if (runBenchmark) {
334  vpImage<vpRGBa> I_color;
335  vpImageIo::read(I_color, imagePathColor);
336  std::cout << "imagePathColor:\n\t" << imagePathColor << "\n\t" << I_color.getWidth() << "x" << I_color.getHeight()
337  << std::endl;
338 
339  vpImage<unsigned char> I_gray;
340  vpImageIo::read(I_gray, imagePathGray);
341  std::cout << "imagePathGray:\n\t" << imagePathGray << "\n\t" << I_gray.getWidth() << "x" << I_gray.getHeight()
342  << std::endl;
343  std::cout << "nThreads: " << nThreads << " / available threads: " << std::thread::hardware_concurrency()
344  << std::endl;
345 
346  int numFailed = session.run();
347 
348  // numFailed is clamped to 255 as some unices only use the lower 8 bits.
349  // This clamping has already been applied, so just return it here
350  // You can also do any post run clean-up here
351  return numFailed;
352  }
353 
354  return EXIT_SUCCESS;
355 }
356 #else
357 #include <iostream>
358 
359 int main() { return EXIT_SUCCESS; }
360 #endif
static void merge(const vpImage< unsigned char > *R, const vpImage< unsigned char > *G, const vpImage< unsigned char > *B, const vpImage< unsigned char > *a, vpImage< vpRGBa > &RGBa)
static void split(const vpImage< vpRGBa > &src, vpImage< unsigned char > *pR, vpImage< unsigned char > *pG, vpImage< unsigned char > *pB, vpImage< unsigned char > *pa=nullptr)
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
static void BGRToGrey(unsigned char *bgr, unsigned char *grey, unsigned int width, unsigned int height, bool flip=false, unsigned int nThreads=0)
static void BGRToRGBa(unsigned char *bgr, unsigned char *rgba, unsigned int width, unsigned int height, bool flip=false)
static void BGRaToRGBa(unsigned char *bgra, unsigned char *rgba, unsigned int width, unsigned int height, bool flip=false)
static void read(vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Definition: vpImageIo.cpp:143
unsigned int getWidth() const
Definition: vpImage.h:245
unsigned int getSize() const
Definition: vpImage.h:224
Type * bitmap
points toward the bitmap
Definition: vpImage.h:139
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