Visual Servoing Platform  version 3.0.1
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
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
7  * modify it under the terms of the GNU General Public License
8  * ("GPL") version 2 as published by the Free Software Foundation.
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 http://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 tools.
32  *
33  * Authors:
34  * Fabien Spindler
35  *
36  *****************************************************************************/
37 
38 #include <visp3/core/vpImageTools.h>
39 
40 #if defined __SSE2__ || defined _M_X64 || (defined _M_IX86_FP && _M_IX86_FP >= 2)
41 # include <emmintrin.h>
42 # define VISP_HAVE_SSE2 1
43 #endif
44 
45 
103  unsigned char A,
104  unsigned char A_star,
105  unsigned char B,
106  unsigned char B_star)
107 {
108  // Test if input values are valid
109  if (B <= A) {
110  vpERROR_TRACE("Bad gray levels") ;
112  "Bad gray levels"));
113  }
114  unsigned char v;
115 
116  double factor = (double)(B_star - A_star)/(double)(B - A);
117 
118  for (unsigned int i=0 ; i < I.getHeight(); i++)
119  for (unsigned int j=0 ; j < I.getWidth(); j++) {
120  v = I[i][j];
121 
122  if (v <= A)
123  I[i][j] = A_star;
124  else if (v >= B)
125  I[i][j] = B_star;
126  else
127  I[i][j] = (unsigned char)(A_star + factor*(v-A));
128  }
129 }
130 
144  const vpImage<unsigned char> &I2,
145  vpImage<unsigned char> &Idiff)
146 {
147  if ((I1.getHeight() != I2.getHeight()) || (I1.getWidth() != I2.getWidth()))
148  {
149  throw (vpException(vpException::dimensionError, "The two images have not the same size"));
150  }
151 
152  if ((I1.getHeight() != Idiff.getHeight()) || (I1.getWidth() != Idiff.getWidth()))
153  Idiff.resize(I1.getHeight(), I1.getWidth());
154 
155  unsigned int n = I1.getHeight() * I1.getWidth() ;
156  for (unsigned int b = 0; b < n ; b++)
157  {
158  int diff = I1.bitmap[b] - I2.bitmap[b] + 128;
159  Idiff.bitmap[b] = (unsigned char) (vpMath::maximum(vpMath::minimum(diff, 255), 0));
160  }
161 }
162 
177  const vpImage<vpRGBa> &I2,
178  vpImage<vpRGBa> &Idiff)
179 {
180  if ((I1.getHeight() != I2.getHeight()) || (I1.getWidth() != I2.getWidth()))
181  {
182  throw (vpException(vpException::dimensionError, "Cannot compute image difference. The two images (%ux%u) and (%ux%u) have not the same size",
183  I1.getWidth(), I1.getHeight(), I2.getWidth(), I2.getHeight()));
184  }
185 
186  if ((I1.getHeight() != Idiff.getHeight()) || (I1.getWidth() != Idiff.getWidth()))
187  Idiff.resize(I1.getHeight(), I1.getWidth());
188 
189  unsigned int n = I1.getHeight() * I1.getWidth() ;
190  for (unsigned int b = 0; b < n ; b++)
191  {
192  int diffR = I1.bitmap[b].R - I2.bitmap[b].R + 128;
193  int diffG = I1.bitmap[b].G - I2.bitmap[b].G + 128;
194  int diffB = I1.bitmap[b].B - I2.bitmap[b].B + 128;
195  int diffA = I1.bitmap[b].A - I2.bitmap[b].A + 128;
196  Idiff.bitmap[b].R = (unsigned char) (vpMath::maximum(vpMath::minimum(diffR, 255), 0));
197  Idiff.bitmap[b].G = (unsigned char) (vpMath::maximum(vpMath::minimum(diffG, 255), 0));
198  Idiff.bitmap[b].B = (unsigned char) (vpMath::maximum(vpMath::minimum(diffB, 255), 0));
199  Idiff.bitmap[b].A = (unsigned char) (vpMath::maximum(vpMath::minimum(diffA, 255), 0));
200  }
201 }
202 
213 void
215  const vpImage<unsigned char> &I2,
216  vpImage<unsigned char> &Idiff)
217 {
218  if ((I1.getHeight() != I2.getHeight()) || (I1.getWidth() != I2.getWidth()))
219  {
220  throw (vpException(vpException::dimensionError, "The two images do not have the same size"));
221  }
222 
223  if ((I1.getHeight() != Idiff.getHeight()) || (I1.getWidth() != Idiff.getWidth()))
224  Idiff.resize(I1.getHeight(), I1.getWidth());
225 
226  unsigned int n = I1.getHeight() * I1.getWidth() ;
227  for (unsigned int b = 0; b < n ; b++)
228  {
229  int diff = I1.bitmap[b] - I2.bitmap[b];
230  Idiff.bitmap[b] = diff;
231  }
232 }
233 
247 void
249  const vpImage<vpRGBa> &I2,
250  vpImage<vpRGBa> &Idiff)
251 {
252  if ((I1.getHeight() != I2.getHeight()) || (I1.getWidth() != I2.getWidth()))
253  {
254  throw (vpException(vpException::dimensionError, "The two images do not have the same size"));
255  }
256 
257  if ((I1.getHeight() != Idiff.getHeight()) || (I1.getWidth() != Idiff.getWidth()))
258  Idiff.resize(I1.getHeight(), I1.getWidth());
259 
260  unsigned int n = I1.getHeight() * I1.getWidth() ;
261  for (unsigned int b = 0; b < n ; b++)
262  {
263  int diffR = I1.bitmap[b].R - I2.bitmap[b].R;
264  int diffG = I1.bitmap[b].G - I2.bitmap[b].G;
265  int diffB = I1.bitmap[b].B - I2.bitmap[b].B;
266  //int diffA = I1.bitmap[b].A - I2.bitmap[b].A;
267  Idiff.bitmap[b].R = diffR;
268  Idiff.bitmap[b].G = diffG;
269  Idiff.bitmap[b].B = diffB;
270  //Idiff.bitmap[b].A = diffA;
271  Idiff.bitmap[b].A = 0;
272  }
273 }
274 
283 void
285  const vpImage<unsigned char> &I2,
287  const bool saturate)
288 {
289  if ((I1.getHeight() != I2.getHeight()) || (I1.getWidth() != I2.getWidth())) {
290  throw (vpException(vpException::dimensionError, "The two images do not have the same size"));
291  }
292 
293  if ((I1.getHeight() != Ires.getHeight()) || (I1.getWidth() != Ires.getWidth())) {
294  Ires.resize(I1.getHeight(), I1.getWidth());
295  }
296 
297  unsigned char *ptr_I1 = I1.bitmap;
298  unsigned char *ptr_I2 = I2.bitmap;
299  unsigned char *ptr_Ires = Ires.bitmap;
300  unsigned int cpt = 0;
301 
302 #if VISP_HAVE_SSE2
303  if (Ires.getSize() >= 16) {
304  for (; cpt <= Ires.getSize() - 16 ; cpt += 16, ptr_I1 += 16, ptr_I2 += 16, ptr_Ires += 16) {
305  const __m128i v1 = _mm_loadu_si128( (const __m128i*) ptr_I1);
306  const __m128i v2 = _mm_loadu_si128( (const __m128i*) ptr_I2);
307  const __m128i vres = saturate ? _mm_adds_epu8(v1, v2) : _mm_add_epi8(v1, v2);
308 
309  _mm_storeu_si128( (__m128i*) ptr_Ires, vres );
310  }
311  }
312 #endif
313 
314  for (; cpt < Ires.getSize(); cpt++, ++ptr_I1, ++ptr_I2, ++ptr_Ires) {
315  *ptr_Ires = saturate ? vpMath::saturate<unsigned char>( (short int) *ptr_I1 + (short int) *ptr_I2 ) : *ptr_I1 + *ptr_I2;
316  }
317 }
318 
327 void
329  const vpImage<unsigned char> &I2,
331  const bool saturate)
332 {
333  if ((I1.getHeight() != I2.getHeight()) || (I1.getWidth() != I2.getWidth())) {
334  throw (vpException(vpException::dimensionError, "The two images do not have the same size"));
335  }
336 
337  if ((I1.getHeight() != Ires.getHeight()) || (I1.getWidth() != Ires.getWidth())) {
338  Ires.resize(I1.getHeight(), I1.getWidth());
339  }
340 
341  unsigned char *ptr_I1 = I1.bitmap;
342  unsigned char *ptr_I2 = I2.bitmap;
343  unsigned char *ptr_Ires = Ires.bitmap;
344  unsigned int cpt = 0;
345 
346 #if VISP_HAVE_SSE2
347  if (Ires.getSize() >= 16) {
348  for (; cpt <= Ires.getSize() - 16 ; cpt += 16, ptr_I1 += 16, ptr_I2 += 16, ptr_Ires += 16) {
349  const __m128i v1 = _mm_loadu_si128( (const __m128i*) ptr_I1);
350  const __m128i v2 = _mm_loadu_si128( (const __m128i*) ptr_I2);
351  const __m128i vres = saturate ? _mm_subs_epu8(v1, v2) : _mm_sub_epi8(v1, v2);
352 
353  _mm_storeu_si128( (__m128i*) ptr_Ires, vres );
354  }
355  }
356 #endif
357 
358  for (; cpt < Ires.getSize(); cpt++, ++ptr_I1, ++ptr_I2, ++ptr_Ires) {
359  *ptr_Ires = saturate ? vpMath::saturate<unsigned char>( (short int) *ptr_I1 - (short int) *ptr_I2 ) : *ptr_I1 - *ptr_I2;
360  }
361 }
362 
363 // Reference: http://blog.demofox.org/2015/08/15/resizing-images-with-bicubic-interpolation/
364 // t is a value that goes from 0 to 1 to interpolate in a C1 continuous way across uniformly sampled data points.
365 // when t is 0, this will return B. When t is 1, this will return C. In between values will return an interpolation
366 // between B and C. A and B are used to calculate the slopes at the edges.
367 float vpImageTools::cubicHermite (const float A, const float B, const float C, const float D, const float t) {
368  float a = (-A + 3.0f*B - 3.0f*C + D) / 2.0f;
369  float b = A + 2.0f*C - (5.0f*B + D) / 2.0f;
370  float c = (-A + C) / 2.0f;
371  float d = B;
372 
373  return a*t*t*t + b*t*t + c*t + d;
374 }
375 
376 float vpImageTools::lerp(const float A, const float B, const float t) {
377  return A * (1.0f - t) + B * t;
378 }
static void imageDifferenceAbsolute(const vpImage< unsigned char > &I1, const vpImage< unsigned char > &I2, vpImage< unsigned char > &Idiff)
unsigned int getWidth() const
Definition: vpImage.h:226
unsigned char B
Blue component.
Definition: vpRGBa.h:155
Type * bitmap
points toward the bitmap
Definition: vpImage.h:134
#define vpERROR_TRACE
Definition: vpDebug.h:391
error that can be emited by ViSP classes.
Definition: vpException.h:73
Error that can be emited by the vpImage class and its derivates.
unsigned char G
Green component.
Definition: vpRGBa.h:154
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:140
unsigned int getSize() const
Definition: vpImage.h:212
unsigned char A
Additionnal component.
Definition: vpRGBa.h:156
void resize(const unsigned int h, const unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:903
static Type minimum(const Type &a, const Type &b)
Definition: vpMath.h:151
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 char R
Red component.
Definition: vpRGBa.h:153
unsigned int getHeight() const
Definition: vpImage.h:175
static void changeLUT(vpImage< unsigned char > &I, unsigned char A, unsigned char newA, unsigned char B, unsigned char newB)