ViSP  2.6.2
vpImageTools.h
1 /****************************************************************************
2  *
3  * $Id: vpImageTools.h 3578 2012-03-01 09:59:24Z fspindle $
4  *
5  * This file is part of the ViSP software.
6  * Copyright (C) 2005 - 2012 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(vpImage<unsigned char> &I1,
117  vpImage<unsigned char> &Idiff) ;
118 } ;
119 
128 template<class Type>
130  unsigned int i_sub, unsigned int j_sub,
131  unsigned int nrow_sub, unsigned int ncol_sub,
132  vpImage<Type> &S)
133 {
134  unsigned int i,j ;
135  unsigned int imax = i_sub + nrow_sub ;
136  unsigned int jmax = j_sub + ncol_sub ;
137 
138  if (imax > I.getHeight())
139  {
140  imax = I.getHeight() -1 ;
141  nrow_sub = imax-i_sub ;
142  }
143  if (jmax > I.getWidth())
144  {
145  jmax = I.getWidth() -1 ;
146  ncol_sub = jmax -j_sub ;
147  }
148 
149  S.resize(nrow_sub, ncol_sub) ;
150  for (i=i_sub ; i < imax ; i++)
151  for (j=j_sub ; j < jmax ; j++)
152  {
153  S[i-i_sub][j-j_sub] = I[i][j] ;
154  }
155 }
166 template<class Type>
168  const vpRect &rect,
169  vpImage<Type> &S)
170 {
171  double dleft = rect.getLeft();
172  double dtop = rect.getTop();
173  double dright = ceil( rect.getRight() );
174  double dbottom = ceil( rect.getBottom() );
175 
176  if (dleft < 0.0) dleft = 0.0;
177  else if (dleft >= I.getWidth()) dleft = I.getWidth() - 1;
178 
179  if (dright < 0.0) dright = 0.0;
180  else if (dright >= I.getWidth()) dright = I.getWidth() - 1;
181 
182  if (dtop < 0.0) dtop = 0.0;
183  else if (dtop >= I.getHeight()) dtop = I.getHeight() - 1;
184 
185  if (dbottom < 0.0) dbottom = 0.0;
186  else if (dbottom >= I.getHeight()) dbottom = I.getHeight() - 1;
187 
188  // Convert the double-precision rectangle coordinates into integer positions
189  unsigned int left = (unsigned int) dleft;
190  unsigned int top = (unsigned int) dtop;
191  unsigned int bottom = (unsigned int) dbottom;
192  unsigned int right = (unsigned int) dright;
193 
194  unsigned int width = right - left + 1;;
195  unsigned int height = bottom - top + 1;
196 
197  S.resize(height, width) ;
198  for (unsigned int i=top ; i <= bottom ; i++) {
199  for (unsigned int j=left ; j <= right ; j++) {
200  S[i-top][j-left] = I[i][j] ;
201  }
202  }
203 }
216 template<class Type>
218  Type threshold1, Type threshold2,
219  Type value1, Type value2, Type value3)
220 {
221  unsigned char v;
222  unsigned char *p = I.bitmap;
223  unsigned char *pend = I.bitmap + I.getWidth()*I.getHeight();
224  for (; p < pend; p ++) {
225  v = *p;
226  if (v < threshold1) *p = value1;
227  else if (v > threshold2) *p = value3;
228  else *p = value2;
229  }
230 
231 }
232 
233 #ifdef VISP_HAVE_PTHREAD
234 
235 #ifndef DOXYGEN_SHOULD_SKIP_THIS
236 template<class Type>
237 class vpUndistortInternalType
238 {
239 public:
240  Type *src;
241  Type *dst;
242  unsigned int width;
243  unsigned int height;
244  vpCameraParameters cam;
245  unsigned int nthreads;
246  unsigned int threadid;
247 public:
248  vpUndistortInternalType() {};
249  vpUndistortInternalType(const vpUndistortInternalType<Type> &u) {
250  src = u.src;
251  dst = u.dst;
252  width = u.width;
253  height = u.height;
254  cam = u.cam;
255  nthreads = u.nthreads;
256  threadid = u.threadid;
257  };
258 
259  static void *vpUndistort_threaded(void *arg);
260 };
261 
262 
263 template<class Type>
264 void *vpUndistortInternalType<Type>::vpUndistort_threaded(void *arg)
265 {
266  vpUndistortInternalType<Type> *undistortSharedData = (vpUndistortInternalType<Type>*)arg;
267  int offset = (int)undistortSharedData->threadid;
268  int width = (int)undistortSharedData->width;
269  int height = (int)undistortSharedData->height;
270  int nthreads = (int)undistortSharedData->nthreads;
271 
272  double u0 = undistortSharedData->cam.get_u0();
273  double v0 = undistortSharedData->cam.get_v0();
274  double px = undistortSharedData->cam.get_px();
275  double py = undistortSharedData->cam.get_py();
276  double kud = undistortSharedData->cam.get_kud();
277 
278  double invpx = 1.0/px;
279  double invpy = 1.0/py;
280 
281  double kud_px2 = kud * invpx * invpx;
282  double kud_py2 = kud * invpy * invpy;
283 
284  Type *dst = undistortSharedData->dst+(height/nthreads*offset)*width;
285  Type *src = undistortSharedData->src;
286 
287  for (double v = height/nthreads*offset;v < height/nthreads*(offset+1) ; v++) {
288  double deltav = v - v0;
289  //double fr1 = 1.0 + kd * (vpMath::sqr(deltav * invpy));
290  double fr1 = 1.0 + kud_py2 * deltav * deltav;
291 
292  for (double u = 0 ; u < width ; u++) {
293  //computation of u,v : corresponding pixel coordinates in I.
294  double deltau = u - u0;
295  //double fr2 = fr1 + kd * (vpMath::sqr(deltau * invpx));
296  double fr2 = fr1 + kud_px2 * deltau * deltau;
297 
298  double u_double = deltau * fr2 + u0;
299  double v_double = deltav * fr2 + v0;
300 
301  //computation of the bilinear interpolation
302 
303  //declarations
304  int u_round = (int) (u_double);
305  int v_round = (int) (v_double);
306  if (u_round < 0.f) u_round = -1;
307  if (v_round < 0.f) v_round = -1;
308  double du_double = (u_double) - (double) u_round;
309  double dv_double = (v_double) - (double) v_round;
310  Type v01;
311  Type v23;
312  if ( (0 <= u_round) && (0 <= v_round) &&
313  (u_round < ((width) - 1)) && (v_round < ((height) - 1)) ) {
314  //process interpolation
315  const Type* _mp = &src[v_round*width+u_round];
316  v01 = (Type)(_mp[0] + ((_mp[1] - _mp[0]) * du_double));
317  _mp += width;
318  v23 = (Type)(_mp[0] + ((_mp[1] - _mp[0]) * du_double));
319  *dst = (Type)(v01 + ((v23 - v01) * dv_double));
320  }
321  else {
322  *dst = 0;
323  }
324  dst++;
325  }
326  }
327 
328  pthread_exit((void*) 0);
329  return NULL;
330 }
331 #endif // DOXYGEN_SHOULD_SKIP_THIS
332 #endif // VISP_HAVE_PTHREAD
333 
353 template<class Type>
355  const vpCameraParameters &cam,
356  vpImage<Type> &undistI)
357 {
358 #ifdef VISP_HAVE_PTHREAD
359  //
360  // Optimized version using pthreads
361  //
362  unsigned int width = I.getWidth();
363  unsigned int height = I.getHeight();
364 
365  undistI.resize(height, width);
366 
367  double kud = cam.get_kud();
368 
369  //if (kud == 0) {
370  if (std::fabs(kud) <= std::numeric_limits<double>::epsilon()) {
371  // There is no need to undistort the image
372  undistI = I;
373  return;
374  }
375 
376  unsigned int nthreads = 2;
377  pthread_attr_t attr;
378  pthread_t *callThd = new pthread_t [nthreads];
379  pthread_attr_init(&attr);
380  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
381 
382  vpUndistortInternalType<Type> *undistortSharedData;
383  undistortSharedData = new vpUndistortInternalType<Type> [nthreads];
384 
385  for(unsigned int i=0;i<nthreads;i++) {
386  // Each thread works on a different set of data.
387  // vpTRACE("create thread %d", i);
388  undistortSharedData[i].src = I.bitmap;
389  undistortSharedData[i].dst = undistI.bitmap;
390  undistortSharedData[i].width = I.getWidth();
391  undistortSharedData[i].height = I.getHeight();
392  undistortSharedData[i].cam = cam;
393  undistortSharedData[i].nthreads = nthreads;
394  undistortSharedData[i].threadid = i;
395  pthread_create( &callThd[i], &attr,
396  &vpUndistortInternalType<Type>::vpUndistort_threaded,
397  &undistortSharedData[i]);
398  }
399  pthread_attr_destroy(&attr);
400  /* Wait on the other threads */
401 
402  for(unsigned int i=0;i<nthreads;i++) {
403  // vpTRACE("join thread %d", i);
404  pthread_join( callThd[i], NULL);
405  }
406 
407  delete [] callThd;
408  delete [] undistortSharedData;
409 #else // VISP_HAVE_PTHREAD
410  //
411  // optimized version without pthreads
412  //
413  unsigned int width = I.getWidth();
414  unsigned int height = I.getHeight();
415 
416  undistI.resize(height, width);
417 
418  double u0 = cam.get_u0();
419  double v0 = cam.get_v0();
420  double px = cam.get_px();
421  double py = cam.get_py();
422  double kud = cam.get_kud();
423 
424  //if (kud == 0) {
425  if (std::fabs(kud) <= std::numeric_limits<double>::epsilon()) {
426  // There is no need to undistort the image
427  undistI = I;
428  return;
429  }
430 
431  double invpx = 1.0/px;
432  double invpy = 1.0/py;
433 
434  double kud_px2 = kud * invpx * invpx;
435  double kud_py2 = kud * invpy * invpy;
436 
437  Type *dst = undistI.bitmap;
438  for (double v = 0;v < height ; v++) {
439  double deltav = v - v0;
440  //double fr1 = 1.0 + kd * (vpMath::sqr(deltav * invpy));
441  double fr1 = 1.0 + kud_py2 * deltav * deltav;
442 
443  for (double u = 0 ; u < width ; u++) {
444  //computation of u,v : corresponding pixel coordinates in I.
445  double deltau = u - u0;
446  //double fr2 = fr1 + kd * (vpMath::sqr(deltau * invpx));
447  double fr2 = fr1 + kud_px2 * deltau * deltau;
448 
449  double u_double = deltau * fr2 + u0;
450  double v_double = deltav * fr2 + v0;
451 
452  //printf("[%g][%g] %g %g : ", u, v, u_double, v_double );
453 
454  //computation of the bilinear interpolation
455 
456  //declarations
457  int u_round = (int) (u_double);
458  int v_round = (int) (v_double);
459  if (u_round < 0.f) u_round = -1;
460  if (v_round < 0.f) v_round = -1;
461  double du_double = (u_double) - (double) u_round;
462  double dv_double = (v_double) - (double) v_round;
463  Type v01;
464  Type v23;
465  if ( (0 <= u_round) && (0 <= v_round) &&
466  (u_round < (((int)width) - 1)) && (v_round < (((int)height) - 1)) ) {
467  //process interpolation
468  const Type* _mp = &I[(unsigned int)v_round][(unsigned int)u_round];
469  v01 = (Type)(_mp[0] + ((_mp[1] - _mp[0]) * du_double));
470  _mp += width;
471  v23 = (Type)(_mp[0] + ((_mp[1] - _mp[0]) * du_double));
472  *dst = (Type)(v01 + ((v23 - v01) * dv_double));
473  //printf("R %d G %d B %d\n", dst->R, dst->G, dst->B);
474  }
475  else {
476  *dst = 0;
477  }
478  dst++;
479  }
480  }
481 #endif // VISP_HAVE_PTHREAD
482 
483 
484 
485 
486 #if 0
487  // non optimized version
488  int width = I.getWidth();
489  int height = I.getHeight();
490 
491  undistI.resize(height,width);
492 
493  double u0 = cam.get_u0();
494  double v0 = cam.get_v0();
495  double px = cam.get_px();
496  double py = cam.get_py();
497  double kd = cam.get_kud();
498 
499  if (kd == 0) {
500  // There is no need to undistort the image
501  undistI = I;
502  return;
503  }
504 
505  for(int v = 0 ; v < height; v++){
506  for(int u = 0; u < height; u++){
507  double r2 = vpMath::sqr(((double)u - u0)/px) +
508  vpMath::sqr(((double)v-v0)/py);
509  double u_double = ((double)u - u0)*(1.0+kd*r2) + u0;
510  double v_double = ((double)v - v0)*(1.0+kd*r2) + v0;
511  undistI[v][u] = I.getPixelBI((float)u_double,(float)v_double);
512  }
513  }
514 #endif
515 }
516 
524 template<class Type>
526  vpImage<Type> &newI)
527 {
528  unsigned int height = 0, width = 0;
529  int i = 0;
530 
531  height = I.getHeight();
532  width = I.getWidth();
533  newI.resize(height, width);
534 
535  for ( i = 0; i < height; i++)
536  {
537  memcpy(newI.bitmap+i*width, I.bitmap+(height-1-i)*width,
538  width*sizeof(Type));
539  }
540 }
541 
542 
548 template<class Type>
550 {
551  unsigned int height = 0, width = 0;
552  unsigned int i = 0;
553  vpImage<Type> Ibuf;
554 
555  height = I.getHeight();
556  width = I.getWidth();
557  Ibuf.resize(1, width);
558 
559  for ( i = 0; i < height/2; i++)
560  {
561  memcpy(Ibuf.bitmap, I.bitmap+i*width,
562  width*sizeof(Type));
563 
564  memcpy(I.bitmap+i*width, I.bitmap+(height-1-i)*width,
565  width*sizeof(Type));
566  memcpy(I.bitmap+(height-1-i)*width, Ibuf.bitmap,
567  width*sizeof(Type));
568  }
569 }
570 
571 #endif
572 
573 
574 /*
575  * Local variables:
576  * c-basic-offset: 2
577  * End:
578  */
double getTop() const
Definition: vpRect.h:169
double get_u0() const
unsigned int getWidth() const
Definition: vpImage.h:154
Type * bitmap
points toward the bitmap
Definition: vpImage.h:115
void resize(const unsigned int height, const unsigned int width)
set the size of the image
Definition: vpImage.h:530
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:217
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:354
static void flip(const vpImage< Type > &I, vpImage< Type > &newI)
Definition: vpImageTools.h:525
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:129
unsigned int getHeight() const
Definition: vpImage.h:145
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:110