Visual Servoing Platform  version 3.6.1 under development (2024-10-09)
perfColorConversion.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 color image conversion.
32  */
33 
37 #include <visp3/core/vpConfig.h>
38 
39 #if defined(VISP_HAVE_CATCH2) && defined(VISP_HAVE_THREADS)
40 
41 #include <catch_amalgamated.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 #ifdef ENABLE_VISP_NAMESPACE
54 using namespace VISP_NAMESPACE_NAME;
55 #endif
56 static std::string ipath = vpIoTools::getViSPImagesDataPath();
57 static std::string imagePathColor = vpIoTools::createFilePath(ipath, "Klimt/Klimt.ppm");
58 static std::string imagePathGray = vpIoTools::createFilePath(ipath, "Klimt/Klimt.pgm");
59 static int nThreads = 0;
60 
61 TEST_CASE("Benchmark rgba to grayscale (naive code)", "[benchmark]")
62 {
64  vpImageIo::read(I, imagePathColor);
65 
66  vpImage<unsigned char> I_gray(I.getHeight(), I.getWidth());
67 
68  BENCHMARK("Benchmark rgba to grayscale (naive code)")
69  {
70  common_tools::RGBaToGrayRef(reinterpret_cast<unsigned char *>(I.bitmap), I_gray.bitmap, I.getSize());
71  return I_gray;
72  };
73 }
74 
75 TEST_CASE("Benchmark rgba to grayscale (ViSP)", "[benchmark]")
76 {
78  vpImageIo::read(I, imagePathColor);
79 
80  vpImage<unsigned char> I_gray(I.getHeight(), I.getWidth());
81 
82  BENCHMARK("Benchmark rgba to grayscale (ViSP)")
83  {
84  vpImageConvert::convert(I, I_gray, nThreads);
85  return I_gray;
86  };
87 }
88 
89 TEST_CASE("Benchmark grayscale to rgba (naive code)", "[benchmark]")
90 {
92  vpImageIo::read(I, imagePathGray);
93 
94  vpImage<vpRGBa> I_color(I.getHeight(), I.getWidth());
95 
96  BENCHMARK("Benchmark grayscale to rgba (naive code)")
97  {
98  common_tools::grayToRGBaRef(I.bitmap, reinterpret_cast<unsigned char *>(I_color.bitmap), I.getSize());
99  return I_color;
100  };
101 }
102 
103 TEST_CASE("Benchmark grayscale to rgba (ViSP)", "[benchmark]")
104 {
106  vpImageIo::read(I, imagePathGray);
107 
108  vpImage<vpRGBa> I_color(I.getHeight(), I.getWidth());
109 
110  BENCHMARK("Benchmark grayscale to rgba (ViSP)")
111  {
112  vpImageConvert::convert(I, I_color);
113  return I_color;
114  };
115 }
116 
117 TEST_CASE("Benchmark split RGBa (ViSP)", "[benchmark]")
118 {
119  vpImage<vpRGBa> I;
120  vpImageIo::read(I, imagePathColor);
121 
122  vpImage<unsigned char> R, G, B, A;
123  BENCHMARK("Benchmark split RGBa (ViSP)")
124  {
125  vpImageConvert::split(I, &R, &G, &B, &A);
126  return R;
127  };
128 }
129 
130 TEST_CASE("Benchmark merge to RGBa (ViSP)", "[benchmark]")
131 {
132  vpImage<vpRGBa> I;
133  vpImageIo::read(I, imagePathColor);
134 
135  vpImage<unsigned char> R, G, B, A;
136  vpImageConvert::split(I, &R, &G, &B, &A);
137 
138  vpImage<vpRGBa> I_merge(I.getHeight(), I.getWidth());
139  BENCHMARK("Benchmark merge to RGBa (ViSP)")
140  {
141  vpImageConvert::merge(&R, &G, &B, &A, I_merge);
142  return I_merge;
143  };
144 }
145 
146 TEST_CASE("Benchmark bgr to grayscale (naive code)", "[benchmark]")
147 {
148  vpImage<vpRGBa> I;
149  vpImageIo::read(I, imagePathColor);
150 
151  std::vector<unsigned char> bgr;
152  common_tools::RGBaToBGR(I, bgr);
153 
154  vpImage<unsigned char> I_gray(I.getHeight(), I.getWidth());
155 
156  BENCHMARK("Benchmark bgr to grayscale (naive code)")
157  {
158  common_tools::BGRToGrayRef(bgr.data(), reinterpret_cast<unsigned char *>(I_gray.bitmap), I_gray.getWidth(),
159  I_gray.getHeight(), false);
160  return I_gray;
161  };
162 }
163 
164 TEST_CASE("Benchmark bgr to grayscale (ViSP)", "[benchmark]")
165 {
166  vpImage<vpRGBa> I;
167  vpImageIo::read(I, imagePathColor);
168 
169  std::vector<unsigned char> bgr;
170  common_tools::RGBaToBGR(I, bgr);
171 
172  vpImage<unsigned char> I_gray(I.getHeight(), I.getWidth());
173 
174  BENCHMARK("Benchmark bgr to grayscale (ViSP)")
175  {
176  vpImageConvert::BGRToGrey(bgr.data(), I_gray.bitmap, I.getWidth(), I.getHeight(), false, nThreads);
177  return I_gray;
178  };
179 
180 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_HIGHGUI) && defined(HAVE_OPENCV_IMGPROC)
181 
182  SECTION("OpenCV Mat type")
183  {
184  cv::Mat img;
185  vpImageConvert::convert(I, img);
186 
187  BENCHMARK("Benchmark bgr to grayscale (ViSP + OpenCV Mat type)")
188  {
189  vpImageConvert::convert(img, I_gray, false, nThreads);
190  return I_gray;
191  };
192  }
193 #endif
194 }
195 
196 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGCODECS) && defined(HAVE_OPENCV_IMGPROC)
197 TEST_CASE("Benchmark bgr to grayscale (OpenCV)", "[benchmark]")
198 {
199  cv::Mat img = cv::imread(imagePathColor);
200  cv::Mat img_gray(img.size(), CV_8UC1);
201 
202  BENCHMARK("Benchmark bgr to grayscale (OpenCV)")
203  {
204  cv::cvtColor(img, img_gray, cv::COLOR_BGR2GRAY);
205  return img_gray;
206  };
207 }
208 #endif
209 
210 TEST_CASE("Benchmark bgr to rgba (naive code)", "[benchmark]")
211 {
212  vpImage<vpRGBa> I;
213  vpImageIo::read(I, imagePathColor);
214 
215  std::vector<unsigned char> bgr;
216  common_tools::RGBaToBGR(I, bgr);
217 
218  vpImage<vpRGBa> I_bench(I.getHeight(), I.getWidth());
219  BENCHMARK("Benchmark bgr to rgba (naive code)")
220  {
221  common_tools::BGRToRGBaRef(bgr.data(), reinterpret_cast<unsigned char *>(I_bench.bitmap), I.getWidth(),
222  I.getHeight(), false);
223  return I_bench;
224  };
225 }
226 
227 TEST_CASE("Benchmark bgr to rgba (ViSP)", "[benchmark]")
228 {
229  vpImage<vpRGBa> I;
230  vpImageIo::read(I, imagePathColor);
231 
232  std::vector<unsigned char> bgr;
233  common_tools::RGBaToBGR(I, bgr);
234 
235  SECTION("Check BGR to RGBa conversion")
236  {
237  vpImage<vpRGBa> ref(I.getHeight(), I.getWidth());
238  common_tools::BGRToRGBaRef(bgr.data(), reinterpret_cast<unsigned char *>(ref.bitmap), I.getWidth(), I.getHeight(),
239  false);
240  vpImage<vpRGBa> rgba(I.getHeight(), I.getWidth());
241  vpImageConvert::BGRToRGBa(bgr.data(), reinterpret_cast<unsigned char *>(rgba.bitmap), I.getWidth(), I.getHeight(),
242  false);
243 
244  CHECK((rgba == ref));
245  }
246 
247  vpImage<vpRGBa> I_rgba(I.getHeight(), I.getWidth());
248  BENCHMARK("Benchmark bgr to rgba (ViSP)")
249  {
250  vpImageConvert::BGRToRGBa(bgr.data(), reinterpret_cast<unsigned char *>(I_rgba.bitmap), I.getWidth(), I.getHeight(),
251  false);
252  return I_rgba;
253  };
254 
255 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_HIGHGUI) && defined(HAVE_OPENCV_IMGPROC)
256  SECTION("OpenCV Mat type")
257  {
258  cv::Mat img;
259  vpImageConvert::convert(I, img);
260 
261  BENCHMARK("Benchmark bgr to rgba (ViSP + OpenCV Mat type)")
262  {
263  vpImageConvert::convert(img, I_rgba);
264  return I_rgba;
265  };
266  }
267 #endif
268 }
269 
270 TEST_CASE("Benchmark bgra to rgba (naive code)", "[benchmark]")
271 {
272  vpImage<vpRGBa> I;
273  vpImageIo::read(I, imagePathColor);
274 
275  std::vector<unsigned char> bgra;
276  common_tools::RGBaToBGRa(I, bgra);
277 
278  vpImage<vpRGBa> I_bench(I.getHeight(), I.getWidth());
279  BENCHMARK("Benchmark bgra to rgba (naive code)")
280  {
281  common_tools::BGRaToRGBaRef(bgra.data(), reinterpret_cast<unsigned char *>(I_bench.bitmap), I.getWidth(),
282  I.getHeight(), false);
283  return I_bench;
284  };
285 }
286 
287 TEST_CASE("Benchmark bgra to rgba (ViSP)", "[benchmark]")
288 {
289  vpImage<vpRGBa> I;
290  vpImageIo::read(I, imagePathColor);
291 
292  std::vector<unsigned char> bgra;
293  common_tools::RGBaToBGRa(I, bgra);
294 
295  SECTION("Check BGRa to RGBa conversion")
296  {
297  vpImage<vpRGBa> ref(I.getHeight(), I.getWidth());
298  common_tools::BGRaToRGBaRef(bgra.data(), reinterpret_cast<unsigned char *>(ref.bitmap), I.getWidth(), I.getHeight(),
299  false);
300  vpImage<vpRGBa> rgba(I.getHeight(), I.getWidth());
301  vpImageConvert::BGRaToRGBa(bgra.data(), reinterpret_cast<unsigned char *>(rgba.bitmap), I.getWidth(), I.getHeight(),
302  false);
303 
304  CHECK((rgba == ref));
305  }
306  vpImage<vpRGBa> I_rgba(I.getHeight(), I.getWidth());
307  BENCHMARK("Benchmark bgra to rgba (ViSP)")
308  {
309  vpImageConvert::BGRaToRGBa(bgra.data(), reinterpret_cast<unsigned char *>(I_rgba.bitmap), I.getWidth(),
310  I.getHeight(), false);
311  return I_rgba;
312  };
313 }
314 
315 int main(int argc, char *argv[])
316 {
317  Catch::Session session;
318 
319  bool runBenchmark = false;
320  auto cli = session.cli()
321  | Catch::Clara::Opt(runBenchmark)["--benchmark"]("run benchmark?")
322  | Catch::Clara::Opt(imagePathColor, "imagePathColor")["--imagePathColor"]("Path to color image")
323  | Catch::Clara::Opt(imagePathGray, "imagePathColor")["--imagePathGray"]("Path to gray image")
324  | Catch::Clara::Opt(nThreads, "nThreads")["--nThreads"]("Number of threads");
325 
326  session.cli(cli);
327 
328  session.applyCommandLine(argc, argv);
329 
330  if (runBenchmark) {
331  vpImage<vpRGBa> I_color;
332  vpImageIo::read(I_color, imagePathColor);
333  std::cout << "imagePathColor:\n\t" << imagePathColor << "\n\t" << I_color.getWidth() << "x" << I_color.getHeight()
334  << std::endl;
335 
336  vpImage<unsigned char> I_gray;
337  vpImageIo::read(I_gray, imagePathGray);
338  std::cout << "imagePathGray:\n\t" << imagePathGray << "\n\t" << I_gray.getWidth() << "x" << I_gray.getHeight()
339  << std::endl;
340  std::cout << "nThreads: " << nThreads << " / available threads: " << std::thread::hardware_concurrency()
341  << std::endl;
342 
343  int numFailed = session.run();
344 
345  return numFailed;
346  }
347 
348  return EXIT_SUCCESS;
349 }
350 #else
351 #include <iostream>
352 
353 int main() { return EXIT_SUCCESS; }
354 #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:147
unsigned int getWidth() const
Definition: vpImage.h:242
unsigned int getSize() const
Definition: vpImage.h:221
Type * bitmap
points toward the bitmap
Definition: vpImage.h:135
unsigned int getHeight() const
Definition: vpImage.h:181
static std::string getViSPImagesDataPath()
Definition: vpIoTools.cpp:1053
static std::string createFilePath(const std::string &parent, const std::string &child)
Definition: vpIoTools.cpp:1427