Visual Servoing Platform  version 3.2.1 under development (2019-07-16)
vpImageTools.h
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2019 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 #ifndef vpImageTools_H
40 #define vpImageTools_H
41 
49 #include <visp3/core/vpImage.h>
50 
51 #ifdef VISP_HAVE_PTHREAD
52 #include <pthread.h>
53 #endif
54 
55 #include <visp3/core/vpCameraParameters.h>
56 #include <visp3/core/vpImageException.h>
57 #include <visp3/core/vpMath.h>
58 #include <visp3/core/vpRect.h>
59 #include <visp3/core/vpRectOriented.h>
60 
61 #include <fstream>
62 #include <iostream>
63 #include <math.h>
64 #include <string.h>
65 
66 #if defined _OPENMP
67 #include <omp.h>
68 #endif
69 
79 class VISP_EXPORT vpImageTools
80 {
81 public:
85  INTERPOLATION_CUBIC
86  };
87 
88  template <class Type>
89  static inline void binarise(vpImage<Type> &I, Type threshold1, Type threshold2, Type value1, Type value2, Type value3,
90  const bool useLUT = true);
91  static void changeLUT(vpImage<unsigned char> &I, unsigned char A, unsigned char newA, unsigned char B,
92  unsigned char newB);
93 
94  template <class Type>
95  static void crop(const vpImage<Type> &I, double roi_top, double roi_left, unsigned int roi_height,
96  unsigned int roi_width, vpImage<Type> &crop, unsigned int v_scale = 1, unsigned int h_scale = 1);
97 
98  static void columnMean(const vpImage<double> &I, vpRowVector &result);
99 
100  template <class Type>
101  static void crop(const vpImage<Type> &I, const vpImagePoint &topLeft, unsigned int roi_height, unsigned int roi_width,
102  vpImage<Type> &crop, unsigned int v_scale = 1, unsigned int h_scale = 1);
103  template <class Type>
104  static void crop(const vpImage<Type> &I, const vpRect &roi, vpImage<Type> &crop, unsigned int v_scale = 1,
105  unsigned int h_scale = 1);
106  template <class Type>
107  static void crop(const unsigned char *bitmap, unsigned int width, unsigned int height, const vpRect &roi,
108  vpImage<Type> &crop, unsigned int v_scale = 1, unsigned int h_scale = 1);
109 
110  static void extract(const vpImage<unsigned char> &Src, vpImage<unsigned char> &Dst, const vpRectOriented &r);
111  static void extract(const vpImage<unsigned char> &Src, vpImage<double> &Dst, const vpRectOriented &r);
112 
113  template <class Type> static void flip(const vpImage<Type> &I, vpImage<Type> &newI);
114 
115  template <class Type> static void flip(vpImage<Type> &I);
116 
117  static void imageDifference(const vpImage<unsigned char> &I1, const vpImage<unsigned char> &I2,
118  vpImage<unsigned char> &Idiff);
119  static void imageDifference(const vpImage<vpRGBa> &I1, const vpImage<vpRGBa> &I2, vpImage<vpRGBa> &Idiff);
120 
121  static void imageDifferenceAbsolute(const vpImage<unsigned char> &I1, const vpImage<unsigned char> &I2,
122  vpImage<unsigned char> &Idiff);
123  static void imageDifferenceAbsolute(const vpImage<double> &I1, const vpImage<double> &I2, vpImage<double> &Idiff);
124  static void imageDifferenceAbsolute(const vpImage<vpRGBa> &I1, const vpImage<vpRGBa> &I2, vpImage<vpRGBa> &Idiff);
125 
126  static void imageAdd(const vpImage<unsigned char> &I1, const vpImage<unsigned char> &I2, vpImage<unsigned char> &Ires,
127  const bool saturate = false);
128 
129  static void imageSubtract(const vpImage<unsigned char> &I1, const vpImage<unsigned char> &I2,
130  vpImage<unsigned char> &Ires, const bool saturate = false);
131 
132  static void initUndistortMap(const vpCameraParameters &cam, unsigned int width, unsigned int height,
133  vpArray2D<int> &mapU, vpArray2D<int> &mapV,
134  vpArray2D<float> &mapDu, vpArray2D<float> &mapDv);
135 
136  static double interpolate(const vpImage<unsigned char> &I, const vpImagePoint &point,
137  const vpImageInterpolationType &method = INTERPOLATION_NEAREST);
138 
139  static void integralImage(const vpImage<unsigned char> &I, vpImage<double> &II, vpImage<double> &IIsq);
140 
141  static double normalizedCorrelation(const vpImage<double> &I1, const vpImage<double> &I2,
142  const bool useOptimized = true);
143 
144  static void normalize(vpImage<double> &I);
145 
146  static void remap(const vpImage<unsigned char> &I, const vpArray2D<int> &mapU, const vpArray2D<int> &mapV,
147  const vpArray2D<float> &mapDu, const vpArray2D<float> &mapDv, vpImage<unsigned char> &Iundist);
148  static void remap(const vpImage<vpRGBa> &I, const vpArray2D<int> &mapU, const vpArray2D<int> &mapV,
149  const vpArray2D<float> &mapDu, const vpArray2D<float> &mapDv, vpImage<vpRGBa> &Iundist);
150 
151  template <class Type>
152  static void resize(const vpImage<Type> &I, vpImage<Type> &Ires, const unsigned int width, const unsigned int height,
153  const vpImageInterpolationType &method = INTERPOLATION_NEAREST, unsigned int nThreads=0);
154 
155  template <class Type>
156  static void resize(const vpImage<Type> &I, vpImage<Type> &Ires,
157  const vpImageInterpolationType &method = INTERPOLATION_NEAREST, unsigned int nThreads=0);
158 
159  static void templateMatching(const vpImage<unsigned char> &I, const vpImage<unsigned char> &I_tpl,
160  vpImage<double> &I_score, const unsigned int step_u, const unsigned int step_v,
161  const bool useOptimized = true);
162 
163  template <class Type>
164  static void undistort(const vpImage<Type> &I, const vpCameraParameters &cam, vpImage<Type> &newI,
165  unsigned int nThreads=2);
166 
167 #if defined(VISP_BUILD_DEPRECATED_FUNCTIONS)
168 
172  template <class Type>
173  vp_deprecated static void createSubImage(const vpImage<Type> &I, unsigned int i_sub, unsigned int j_sub,
174  unsigned int nrow_sub, unsigned int ncol_sub, vpImage<Type> &S);
175 
176  template <class Type>
177  vp_deprecated static void createSubImage(const vpImage<Type> &I, const vpRect &rect, vpImage<Type> &S);
179 #endif
180 
181 private:
182  // Cubic interpolation
183  static float cubicHermite(const float A, const float B, const float C, const float D, const float t);
184 
185  template <class Type> static Type getPixelClamped(const vpImage<Type> &I, const float u, const float v);
186 
187  // Linear interpolation
188  static float lerp(const float A, const float B, const float t);
189  static int64_t lerp2(int64_t A, int64_t B, int64_t t, int64_t t_1);
190 
191  static double normalizedCorrelation(const vpImage<double> &I1, const vpImage<double> &I2, const vpImage<double> &II,
192  const vpImage<double> &IIsq, const vpImage<double> &II_tpl,
193  const vpImage<double> &IIsq_tpl, const unsigned int i0, const unsigned int j0);
194 
195  template <class Type>
196  static void resizeBicubic(const vpImage<Type> &I, vpImage<Type> &Ires, const unsigned int i, const unsigned int j,
197  const float u, const float v, const float xFrac, const float yFrac);
198 
199  template <class Type>
200  static void resizeBilinear(const vpImage<Type> &I, vpImage<Type> &Ires, const unsigned int i, const unsigned int j,
201  const float u, const float v, const float xFrac, const float yFrac);
202 
203  template <class Type>
204  static void resizeNearest(const vpImage<Type> &I, vpImage<Type> &Ires, const unsigned int i, const unsigned int j,
205  const float u, const float v);
206 };
207 
208 #if defined(VISP_BUILD_DEPRECATED_FUNCTIONS)
209 
229 template <class Type>
230 void vpImageTools::createSubImage(const vpImage<Type> &I, unsigned int roi_top, unsigned int roi_left,
231  unsigned int roi_height, unsigned int roi_width, vpImage<Type> &crop)
232 {
233  vpImageTools::crop(I, roi_top, roi_left, roi_height, roi_width, crop);
234 }
235 
251 template <class Type> void vpImageTools::createSubImage(const vpImage<Type> &I, const vpRect &roi, vpImage<Type> &crop)
252 {
253  vpImageTools::crop(I, roi, crop);
254 }
255 
256 #endif // #if defined(VISP_BUILD_DEPRECATED_FUNCTIONS)
257 
281 template <class Type>
282 void vpImageTools::crop(const vpImage<Type> &I, double roi_top, double roi_left, unsigned int roi_height,
283  unsigned int roi_width, vpImage<Type> &crop, unsigned int v_scale, unsigned int h_scale)
284 {
285  int i_min = (std::max)((int)(ceil(roi_top / v_scale)), 0);
286  int j_min = (std::max)((int)(ceil(roi_left / h_scale)), 0);
287  int i_max = (std::min)((int)(ceil((roi_top + roi_height)) / v_scale), (int)(I.getHeight() / v_scale));
288  int j_max = (std::min)((int)(ceil((roi_left + roi_width) / h_scale)), (int)(I.getWidth() / h_scale));
289 
290  unsigned int i_min_u = (unsigned int)i_min;
291  unsigned int j_min_u = (unsigned int)j_min;
292 
293  unsigned int r_width = (unsigned int)(j_max - j_min);
294  unsigned int r_height = (unsigned int)(i_max - i_min);
295 
296  crop.resize(r_height, r_width);
297 
298  if (v_scale == 1 && h_scale == 1) {
299  for (unsigned int i = 0; i < r_height; i++) {
300  void *src = (void *)(I[i + i_min_u] + j_min_u);
301  void *dst = (void *)crop[i];
302  memcpy(dst, src, r_width * sizeof(Type));
303  }
304  } else if (h_scale == 1) {
305  for (unsigned int i = 0; i < r_height; i++) {
306  void *src = (void *)(I[(i + i_min_u) * v_scale] + j_min_u);
307  void *dst = (void *)crop[i];
308  memcpy(dst, src, r_width * sizeof(Type));
309  }
310  } else {
311  for (unsigned int i = 0; i < r_height; i++) {
312  for (unsigned int j = 0; j < r_width; j++) {
313  crop[i][j] = I[(i + i_min_u) * v_scale][(j + j_min_u) * h_scale];
314  }
315  }
316  }
317 }
318 
337 template <class Type>
338 void vpImageTools::crop(const vpImage<Type> &I, const vpImagePoint &topLeft, unsigned int roi_height,
339  unsigned int roi_width, vpImage<Type> &crop, unsigned int v_scale, unsigned int h_scale)
340 {
341  vpImageTools::crop(I, topLeft.get_i(), topLeft.get_j(), roi_height, roi_width, crop, v_scale, h_scale);
342 }
343 
361 template <class Type>
362 void vpImageTools::crop(const vpImage<Type> &I, const vpRect &roi, vpImage<Type> &crop, unsigned int v_scale,
363  unsigned int h_scale)
364 {
365  vpImageTools::crop(I, roi.getTop(), roi.getLeft(), (unsigned int)roi.getHeight(), (unsigned int)roi.getWidth(), crop,
366  v_scale, h_scale);
367 }
368 
386 template <class Type>
387 void vpImageTools::crop(const unsigned char *bitmap, unsigned int width, unsigned int height, const vpRect &roi,
388  vpImage<Type> &crop, unsigned int v_scale, unsigned int h_scale)
389 {
390  int i_min = (std::max)((int)(ceil(roi.getTop() / v_scale)), 0);
391  int j_min = (std::max)((int)(ceil(roi.getLeft() / h_scale)), 0);
392  int i_max = (std::min)((int)(ceil((roi.getTop() + roi.getHeight()) / v_scale)), (int)(height / v_scale));
393  int j_max = (std::min)((int)(ceil((roi.getLeft() + roi.getWidth()) / h_scale)), (int)(width / h_scale));
394 
395  unsigned int i_min_u = (unsigned int)i_min;
396  unsigned int j_min_u = (unsigned int)j_min;
397 
398  unsigned int r_width = (unsigned int)(j_max - j_min);
399  unsigned int r_height = (unsigned int)(i_max - i_min);
400 
401  crop.resize(r_height, r_width);
402 
403  if (v_scale == 1 && h_scale == 1) {
404  for (unsigned int i = 0; i < r_height; i++) {
405  void *src = (void *)(bitmap + ((i + i_min_u) * width + j_min_u) * sizeof(Type));
406  void *dst = (void *)crop[i];
407  memcpy(dst, src, r_width * sizeof(Type));
408  }
409  } else if (h_scale == 1) {
410  for (unsigned int i = 0; i < r_height; i++) {
411  void *src = (void *)(bitmap + ((i + i_min_u) * width * v_scale + j_min_u) * sizeof(Type));
412  void *dst = (void *)crop[i];
413  memcpy(dst, src, r_width * sizeof(Type));
414  }
415  } else {
416  for (unsigned int i = 0; i < r_height; i++) {
417  unsigned int i_src = (i + i_min_u) * width * v_scale + j_min_u * h_scale;
418  for (unsigned int j = 0; j < r_width; j++) {
419  void *src = (void *)(bitmap + (i_src + j * h_scale) * sizeof(Type));
420  void *dst = (void *)&crop[i][j];
421  memcpy(dst, src, sizeof(Type));
422  }
423  }
424  }
425 }
426 
439 template <class Type>
440 inline void vpImageTools::binarise(vpImage<Type> &I, Type threshold1, Type threshold2, Type value1, Type value2,
441  Type value3, const bool useLUT)
442 {
443  if (useLUT) {
444  std::cerr << "LUT not available for this type ! Will use the iteration method." << std::endl;
445  }
446 
447  Type v;
448  Type *p = I.bitmap;
449  Type *pend = I.bitmap + I.getWidth() * I.getHeight();
450  for (; p < pend; p++) {
451  v = *p;
452  if (v < threshold1)
453  *p = value1;
454  else if (v > threshold2)
455  *p = value3;
456  else
457  *p = value2;
458  }
459 }
460 
473 template <>
474 inline void vpImageTools::binarise(vpImage<unsigned char> &I, unsigned char threshold1, unsigned char threshold2,
475  unsigned char value1, unsigned char value2, unsigned char value3, const bool useLUT)
476 {
477  if (useLUT) {
478  // Construct the LUT
479  unsigned char lut[256];
480  for (unsigned int i = 0; i < 256; i++) {
481  lut[i] = i < threshold1 ? value1 : (i > threshold2 ? value3 : value2);
482  }
483 
484  I.performLut(lut);
485  } else {
486  unsigned char *p = I.bitmap;
487  unsigned char *pend = I.bitmap + I.getWidth() * I.getHeight();
488  for (; p < pend; p++) {
489  unsigned char v = *p;
490  if (v < threshold1)
491  *p = value1;
492  else if (v > threshold2)
493  *p = value3;
494  else
495  *p = value2;
496  }
497  }
498 }
499 
500 #ifdef VISP_HAVE_PTHREAD
501 
502 #ifndef DOXYGEN_SHOULD_SKIP_THIS
503 template <class Type> class vpUndistortInternalType
504 {
505 public:
506  Type *src;
507  Type *dst;
508  unsigned int width;
509  unsigned int height;
510  vpCameraParameters cam;
511  unsigned int nthreads;
512  unsigned int threadid;
513 
514 public:
515  vpUndistortInternalType() : src(NULL), dst(NULL), width(0), height(0), cam(), nthreads(0), threadid(0) {}
516 
517  vpUndistortInternalType(const vpUndistortInternalType<Type> &u) { *this = u; }
518  vpUndistortInternalType &operator=(const vpUndistortInternalType<Type> &u)
519  {
520  src = u.src;
521  dst = u.dst;
522  width = u.width;
523  height = u.height;
524  cam = u.cam;
525  nthreads = u.nthreads;
526  threadid = u.threadid;
527 
528  return *this;
529  }
530 
531  static void *vpUndistort_threaded(void *arg);
532 };
533 
534 template <class Type> void *vpUndistortInternalType<Type>::vpUndistort_threaded(void *arg)
535 {
536  vpUndistortInternalType<Type> *undistortSharedData = static_cast<vpUndistortInternalType<Type> *>(arg);
537  int offset = (int)undistortSharedData->threadid;
538  int width = (int)undistortSharedData->width;
539  int height = (int)undistortSharedData->height;
540  int nthreads = (int)undistortSharedData->nthreads;
541 
542  double u0 = undistortSharedData->cam.get_u0();
543  double v0 = undistortSharedData->cam.get_v0();
544  double px = undistortSharedData->cam.get_px();
545  double py = undistortSharedData->cam.get_py();
546  double kud = undistortSharedData->cam.get_kud();
547 
548  double invpx = 1.0 / px;
549  double invpy = 1.0 / py;
550 
551  double kud_px2 = kud * invpx * invpx;
552  double kud_py2 = kud * invpy * invpy;
553 
554  Type *dst = undistortSharedData->dst + (height / nthreads * offset) * width;
555  Type *src = undistortSharedData->src;
556 
557  for (double v = height / nthreads * offset; v < height / nthreads * (offset + 1); v++) {
558  double deltav = v - v0;
559  // double fr1 = 1.0 + kd * (vpMath::sqr(deltav * invpy));
560  double fr1 = 1.0 + kud_py2 * deltav * deltav;
561 
562  for (double u = 0; u < width; u++) {
563  // computation of u,v : corresponding pixel coordinates in I.
564  double deltau = u - u0;
565  // double fr2 = fr1 + kd * (vpMath::sqr(deltau * invpx));
566  double fr2 = fr1 + kud_px2 * deltau * deltau;
567 
568  double u_double = deltau * fr2 + u0;
569  double v_double = deltav * fr2 + v0;
570 
571  // computation of the bilinear interpolation
572 
573  // declarations
574  int u_round = (int)(u_double);
575  int v_round = (int)(v_double);
576  if (u_round < 0.f)
577  u_round = -1;
578  if (v_round < 0.f)
579  v_round = -1;
580  double du_double = (u_double) - (double)u_round;
581  double dv_double = (v_double) - (double)v_round;
582  Type v01;
583  Type v23;
584  if ((0 <= u_round) && (0 <= v_round) && (u_round < ((width)-1)) && (v_round < ((height)-1))) {
585  // process interpolation
586  const Type *_mp = &src[v_round * width + u_round];
587  v01 = (Type)(_mp[0] + ((_mp[1] - _mp[0]) * du_double));
588  _mp += width;
589  v23 = (Type)(_mp[0] + ((_mp[1] - _mp[0]) * du_double));
590  *dst = (Type)(v01 + ((v23 - v01) * dv_double));
591  } else {
592  *dst = 0;
593  }
594  dst++;
595  }
596  }
597 
598  pthread_exit((void *)0);
599  return NULL;
600 }
601 #endif // DOXYGEN_SHOULD_SKIP_THIS
602 #endif // VISP_HAVE_PTHREAD
603 
630 template <class Type>
632  unsigned int nThreads)
633 {
634 #ifdef VISP_HAVE_PTHREAD
635  //
636  // Optimized version using pthreads
637  //
638  unsigned int width = I.getWidth();
639  unsigned int height = I.getHeight();
640 
641  undistI.resize(height, width);
642 
643  double kud = cam.get_kud();
644 
645  // if (kud == 0) {
646  if (std::fabs(kud) <= std::numeric_limits<double>::epsilon()) {
647  // There is no need to undistort the image
648  undistI = I;
649  return;
650  }
651 
652  unsigned int nthreads = nThreads;
653  pthread_attr_t attr;
654  pthread_t *callThd = new pthread_t[nthreads];
655  pthread_attr_init(&attr);
656  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
657 
658  vpUndistortInternalType<Type> *undistortSharedData;
659  undistortSharedData = new vpUndistortInternalType<Type>[nthreads];
660 
661  for (unsigned int i = 0; i < nthreads; i++) {
662  // Each thread works on a different set of data.
663  // vpTRACE("create thread %d", i);
664  undistortSharedData[i].src = I.bitmap;
665  undistortSharedData[i].dst = undistI.bitmap;
666  undistortSharedData[i].width = I.getWidth();
667  undistortSharedData[i].height = I.getHeight();
668  undistortSharedData[i].cam = cam;
669  undistortSharedData[i].nthreads = nthreads;
670  undistortSharedData[i].threadid = i;
671  pthread_create(&callThd[i], &attr, &vpUndistortInternalType<Type>::vpUndistort_threaded, &undistortSharedData[i]);
672  }
673  pthread_attr_destroy(&attr);
674  /* Wait on the other threads */
675 
676  for (unsigned int i = 0; i < nthreads; i++) {
677  // vpTRACE("join thread %d", i);
678  pthread_join(callThd[i], NULL);
679  }
680 
681  delete[] callThd;
682  delete[] undistortSharedData;
683 #else // VISP_HAVE_PTHREAD
684  (void)nThreads;
685  //
686  // optimized version without pthreads
687  //
688  unsigned int width = I.getWidth();
689  unsigned int height = I.getHeight();
690 
691  undistI.resize(height, width);
692 
693  double u0 = cam.get_u0();
694  double v0 = cam.get_v0();
695  double px = cam.get_px();
696  double py = cam.get_py();
697  double kud = cam.get_kud();
698 
699  // if (kud == 0) {
700  if (std::fabs(kud) <= std::numeric_limits<double>::epsilon()) {
701  // There is no need to undistort the image
702  undistI = I;
703  return;
704  }
705 
706  double invpx = 1.0 / px;
707  double invpy = 1.0 / py;
708 
709  double kud_px2 = kud * invpx * invpx;
710  double kud_py2 = kud * invpy * invpy;
711 
712  Type *dst = undistI.bitmap;
713  for (double v = 0; v < height; v++) {
714  double deltav = v - v0;
715  // double fr1 = 1.0 + kd * (vpMath::sqr(deltav * invpy));
716  double fr1 = 1.0 + kud_py2 * deltav * deltav;
717 
718  for (double u = 0; u < width; u++) {
719  // computation of u,v : corresponding pixel coordinates in I.
720  double deltau = u - u0;
721  // double fr2 = fr1 + kd * (vpMath::sqr(deltau * invpx));
722  double fr2 = fr1 + kud_px2 * deltau * deltau;
723 
724  double u_double = deltau * fr2 + u0;
725  double v_double = deltav * fr2 + v0;
726 
727  // printf("[%g][%g] %g %g : ", u, v, u_double, v_double );
728 
729  // computation of the bilinear interpolation
730 
731  // declarations
732  int u_round = (int)(u_double);
733  int v_round = (int)(v_double);
734  if (u_round < 0.f)
735  u_round = -1;
736  if (v_round < 0.f)
737  v_round = -1;
738  double du_double = (u_double) - (double)u_round;
739  double dv_double = (v_double) - (double)v_round;
740  Type v01;
741  Type v23;
742  if ((0 <= u_round) && (0 <= v_round) && (u_round < (((int)width) - 1)) && (v_round < (((int)height) - 1))) {
743  // process interpolation
744  const Type *_mp = &I[(unsigned int)v_round][(unsigned int)u_round];
745  v01 = (Type)(_mp[0] + ((_mp[1] - _mp[0]) * du_double));
746  _mp += width;
747  v23 = (Type)(_mp[0] + ((_mp[1] - _mp[0]) * du_double));
748  *dst = (Type)(v01 + ((v23 - v01) * dv_double));
749  // printf("R %d G %d B %d\n", dst->R, dst->G, dst->B);
750  } else {
751  *dst = 0;
752  }
753  dst++;
754  }
755  }
756 #endif // VISP_HAVE_PTHREAD
757 
758 #if 0
759  // non optimized version
760  int width = I.getWidth();
761  int height = I.getHeight();
762 
763  undistI.resize(height,width);
764 
765  double u0 = cam.get_u0();
766  double v0 = cam.get_v0();
767  double px = cam.get_px();
768  double py = cam.get_py();
769  double kd = cam.get_kud();
770 
771  if (kd == 0) {
772  // There is no need to undistort the image
773  undistI = I;
774  return;
775  }
776 
777  for(int v = 0 ; v < height; v++){
778  for(int u = 0; u < height; u++){
779  double r2 = vpMath::sqr(((double)u - u0)/px) +
780  vpMath::sqr(((double)v-v0)/py);
781  double u_double = ((double)u - u0)*(1.0+kd*r2) + u0;
782  double v_double = ((double)v - v0)*(1.0+kd*r2) + v0;
783  undistI[v][u] = I.getPixelBI((float)u_double,(float)v_double);
784  }
785  }
786 #endif
787 }
788 
796 template <class Type> void vpImageTools::flip(const vpImage<Type> &I, vpImage<Type> &newI)
797 {
798  unsigned int height = 0, width = 0;
799 
800  height = I.getHeight();
801  width = I.getWidth();
802  newI.resize(height, width);
803 
804  for (unsigned int i = 0; i < height; i++) {
805  memcpy(newI.bitmap + i * width, I.bitmap + (height - 1 - i) * width, width * sizeof(Type));
806  }
807 }
808 
840 template <class Type> void vpImageTools::flip(vpImage<Type> &I)
841 {
842  unsigned int height = 0, width = 0;
843  unsigned int i = 0;
844  vpImage<Type> Ibuf;
845 
846  height = I.getHeight();
847  width = I.getWidth();
848  Ibuf.resize(1, width);
849 
850  for (i = 0; i < height / 2; i++) {
851  memcpy(Ibuf.bitmap, I.bitmap + i * width, width * sizeof(Type));
852 
853  memcpy(I.bitmap + i * width, I.bitmap + (height - 1 - i) * width, width * sizeof(Type));
854  memcpy(I.bitmap + (height - 1 - i) * width, Ibuf.bitmap, width * sizeof(Type));
855  }
856 }
857 
858 template <class Type> Type vpImageTools::getPixelClamped(const vpImage<Type> &I, const float u, const float v)
859 {
860  unsigned int i, j;
861  if (u < 0.f)
862  j = 0;
863  else if (u > static_cast<float>(I.getWidth()) - 1.f)
864  j = I.getWidth() - 1;
865  else
866  j = static_cast<unsigned int>(u);
867 
868  if (v < 0.f)
869  i = 0;
870  else if (v > static_cast<float>(I.getHeight()) - 1.f)
871  i = I.getHeight() - 1;
872  else
873  i = static_cast<unsigned int>(v);
874 
875  return I[i][j];
876 }
877 
878 // Reference:
879 // http://blog.demofox.org/2015/08/15/resizing-images-with-bicubic-interpolation/
880 template <class Type>
881 void vpImageTools::resizeBicubic(const vpImage<Type> &I, vpImage<Type> &Ires, const unsigned int i,
882  const unsigned int j, const float u, const float v, const float xFrac,
883  const float yFrac)
884 {
885  // 1st row
886  Type p00 = getPixelClamped(I, u - 1, v - 1);
887  Type p01 = getPixelClamped(I, u + 0, v - 1);
888  Type p02 = getPixelClamped(I, u + 1, v - 1);
889  Type p03 = getPixelClamped(I, u + 2, v - 1);
890 
891  // 2nd row
892  Type p10 = getPixelClamped(I, u - 1, v + 0);
893  Type p11 = getPixelClamped(I, u + 0, v + 0);
894  Type p12 = getPixelClamped(I, u + 1, v + 0);
895  Type p13 = getPixelClamped(I, u + 2, v + 0);
896 
897  // 3rd row
898  Type p20 = getPixelClamped(I, u - 1, v + 1);
899  Type p21 = getPixelClamped(I, u + 0, v + 1);
900  Type p22 = getPixelClamped(I, u + 1, v + 1);
901  Type p23 = getPixelClamped(I, u + 2, v + 1);
902 
903  // 4th row
904  Type p30 = getPixelClamped(I, u - 1, v + 2);
905  Type p31 = getPixelClamped(I, u + 0, v + 2);
906  Type p32 = getPixelClamped(I, u + 1, v + 2);
907  Type p33 = getPixelClamped(I, u + 2, v + 2);
908 
909  float col0 = cubicHermite(p00, p01, p02, p03, xFrac);
910  float col1 = cubicHermite(p10, p11, p12, p13, xFrac);
911  float col2 = cubicHermite(p20, p21, p22, p23, xFrac);
912  float col3 = cubicHermite(p30, p31, p32, p33, xFrac);
913  float value = cubicHermite(col0, col1, col2, col3, yFrac);
914  Ires[i][j] = vpMath::saturate<Type>(value);
915 }
916 
917 template <>
918 inline void vpImageTools::resizeBicubic(const vpImage<vpRGBa> &I, vpImage<vpRGBa> &Ires, const unsigned int i,
919  const unsigned int j, const float u, const float v, const float xFrac,
920  const float yFrac)
921 {
922  // 1st row
923  vpRGBa p00 = getPixelClamped(I, u - 1, v - 1);
924  vpRGBa p01 = getPixelClamped(I, u + 0, v - 1);
925  vpRGBa p02 = getPixelClamped(I, u + 1, v - 1);
926  vpRGBa p03 = getPixelClamped(I, u + 2, v - 1);
927 
928  // 2nd row
929  vpRGBa p10 = getPixelClamped(I, u - 1, v + 0);
930  vpRGBa p11 = getPixelClamped(I, u + 0, v + 0);
931  vpRGBa p12 = getPixelClamped(I, u + 1, v + 0);
932  vpRGBa p13 = getPixelClamped(I, u + 2, v + 0);
933 
934  // 3rd row
935  vpRGBa p20 = getPixelClamped(I, u - 1, v + 1);
936  vpRGBa p21 = getPixelClamped(I, u + 0, v + 1);
937  vpRGBa p22 = getPixelClamped(I, u + 1, v + 1);
938  vpRGBa p23 = getPixelClamped(I, u + 2, v + 1);
939 
940  // 4th row
941  vpRGBa p30 = getPixelClamped(I, u - 1, v + 2);
942  vpRGBa p31 = getPixelClamped(I, u + 0, v + 2);
943  vpRGBa p32 = getPixelClamped(I, u + 1, v + 2);
944  vpRGBa p33 = getPixelClamped(I, u + 2, v + 2);
945 
946  for (int c = 0; c < 3; c++) {
947  float col0 = cubicHermite(static_cast<float>(reinterpret_cast<unsigned char *>(&p00)[c]),
948  static_cast<float>(reinterpret_cast<unsigned char *>(&p01)[c]),
949  static_cast<float>(reinterpret_cast<unsigned char *>(&p02)[c]),
950  static_cast<float>(reinterpret_cast<unsigned char *>(&p03)[c]), xFrac);
951  float col1 = cubicHermite(static_cast<float>(reinterpret_cast<unsigned char *>(&p10)[c]),
952  static_cast<float>(reinterpret_cast<unsigned char *>(&p11)[c]),
953  static_cast<float>(reinterpret_cast<unsigned char *>(&p12)[c]),
954  static_cast<float>(reinterpret_cast<unsigned char *>(&p13)[c]), xFrac);
955  float col2 = cubicHermite(static_cast<float>(reinterpret_cast<unsigned char *>(&p20)[c]),
956  static_cast<float>(reinterpret_cast<unsigned char *>(&p21)[c]),
957  static_cast<float>(reinterpret_cast<unsigned char *>(&p22)[c]),
958  static_cast<float>(reinterpret_cast<unsigned char *>(&p23)[c]), xFrac);
959  float col3 = cubicHermite(static_cast<float>(reinterpret_cast<unsigned char *>(&p30)[c]),
960  static_cast<float>(reinterpret_cast<unsigned char *>(&p31)[c]),
961  static_cast<float>(reinterpret_cast<unsigned char *>(&p32)[c]),
962  static_cast<float>(reinterpret_cast<unsigned char *>(&p33)[c]), xFrac);
963  float value = cubicHermite(col0, col1, col2, col3, yFrac);
964 
965  reinterpret_cast<unsigned char *>(&Ires[i][j])[c] = vpMath::saturate<unsigned char>(value);
966  }
967 }
968 
969 template <class Type>
970 void vpImageTools::resizeBilinear(const vpImage<Type> &I, vpImage<Type> &Ires, const unsigned int i,
971  const unsigned int j, const float u, const float v, const float xFrac,
972  const float yFrac)
973 {
974  unsigned int u0 = static_cast<unsigned int>(u);
975  unsigned int v0 = static_cast<unsigned int>(v);
976 
977  unsigned int u1 = (std::min)(I.getWidth() - 1, static_cast<unsigned int>(u) + 1);
978  unsigned int v1 = v0;
979 
980  unsigned int u2 = u0;
981  unsigned int v2 = (std::min)(I.getHeight() - 1, static_cast<unsigned int>(v) + 1);
982 
983  unsigned int u3 = u1;
984  unsigned int v3 = v2;
985 
986  float col0 = lerp(I[v0][u0], I[v1][u1], xFrac);
987  float col1 = lerp(I[v2][u2], I[v3][u3], xFrac);
988  float value = lerp(col0, col1, yFrac);
989 
990  Ires[i][j] = vpMath::saturate<Type>(value);
991 }
992 
993 template <>
994 inline void vpImageTools::resizeBilinear(const vpImage<vpRGBa> &I, vpImage<vpRGBa> &Ires, const unsigned int i,
995  const unsigned int j, const float u, const float v, const float xFrac,
996  const float yFrac)
997 {
998  unsigned int u0 = static_cast<unsigned int>(u);
999  unsigned int v0 = static_cast<unsigned int>(v);
1000 
1001  unsigned int u1 = (std::min)(I.getWidth() - 1, static_cast<unsigned int>(u) + 1);
1002  unsigned int v1 = v0;
1003 
1004  unsigned int u2 = u0;
1005  unsigned int v2 = (std::min)(I.getHeight() - 1, static_cast<unsigned int>(v) + 1);
1006 
1007  unsigned int u3 = (std::min)(I.getWidth() - 1, static_cast<unsigned int>(u) + 1);
1008  unsigned int v3 = (std::min)(I.getHeight() - 1, static_cast<unsigned int>(v) + 1);
1009 
1010  for (int c = 0; c < 3; c++) {
1011  float col0 = lerp(static_cast<float>(reinterpret_cast<const unsigned char *>(&I[v0][u0])[c]),
1012  static_cast<float>(reinterpret_cast<const unsigned char *>(&I[v1][u1])[c]), xFrac);
1013  float col1 = lerp(static_cast<float>(reinterpret_cast<const unsigned char *>(&I[v2][u2])[c]),
1014  static_cast<float>(reinterpret_cast<const unsigned char *>(&I[v3][u3])[c]), xFrac);
1015  float value = lerp(col0, col1, yFrac);
1016 
1017  reinterpret_cast<unsigned char *>(&Ires[i][j])[c] = vpMath::saturate<unsigned char>(value);
1018  }
1019 }
1020 
1021 template <class Type>
1022 void vpImageTools::resizeNearest(const vpImage<Type> &I, vpImage<Type> &Ires, const unsigned int i,
1023  const unsigned int j, const float u, const float v)
1024 {
1025  Ires[i][j] = getPixelClamped(I, u, v);
1026 }
1027 
1041 template <class Type>
1042 void vpImageTools::resize(const vpImage<Type> &I, vpImage<Type> &Ires, const unsigned int width,
1043  const unsigned int height, const vpImageInterpolationType &method,
1044  unsigned int nThreads)
1045 {
1046  Ires.resize(height, width);
1047 
1048  vpImageTools::resize(I, Ires, method, nThreads);
1049 }
1050 
1063 template <class Type>
1065  unsigned int
1066  #if defined _OPENMP
1067  nThreads
1068  #endif
1069  )
1070 {
1071  if (I.getWidth() < 2 || I.getHeight() < 2 || Ires.getWidth() < 2 || Ires.getHeight() < 2) {
1072  std::cerr << "Input or output image is too small!" << std::endl;
1073  return;
1074  }
1075 
1076  float scaleY = (I.getHeight() - 1) / static_cast<float>(Ires.getHeight() - 1);
1077  float scaleX = (I.getWidth() - 1) / static_cast<float>(Ires.getWidth() - 1);
1078 
1079  if (method == INTERPOLATION_NEAREST) {
1080  scaleY = I.getHeight() / static_cast<float>(Ires.getHeight() - 1);
1081  scaleX = I.getWidth() / static_cast<float>(Ires.getWidth() - 1);
1082  }
1083 
1084 #if defined _OPENMP
1085  if (nThreads > 0) {
1086  omp_set_num_threads(static_cast<int>(nThreads));
1087  }
1088  #pragma omp parallel for schedule(dynamic)
1089 #endif
1090  for (int i = 0; i < static_cast<int>(Ires.getHeight()); i++) {
1091  float v = i * scaleY;
1092  float yFrac = v - static_cast<int>(v);
1093 
1094  for (unsigned int j = 0; j < Ires.getWidth(); j++) {
1095  float u = j * scaleX;
1096  float xFrac = u - static_cast<int>(u);
1097 
1098  if (method == INTERPOLATION_NEAREST) {
1099  resizeNearest(I, Ires, static_cast<unsigned int>(i), j, u, v);
1100  } else if (method == INTERPOLATION_LINEAR) {
1101  resizeBilinear(I, Ires, static_cast<unsigned int>(i), j, u, v, xFrac, yFrac);
1102  } else if (method == INTERPOLATION_CUBIC) {
1103  resizeBicubic(I, Ires, static_cast<unsigned int>(i), j, u, v, xFrac, yFrac);
1104  }
1105  }
1106  }
1107 }
1108 
1109 template <> inline
1111  const vpImageInterpolationType &method, unsigned int
1112  #if defined _OPENMP
1113  nThreads
1114  #endif
1115  )
1116 {
1117  if (I.getWidth() < 2 || I.getHeight() < 2 || Ires.getWidth() < 2 || Ires.getHeight() < 2) {
1118  std::cerr << "Input or output image is too small!" << std::endl;
1119  return;
1120  }
1121 
1122  if (method == INTERPOLATION_NEAREST || method == INTERPOLATION_CUBIC) {
1123  float scaleY = (I.getHeight() - 1) / static_cast<float>(Ires.getHeight() - 1);
1124  float scaleX = (I.getWidth() - 1) / static_cast<float>(Ires.getWidth() - 1);
1125 
1126  if (method == INTERPOLATION_NEAREST) {
1127  scaleY = I.getHeight() / static_cast<float>(Ires.getHeight() - 1);
1128  scaleX = I.getWidth() / static_cast<float>(Ires.getWidth() - 1);
1129  }
1130 
1131  #if defined _OPENMP
1132  if (nThreads > 0) {
1133  omp_set_num_threads(static_cast<int>(nThreads));
1134  }
1135  #pragma omp parallel for schedule(dynamic)
1136  #endif
1137  for (int i = 0; i < static_cast<int>(Ires.getHeight()); i++) {
1138  float v = i * scaleY;
1139  float yFrac = v - static_cast<int>(v);
1140 
1141  for (unsigned int j = 0; j < Ires.getWidth(); j++) {
1142  float u = j * scaleX;
1143  float xFrac = u - static_cast<int>(u);
1144 
1145  if (method == INTERPOLATION_NEAREST) {
1146  resizeNearest(I, Ires, static_cast<unsigned int>(i), j, u, v);
1147  } else if (method == INTERPOLATION_CUBIC) {
1148  resizeBicubic(I, Ires, static_cast<unsigned int>(i), j, u, v, xFrac, yFrac);
1149  }
1150  }
1151  }
1152  } else if (method == INTERPOLATION_LINEAR) {
1153  const int precision = 1 << 16;
1154  int64_t scaleY = static_cast<int64_t>((I.getHeight() - 1) / static_cast<float>(Ires.getHeight() - 1) * precision);
1155  int64_t scaleX = static_cast<int64_t>((I.getWidth() - 1) / static_cast<float>(Ires.getWidth() - 1) * precision);
1156 
1157 #if defined _OPENMP
1158  if (nThreads > 0) {
1159  omp_set_num_threads(static_cast<int>(nThreads));
1160  }
1161 #pragma omp parallel for schedule(dynamic)
1162 #endif
1163  for (int i = 0; i < static_cast<int>(Ires.getHeight()); i++) {
1164  int64_t v = i * scaleY;
1165  int64_t vround = v & (~0xFFFF);
1166  int64_t rratio = v - vround;
1167  int64_t y_ = v >> 16;
1168  int64_t rfrac = precision - rratio;
1169 
1170  for (unsigned int j = 0; j < Ires.getWidth(); j++) {
1171  int64_t u = j * scaleX;
1172  int64_t uround = u & (~0xFFFF);
1173  int64_t cratio = u - uround;
1174  int64_t x_ = u >> 16;
1175  int64_t cfrac = precision - cratio;
1176 
1177  if (y_ + 1 < static_cast<int64_t>(I.getHeight()) && x_ + 1 < static_cast<int64_t>(I.getWidth())) {
1178  int64_t up = *reinterpret_cast<uint16_t *>(I.bitmap + y_ * I.getWidth() + x_);
1179  int64_t down = *reinterpret_cast<uint16_t *>(I.bitmap + (y_ + 1) * I.getWidth() + x_);
1180 
1181  Ires[i][j] = static_cast<unsigned char>((((up & 0x00FF) * rfrac + (down & 0x00FF) * rratio) * cfrac +
1182  ((up >> 8) * rfrac + (down >> 8) * rratio) * cratio) >> 32);
1183  } else if (y_ + 1 < static_cast<int64_t>(I.getHeight())) {
1184  Ires[i][j] = static_cast<unsigned char>(((*(I.bitmap + y_ * I.getWidth() + x_)
1185  * rfrac + *(I.bitmap + (y_ + 1) * I.getWidth() + x_) * rratio)) >> 16);
1186  } else if (x_ + 1 < static_cast<int64_t>(I.getWidth())) {
1187  uint16_t up = *reinterpret_cast<uint16_t *>(I.bitmap + y_ * I.getWidth() + x_);
1188  Ires[i][j] = static_cast<unsigned char>(((up & 0x00FF) * cfrac + (up >> 8) * cratio) >> 16);
1189  } else {
1190  Ires[i][j] = *(I.bitmap + y_ * I.getWidth() + x_);
1191  }
1192  }
1193  }
1194  }
1195 }
1196 
1197 template <> inline
1199  const vpImageInterpolationType &method, unsigned int
1200  #if defined _OPENMP
1201  nThreads
1202  #endif
1203  )
1204 {
1205  if (I.getWidth() < 2 || I.getHeight() < 2 || Ires.getWidth() < 2 || Ires.getHeight() < 2) {
1206  std::cerr << "Input or output image is too small!" << std::endl;
1207  return;
1208  }
1209 
1210  if (method == INTERPOLATION_NEAREST || method == INTERPOLATION_CUBIC) {
1211  float scaleY = (I.getHeight() - 1) / static_cast<float>(Ires.getHeight() - 1);
1212  float scaleX = (I.getWidth() - 1) / static_cast<float>(Ires.getWidth() - 1);
1213 
1214  if (method == INTERPOLATION_NEAREST) {
1215  scaleY = I.getHeight() / static_cast<float>(Ires.getHeight() - 1);
1216  scaleX = I.getWidth() / static_cast<float>(Ires.getWidth() - 1);
1217  }
1218 
1219  #if defined _OPENMP
1220  if (nThreads > 0) {
1221  omp_set_num_threads(static_cast<int>(nThreads));
1222  }
1223  #pragma omp parallel for schedule(dynamic)
1224  #endif
1225  for (int i = 0; i < static_cast<int>(Ires.getHeight()); i++) {
1226  float v = i * scaleY;
1227  float yFrac = v - static_cast<int>(v);
1228 
1229  for (unsigned int j = 0; j < Ires.getWidth(); j++) {
1230  float u = j * scaleX;
1231  float xFrac = u - static_cast<int>(u);
1232 
1233  if (method == INTERPOLATION_NEAREST) {
1234  resizeNearest(I, Ires, static_cast<unsigned int>(i), j, u, v);
1235  } else if (method == INTERPOLATION_CUBIC) {
1236  resizeBicubic(I, Ires, static_cast<unsigned int>(i), j, u, v, xFrac, yFrac);
1237  }
1238  }
1239  }
1240  } else {
1241  const int precision = 1 << 16;
1242  int64_t scaleY = static_cast<int64_t>((I.getHeight() - 1) / static_cast<float>(Ires.getHeight() - 1) * precision);
1243  int64_t scaleX = static_cast<int64_t>((I.getWidth() - 1) / static_cast<float>(Ires.getWidth() - 1) * precision);
1244 
1245 #if defined _OPENMP
1246  if (nThreads > 0) {
1247  omp_set_num_threads(static_cast<int>(nThreads));
1248  }
1249 #pragma omp parallel for schedule(dynamic)
1250 #endif
1251  for (int i = 0; i < static_cast<int>(Ires.getHeight()); i++) {
1252  int64_t v = i * scaleY;
1253  int64_t vround = v & (~0xFFFF);
1254  int64_t rratio = v - vround;
1255  int64_t y_ = v >> 16;
1256  int64_t rfrac = precision - rratio;
1257 
1258  for (unsigned int j = 0; j < Ires.getWidth(); j++) {
1259  int64_t u = j * scaleX;
1260  int64_t uround = u & (~0xFFFF);
1261  int64_t cratio = u - uround;
1262  int64_t x_ = u >> 16;
1263  int64_t cfrac = precision - cratio;
1264 
1265  if (y_ + 1 < static_cast<int64_t>(I.getHeight()) && x_ + 1 < static_cast<int64_t>(I.getWidth())) {
1266  int64_t col0 = lerp2((I.bitmap + y_ * I.getWidth() + x_)->R, (I.bitmap + (y_ + 1) * I.getWidth() + x_)->R, rratio, rfrac);
1267  int64_t col1 = lerp2((I.bitmap + y_ * I.getWidth() + x_ + 1)->R, (I.bitmap + (y_ + 1) * I.getWidth() + x_ + 1)->R, rratio, rfrac);
1268  int64_t valueR = lerp2(col0, col1, cratio, cfrac);
1269 
1270  col0 = lerp2((I.bitmap + y_ * I.getWidth() + x_)->G, (I.bitmap + (y_ + 1) * I.getWidth() + x_)->G, rratio, rfrac);
1271  col1 = lerp2((I.bitmap + y_ * I.getWidth() + x_ + 1)->G, (I.bitmap + (y_ + 1) * I.getWidth() + x_ + 1)->G, rratio, rfrac);
1272  int64_t valueG = lerp2(col0, col1, cratio, cfrac);
1273 
1274  col0 = lerp2((I.bitmap + y_ * I.getWidth() + x_)->B, (I.bitmap + (y_ + 1) * I.getWidth() + x_)->B, rratio, rfrac);
1275  col1 = lerp2((I.bitmap + y_ * I.getWidth() + x_ + 1)->B, (I.bitmap + (y_ + 1) * I.getWidth() + x_ + 1)->B, rratio, rfrac);
1276  int64_t valueB = lerp2(col0, col1, cratio, cfrac);
1277 
1278  Ires[i][j] = vpRGBa(static_cast<unsigned char>(valueR >> 32),
1279  static_cast<unsigned char>(valueG >> 32),
1280  static_cast<unsigned char>(valueB >> 32));
1281  } else if (y_ + 1 < static_cast<int64_t>(I.getHeight())) {
1282  int64_t valueR = lerp2((I.bitmap + y_ * I.getWidth() + x_)->R, (I.bitmap + (y_ + 1) * I.getWidth() + x_)->R, rratio, rfrac);
1283  int64_t valueG = lerp2((I.bitmap + y_ * I.getWidth() + x_)->G, (I.bitmap + (y_ + 1) * I.getWidth() + x_)->G, rratio, rfrac);
1284  int64_t valueB = lerp2((I.bitmap + y_ * I.getWidth() + x_)->B, (I.bitmap + (y_ + 1) * I.getWidth() + x_)->B, rratio, rfrac);
1285 
1286  Ires[i][j] = vpRGBa(static_cast<unsigned char>(valueR >> 16),
1287  static_cast<unsigned char>(valueG >> 16),
1288  static_cast<unsigned char>(valueB >> 16));
1289  } else if (x_ + 1 < static_cast<int64_t>(I.getWidth())) {
1290  int64_t valueR = lerp2((I.bitmap + x_)->R, (I.bitmap + x_ + 1)->R, cratio, cfrac);
1291  int64_t valueG = lerp2((I.bitmap + x_)->G, (I.bitmap + x_ + 1)->G, cratio, cfrac);
1292  int64_t valueB = lerp2((I.bitmap + x_)->B, (I.bitmap + x_ + 1)->B, cratio, cfrac);
1293 
1294  Ires[i][j] = vpRGBa(static_cast<unsigned char>(valueR >> 16),
1295  static_cast<unsigned char>(valueG >> 16),
1296  static_cast<unsigned char>(valueB >> 16));
1297  } else {
1298  Ires[i][j] = *(I.bitmap + y_ * I.getWidth() + x_);
1299  }
1300  }
1301  }
1302  }
1303 }
1304 
1305 #endif
static void binarise(vpImage< Type > &I, Type threshold1, Type threshold2, Type value1, Type value2, Type value3, const bool useLUT=true)
Definition: vpImageTools.h:440
double getTop() const
Definition: vpRect.h:173
double get_u0() const
double get_i() const
Definition: vpImagePoint.h:204
unsigned int getWidth() const
Definition: vpImage.h:244
Implementation of row vector and the associated operations.
Definition: vpRowVector.h:115
Type * bitmap
points toward the bitmap
Definition: vpImage.h:141
double getHeight() const
Definition: vpRect.h:147
Implementation of a generic 2D array used as base class for matrices and vectors. ...
Definition: vpArray2D.h:131
double get_py() const
double get_j() const
Definition: vpImagePoint.h:215
Definition: vpRGBa.h:66
double getWidth() const
Definition: vpRect.h:195
double get_v0() const
static double sqr(double x)
Definition: vpMath.h:114
Generic class defining intrinsic camera parameters.
void resize(const unsigned int h, const unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:879
static void flip(const vpImage< Type > &I, vpImage< Type > &newI)
Definition: vpImageTools.h:796
double get_px() const
static void undistort(const vpImage< Type > &I, const vpCameraParameters &cam, vpImage< Type > &newI, unsigned int nThreads=2)
Definition: vpImageTools.h:631
double get_kud() const
Various image tools; sub-image extraction, modification of the look up table, binarisation...
Definition: vpImageTools.h:79
static void crop(const vpImage< Type > &I, double roi_top, double roi_left, unsigned int roi_height, unsigned int roi_width, vpImage< Type > &crop, unsigned int v_scale=1, unsigned int h_scale=1)
Definition: vpImageTools.h:282
static vp_deprecated 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)
unsigned int getHeight() const
Definition: vpImage.h:186
Defines a rectangle in the plane.
Definition: vpRect.h:78
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:88
void performLut(const Type(&lut)[256], const unsigned int nbThreads=1)
Definition: vpImage.h:1731
double getLeft() const
Definition: vpRect.h:154
Definition of the vpImage class member functions.
Definition: vpImage.h:124
Defines an oriented rectangle in the plane.
static void resize(const vpImage< Type > &I, vpImage< Type > &Ires, const unsigned int width, const unsigned int height, const vpImageInterpolationType &method=INTERPOLATION_NEAREST, unsigned int nThreads=0)