ViSP  2.8.0
vpImageTools.h
1 /****************************************************************************
2  *
3  * $Id: vpImageTools.h 4317 2013-07-17 09:40:17Z fspindle $
4  *
5  * This file is part of the ViSP software.
6  * Copyright (C) 2005 - 2013 by INRIA. All rights reserved.
7  *
8  * This software is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * ("GPL") version 2 as published by the Free Software Foundation.
11  * See the file LICENSE.txt at the root directory of this source
12  * distribution for additional information about the GNU GPL.
13  *
14  * For using ViSP with software that can not be combined with the GNU
15  * GPL, please contact INRIA about acquiring a ViSP Professional
16  * Edition License.
17  *
18  * See http://www.irisa.fr/lagadic/visp/visp.html for more information.
19  *
20  * This software was developed at:
21  * INRIA Rennes - Bretagne Atlantique
22  * Campus Universitaire de Beaulieu
23  * 35042 Rennes Cedex
24  * France
25  * http://www.irisa.fr/lagadic
26  *
27  * If you have questions regarding the use of this file, please contact
28  * INRIA at visp@inria.fr
29  *
30  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
31  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
32  *
33  *
34  * Description:
35  * Image tools.
36  *
37  * Authors:
38  * Fabien Spindler
39  *
40  *****************************************************************************/
41 
42 
43 #ifndef vpImageTools_H
44 #define vpImageTools_H
45 
54 #include <visp/vpImage.h>
55 
56 #ifdef VISP_HAVE_PTHREAD
57 # include <pthread.h>
58 #endif
59 
60 #include <visp/vpImageException.h>
61 #include <visp/vpMath.h>
62 #include <visp/vpRect.h>
63 #include <visp/vpCameraParameters.h>
64 
65 #include <fstream>
66 #include <iostream>
67 #include <math.h>
68 #include <string.h>
69 
79 class VISP_EXPORT vpImageTools
80 {
81 
82 public:
83  template<class Type>
84  static void createSubImage(const vpImage<Type> &I,
85  unsigned int i_sub, unsigned int j_sub,
86  unsigned int nrow_sub, unsigned int ncol_sub,
87  vpImage<Type> &S);
88 
89  template<class Type>
90  static void createSubImage(const vpImage<Type> &I,
91  const vpRect &rect,
92  vpImage<Type> &S);
93  template<class Type>
94  static void binarise(vpImage<Type> &I,
95  Type threshold1, Type threshold2,
96  Type value1, Type value2, Type value3);
97  static void changeLUT(vpImage<unsigned char>& I,
98  unsigned char A,
99  unsigned char newA,
100  unsigned char B,
101  unsigned char newB);
102  template<class Type>
103  static void undistort(const vpImage<Type> &I,
104  const vpCameraParameters &cam,
105  vpImage<Type> &newI);
106 
107  template<class Type>
108  static void flip(const vpImage<Type> &I,
109  vpImage<Type> &newI);
110 
111  template<class Type>
112  static void flip(vpImage<Type> &I);
113 
114 
115  static void imageDifference(const vpImage<unsigned char> &I1,
116  const vpImage<unsigned char> &I2,
117  vpImage<unsigned char> &Idiff) ;
118 
119  static void imageDifferenceAbsolute(const vpImage<unsigned char> &I1,
120  const vpImage<unsigned char> &I2,
121  vpImage<unsigned char> &Idiff);
122 } ;
123 
132 template<class Type>
134  unsigned int i_sub, unsigned int j_sub,
135  unsigned int nrow_sub, unsigned int ncol_sub,
136  vpImage<Type> &S)
137 {
138  unsigned int i,j ;
139  unsigned int imax = i_sub + nrow_sub ;
140  unsigned int jmax = j_sub + ncol_sub ;
141 
142  if (imax > I.getHeight())
143  {
144  imax = I.getHeight() -1 ;
145  nrow_sub = imax-i_sub ;
146  }
147  if (jmax > I.getWidth())
148  {
149  jmax = I.getWidth() -1 ;
150  ncol_sub = jmax -j_sub ;
151  }
152 
153  S.resize(nrow_sub, ncol_sub) ;
154  for (i=i_sub ; i < imax ; i++)
155  for (j=j_sub ; j < jmax ; j++)
156  {
157  S[i-i_sub][j-j_sub] = I[i][j] ;
158  }
159 }
170 template<class Type>
172  const vpRect &rect,
173  vpImage<Type> &S)
174 {
175  double dleft = rect.getLeft();
176  double dtop = rect.getTop();
177  double dright = ceil( rect.getRight() );
178  double dbottom = ceil( rect.getBottom() );
179 
180  if (dleft < 0.0) dleft = 0.0;
181  else if (dleft >= I.getWidth()) dleft = I.getWidth() - 1;
182 
183  if (dright < 0.0) dright = 0.0;
184  else if (dright >= I.getWidth()) dright = I.getWidth() - 1;
185 
186  if (dtop < 0.0) dtop = 0.0;
187  else if (dtop >= I.getHeight()) dtop = I.getHeight() - 1;
188 
189  if (dbottom < 0.0) dbottom = 0.0;
190  else if (dbottom >= I.getHeight()) dbottom = I.getHeight() - 1;
191 
192  // Convert the double-precision rectangle coordinates into integer positions
193  unsigned int left = (unsigned int) dleft;
194  unsigned int top = (unsigned int) dtop;
195  unsigned int bottom = (unsigned int) dbottom;
196  unsigned int right = (unsigned int) dright;
197 
198  unsigned int width = right - left + 1;;
199  unsigned int height = bottom - top + 1;
200 
201  S.resize(height, width) ;
202  for (unsigned int i=top ; i <= bottom ; i++) {
203  for (unsigned int j=left ; j <= right ; j++) {
204  S[i-top][j-left] = I[i][j] ;
205  }
206  }
207 }
220 template<class Type>
222  Type threshold1, Type threshold2,
223  Type value1, Type value2, Type value3)
224 {
225  unsigned char v;
226  unsigned char *p = I.bitmap;
227  unsigned char *pend = I.bitmap + I.getWidth()*I.getHeight();
228  for (; p < pend; p ++) {
229  v = *p;
230  if (v < threshold1) *p = value1;
231  else if (v > threshold2) *p = value3;
232  else *p = value2;
233  }
234 
235 }
236 
237 #ifdef VISP_HAVE_PTHREAD
238 
239 #ifndef DOXYGEN_SHOULD_SKIP_THIS
240 template<class Type>
241 class vpUndistortInternalType
242 {
243 public:
244  Type *src;
245  Type *dst;
246  unsigned int width;
247  unsigned int height;
248  vpCameraParameters cam;
249  unsigned int nthreads;
250  unsigned int threadid;
251 public:
252  vpUndistortInternalType() {};
253  vpUndistortInternalType(const vpUndistortInternalType<Type> &u) {
254  src = u.src;
255  dst = u.dst;
256  width = u.width;
257  height = u.height;
258  cam = u.cam;
259  nthreads = u.nthreads;
260  threadid = u.threadid;
261  };
262 
263  static void *vpUndistort_threaded(void *arg);
264 };
265 
266 
267 template<class Type>
268 void *vpUndistortInternalType<Type>::vpUndistort_threaded(void *arg)
269 {
270  vpUndistortInternalType<Type> *undistortSharedData = (vpUndistortInternalType<Type>*)arg;
271  int offset = (int)undistortSharedData->threadid;
272  int width = (int)undistortSharedData->width;
273  int height = (int)undistortSharedData->height;
274  int nthreads = (int)undistortSharedData->nthreads;
275 
276  double u0 = undistortSharedData->cam.get_u0();
277  double v0 = undistortSharedData->cam.get_v0();
278  double px = undistortSharedData->cam.get_px();
279  double py = undistortSharedData->cam.get_py();
280  double kud = undistortSharedData->cam.get_kud();
281 
282  double invpx = 1.0/px;
283  double invpy = 1.0/py;
284 
285  double kud_px2 = kud * invpx * invpx;
286  double kud_py2 = kud * invpy * invpy;
287 
288  Type *dst = undistortSharedData->dst+(height/nthreads*offset)*width;
289  Type *src = undistortSharedData->src;
290 
291  for (double v = height/nthreads*offset;v < height/nthreads*(offset+1) ; v++) {
292  double deltav = v - v0;
293  //double fr1 = 1.0 + kd * (vpMath::sqr(deltav * invpy));
294  double fr1 = 1.0 + kud_py2 * deltav * deltav;
295 
296  for (double u = 0 ; u < width ; u++) {
297  //computation of u,v : corresponding pixel coordinates in I.
298  double deltau = u - u0;
299  //double fr2 = fr1 + kd * (vpMath::sqr(deltau * invpx));
300  double fr2 = fr1 + kud_px2 * deltau * deltau;
301 
302  double u_double = deltau * fr2 + u0;
303  double v_double = deltav * fr2 + v0;
304 
305  //computation of the bilinear interpolation
306 
307  //declarations
308  int u_round = (int) (u_double);
309  int v_round = (int) (v_double);
310  if (u_round < 0.f) u_round = -1;
311  if (v_round < 0.f) v_round = -1;
312  double du_double = (u_double) - (double) u_round;
313  double dv_double = (v_double) - (double) v_round;
314  Type v01;
315  Type v23;
316  if ( (0 <= u_round) && (0 <= v_round) &&
317  (u_round < ((width) - 1)) && (v_round < ((height) - 1)) ) {
318  //process interpolation
319  const Type* _mp = &src[v_round*width+u_round];
320  v01 = (Type)(_mp[0] + ((_mp[1] - _mp[0]) * du_double));
321  _mp += width;
322  v23 = (Type)(_mp[0] + ((_mp[1] - _mp[0]) * du_double));
323  *dst = (Type)(v01 + ((v23 - v01) * dv_double));
324  }
325  else {
326  *dst = 0;
327  }
328  dst++;
329  }
330  }
331 
332  pthread_exit((void*) 0);
333  return NULL;
334 }
335 #endif // DOXYGEN_SHOULD_SKIP_THIS
336 #endif // VISP_HAVE_PTHREAD
337 
357 template<class Type>
359  const vpCameraParameters &cam,
360  vpImage<Type> &undistI)
361 {
362 #ifdef VISP_HAVE_PTHREAD
363  //
364  // Optimized version using pthreads
365  //
366  unsigned int width = I.getWidth();
367  unsigned int height = I.getHeight();
368 
369  undistI.resize(height, width);
370 
371  double kud = cam.get_kud();
372 
373  //if (kud == 0) {
374  if (std::fabs(kud) <= std::numeric_limits<double>::epsilon()) {
375  // There is no need to undistort the image
376  undistI = I;
377  return;
378  }
379 
380  unsigned int nthreads = 2;
381  pthread_attr_t attr;
382  pthread_t *callThd = new pthread_t [nthreads];
383  pthread_attr_init(&attr);
384  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
385 
386  vpUndistortInternalType<Type> *undistortSharedData;
387  undistortSharedData = new vpUndistortInternalType<Type> [nthreads];
388 
389  for(unsigned int i=0;i<nthreads;i++) {
390  // Each thread works on a different set of data.
391  // vpTRACE("create thread %d", i);
392  undistortSharedData[i].src = I.bitmap;
393  undistortSharedData[i].dst = undistI.bitmap;
394  undistortSharedData[i].width = I.getWidth();
395  undistortSharedData[i].height = I.getHeight();
396  undistortSharedData[i].cam = cam;
397  undistortSharedData[i].nthreads = nthreads;
398  undistortSharedData[i].threadid = i;
399  pthread_create( &callThd[i], &attr,
400  &vpUndistortInternalType<Type>::vpUndistort_threaded,
401  &undistortSharedData[i]);
402  }
403  pthread_attr_destroy(&attr);
404  /* Wait on the other threads */
405 
406  for(unsigned int i=0;i<nthreads;i++) {
407  // vpTRACE("join thread %d", i);
408  pthread_join( callThd[i], NULL);
409  }
410 
411  delete [] callThd;
412  delete [] undistortSharedData;
413 #else // VISP_HAVE_PTHREAD
414  //
415  // optimized version without pthreads
416  //
417  unsigned int width = I.getWidth();
418  unsigned int height = I.getHeight();
419 
420  undistI.resize(height, width);
421 
422  double u0 = cam.get_u0();
423  double v0 = cam.get_v0();
424  double px = cam.get_px();
425  double py = cam.get_py();
426  double kud = cam.get_kud();
427 
428  //if (kud == 0) {
429  if (std::fabs(kud) <= std::numeric_limits<double>::epsilon()) {
430  // There is no need to undistort the image
431  undistI = I;
432  return;
433  }
434 
435  double invpx = 1.0/px;
436  double invpy = 1.0/py;
437 
438  double kud_px2 = kud * invpx * invpx;
439  double kud_py2 = kud * invpy * invpy;
440 
441  Type *dst = undistI.bitmap;
442  for (double v = 0;v < height ; v++) {
443  double deltav = v - v0;
444  //double fr1 = 1.0 + kd * (vpMath::sqr(deltav * invpy));
445  double fr1 = 1.0 + kud_py2 * deltav * deltav;
446 
447  for (double u = 0 ; u < width ; u++) {
448  //computation of u,v : corresponding pixel coordinates in I.
449  double deltau = u - u0;
450  //double fr2 = fr1 + kd * (vpMath::sqr(deltau * invpx));
451  double fr2 = fr1 + kud_px2 * deltau * deltau;
452 
453  double u_double = deltau * fr2 + u0;
454  double v_double = deltav * fr2 + v0;
455 
456  //printf("[%g][%g] %g %g : ", u, v, u_double, v_double );
457 
458  //computation of the bilinear interpolation
459 
460  //declarations
461  int u_round = (int) (u_double);
462  int v_round = (int) (v_double);
463  if (u_round < 0.f) u_round = -1;
464  if (v_round < 0.f) v_round = -1;
465  double du_double = (u_double) - (double) u_round;
466  double dv_double = (v_double) - (double) v_round;
467  Type v01;
468  Type v23;
469  if ( (0 <= u_round) && (0 <= v_round) &&
470  (u_round < (((int)width) - 1)) && (v_round < (((int)height) - 1)) ) {
471  //process interpolation
472  const Type* _mp = &I[(unsigned int)v_round][(unsigned int)u_round];
473  v01 = (Type)(_mp[0] + ((_mp[1] - _mp[0]) * du_double));
474  _mp += width;
475  v23 = (Type)(_mp[0] + ((_mp[1] - _mp[0]) * du_double));
476  *dst = (Type)(v01 + ((v23 - v01) * dv_double));
477  //printf("R %d G %d B %d\n", dst->R, dst->G, dst->B);
478  }
479  else {
480  *dst = 0;
481  }
482  dst++;
483  }
484  }
485 #endif // VISP_HAVE_PTHREAD
486 
487 
488 
489 
490 #if 0
491  // non optimized version
492  int width = I.getWidth();
493  int height = I.getHeight();
494 
495  undistI.resize(height,width);
496 
497  double u0 = cam.get_u0();
498  double v0 = cam.get_v0();
499  double px = cam.get_px();
500  double py = cam.get_py();
501  double kd = cam.get_kud();
502 
503  if (kd == 0) {
504  // There is no need to undistort the image
505  undistI = I;
506  return;
507  }
508 
509  for(int v = 0 ; v < height; v++){
510  for(int u = 0; u < height; u++){
511  double r2 = vpMath::sqr(((double)u - u0)/px) +
512  vpMath::sqr(((double)v-v0)/py);
513  double u_double = ((double)u - u0)*(1.0+kd*r2) + u0;
514  double v_double = ((double)v - v0)*(1.0+kd*r2) + v0;
515  undistI[v][u] = I.getPixelBI((float)u_double,(float)v_double);
516  }
517  }
518 #endif
519 }
520 
528 template<class Type>
530  vpImage<Type> &newI)
531 {
532  unsigned int height = 0, width = 0;
533  int i = 0;
534 
535  height = I.getHeight();
536  width = I.getWidth();
537  newI.resize(height, width);
538 
539  for ( i = 0; i < height; i++)
540  {
541  memcpy(newI.bitmap+i*width, I.bitmap+(height-1-i)*width,
542  width*sizeof(Type));
543  }
544 }
545 
546 
552 template<class Type>
554 {
555  unsigned int height = 0, width = 0;
556  unsigned int i = 0;
557  vpImage<Type> Ibuf;
558 
559  height = I.getHeight();
560  width = I.getWidth();
561  Ibuf.resize(1, width);
562 
563  for ( i = 0; i < height/2; i++)
564  {
565  memcpy(Ibuf.bitmap, I.bitmap+i*width,
566  width*sizeof(Type));
567 
568  memcpy(I.bitmap+i*width, I.bitmap+(height-1-i)*width,
569  width*sizeof(Type));
570  memcpy(I.bitmap+(height-1-i)*width, Ibuf.bitmap,
571  width*sizeof(Type));
572  }
573 }
574 
575 #endif
576 
577 
578 /*
579  * Local variables:
580  * c-basic-offset: 2
581  * End:
582  */
double getTop() const
Definition: vpRect.h:169
double get_u0() const
unsigned int getWidth() const
Definition: vpImage.h:159
Type * bitmap
points toward the bitmap
Definition: vpImage.h:120
void resize(const unsigned int height, const unsigned int width)
set the size of the image
Definition: vpImage.h:535
double get_py() const
double getRight() const
Definition: vpRect.h:162
double getBottom() const
Definition: vpRect.h:98
double get_v0() const
static void binarise(vpImage< Type > &I, Type threshold1, Type threshold2, Type value1, Type value2, Type value3)
Definition: vpImageTools.h:221
static double sqr(double x)
Definition: vpMath.h:106
Generic class defining intrinsic camera parameters.
static void undistort(const vpImage< Type > &I, const vpCameraParameters &cam, vpImage< Type > &newI)
Definition: vpImageTools.h:358
static void flip(const vpImage< Type > &I, vpImage< Type > &newI)
Definition: vpImageTools.h:529
double get_px() const
double get_kud() const
Various image tools; sub-image extraction, modification of the look up table, binarisation...
Definition: vpImageTools.h:79
static void createSubImage(const vpImage< Type > &I, unsigned int i_sub, unsigned int j_sub, unsigned int nrow_sub, unsigned int ncol_sub, vpImage< Type > &S)
Definition: vpImageTools.h:133
unsigned int getHeight() const
Definition: vpImage.h:150
Defines a rectangle in the plane.
Definition: vpRect.h:82
double getLeft() const
Definition: vpRect.h:156
Definition of the vpImage class member functions.
Definition: vpImage.h:115