Visual Servoing Platform version 3.6.0
Loading...
Searching...
No Matches
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
47namespace
48{
49void 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
66void 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
92int 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
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
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)
Definition of the vpImage class member functions.
Definition vpImage.h:135
unsigned int getWidth() const
Definition vpImage.h:242
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition vpImage.h:795
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:172
static Type minimum(const Type &a, const Type &b)
Definition vpMath.h:180
VISP_EXPORT double measureTimeMs()