Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
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
43using namespace VISP_NAMESPACE_NAME;
44#endif
45
46namespace
47{
48void 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
65void 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
91int 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
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
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)
Definition of the vpImage class member functions.
Definition vpImage.h:131
unsigned int getWidth() const
Definition vpImage.h:242
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition vpImage.h:544
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:257
static Type minimum(const Type &a, const Type &b)
Definition vpMath.h:265
VISP_EXPORT double measureTimeMs()