Visual Servoing Platform  version 3.2.0 under development (2019-01-22)
testImageMorphology.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2019 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  * Test for vpImageMorphology functions.
33  *
34  * Authors:
35  * Souriya Trinh
36  *
37  *****************************************************************************/
44 #include <visp3/core/vpImageMorphology.h>
45 #include <visp3/core/vpImageTools.h>
46 #include <visp3/core/vpIoTools.h>
47 #include <visp3/io/vpImageIo.h>
48 #include <visp3/io/vpParseArgv.h>
49 
50 // List of allowed command line options
51 #define GETOPTARGS "cdi:n:h"
52 
53 /*
54  Print the program options.
55 
56  \param name : Program name.
57  \param badparam : Bad parameter name.
58  \param ipath: Input image path.
59  \param nbiter : Iteration number.
60  */
61 void usage(const char *name, const char *badparam, std::string ipath, int nbiter)
62 {
63  fprintf(stdout, "\n\
64 Test vpImageMorphology functions.\n\
65 \n\
66 SYNOPSIS\n\
67  %s [-i <input image path>] [-n <nb benchmark iterations>]\n\
68  [-h]\n \
69 ", name);
70 
71  fprintf(stdout, "\n\
72 OPTIONS: Default\n\
73  -i <input image path> %s\n\
74  Set image input path.\n\
75  From this path read \"Klimt/Klimt.pgm\"\n\
76  and \"Klimt/Klimt.ppm\" images.\n\
77  Setting the VISP_INPUT_IMAGE_PATH environment\n\
78  variable produces the same behaviour than using\n\
79  this option.\n\
80  -n <nb benchmark iterations> %d\n\
81  Set the number of benchmark iterations.\n\
82 \n\
83  -h\n\
84  Print the help.\n\n", ipath.c_str(), nbiter);
85 
86  if (badparam)
87  fprintf(stdout, "\nERROR: Bad parameter [%s]\n", badparam);
88 }
89 
99 bool getOptions(int argc, const char **argv, std::string &ipath, int &nbIterations)
100 {
101  const char *optarg_;
102  int c;
103  while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
104 
105  switch (c) {
106  case 'i':
107  ipath = optarg_;
108  break;
109  case 'n':
110  nbIterations = atoi(optarg_);
111  break;
112  case 'h':
113  usage(argv[0], NULL, ipath, nbIterations);
114  return false;
115  break;
116 
117  case 'c':
118  case 'd':
119  break;
120 
121  default:
122  usage(argv[0], optarg_, ipath, nbIterations);
123  return false;
124  break;
125  }
126  }
127 
128  if ((c == 1) || (c == -1)) {
129  // standalone param or error
130  usage(argv[0], NULL, ipath, nbIterations);
131  std::cerr << "ERROR: " << std::endl;
132  std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
133  return false;
134  }
135 
136  return true;
137 }
138 
139 void printMatrix(const vpImage<unsigned char> &I, const std::string &name)
140 {
141  std::cout << "\n" << name << ":" << std::endl;
142  for (unsigned int i = 0; i < I.getHeight(); i++) {
143  for (unsigned int j = 0; j < I.getWidth(); j++) {
144  std::cout << static_cast<unsigned>(I[i][j]) << " ";
145  }
146  std::cout << std::endl;
147  }
148 }
149 
150 // Erosion in the general case on grayscale images
151 void generalErosion(vpImage<unsigned char> &I,
153 {
154  if (I.getSize() == 0) {
155  std::cerr << "Input image is empty!" << std::endl;
156  return;
157  }
158 
159  const unsigned char null_value = 255;
160 
161  vpImage<unsigned char> J(I.getHeight() + 2, I.getWidth() + 2);
162  // Copy I to J and add border
163  for (unsigned int i = 0; i < J.getHeight(); i++) {
164  if (i == 0 || i == J.getHeight() - 1) {
165  for (unsigned int j = 0; j < J.getWidth(); j++) {
166  J[i][j] = null_value;
167  }
168  } else {
169  J[i][0] = null_value;
170  memcpy(J[i] + 1, I[i - 1], sizeof(unsigned char) * I.getWidth());
171  J[i][J.getWidth() - 1] = null_value;
172  }
173  }
174 
175  if (connexity == vpImageMorphology::CONNEXITY_4) {
176  unsigned int offset[5] = {1, J.getWidth(), J.getWidth() + 1, J.getWidth() + 2, J.getWidth() * 2 + 1};
177 
178  for (unsigned int i = 0; i < I.getHeight(); i++) {
179  unsigned char *ptr_curr_J = J.bitmap + i * J.getWidth();
180  unsigned char *ptr_curr_I = I.bitmap + i * I.getWidth();
181 
182  for (unsigned int j = 0; j < I.getWidth(); j++) {
183  unsigned char min_value = null_value;
184  for (int k = 0; k < 5; k++) {
185  min_value = (std::min)(min_value, *(ptr_curr_J + j + offset[k]));
186  }
187 
188  *(ptr_curr_I + j) = min_value;
189  }
190  }
191  } else {
192  // CONNEXITY_8
193  unsigned int offset[9] = {0,
194  1,
195  2,
196  J.getWidth(),
197  J.getWidth() + 1,
198  J.getWidth() + 2,
199  J.getWidth() * 2,
200  J.getWidth() * 2 + 1,
201  J.getWidth() * 2 + 2};
202 
203  for (unsigned int i = 0; i < I.getHeight(); i++) {
204  unsigned char *ptr_curr_J = J.bitmap + i * J.getWidth();
205  unsigned char *ptr_curr_I = I.bitmap + i * I.getWidth();
206 
207  for (unsigned int j = 0; j < I.getWidth(); j++) {
208  unsigned char min_value = null_value;
209  for (int k = 0; k < 9; k++) {
210  min_value = (std::min)(min_value, *(ptr_curr_J + j + offset[k]));
211  }
212 
213  *(ptr_curr_I + j) = min_value;
214  }
215  }
216  }
217 }
218 
219 // Dilatation in the general case on grayscale images
220 void generalDilatation(vpImage<unsigned char> &I,
222 {
223  if (I.getSize() == 0) {
224  std::cerr << "Input image is empty!" << std::endl;
225  return;
226  }
227 
228  const unsigned char null_value = 0;
229 
230  vpImage<unsigned char> J(I.getHeight() + 2, I.getWidth() + 2);
231  // Copy I to J and add border
232  for (unsigned int i = 0; i < J.getHeight(); i++) {
233  if (i == 0 || i == J.getHeight() - 1) {
234  for (unsigned int j = 0; j < J.getWidth(); j++) {
235  J[i][j] = null_value;
236  }
237  } else {
238  J[i][0] = null_value;
239  memcpy(J[i] + 1, I[i - 1], sizeof(unsigned char) * I.getWidth());
240  J[i][J.getWidth() - 1] = null_value;
241  }
242  }
243 
244  if (connexity == vpImageMorphology::CONNEXITY_4) {
245  unsigned int offset[5] = {1, J.getWidth(), J.getWidth() + 1, J.getWidth() + 2, J.getWidth() * 2 + 1};
246 
247  for (unsigned int i = 0; i < I.getHeight(); i++) {
248  unsigned char *ptr_curr_J = J.bitmap + i * J.getWidth();
249  unsigned char *ptr_curr_I = I.bitmap + i * I.getWidth();
250 
251  for (unsigned int j = 0; j < I.getWidth(); j++) {
252  unsigned char max_value = null_value;
253  for (int k = 0; k < 5; k++) {
254  max_value = (std::max)(max_value, *(ptr_curr_J + j + offset[k]));
255  }
256 
257  *(ptr_curr_I + j) = max_value;
258  }
259  }
260  } else {
261  // CONNEXITY_8
262  unsigned int offset[9] = {0,
263  1,
264  2,
265  J.getWidth(),
266  J.getWidth() + 1,
267  J.getWidth() + 2,
268  J.getWidth() * 2,
269  J.getWidth() * 2 + 1,
270  J.getWidth() * 2 + 2};
271 
272  for (unsigned int i = 0; i < I.getHeight(); i++) {
273  unsigned char *ptr_curr_J = J.bitmap + i * J.getWidth();
274  unsigned char *ptr_curr_I = I.bitmap + i * I.getWidth();
275 
276  for (unsigned int j = 0; j < I.getWidth(); j++) {
277  unsigned char max_value = null_value;
278  for (int k = 0; k < 9; k++) {
279  max_value = (std::max)(max_value, *(ptr_curr_J + j + offset[k]));
280  }
281 
282  *(ptr_curr_I + j) = max_value;
283  }
284  }
285  }
286 }
287 
288 // Generate a magic square matrix to get a consistent grayscale image
289 void magicSquare(vpImage<unsigned char> &magic_square, const int N)
290 {
291  magic_square.resize((unsigned int)N, (unsigned int)N, 0);
292 
293  int n = 1;
294  int i = 0, j = N / 2;
295 
296  while (n <= N * N) {
297  magic_square[i][j] = vpMath::saturate<unsigned char>(n);
298  n++;
299 
300  int newi = vpMath::modulo((i - 1), N), newj = vpMath::modulo((j + 1), N);
301 
302  if (magic_square[newi][newj]) {
303  i++;
304  } else {
305  i = newi;
306  j = newj;
307  }
308  }
309 }
310 
311 int main(int argc, const char **argv)
312 {
313  try {
314  std::string env_ipath;
315  std::string opt_ipath;
316  std::string ipath;
317  std::string filename;
318  int nbIterations = 100;
319 
320  // Get the visp-images-data package path or VISP_INPUT_IMAGE_PATH
321  // environment variable value
322  env_ipath = vpIoTools::getViSPImagesDataPath();
323 
324  // Set the default input path
325  if (!env_ipath.empty())
326  ipath = env_ipath;
327 
328  // Read the command line options
329  if (getOptions(argc, argv, opt_ipath, nbIterations) == false) {
330  exit(EXIT_FAILURE);
331  }
332 
333  // Get the option values
334  if (!opt_ipath.empty())
335  ipath = opt_ipath;
336 
337  // Compare ipath and env_ipath. If they differ, we take into account
338  // the input path comming from the command line option
339  if (opt_ipath.empty()) {
340  if (ipath != env_ipath) {
341  std::cout << std::endl << "WARNING: " << std::endl;
342  std::cout << " Since -i <visp image path=" << ipath << "> "
343  << " is different from VISP_IMAGE_PATH=" << env_ipath << std::endl
344  << " we skip the environment variable." << std::endl;
345  }
346  }
347 
348  // Test if an input path is set
349  if (opt_ipath.empty() && env_ipath.empty()) {
350  usage(argv[0], NULL, ipath, nbIterations);
351  std::cerr << std::endl << "ERROR:" << std::endl;
352  std::cerr << " Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH " << std::endl
353  << " environment variable to specify the location of the " << std::endl
354  << " image path where test images are located." << std::endl
355  << std::endl;
356  exit(EXIT_FAILURE);
357  }
358 
359  // Create a binary image
360  unsigned char image_data[8 * 16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0,
361  0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1,
362  1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0,
363  0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1,
364  0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0};
365 
366  vpImage<unsigned char> I(image_data, 8, 16, true);
367  printMatrix(I, "I");
368 
369  // Regular code
370  // Dilatation
371  vpImage<unsigned char> I_dilatation1 = I;
372  vpImage<unsigned char> I_dilatation2 = I;
373 
374  vpImageMorphology::dilatation(I_dilatation1, (unsigned char)1, (unsigned char)0, vpImageMorphology::CONNEXITY_4);
375  vpImageMorphology::dilatation(I_dilatation2, (unsigned char)1, (unsigned char)0, vpImageMorphology::CONNEXITY_8);
376 
377  printMatrix(I_dilatation1, "I_dilatation1");
378  printMatrix(I_dilatation2, "I_dilatation2");
379 
380  // Erosion
381  vpImage<unsigned char> I_erosion1 = I_dilatation1;
382  vpImage<unsigned char> I_erosion2 = I_dilatation2;
383 
384  vpImageMorphology::erosion(I_erosion1, (unsigned char)1, (unsigned char)0, vpImageMorphology::CONNEXITY_4);
385  vpImageMorphology::erosion(I_erosion2, (unsigned char)1, (unsigned char)0, vpImageMorphology::CONNEXITY_8);
386 
387  printMatrix(I_erosion1, "I_erosion1");
388  printMatrix(I_erosion2, "I_erosion2");
389 
390  // SSE code
391  // Dilatation
392  vpImage<unsigned char> I_dilatation1_sse = I;
393  vpImage<unsigned char> I_dilatation2_sse = I;
394 
397 
398  printMatrix(I_dilatation1_sse, "I_dilatation1_sse");
399  printMatrix(I_dilatation2_sse, "I_dilatation2_sse");
400 
401  std::cout << "\n(I_dilatation1 == I_dilatation1_sse)? " << (I_dilatation1 == I_dilatation1_sse) << std::endl;
402  std::cout << "(I_dilatation2 == I_dilatation2_sse)? " << (I_dilatation2 == I_dilatation2_sse) << std::endl;
403 
404  if ((I_dilatation1 != I_dilatation1_sse)) {
405  throw vpException(vpException::fatalError, "(I_dilatation1 != I_dilatation1_sse)");
406  }
407  if ((I_dilatation2 != I_dilatation2_sse)) {
408  throw vpException(vpException::fatalError, "(I_dilatation2 != I_dilatation2_sse)");
409  }
410 
411  // Erosion
412  vpImage<unsigned char> I_erosion1_sse = I_dilatation1_sse;
413  vpImage<unsigned char> I_erosion2_sse = I_dilatation2_sse;
414 
417 
418  printMatrix(I_erosion1_sse, "I_erosion1_sse");
419  printMatrix(I_erosion2_sse, "I_erosion2_sse");
420 
421  std::cout << "\n(I_erosion1 == I_erosion1_sse)? " << (I_erosion1 == I_erosion1_sse) << std::endl;
422  std::cout << "(I_erosion2 == I_erosion2_sse)? " << (I_erosion2 == I_erosion2_sse) << std::endl;
423 
424  if ((I_erosion1 != I_erosion1_sse)) {
425  throw vpException(vpException::fatalError, "(I_erosion1 != I_erosion1_sse)");
426  }
427  if ((I_erosion2 != I_erosion2_sse)) {
428  throw vpException(vpException::fatalError, "(I_erosion2 != I_erosion2_sse)");
429  }
430 
431  // Check results against Matlab
432  unsigned char image_data_dilated1[8 * 16] = {
433  0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0,
434  0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1,
435  1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1,
436  1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1};
437 
438  vpImage<unsigned char> I_check_dilated1(image_data_dilated1, 8, 16, true);
439 
440  if (I_check_dilated1 != I_dilatation1_sse) {
441  throw vpException(vpException::fatalError, "(I_check_dilated1 != I_dilatation1_sse)");
442  }
443 
444  unsigned char image_data_dilated2[8 * 16] = {
445  0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1,
446  0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
447  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1,
448  1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1};
449 
450  vpImage<unsigned char> I_check_dilated2(image_data_dilated2, 8, 16, true);
451 
452  if (I_check_dilated2 != I_dilatation2_sse) {
453  throw vpException(vpException::fatalError, "(I_check_dilated2 != I_dilatation2_sse)");
454  }
455 
456  unsigned char image_data_eroded1[8 * 16] = {
457  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0,
458  0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1,
459  0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
460  1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0};
461 
462  vpImage<unsigned char> I_check_eroded1(image_data_eroded1, 8, 16, true);
463 
464  if (I_check_eroded1 != I_erosion1_sse) {
465  throw vpException(vpException::fatalError, "(I_check_eroded1 != I_erosion1_sse)");
466  }
467 
468  unsigned char image_data_eroded2[8 * 16] = {
469  0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0,
470  0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1,
471  0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1,
472  1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1};
473 
474  vpImage<unsigned char> I_check_eroded2(image_data_eroded2, 8, 16, true);
475 
476  if (I_check_eroded2 != I_erosion2_sse) {
477  throw vpException(vpException::fatalError, "(I_check_eroded2 != I_erosion2_sse)");
478  }
479 
480  // Morphology on grayscale images
481  vpImage<unsigned char> I_magic_square;
482  magicSquare(I_magic_square, 17);
483  printMatrix(I_magic_square, "I_magic_square");
484 
485  // Dilatation CONNEXITY_4 grayscale
486  vpImage<unsigned char> I_magic_square_dilatation1 = I_magic_square;
487  vpImage<unsigned char> I_magic_square_dilatation1_sse = I_magic_square;
488 
489  generalDilatation(I_magic_square_dilatation1, vpImageMorphology::CONNEXITY_4);
490  vpImageMorphology::dilatation(I_magic_square_dilatation1_sse, vpImageMorphology::CONNEXITY_4);
491 
492  if ((I_magic_square_dilatation1 != I_magic_square_dilatation1_sse)) {
493  throw vpException(vpException::fatalError, "(I_magic_square_dilatation1 != I_magic_square_dilatation1_sse)");
494  }
495 
496  // Dilatation CONNEXITY_8 grayscale
497  vpImage<unsigned char> I_magic_square_dilatation2 = I_magic_square;
498  vpImage<unsigned char> I_magic_square_dilatation2_sse = I_magic_square;
499 
500  generalDilatation(I_magic_square_dilatation2, vpImageMorphology::CONNEXITY_8);
501  vpImageMorphology::dilatation(I_magic_square_dilatation2_sse, vpImageMorphology::CONNEXITY_8);
502 
503  if ((I_magic_square_dilatation2 != I_magic_square_dilatation2_sse)) {
504  throw vpException(vpException::fatalError, "(I_magic_square_dilatation2 != I_magic_square_dilatation2_sse)");
505  }
506 
507  // Erosion CONNEXITY_4 grayscale
508  vpImage<unsigned char> I_magic_square_erosion1 = I_magic_square_dilatation1;
509  vpImage<unsigned char> I_magic_square_erosion1_sse = I_magic_square_dilatation1_sse;
510 
511  generalErosion(I_magic_square_erosion1, vpImageMorphology::CONNEXITY_4);
512  vpImageMorphology::erosion(I_magic_square_erosion1_sse, vpImageMorphology::CONNEXITY_4);
513 
514  if ((I_magic_square_erosion1 != I_magic_square_erosion1_sse)) {
515  throw vpException(vpException::fatalError, "(I_magic_square_erosion1 != I_magic_square_erosion1_sse)");
516  }
517 
518  // Dilatation CONNEXITY_8 grayscale
519  vpImage<unsigned char> I_magic_square_erosion2 = I_magic_square_dilatation2;
520  vpImage<unsigned char> I_magic_square_erosion2_sse = I_magic_square_dilatation2_sse;
521 
522  generalErosion(I_magic_square_erosion2, vpImageMorphology::CONNEXITY_8);
523  vpImageMorphology::erosion(I_magic_square_erosion2_sse, vpImageMorphology::CONNEXITY_8);
524 
525  if ((I_magic_square_erosion2 != I_magic_square_erosion2_sse)) {
526  throw vpException(vpException::fatalError, "(I_magic_square_erosion2 != I_magic_square_erosion2_sse)");
527  }
528 
529  // Check results against Matlab (grayscale)
530  unsigned char image_data2_dilated1[17 * 17] = {
531  174, 193, 212, 231, 250, 255, 255, 255, 255, 39, 58, 77, 96, 115, 134, 153, 154, 192, 211, 230, 249,
532  255, 255, 255, 255, 38, 57, 76, 95, 114, 133, 152, 170, 172, 210, 229, 248, 255, 255, 255, 255, 37,
533  56, 75, 94, 113, 132, 151, 170, 172, 190, 228, 247, 255, 255, 255, 255, 36, 55, 74, 93, 112, 131,
534  150, 169, 187, 190, 208, 246, 255, 255, 255, 255, 51, 54, 73, 92, 111, 130, 149, 168, 187, 189, 208,
535  226, 255, 255, 255, 255, 51, 53, 72, 91, 110, 129, 148, 167, 186, 204, 207, 226, 244, 255, 255, 255,
536  50, 68, 71, 90, 109, 128, 147, 166, 185, 204, 206, 225, 244, 255, 255, 255, 49, 68, 70, 89, 108,
537  127, 146, 165, 184, 203, 221, 224, 243, 255, 255, 255, 48, 67, 85, 88, 107, 126, 145, 164, 183, 202,
538  221, 223, 242, 255, 255, 255, 47, 66, 85, 87, 106, 125, 144, 163, 182, 201, 220, 238, 241, 255, 255,
539  255, 255, 65, 84, 102, 105, 124, 143, 162, 181, 200, 219, 238, 240, 255, 255, 255, 255, 45, 83, 102,
540  104, 123, 142, 161, 180, 199, 218, 237, 255, 255, 255, 255, 255, 45, 63, 101, 119, 122, 141, 160, 179,
541  198, 217, 236, 255, 255, 255, 255, 255, 44, 63, 81, 119, 121, 140, 159, 178, 197, 216, 235, 254, 255,
542  255, 255, 255, 43, 62, 81, 99, 136, 139, 158, 177, 196, 215, 234, 253, 255, 255, 255, 255, 42, 61,
543  80, 99, 117, 138, 157, 176, 195, 214, 233, 252, 255, 255, 255, 255, 41, 60, 79, 98, 117, 135, 156,
544  175, 194, 213, 232, 251, 255, 255, 255, 255, 40, 59, 78, 97, 116, 135, 135};
545 
546  vpImage<unsigned char> I2_check_dilated1(image_data2_dilated1, 17, 17, true);
547 
548  if (I2_check_dilated1 != I_magic_square_dilatation1_sse) {
549  throw vpException(vpException::fatalError, "(I2_check_dilated1 != I_magic_square_dilatation1_sse)");
550  }
551 
552  unsigned char image_data2_dilated2[17 * 17] = {
553  192, 211, 230, 249, 255, 255, 255, 255, 255, 57, 76, 95, 114, 133, 152, 154, 154, 210, 229, 248, 255,
554  255, 255, 255, 255, 255, 75, 94, 113, 132, 151, 170, 172, 172, 228, 247, 255, 255, 255, 255, 255, 255,
555  74, 93, 112, 131, 150, 169, 171, 190, 190, 246, 255, 255, 255, 255, 255, 255, 73, 92, 111, 130, 149,
556  168, 187, 189, 208, 208, 255, 255, 255, 255, 255, 255, 72, 91, 110, 129, 148, 167, 186, 188, 207, 226,
557  226, 255, 255, 255, 255, 255, 71, 90, 109, 128, 147, 166, 185, 204, 206, 225, 244, 244, 255, 255, 255,
558  255, 70, 89, 108, 127, 146, 165, 184, 203, 205, 224, 243, 255, 255, 255, 255, 255, 69, 88, 107, 126,
559  145, 164, 183, 202, 221, 223, 242, 255, 255, 255, 255, 255, 85, 87, 106, 125, 144, 163, 182, 201, 220,
560  222, 241, 255, 255, 255, 255, 65, 84, 86, 105, 124, 143, 162, 181, 200, 219, 238, 240, 255, 255, 255,
561  255, 255, 83, 102, 104, 123, 142, 161, 180, 199, 218, 237, 239, 255, 255, 255, 255, 255, 255, 101, 103,
562  122, 141, 160, 179, 198, 217, 236, 255, 255, 255, 255, 255, 255, 255, 63, 119, 121, 140, 159, 178, 197,
563  216, 235, 254, 255, 255, 255, 255, 255, 255, 81, 81, 120, 139, 158, 177, 196, 215, 234, 253, 255, 255,
564  255, 255, 255, 255, 80, 99, 99, 138, 157, 176, 195, 214, 233, 252, 255, 255, 255, 255, 255, 255, 79,
565  98, 117, 117, 156, 175, 194, 213, 232, 251, 255, 255, 255, 255, 255, 255, 78, 97, 116, 135, 135, 156,
566  175, 194, 213, 232, 251, 255, 255, 255, 255, 255, 59, 78, 97, 116, 135, 135};
567 
568  vpImage<unsigned char> I2_check_dilated2(image_data2_dilated2, 17, 17, true);
569 
570  if (I2_check_dilated2 != I_magic_square_dilatation2_sse) {
571  throw vpException(vpException::fatalError, "(I2_check_dilated2 != I_magic_square_dilatation2_sse)");
572  }
573 
574  unsigned char image_data2_eroded1[17 * 17] = {
575  174, 174, 193, 212, 231, 250, 255, 255, 38, 39, 39, 58, 77, 96, 115, 134, 153, 174, 192, 211, 230,
576  249, 255, 255, 37, 38, 38, 57, 76, 95, 114, 133, 152, 154, 192, 210, 229, 248, 255, 255, 36, 37,
577  37, 56, 75, 94, 113, 132, 151, 170, 172, 210, 228, 247, 255, 255, 36, 36, 36, 55, 74, 93, 112,
578  131, 150, 169, 172, 190, 228, 246, 255, 255, 51, 51, 36, 54, 73, 92, 111, 130, 149, 168, 187, 189,
579  208, 246, 255, 255, 50, 51, 51, 53, 72, 91, 110, 129, 148, 167, 186, 189, 207, 226, 255, 255, 49,
580  50, 50, 53, 71, 90, 109, 128, 147, 166, 185, 204, 206, 225, 244, 255, 48, 49, 49, 68, 70, 89,
581  108, 127, 146, 165, 184, 203, 206, 224, 243, 255, 47, 48, 48, 67, 70, 88, 107, 126, 145, 164, 183,
582  202, 221, 223, 242, 255, 255, 47, 47, 66, 85, 87, 106, 125, 144, 163, 182, 201, 220, 223, 241, 255,
583  255, 45, 47, 65, 84, 87, 105, 124, 143, 162, 181, 200, 219, 238, 240, 255, 255, 45, 45, 65, 83,
584  102, 104, 123, 142, 161, 180, 199, 218, 237, 240, 255, 255, 44, 45, 45, 83, 101, 104, 122, 141, 160,
585  179, 198, 217, 236, 255, 255, 255, 43, 44, 44, 63, 101, 119, 121, 140, 159, 178, 197, 216, 235, 254,
586  255, 255, 42, 43, 43, 62, 81, 119, 121, 139, 158, 177, 196, 215, 234, 253, 255, 255, 41, 42, 42,
587  61, 80, 99, 136, 138, 157, 176, 195, 214, 233, 252, 255, 255, 40, 41, 41, 60, 79, 98, 117, 138,
588  156, 175, 194, 213, 232, 251, 255, 255, 40, 40, 40, 59, 78, 97, 116, 135};
589 
590  vpImage<unsigned char> I2_check_eroded1(image_data2_eroded1, 17, 17, true);
591 
592  if (I2_check_eroded1 != I_magic_square_erosion1_sse) {
593  printMatrix(I_magic_square_erosion1_sse, "I_magic_square_erosion1_sse");
594 
595  throw vpException(vpException::fatalError, "(I2_check_eroded1 != I_magic_square_erosion1_sse)");
596  }
597 
598  unsigned char image_data2_eroded2[17 * 17] = {
599  192, 192, 211, 230, 249, 255, 255, 255, 57, 57, 57, 76, 95, 114, 133, 152, 154, 192, 192, 211, 230,
600  249, 255, 255, 74, 57, 57, 57, 76, 95, 114, 133, 152, 154, 210, 210, 229, 248, 255, 255, 73, 73,
601  73, 74, 75, 94, 113, 132, 151, 170, 172, 228, 228, 247, 255, 255, 72, 72, 72, 73, 74, 93, 112,
602  131, 150, 169, 171, 190, 246, 246, 255, 255, 71, 71, 71, 72, 73, 92, 111, 130, 149, 168, 187, 189,
603  208, 255, 255, 255, 70, 70, 70, 71, 72, 91, 110, 129, 148, 167, 186, 188, 207, 226, 255, 255, 69,
604  69, 69, 70, 71, 90, 109, 128, 147, 166, 185, 204, 206, 225, 244, 255, 85, 69, 69, 69, 70, 89,
605  108, 127, 146, 165, 184, 203, 205, 224, 243, 255, 65, 65, 69, 69, 69, 88, 107, 126, 145, 164, 183,
606  202, 221, 223, 242, 255, 255, 65, 65, 84, 85, 87, 106, 125, 144, 163, 182, 201, 220, 222, 241, 255,
607  255, 255, 65, 65, 84, 86, 105, 124, 143, 162, 181, 200, 219, 238, 240, 255, 255, 63, 63, 83, 83,
608  102, 104, 123, 142, 161, 180, 199, 218, 237, 239, 255, 255, 81, 63, 63, 101, 101, 103, 122, 141, 160,
609  179, 198, 217, 236, 255, 255, 255, 80, 80, 63, 63, 119, 119, 121, 140, 159, 178, 197, 216, 235, 254,
610  255, 255, 79, 79, 79, 80, 81, 120, 120, 139, 158, 177, 196, 215, 234, 253, 255, 255, 78, 78, 78,
611  79, 80, 99, 138, 138, 157, 176, 195, 214, 233, 252, 255, 255, 59, 59, 59, 78, 79, 98, 117, 156,
612  156, 175, 194, 213, 232, 251, 255, 255, 255, 59, 59, 59, 78, 97, 116, 135};
613 
614  vpImage<unsigned char> I2_check_eroded2(image_data2_eroded2, 17, 17, true);
615 
616  if (I2_check_eroded2 != I_magic_square_erosion2_sse) {
617  throw vpException(vpException::fatalError, "(I2_check_eroded2 != I_magic_square_erosion2_sse)");
618  }
619 
620  std::cout << std::endl;
621  vpImage<unsigned char> I_Klimt;
622  filename = vpIoTools::createFilePath(ipath, "Klimt/Klimt.pgm");
623  vpImageIo::read(I_Klimt, filename);
624 
625  // Benchmark on binarized image (compare regular code with SSE
626  // implementation)
627 
628  vpImage<unsigned char> I_Klimt_binarized = I_Klimt;
629  vpImageTools::binarise(I_Klimt_binarized, (unsigned char)127, (unsigned char)127, (unsigned char)0,
630  (unsigned char)1, (unsigned char)1, true);
631 
632  // Dilatation CONNEXITY_4
633  vpImage<unsigned char> I_Klimt_binarized_dilatation1 = I_Klimt_binarized;
634  vpImage<unsigned char> I_Klimt_binarized_dilatation1_sse = I_Klimt_binarized;
635 
636  double t = vpTime::measureTimeMs();
637  for (int cpt = 0; cpt < nbIterations; cpt++) {
638  vpImageMorphology::dilatation(I_Klimt_binarized_dilatation1, (unsigned char)1, (unsigned char)0,
640  }
641  t = vpTime::measureTimeMs() - t;
642 
643  double t_sse = vpTime::measureTimeMs();
644  for (int cpt = 0; cpt < nbIterations; cpt++) {
645  vpImageMorphology::dilatation(I_Klimt_binarized_dilatation1_sse, vpImageMorphology::CONNEXITY_4);
646  }
647  t_sse = vpTime::measureTimeMs() - t_sse;
648 
649  std::cout << "(I_Klimt_binarized_dilatation1 == "
650  "I_Klimt_binarized_dilatation1_sse)? "
651  << (I_Klimt_binarized_dilatation1 == I_Klimt_binarized_dilatation1_sse) << " ; t=" << t
652  << " ms ; t_sse=" << t_sse << " ms"
653  << " ; speed-up=" << (t / t_sse) << "X" << std::endl;
654 
655  // Dilatation CONNEXITY_8
656  vpImage<unsigned char> I_Klimt_binarized_dilatation2 = I_Klimt_binarized;
657  vpImage<unsigned char> I_Klimt_binarized_dilatation2_sse = I_Klimt_binarized;
658 
659  t = vpTime::measureTimeMs();
660  for (int cpt = 0; cpt < nbIterations; cpt++) {
661  vpImageMorphology::dilatation(I_Klimt_binarized_dilatation2, (unsigned char)1, (unsigned char)0,
663  }
664  t = vpTime::measureTimeMs() - t;
665 
666  t_sse = vpTime::measureTimeMs();
667  for (int cpt = 0; cpt < nbIterations; cpt++) {
668  vpImageMorphology::dilatation(I_Klimt_binarized_dilatation2_sse, vpImageMorphology::CONNEXITY_8);
669  }
670  t_sse = vpTime::measureTimeMs() - t_sse;
671 
672  std::cout << "(I_Klimt_binarized_dilatation2 == "
673  "I_Klimt_binarized_dilatation2_sse)? "
674  << (I_Klimt_binarized_dilatation2 == I_Klimt_binarized_dilatation2_sse) << " ; t=" << t
675  << " ms ; t_sse=" << t_sse << " ms"
676  << " ; speed-up=" << (t / t_sse) << "X" << std::endl;
677 
678  // Erosion CONNEXITY_4
679  vpImage<unsigned char> I_Klimt_binarized_erosion1 = I_Klimt_binarized;
680  vpImage<unsigned char> I_Klimt_binarized_erosion1_sse = I_Klimt_binarized;
681 
682  t = vpTime::measureTimeMs();
683  for (int cpt = 0; cpt < nbIterations; cpt++) {
684  vpImageMorphology::erosion(I_Klimt_binarized_erosion1, (unsigned char)1, (unsigned char)0,
686  }
687  t = vpTime::measureTimeMs() - t;
688 
689  t_sse = vpTime::measureTimeMs();
690  for (int cpt = 0; cpt < nbIterations; cpt++) {
691  vpImageMorphology::erosion(I_Klimt_binarized_erosion1_sse, vpImageMorphology::CONNEXITY_4);
692  }
693  t_sse = vpTime::measureTimeMs() - t_sse;
694 
695  std::cout << "(I_Klimt_binarized_erosion1 == I_Klimt_binarized_erosion1_sse)? "
696  << (I_Klimt_binarized_erosion1 == I_Klimt_binarized_erosion1_sse) << " ; t=" << t
697  << " ms ; t_sse=" << t_sse << " ms"
698  << " ; speed-up=" << (t / t_sse) << "X" << std::endl;
699 
700  // Erosion CONNEXITY_8
701  vpImage<unsigned char> I_Klimt_binarized_erosion2 = I_Klimt_binarized;
702  vpImage<unsigned char> I_Klimt_binarized_erosion2_sse = I_Klimt_binarized;
703 
704  t = vpTime::measureTimeMs();
705  for (int cpt = 0; cpt < nbIterations; cpt++) {
706  vpImageMorphology::erosion(I_Klimt_binarized_erosion2, (unsigned char)1, (unsigned char)0,
708  }
709  t = vpTime::measureTimeMs() - t;
710 
711  t_sse = vpTime::measureTimeMs();
712  for (int cpt = 0; cpt < nbIterations; cpt++) {
713  vpImageMorphology::erosion(I_Klimt_binarized_erosion2_sse, vpImageMorphology::CONNEXITY_8);
714  }
715  t_sse = vpTime::measureTimeMs() - t_sse;
716 
717  std::cout << "(I_Klimt_binarized_erosion2 == I_Klimt_binarized_erosion2_sse)? "
718  << (I_Klimt_binarized_erosion2 == I_Klimt_binarized_erosion2_sse) << " ; t=" << t
719  << " ms ; t_sse=" << t_sse << " ms"
720  << " ; speed-up=" << (t / t_sse) << "X" << std::endl;
721 
722  // Benchmark on grayscale images (compare regular code with SSE
723  // implementation)
724 
725  // Dilatation CONNEXITY_4 grayscale
726  vpImage<unsigned char> I_Klimt_dilatation1 = I_Klimt;
727  vpImage<unsigned char> I_Klimt_dilatation1_sse = I_Klimt;
728 
729  t = vpTime::measureTimeMs();
730  for (int cpt = 0; cpt < nbIterations; cpt++) {
731  generalDilatation(I_Klimt_dilatation1, vpImageMorphology::CONNEXITY_4);
732  }
733  t = vpTime::measureTimeMs() - t;
734 
735  t_sse = vpTime::measureTimeMs();
736  for (int cpt = 0; cpt < nbIterations; cpt++) {
738  }
739  t_sse = vpTime::measureTimeMs() - t_sse;
740 
741  std::cout << "(I_Klimt_dilatation1 == I_Klimt_dilatation1_sse)? "
742  << (I_Klimt_dilatation1 == I_Klimt_dilatation1_sse) << " ; t=" << t << " ms ; t_sse=" << t_sse << " ms"
743  << " ; speed-up=" << (t / t_sse) << "X" << std::endl;
744 
745  // Dilatation CONNEXITY_8 grayscale
746  vpImage<unsigned char> I_Klimt_dilatation2 = I_Klimt;
747  vpImage<unsigned char> I_Klimt_dilatation2_sse = I_Klimt;
748 
749  t = vpTime::measureTimeMs();
750  for (int cpt = 0; cpt < nbIterations; cpt++) {
751  generalDilatation(I_Klimt_dilatation2, vpImageMorphology::CONNEXITY_8);
752  }
753  t = vpTime::measureTimeMs() - t;
754 
755  t_sse = vpTime::measureTimeMs();
756  for (int cpt = 0; cpt < nbIterations; cpt++) {
758  }
759  t_sse = vpTime::measureTimeMs() - t_sse;
760 
761  std::cout << "(I_Klimt_dilatation2 == I_Klimt_dilatation2_sse)? "
762  << (I_Klimt_dilatation2 == I_Klimt_dilatation2_sse) << " ; t=" << t << " ms ; t_sse=" << t_sse << " ms"
763  << " ; speed-up=" << (t / t_sse) << "X" << std::endl;
764 
765  // Erosion CONNEXITY_4 grayscale
766  vpImage<unsigned char> I_Klimt_erosion1 = I_Klimt;
767  vpImage<unsigned char> I_Klimt_erosion1_sse = I_Klimt;
768 
769  t = vpTime::measureTimeMs();
770  for (int cpt = 0; cpt < nbIterations; cpt++) {
771  generalErosion(I_Klimt_erosion1, vpImageMorphology::CONNEXITY_4);
772  }
773  t = vpTime::measureTimeMs() - t;
774 
775  t_sse = vpTime::measureTimeMs();
776  for (int cpt = 0; cpt < nbIterations; cpt++) {
778  }
779  t_sse = vpTime::measureTimeMs() - t_sse;
780 
781  std::cout << "(I_Klimt_erosion1 == I_Klimt_erosion1_sse)? " << (I_Klimt_erosion1 == I_Klimt_erosion1_sse)
782  << " ; t=" << t << " ms ; t_sse=" << t_sse << " ms"
783  << " ; speed-up=" << (t / t_sse) << "X" << std::endl;
784 
785  // Erosion CONNEXITY_8 grayscale
786  vpImage<unsigned char> I_Klimt_erosion2 = I_Klimt;
787  vpImage<unsigned char> I_Klimt_erosion2_sse = I_Klimt;
788 
789  t = vpTime::measureTimeMs();
790  for (int cpt = 0; cpt < nbIterations; cpt++) {
791  generalErosion(I_Klimt_erosion2, vpImageMorphology::CONNEXITY_8);
792  }
793  t = vpTime::measureTimeMs() - t;
794 
795  t_sse = vpTime::measureTimeMs();
796  for (int cpt = 0; cpt < nbIterations; cpt++) {
798  }
799  t_sse = vpTime::measureTimeMs() - t_sse;
800 
801  std::cout << "(I_Klimt_erosion2 == I_Klimt_erosion2_sse)? " << (I_Klimt_erosion2 == I_Klimt_erosion2_sse)
802  << " ; t=" << t << " ms ; t_sse=" << t_sse << " ms"
803  << " ; speed-up=" << (t / t_sse) << "X" << std::endl;
804 
805 // Compare with OpenCV
806 #if (VISP_HAVE_OPENCV_VERSION >= 0x030000)
807  std::cout << std::endl;
808 
809  cv::Mat cross_SE = cv::getStructuringElement(cv::MORPH_CROSS, cv::Size(3, 3));
810  cv::Mat rect_SE = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));
811 
812  // Dilatation CONNEXITY_4 grayscale
813  cv::Mat matImg_dilatation1;
814  vpImageConvert::convert(I_Klimt, matImg_dilatation1);
815 
816  double t_opencv = vpTime::measureTimeMs();
817  for (int cpt = 0; cpt < nbIterations; cpt++) {
818  cv::morphologyEx(matImg_dilatation1, matImg_dilatation1, cv::MORPH_DILATE, cross_SE);
819  }
820  t_opencv = vpTime::measureTimeMs() - t_opencv;
821 
822  vpImage<unsigned char> I_matImg_dilatation1;
823  vpImageConvert::convert(matImg_dilatation1, I_matImg_dilatation1);
824  std::cout << "(I_matImg_dilatation1 == I_Klimt_dilatation1_sse)? "
825  << (I_matImg_dilatation1 == I_Klimt_dilatation1_sse) << " ; t_opencv=" << t_opencv << " ms" << std::endl;
826 
827  // Dilatation CONNEXITY_8 grayscale
828  cv::Mat matImg_dilatation2;
829  vpImageConvert::convert(I_Klimt, matImg_dilatation2);
830 
831  t_opencv = vpTime::measureTimeMs();
832  for (int cpt = 0; cpt < nbIterations; cpt++) {
833  cv::morphologyEx(matImg_dilatation2, matImg_dilatation2, cv::MORPH_DILATE, rect_SE);
834  }
835  t_opencv = vpTime::measureTimeMs() - t_opencv;
836 
837  vpImage<unsigned char> I_matImg_dilatation2;
838  vpImageConvert::convert(matImg_dilatation2, I_matImg_dilatation2);
839  std::cout << "(I_matImg_dilatation2 == I_Klimt_dilatation2_sse)? "
840  << (I_matImg_dilatation2 == I_Klimt_dilatation2_sse) << " ; t_opencv=" << t_opencv << " ms" << std::endl;
841 
842  // Erosion CONNEXITY_4 grayscale
843  cv::Mat matImg_erosion1;
844  vpImageConvert::convert(I_Klimt, matImg_erosion1);
845 
846  t_opencv = vpTime::measureTimeMs();
847  for (int cpt = 0; cpt < nbIterations; cpt++) {
848  cv::morphologyEx(matImg_erosion1, matImg_erosion1, cv::MORPH_ERODE, cross_SE);
849  }
850  t_opencv = vpTime::measureTimeMs() - t_opencv;
851 
852  vpImage<unsigned char> I_matImg_erosion1;
853  vpImageConvert::convert(matImg_erosion1, I_matImg_erosion1);
854  std::cout << "(I_matImg_erosion1 == I_Klimt_erosion1_sse)? " << (I_matImg_erosion1 == I_Klimt_erosion1_sse)
855  << " ; t_opencv=" << t_opencv << " ms" << std::endl;
856 
857  // Erosion CONNEXITY_8 grayscale
858  cv::Mat matImg_erosion2;
859  vpImageConvert::convert(I_Klimt, matImg_erosion2);
860 
861  t_opencv = vpTime::measureTimeMs();
862  for (int cpt = 0; cpt < nbIterations; cpt++) {
863  cv::morphologyEx(matImg_erosion2, matImg_erosion2, cv::MORPH_ERODE, rect_SE);
864  }
865  t_opencv = vpTime::measureTimeMs() - t_opencv;
866 
867  vpImage<unsigned char> I_matImg_erosion2;
868  vpImageConvert::convert(matImg_erosion2, I_matImg_erosion2);
869  std::cout << "(I_matImg_erosion2 == I_Klimt_erosion2_sse)? " << (I_matImg_erosion2 == I_Klimt_erosion2_sse)
870  << " ; t_opencv=" << t_opencv << " ms" << std::endl;
871 
872 #endif
873 
874  } catch (const vpException &e) {
875  std::cout << "\nCatch an exception: " << e << std::endl;
876  return EXIT_FAILURE;
877  }
878 
879  std::cout << "\nTest of morphology erosion / dilatation functions are OK!" << std::endl;
880  return EXIT_SUCCESS;
881 }
static void binarise(vpImage< Type > &I, Type threshold1, Type threshold2, Type value1, Type value2, Type value3, const bool useLUT=true)
Definition: vpImageTools.h:430
static int modulo(const int a, const int n)
Definition: vpMath.cpp:281
static std::string getViSPImagesDataPath()
Definition: vpIoTools.cpp:1316
static void dilatation(vpImage< Type > &I, Type value, Type value_out, vpConnexityType connexity=CONNEXITY_4)
unsigned int getWidth() const
Definition: vpImage.h:239
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
Type * bitmap
points toward the bitmap
Definition: vpImage.h:133
error that can be emited by ViSP classes.
Definition: vpException.h:71
VISP_EXPORT double measureTimeMs()
Definition: vpTime.cpp:88
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
Definition: vpParseArgv.cpp:69
static void erosion(vpImage< Type > &I, Type value, Type value_out, vpConnexityType connexity=CONNEXITY_4)
static std::string createFilePath(const std::string &parent, const std::string &child)
Definition: vpIoTools.cpp:1541
unsigned int getSize() const
Definition: vpImage.h:219
void resize(const unsigned int h, const unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:866
static void read(vpImage< unsigned char > &I, const std::string &filename)
Definition: vpImageIo.cpp:207
unsigned int getHeight() const
Definition: vpImage.h:178