Visual Servoing Platform  version 3.1.0
vpImageTools.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2017 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  * Image tools.
33  *
34  * Authors:
35  * Fabien Spindler
36  *
37  *****************************************************************************/
38 
39 #include <visp3/core/vpCPUFeatures.h>
40 #include <visp3/core/vpImageTools.h>
41 
42 #if defined __SSE2__ || defined _M_X64 || (defined _M_IX86_FP && _M_IX86_FP >= 2)
43 #include <emmintrin.h>
44 #define VISP_HAVE_SSE2 1
45 #endif
46 
103 void vpImageTools::changeLUT(vpImage<unsigned char> &I, unsigned char A, unsigned char A_star, unsigned char B,
104  unsigned char B_star)
105 {
106  // Test if input values are valid
107  if (B <= A) {
108  vpERROR_TRACE("Bad gray levels");
110  }
111  unsigned char v;
112 
113  double factor = (double)(B_star - A_star) / (double)(B - A);
114 
115  for (unsigned int i = 0; i < I.getHeight(); i++)
116  for (unsigned int j = 0; j < I.getWidth(); j++) {
117  v = I[i][j];
118 
119  if (v <= A)
120  I[i][j] = A_star;
121  else if (v >= B)
122  I[i][j] = B_star;
123  else
124  I[i][j] = (unsigned char)(A_star + factor * (v - A));
125  }
126 }
127 
141  vpImage<unsigned char> &Idiff)
142 {
143  if ((I1.getHeight() != I2.getHeight()) || (I1.getWidth() != I2.getWidth())) {
144  throw(vpException(vpException::dimensionError, "The two images have not the same size"));
145  }
146 
147  if ((I1.getHeight() != Idiff.getHeight()) || (I1.getWidth() != Idiff.getWidth()))
148  Idiff.resize(I1.getHeight(), I1.getWidth());
149 
150  unsigned int n = I1.getHeight() * I1.getWidth();
151  for (unsigned int b = 0; b < n; b++) {
152  int diff = I1.bitmap[b] - I2.bitmap[b] + 128;
153  Idiff.bitmap[b] = (unsigned char)(vpMath::maximum(vpMath::minimum(diff, 255), 0));
154  }
155 }
156 
171 {
172  if ((I1.getHeight() != I2.getHeight()) || (I1.getWidth() != I2.getWidth())) {
174  "Cannot compute image difference. The two images "
175  "(%ux%u) and (%ux%u) have not the same size",
176  I1.getWidth(), I1.getHeight(), I2.getWidth(), I2.getHeight()));
177  }
178 
179  if ((I1.getHeight() != Idiff.getHeight()) || (I1.getWidth() != Idiff.getWidth()))
180  Idiff.resize(I1.getHeight(), I1.getWidth());
181 
182  unsigned int n = I1.getHeight() * I1.getWidth();
183  for (unsigned int b = 0; b < n; b++) {
184  int diffR = I1.bitmap[b].R - I2.bitmap[b].R + 128;
185  int diffG = I1.bitmap[b].G - I2.bitmap[b].G + 128;
186  int diffB = I1.bitmap[b].B - I2.bitmap[b].B + 128;
187  int diffA = I1.bitmap[b].A - I2.bitmap[b].A + 128;
188  Idiff.bitmap[b].R = (unsigned char)(vpMath::maximum(vpMath::minimum(diffR, 255), 0));
189  Idiff.bitmap[b].G = (unsigned char)(vpMath::maximum(vpMath::minimum(diffG, 255), 0));
190  Idiff.bitmap[b].B = (unsigned char)(vpMath::maximum(vpMath::minimum(diffB, 255), 0));
191  Idiff.bitmap[b].A = (unsigned char)(vpMath::maximum(vpMath::minimum(diffA, 255), 0));
192  }
193 }
194 
206  vpImage<unsigned char> &Idiff)
207 {
208  if ((I1.getHeight() != I2.getHeight()) || (I1.getWidth() != I2.getWidth())) {
209  throw(vpException(vpException::dimensionError, "The two images do not have the same size"));
210  }
211 
212  if ((I1.getHeight() != Idiff.getHeight()) || (I1.getWidth() != Idiff.getWidth()))
213  Idiff.resize(I1.getHeight(), I1.getWidth());
214 
215  unsigned int n = I1.getHeight() * I1.getWidth();
216  for (unsigned int b = 0; b < n; b++) {
217  int diff = I1.bitmap[b] - I2.bitmap[b];
218  Idiff.bitmap[b] = diff;
219  }
220 }
221 
236 {
237  if ((I1.getHeight() != I2.getHeight()) || (I1.getWidth() != I2.getWidth())) {
238  throw(vpException(vpException::dimensionError, "The two images do not have the same size"));
239  }
240 
241  if ((I1.getHeight() != Idiff.getHeight()) || (I1.getWidth() != Idiff.getWidth()))
242  Idiff.resize(I1.getHeight(), I1.getWidth());
243 
244  unsigned int n = I1.getHeight() * I1.getWidth();
245  for (unsigned int b = 0; b < n; b++) {
246  int diffR = I1.bitmap[b].R - I2.bitmap[b].R;
247  int diffG = I1.bitmap[b].G - I2.bitmap[b].G;
248  int diffB = I1.bitmap[b].B - I2.bitmap[b].B;
249  // int diffA = I1.bitmap[b].A - I2.bitmap[b].A;
250  Idiff.bitmap[b].R = diffR;
251  Idiff.bitmap[b].G = diffG;
252  Idiff.bitmap[b].B = diffB;
253  // Idiff.bitmap[b].A = diffA;
254  Idiff.bitmap[b].A = 0;
255  }
256 }
257 
268  vpImage<unsigned char> &Ires, const bool saturate)
269 {
270  if ((I1.getHeight() != I2.getHeight()) || (I1.getWidth() != I2.getWidth())) {
271  throw(vpException(vpException::dimensionError, "The two images do not have the same size"));
272  }
273 
274  if ((I1.getHeight() != Ires.getHeight()) || (I1.getWidth() != Ires.getWidth())) {
275  Ires.resize(I1.getHeight(), I1.getWidth());
276  }
277 
278  unsigned char *ptr_I1 = I1.bitmap;
279  unsigned char *ptr_I2 = I2.bitmap;
280  unsigned char *ptr_Ires = Ires.bitmap;
281  unsigned int cpt = 0;
282 
283 #if VISP_HAVE_SSE2
284  if (vpCPUFeatures::checkSSE2() && Ires.getSize() >= 16) {
285  for (; cpt <= Ires.getSize() - 16; cpt += 16, ptr_I1 += 16, ptr_I2 += 16, ptr_Ires += 16) {
286  const __m128i v1 = _mm_loadu_si128((const __m128i *)ptr_I1);
287  const __m128i v2 = _mm_loadu_si128((const __m128i *)ptr_I2);
288  const __m128i vres = saturate ? _mm_adds_epu8(v1, v2) : _mm_add_epi8(v1, v2);
289 
290  _mm_storeu_si128((__m128i *)ptr_Ires, vres);
291  }
292  }
293 #endif
294 
295  for (; cpt < Ires.getSize(); cpt++, ++ptr_I1, ++ptr_I2, ++ptr_Ires) {
296  *ptr_Ires = saturate ? vpMath::saturate<unsigned char>((short int)*ptr_I1 + (short int)*ptr_I2) : *ptr_I1 + *ptr_I2;
297  }
298 }
299 
310  vpImage<unsigned char> &Ires, const bool saturate)
311 {
312  if ((I1.getHeight() != I2.getHeight()) || (I1.getWidth() != I2.getWidth())) {
313  throw(vpException(vpException::dimensionError, "The two images do not have the same size"));
314  }
315 
316  if ((I1.getHeight() != Ires.getHeight()) || (I1.getWidth() != Ires.getWidth())) {
317  Ires.resize(I1.getHeight(), I1.getWidth());
318  }
319 
320  unsigned char *ptr_I1 = I1.bitmap;
321  unsigned char *ptr_I2 = I2.bitmap;
322  unsigned char *ptr_Ires = Ires.bitmap;
323  unsigned int cpt = 0;
324 
325 #if VISP_HAVE_SSE2
326  if (vpCPUFeatures::checkSSE2() && Ires.getSize() >= 16) {
327  for (; cpt <= Ires.getSize() - 16; cpt += 16, ptr_I1 += 16, ptr_I2 += 16, ptr_Ires += 16) {
328  const __m128i v1 = _mm_loadu_si128((const __m128i *)ptr_I1);
329  const __m128i v2 = _mm_loadu_si128((const __m128i *)ptr_I2);
330  const __m128i vres = saturate ? _mm_subs_epu8(v1, v2) : _mm_sub_epi8(v1, v2);
331 
332  _mm_storeu_si128((__m128i *)ptr_Ires, vres);
333  }
334  }
335 #endif
336 
337  for (; cpt < Ires.getSize(); cpt++, ++ptr_I1, ++ptr_I2, ++ptr_Ires) {
338  *ptr_Ires = saturate ? vpMath::saturate<unsigned char>((short int)*ptr_I1 - (short int)*ptr_I2) : *ptr_I1 - *ptr_I2;
339  }
340 }
341 
342 // Reference:
343 // http://blog.demofox.org/2015/08/15/resizing-images-with-bicubic-interpolation/
344 // t is a value that goes from 0 to 1 to interpolate in a C1 continuous way
345 // across uniformly sampled data points. when t is 0, this will return B.
346 // When t is 1, this will return C. In between values will return an
347 // interpolation between B and C. A and B are used to calculate the slopes at
348 // the edges.
349 float vpImageTools::cubicHermite(const float A, const float B, const float C, const float D, const float t)
350 {
351  float a = (-A + 3.0f * B - 3.0f * C + D) / 2.0f;
352  float b = A + 2.0f * C - (5.0f * B + D) / 2.0f;
353  float c = (-A + C) / 2.0f;
354  float d = B;
355 
356  return a * t * t * t + b * t * t + c * t + d;
357 }
358 
359 float vpImageTools::lerp(const float A, const float B, const float t) { return A * (1.0f - t) + B * t; }
static void imageDifferenceAbsolute(const vpImage< unsigned char > &I1, const vpImage< unsigned char > &I2, vpImage< unsigned char > &Idiff)
unsigned char B
Blue component.
Definition: vpRGBa.h:150
Type * bitmap
points toward the bitmap
Definition: vpImage.h:133
#define vpERROR_TRACE
Definition: vpDebug.h:393
error that can be emited by ViSP classes.
Definition: vpException.h:71
Error that can be emited by the vpImage class and its derivates.
unsigned char G
Green component.
Definition: vpRGBa.h:149
static void imageDifference(const vpImage< unsigned char > &I1, const vpImage< unsigned char > &I2, vpImage< unsigned char > &Idiff)
static Type maximum(const Type &a, const Type &b)
Definition: vpMath.h:137
VISP_EXPORT bool checkSSE2()
unsigned char A
Additionnal component.
Definition: vpRGBa.h:151
void resize(const unsigned int h, const unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:856
static Type minimum(const Type &a, const Type &b)
Definition: vpMath.h:145
unsigned int getHeight() const
Definition: vpImage.h:178
static void imageAdd(const vpImage< unsigned char > &I1, const vpImage< unsigned char > &I2, vpImage< unsigned char > &Ires, const bool saturate=false)
static void imageSubtract(const vpImage< unsigned char > &I1, const vpImage< unsigned char > &I2, vpImage< unsigned char > &Ires, const bool saturate=false)
unsigned int getSize() const
Definition: vpImage.h:215
unsigned char R
Red component.
Definition: vpRGBa.h:148
static void changeLUT(vpImage< unsigned char > &I, unsigned char A, unsigned char newA, unsigned char B, unsigned char newB)
unsigned int getWidth() const
Definition: vpImage.h:229