Visual Servoing Platform  version 3.6.1 under development (2024-11-15)
testDisplayScaled.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  * Display testing.
32  */
33 
37 #include <sstream>
38 
39 #include <visp3/core/vpConfig.h>
40 #include <visp3/core/vpImageTools.h>
41 #include <visp3/core/vpIoTools.h>
42 #include <visp3/gui/vpDisplayD3D.h>
43 #include <visp3/gui/vpDisplayGDI.h>
44 #include <visp3/gui/vpDisplayGTK.h>
45 #include <visp3/gui/vpDisplayOpenCV.h>
46 #include <visp3/gui/vpDisplayX.h>
47 #include <visp3/io/vpImageIo.h>
48 
49 #ifdef ENABLE_VISP_NAMESPACE
50 using namespace VISP_NAMESPACE_NAME;
51 #endif
52 
53 template <typename Type> bool test(const std::string &display, vpImage<Type> &I, unsigned int scale, bool click)
54 {
55  bool success = true;
56  unsigned int radius(I.getHeight() / 4);
57  int scale_ = (int)scale;
58  int radius_ = (int)radius;
59  unsigned int thickness = 2;
60  vpImagePoint center(I.getHeight() / 2, I.getWidth() / 2);
61  vpImagePoint offset(30, 160);
62  vpImagePoint v_offset(radius, 0);
63  vpImagePoint h_offset(0, radius);
64  vpRect roi(center, radius_ + scale_, radius_);
65  std::string itype;
66 
67  // backup the input image
68  vpImage<Type> Ibackup(I);
69 
70  vpDisplay *d = nullptr;
71  if (display == "GDI") {
72 #ifdef VISP_HAVE_GDI
73  d = new vpDisplayGDI;
74 #endif
75  }
76  else if (display == "GTK") {
77 #ifdef VISP_HAVE_GTK
78  d = new vpDisplayGTK;
79 #endif
80  }
81  else if (display == "X") {
82 #ifdef VISP_HAVE_X11
83  d = new vpDisplayX;
84 #endif
85  }
86  else if (display == "OpenCV") {
87 #ifdef HAVE_OPENCV_HIGHGUI
88  d = new vpDisplayOpenCV;
89 #endif
90  }
91  else if (display == "D3D9") {
92 #ifdef VISP_HAVE_D3D9
93  d = new vpDisplayD3D;
94 #endif
95  }
96  std::cout << "Start test for " << display << " renderer..." << std::endl;
97  std::cout << " Screen resolution: " << d->getScreenWidth() << " " << d->getScreenHeight() << std::endl;
98  d->setDownScalingFactor(scale);
99  d->init(I);
101  vpDisplay::flush(I);
102 
103  vpImage<Type> crop;
104  vpImageTools::crop(I, vpImagePoint(0, 245), (unsigned int)roi.getHeight(), (unsigned int)roi.getWidth(), crop);
105  I.insert(crop, roi.getTopLeft());
106  vpDisplay::displayROI(I, roi);
107  vpDisplay::flush(I);
108 
109  // Compare input and rendered images
110  if (sizeof(Type) == 1) {
111  itype = "uchar";
112  vpImage<Type> Iinsert = I;
113  vpImage<vpRGBa> Isampled;
114  vpImage<vpRGBa> Icolor;
115  vpImageConvert::convert(Iinsert, Icolor);
116  Icolor.subsample(scale, scale, Isampled);
117 
118  vpImage<vpRGBa> Irendered;
119  vpDisplay::getImage(I, Irendered);
120 
121  if (Isampled != Irendered) {
122  success = false;
123  std::cout << " -- Test width scale= " << scale << " type= " << itype << ": failed" << std::endl;
124 
125  std::stringstream ss;
126  ss << "Isampled-" << itype << "-scale-" << scale;
127 #ifdef VISP_HAVE_OPENCV
128  ss << ".png";
129 #else
130  ss << ".ppm";
131 #endif
132 
133  vpImageIo::write(Isampled, ss.str());
134 
135  ss.str("");
136  ss.clear();
137  ss << "Irendered-" << itype << "-scale-" << scale;
138 #ifdef VISP_HAVE_OPENCV
139  ss << ".png";
140 #else
141  ss << ".ppm";
142 #endif
143 
144  vpImageIo::write(Irendered, ss.str());
145  vpImage<vpRGBa> Idiff;
146  vpImageTools::imageDifference(Isampled, Irendered, Idiff);
147 
148  ss.str("");
149  ss.clear();
150  ss << "Idiff-" << itype << "-scale-" << scale;
151 #ifdef VISP_HAVE_OPENCV
152  ss << ".png";
153 #else
154  ss << ".ppm";
155 #endif
156 
157  vpImageIo::write(Idiff, ss.str());
158  }
159  else {
160  std::cout << " ++ Test width scale= " << scale << " type= " << itype << ": succeed" << std::endl;
161  }
162  }
163  else {
164  itype = "rgba";
165  vpImage<Type> Iinsert = I;
166  vpImage<Type> Isampled; // vpRGBa necessary
167  Iinsert.subsample(scale, scale, Isampled);
168 
169  vpImage<vpRGBa> Irendered; // vpRGBa necessary
170  vpDisplay::getImage(I, Irendered);
171 
172  vpImage<vpRGBa> IsampledCopy; // vpRGBa necessary
173 
174  vpImageConvert::convert(Isampled, IsampledCopy);
175  if (IsampledCopy != Irendered) {
176  success = false;
177  std::cout << " -- Test width scale= " << scale << " type= " << itype << ": failed" << std::endl;
178 
179  std::stringstream ss;
180  ss << "Isampled-" << itype << "-scale-" << scale;
181 #ifdef VISP_HAVE_OPENCV
182  ss << ".png";
183 #else
184  ss << ".ppm";
185 #endif
186 
187  vpImageIo::write(Isampled, ss.str());
188 
189  ss.str("");
190  ss.clear();
191  ss << "Irendered-" << itype << "-scale-" << scale;
192 #ifdef VISP_HAVE_OPENCV
193  ss << ".png";
194 #else
195  ss << ".ppm";
196 #endif
197 
198  vpImageIo::write(Irendered, ss.str());
199  vpImage<vpRGBa> Idiff;
200  vpImageTools::imageDifference(IsampledCopy, Irendered, Idiff);
201  ss.str("");
202  ss.clear();
203  ss << "Idiff-" << itype << "-scale-" << scale;
204 #ifdef VISP_HAVE_OPENCV
205  ss << ".png";
206 #else
207  ss << ".ppm";
208 #endif
209 
210  vpImageIo::write(Idiff, ss.str());
211 
212  }
213  else {
214  std::cout << " ++ Test width scale= " << scale << " type= " << itype << ": succeed" << std::endl;
215  }
216  }
217 
218  vpDisplay::displayRectangle(I, center - v_offset - h_offset, radius, radius, vpColor::blue, false, thickness);
219  vpDisplay::displayRectangle(I, center, center + v_offset + h_offset, vpColor::blue, false, thickness);
220  vpDisplay::displayRectangle(I, vpRect(center - v_offset - h_offset, center + v_offset + h_offset), vpColor::blue,
221  false, thickness);
222  vpDisplay::displayRectangle(I, center - v_offset * 3. / 2 + h_offset, radius / 2, radius / 2, vpColor::green, true);
223  vpDisplay::displayCircle(I, center, radius, vpColor::blue, false, thickness);
224  vpDisplay::displayArrow(I, center, center - v_offset / 4 - h_offset, vpColor::red, 10, 6, thickness);
225  vpDisplay::displayCross(I, center - radius / 2., radius, vpColor::green, thickness);
226  vpDisplay::displayDotLine(I, center - v_offset - h_offset, center, vpColor::cyan, thickness);
227  vpDisplay::displayLine(I, center + v_offset - h_offset, center - v_offset + h_offset, vpColor::cyan, thickness);
228  int nbpoints = (int)(radius * sqrt(2.) / 8 / scale);
229  for (int i = 0; i < nbpoints; i++) {
231  I, center - h_offset / 2. + vpImagePoint(-i * radius_ / (nbpoints * 2), i * radius_ / (nbpoints * 2)),
232  vpColor::cyan);
233  vpDisplay::displayPoint(I, center - h_offset + vpImagePoint(-i * radius_ / nbpoints, i * radius_ / nbpoints),
234  vpColor::cyan, thickness);
235  }
236 
237  if (click)
238  vpDisplay::displayText(I, 10 * scale_, 10 * scale_, "A click to continue", vpColor::red);
239  else
240  vpDisplay::displayText(I, 10 * scale_, 10 * scale_, "This is an image", vpColor::red);
241 
242  vpDisplay::flush(I);
243 
244  vpImage<vpRGBa> Irendered;
245  vpDisplay::getImage(I, Irendered);
246 
247  std::stringstream ss;
248  ss << "overlay-" << display << "-" << itype << "-scale-" << scale;
249 #ifdef VISP_HAVE_OPENCV
250  ss << ".png";
251 #else
252  ss << ".ppm";
253 #endif
254  std::cout << " Overlay saved in: " << ss.str() << std::endl;
255  vpImageIo::write(Irendered, ss.str());
256 
257  if (click)
259 
260  // Restore the input image
261  I = Ibackup;
262 
263  vpDisplay::close(I);
264 
265  if (d != nullptr)
266  delete d;
267 
268  if (success)
269  return true;
270  else
271  return false;
272 }
273 
274 int main(int argc, const char *argv[])
275 {
276  bool opt_click = true;
277  bool opt_display = true;
278  std::string opt_ipath;
279  std::string env_ipath;
280  std::string ipath;
281 
282  for (int i = 0; i < argc; i++) {
283  if (std::string(argv[i]) == "-c")
284  opt_click = false;
285  else if (std::string(argv[i]) == "-d")
286  opt_display = false;
287  else if (std::string(argv[i]) == "-i")
288  opt_ipath = std::string(argv[i + 1]);
289  else if (std::string(argv[i]) == "--help" || std::string(argv[i]) == "-h") {
290  std::cout << "\nUsage: " << argv[0] << " [-i <image path>] [-c] [-d] [--help]\n" << std::endl;
291  std::cout << "\nOptions: " << std::endl;
292  std::cout << " -i <input image path> : set image input path.\n"
293  << " From this path read \"Klimt/Klimt.pgm\" image.\n"
294  << " Setting the VISP_INPUT_IMAGE_PATH environment\n"
295  << " variable produces the same behaviour than using\n"
296  << " this option." << std::endl;
297  std::cout << " -c : disable mouse click" << std::endl;
298  std::cout << " -d : disable display" << std::endl;
299  std::cout << " -h, --help : print this help\n" << std::endl;
300  return EXIT_SUCCESS;
301  }
302  }
303 
304  // Get the visp-images-data package path or VISP_INPUT_IMAGE_PATH
305  // environment variable value
306  env_ipath = vpIoTools::getViSPImagesDataPath();
307 
308  // Set the default input path
309  if (!env_ipath.empty())
310  ipath = env_ipath;
311 
312  // Get the option values
313  if (!opt_ipath.empty())
314  ipath = opt_ipath;
315 
316  std::string filename;
317 
318  std::vector<std::string> display;
319  if (opt_display) {
320 #ifdef VISP_HAVE_GDI
321  display.push_back("GDI");
322 #endif
323 #ifdef VISP_HAVE_GTK
324  display.push_back("GTK");
325 #endif
326 #ifdef VISP_HAVE_X11
327  display.push_back("X");
328 #endif
329 #ifdef VISP_HAVE_OPENCV
330  display.push_back("OpenCV");
331 #endif
332 #ifdef VISP_HAVE_D3D9
333  display.push_back("D3D9");
334 #endif
335 
336  if (display.size() == 0) {
337  std::cout << "No display available. We stop here." << std::endl;
338  return EXIT_FAILURE;
339  }
341  filename = vpIoTools::createFilePath(ipath, "Klimt/Klimt.pgm");
342  vpImageIo::read(I, filename);
343 
344  vpImage<vpRGBa> C;
345  filename = vpIoTools::createFilePath(ipath, "Klimt/Klimt.ppm");
346  vpImageIo::read(C, filename);
347 
348  int nbfailure = 0;
349 
350  for (unsigned int i = 0; i < display.size(); i++) {
351 
352  for (unsigned int scale = 1; scale < 4; scale++) {
353  if (!test(display[i], I, scale, opt_click))
354  nbfailure++;
355  if (!test(display[i], C, scale, opt_click))
356  nbfailure++;
357  }
358  }
359  if (nbfailure == 0)
360  std::cout << "Test succeed" << std::endl;
361  else
362  std::cout << "Test failed with " << nbfailure << " failures" << std::endl;
363  }
364 
365  return EXIT_SUCCESS;
366 }
static const vpColor red
Definition: vpColor.h:217
static const vpColor cyan
Definition: vpColor.h:226
static const vpColor blue
Definition: vpColor.h:223
static const vpColor green
Definition: vpColor.h:220
Display for windows using Direct3D 3rd party. Thus to enable this class Direct3D should be installed....
Definition: vpDisplayD3D.h:106
Display for windows using GDI (available on any windows 32 platform).
Definition: vpDisplayGDI.h:130
The vpDisplayGTK allows to display image using the GTK 3rd party library. Thus to enable this class G...
Definition: vpDisplayGTK.h:133
The vpDisplayOpenCV allows to display image using the OpenCV library. Thus to enable this class OpenC...
void init(vpImage< unsigned char > &I, int winx=-1, int winy=-1, const std::string &title="") VP_OVERRIDE
unsigned int getScreenWidth() VP_OVERRIDE
unsigned int getScreenHeight() VP_OVERRIDE
void setDownScalingFactor(unsigned int scale)
Class that defines generic functionalities for display.
Definition: vpDisplay.h:178
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
static void displayCircle(const vpImage< unsigned char > &I, const vpImageCircle &circle, const vpColor &color, bool fill=false, unsigned int thickness=1)
static void displayROI(const vpImage< unsigned char > &I, const vpRect &roi)
static void display(const vpImage< unsigned char > &I)
static void displayLine(const vpImage< unsigned char > &I, const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1, bool segment=true)
static void getImage(const vpImage< unsigned char > &Is, vpImage< vpRGBa > &Id)
Definition: vpDisplay.cpp:140
static void displayCross(const vpImage< unsigned char > &I, const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)
static void close(vpImage< unsigned char > &I)
static void flush(const vpImage< unsigned char > &I)
static void displayArrow(const vpImage< unsigned char > &I, const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color=vpColor::white, unsigned int w=4, unsigned int h=2, unsigned int thickness=1)
static void displayPoint(const vpImage< unsigned char > &I, const vpImagePoint &ip, const vpColor &color, unsigned int thickness=1)
static void displayDotLine(const vpImage< unsigned char > &I, const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1)
static void displayRectangle(const vpImage< unsigned char > &I, const vpImagePoint &topLeft, unsigned int width, unsigned int height, const vpColor &color, bool fill=false, unsigned int thickness=1)
static void displayText(const vpImage< unsigned char > &I, const vpImagePoint &ip, const std::string &s, const vpColor &color)
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 write(const vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Definition: vpImageIo.cpp:291
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:82
static void imageDifference(const vpImage< unsigned char > &I1, const vpImage< unsigned char > &I2, vpImage< unsigned char > &Idiff)
static void crop(const vpImage< Type > &I, double roi_top, double roi_left, unsigned int roi_height, unsigned int roi_width, vpImage< Type > &crop, unsigned int v_scale=1, unsigned int h_scale=1)
Definition: vpImageTools.h:315
Definition of the vpImage class member functions.
Definition: vpImage.h:131
void subsample(unsigned int v_scale, unsigned int h_scale, vpImage< Type > &sampled) const
Definition: vpImage.h:753
unsigned int getWidth() const
Definition: vpImage.h:242
void insert(const vpImage< Type > &src, const vpImagePoint &topLeft)
Definition: vpImage.h:637
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
Defines a rectangle in the plane.
Definition: vpRect.h:79