Visual Servoing Platform  version 3.6.1 under development (2024-02-13)
testImageDifference.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  * Image difference.
33  *
34  * Authors:
35  * Souriya Trinh
36  *
37 *****************************************************************************/
38 
39 #include <iostream>
40 #include <visp3/core/vpImageTools.h>
41 
47 namespace
48 {
49 void regularImageDifference(const vpImage<unsigned char> &I1, const vpImage<unsigned char> &I2,
51 {
52  if ((I1.getHeight() != I2.getHeight()) || (I1.getWidth() != I2.getWidth())) {
53  throw(vpException(vpException::dimensionError, "The two images have not the same size"));
54  }
55 
56  if ((I1.getHeight() != Idiff.getHeight()) || (I1.getWidth() != Idiff.getWidth()))
57  Idiff.resize(I1.getHeight(), I1.getWidth());
58 
59  unsigned int n = I1.getHeight() * I1.getWidth();
60  for (unsigned int b = 0; b < n; b++) {
61  int diff = I1.bitmap[b] - I2.bitmap[b] + 128u;
62  Idiff.bitmap[b] = static_cast<unsigned char>(vpMath::maximum(vpMath::minimum(diff, 255), 0));
63  }
64 }
65 
66 void regularImageDifference(const vpImage<vpRGBa> &I1, const vpImage<vpRGBa> &I2, vpImage<vpRGBa> &Idiff)
67 {
68  if ((I1.getHeight() != I2.getHeight()) || (I1.getWidth() != I2.getWidth())) {
70  "Cannot compute image difference. The two images "
71  "(%ux%u) and (%ux%u) have not the same size",
72  I1.getWidth(), I1.getHeight(), I2.getWidth(), I2.getHeight()));
73  }
74 
75  if ((I1.getHeight() != Idiff.getHeight()) || (I1.getWidth() != Idiff.getWidth()))
76  Idiff.resize(I1.getHeight(), I1.getWidth());
77 
78  unsigned int n = I1.getHeight() * I1.getWidth();
79  for (unsigned int b = 0; b < n; b++) {
80  int diffR = I1.bitmap[b].R - I2.bitmap[b].R + 128;
81  int diffG = I1.bitmap[b].G - I2.bitmap[b].G + 128;
82  int diffB = I1.bitmap[b].B - I2.bitmap[b].B + 128;
83  int diffA = I1.bitmap[b].A - I2.bitmap[b].A + 128;
84  Idiff.bitmap[b].R = static_cast<unsigned char>(vpMath::maximum(vpMath::minimum(diffR, 255), 0));
85  Idiff.bitmap[b].G = static_cast<unsigned char>(vpMath::maximum(vpMath::minimum(diffG, 255), 0));
86  Idiff.bitmap[b].B = static_cast<unsigned char>(vpMath::maximum(vpMath::minimum(diffB, 255), 0));
87  Idiff.bitmap[b].A = static_cast<unsigned char>(vpMath::maximum(vpMath::minimum(diffA, 255), 0));
88  }
89 }
90 } // namespace
91 
92 int main()
93 {
94  unsigned int width = 501, height = 447;
95  vpImage<unsigned char> I1(height, width), I2(height, width), Idiff_regular(height, width), Idiff_sse(height, width);
96  vpImage<vpRGBa> I1_color(height, width), I2_color(height, width), Idiff_regular_color(height, width),
97  Idiff_sse_color(height, width);
98  for (unsigned int i = 0; i < I1.getRows(); i++) {
99  for (unsigned int j = 0; j < I1.getCols(); j++) {
100  I1[i][j] = static_cast<unsigned char>(i * I1.getCols() + j);
101  I1_color[i][j] = vpRGBa(static_cast<unsigned char>(i * I1.getCols() + j));
102  }
103  }
104 
105  {
106  std::cout << "Grayscale:" << std::endl;
107 
108  double t_regular = 0.0, t_sse = 0.0;
109  for (unsigned int cpt = 0; cpt < 256; cpt++) {
110  for (unsigned int i = 0; i < I2.getRows(); i++) {
111  for (unsigned int j = 0; j < I2.getCols(); j++) {
112  I2[i][j] = static_cast<unsigned char>(i * I2.getCols() + j + cpt);
113  }
114  }
115 
116  double t = vpTime::measureTimeMs();
117  regularImageDifference(I1, I2, Idiff_regular);
118  t_regular += vpTime::measureTimeMs() - t;
119 
120  t = vpTime::measureTimeMs();
121  vpImageTools::imageDifference(I1, I2, Idiff_sse);
122  t_sse += vpTime::measureTimeMs() - t;
123 
124  if (Idiff_regular != Idiff_sse) {
125  std::cerr << "Problem with vpImageTools::imageDifference()" << std::endl;
126  return EXIT_FAILURE;
127  }
128  }
129 
130  std::cout << "(Idiff_regular == Idiff_sse)" << std::endl;
131  std::cout << "t_regular: " << t_regular << " ms ; mean t_regular: " << t_regular / 256 << " ms" << std::endl;
132  std::cout << "t_sse: " << t_sse << " ms ; mean t_sse: " << t_sse / 256 << " ms" << std::endl;
133  std::cout << "speed-up: " << t_regular / t_sse << " times" << std::endl;
134  }
135 
136  {
137  std::cout << "\nColor:" << std::endl;
138 
139  double t_regular = 0.0, t_sse = 0.0;
140  for (unsigned int cpt = 0; cpt < 256; cpt++) {
141  for (unsigned int i = 0; i < I2.getRows(); i++) {
142  for (unsigned int j = 0; j < I2.getCols(); j++) {
143  I2_color[i][j] = vpRGBa(static_cast<unsigned char>(i * I2.getCols() + j + cpt));
144  }
145  }
146 
147  double t = vpTime::measureTimeMs();
148  regularImageDifference(I1_color, I2_color, Idiff_regular_color);
149  t_regular += vpTime::measureTimeMs() - t;
150 
151  t = vpTime::measureTimeMs();
152  vpImageTools::imageDifference(I1_color, I2_color, Idiff_sse_color);
153  t_sse += vpTime::measureTimeMs() - t;
154 
155  if (Idiff_regular_color != Idiff_sse_color) {
156  std::cerr << "Problem with vpImageTools::imageDifference()" << std::endl;
157  return EXIT_FAILURE;
158  }
159  }
160 
161  std::cout << "(Idiff_regular_color == Idiff_sse_color)" << std::endl;
162  std::cout << "t_regular: " << t_regular << " ms ; mean t_regular: " << t_regular / 256 << " ms" << std::endl;
163  std::cout << "t_sse: " << t_sse << " ms ; mean t_sse: " << t_sse / 256 << " ms" << std::endl;
164  std::cout << "speed-up: " << t_regular / t_sse << " times" << std::endl;
165  }
166 
167  {
168  std::cout << "Test vpRGBa" << std::endl;
169  vpRGBa rgba_1(10, 20, 30);
170  vpRGBa rgba_2(10, 20, 30);
171 
172  if (rgba_1 == rgba_2) {
173  std::cout << "Test ok: same rgba" << std::endl;
174  }
175  else {
176  std::cerr << "Error in rgba operator==" << std::endl;
177  return EXIT_FAILURE;
178  }
179  if (rgba_1 != rgba_2) {
180  std::cerr << "Error in rgba operator!=" << std::endl;
181  return EXIT_FAILURE;
182  }
183  {
184  vpRGBa rgba_3(1, 0, 0);
185  if (rgba_1 == (rgba_2 + rgba_3)) {
186  std::cerr << "Error in rgba operator==" << std::endl;
187  return EXIT_FAILURE;
188  }
189  if (rgba_1 != (rgba_2 + rgba_3)) {
190  std::cerr << "Test ok: R value differ" << std::endl;
191  }
192  }
193  {
194  vpRGBa rgba_3(0, 1, 0);
195  if (rgba_1 == (rgba_2 + rgba_3)) {
196  std::cerr << "Error in rgba operator==" << std::endl;
197  return EXIT_FAILURE;
198  }
199  if (rgba_1 != (rgba_2 + rgba_3)) {
200  std::cerr << "Test ok: G value differ" << std::endl;
201  }
202  }
203  {
204  vpRGBa rgba_3(0, 0, 1);
205  if (rgba_1 == (rgba_2 + rgba_3)) {
206  std::cerr << "Error in rgba operator==" << std::endl;
207  return EXIT_FAILURE;
208  }
209  if (rgba_1 != (rgba_2 + rgba_3)) {
210  std::cerr << "Test ok: B value differ" << std::endl;
211  }
212  }
213  }
214 
215  {
216  std::cout << "Test vpRGBf" << std::endl;
217  vpRGBf rgbf_1(10.f, 20.f, 30.f);
218  vpRGBf rgbf_2(10.f, 20.f, 30.f);
219 
220  if (rgbf_1 == rgbf_2) {
221  std::cout << "Test ok: same rgbf" << std::endl;
222  }
223  else {
224  std::cerr << "Error in rgbf operator==" << std::endl;
225  return EXIT_FAILURE;
226  }
227  if (rgbf_1 != rgbf_2) {
228  std::cerr << "Error in rgbf operator!=" << std::endl;
229  return EXIT_FAILURE;
230  }
231  {
232  vpRGBf rgbf_3(1e-6f, 0.f, 0.f);
233  if (rgbf_1 == (rgbf_2 + rgbf_3)) {
234  std::cerr << "Rf Error in rgbf operator==" << std::endl;
235  return EXIT_FAILURE;
236  }
237  if (rgbf_1 != (rgbf_2 + rgbf_3)) {
238  std::cerr << "Test ok: Rf value differ" << std::endl;
239  }
240  }
241  {
242  vpRGBf rgbf_3(0.f, 1e-6f, 0.f);
243  if (rgbf_1 == (rgbf_2 + rgbf_3)) {
244  std::cerr << "Gf Error in rgbf operator==" << std::endl;
245  return EXIT_FAILURE;
246  }
247  if (rgbf_1 != (rgbf_2 + rgbf_3)) {
248  std::cerr << "Test ok: Gf value differ" << std::endl;
249  }
250  }
251  {
252  vpRGBf rgbf_3(0.f, 0.f, 1e-6f);
253  if (rgbf_1 == (rgbf_2 + rgbf_3)) {
254  std::cerr << "Bf Error in rgbf operator==" << std::endl;
255  return EXIT_FAILURE;
256  }
257  if (rgbf_1 != (rgbf_2 + rgbf_3)) {
258  std::cerr << "Test ok: Bf value differ" << std::endl;
259  }
260  }
261  }
262 
263  std::cout << "Test succeed" << std::endl;
264  return EXIT_SUCCESS;
265 }
error that can be emitted by ViSP classes.
Definition: vpException.h:59
@ dimensionError
Bad dimension.
Definition: vpException.h:83
static void imageDifference(const vpImage< unsigned char > &I1, const vpImage< unsigned char > &I2, vpImage< unsigned char > &Idiff)
unsigned int getWidth() const
Definition: vpImage.h:242
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:780
unsigned int getCols() const
Definition: vpImage.h:175
Type * bitmap
points toward the bitmap
Definition: vpImage.h:139
unsigned int getHeight() const
Definition: vpImage.h:184
unsigned int getRows() const
Definition: vpImage.h:214
static Type maximum(const Type &a, const Type &b)
Definition: vpMath.h:252
static Type minimum(const Type &a, const Type &b)
Definition: vpMath.h:260
Definition: vpRGBa.h:61
unsigned char B
Blue component.
Definition: vpRGBa.h:139
unsigned char R
Red component.
Definition: vpRGBa.h:137
unsigned char G
Green component.
Definition: vpRGBa.h:138
unsigned char A
Additionnal component.
Definition: vpRGBa.h:140
Definition: vpRGBf.h:57
VISP_EXPORT double measureTimeMs()