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