Visual Servoing Platform  version 3.6.1 under development (2024-03-18)
vpImage.h
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2023 by Inria. All rights reserved.
4  *
5  * This software is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
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 https://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 handling.
32  */
33 
39 #ifndef vpImage_H
40 #define vpImage_H
41 
42 #include <visp3/core/vpConfig.h>
43 #include <visp3/core/vpDebug.h>
44 #include <visp3/core/vpEndian.h>
45 #include <visp3/core/vpException.h>
46 #include <visp3/core/vpImageException.h>
47 #include <visp3/core/vpImagePoint.h>
48 #include <visp3/core/vpRGBa.h>
49 #include <visp3/core/vpRGBf.h>
50 
51 #if defined(VISP_HAVE_THREADS)
52 #include <thread>
53 #endif
54 
55 #include <fstream>
56 #include <iomanip> // std::setw
57 #include <iostream>
58 #include <math.h>
59 #include <string.h>
60 
61 // Visual Studio 2010 or previous is missing inttypes.h
62 #if defined(_MSC_VER) && (_MSC_VER < 1700)
63 typedef long long int64_t;
64 typedef unsigned short uint16_t;
65 #else
66 #include <inttypes.h>
67 #endif
68 
69 class vpDisplay;
70 
121 // Ref: http://en.cppreference.com/w/cpp/language/friend#Template_friends
122 template <class Type> class vpImage; // forward declare to make function declaration possible
123 
124 // declarations
125 template <class Type> std::ostream &operator<<(std::ostream &, const vpImage<Type> &);
126 
127 std::ostream &operator<<(std::ostream &, const vpImage<unsigned char> &);
128 std::ostream &operator<<(std::ostream &, const vpImage<char> &);
129 std::ostream &operator<<(std::ostream &, const vpImage<float> &);
130 std::ostream &operator<<(std::ostream &, const vpImage<double> &);
131 
132 template <class Type> void swap(vpImage<Type> &first, vpImage<Type> &second);
133 
134 template <class Type> class vpImage
135 {
136  friend class vpImageConvert;
137 
138 public:
139  Type *bitmap;
141 
146 #if ((__cplusplus >= 201103L) || (defined(_MSVC_LANG) && (_MSVC_LANG >= 201103L))) // Check if cxx11 or higher
148  vpImage(vpImage<Type> &&);
149 #endif
151  vpImage(unsigned int height, unsigned int width);
153  vpImage(unsigned int height, unsigned int width, Type value);
155  vpImage(Type *const array, unsigned int height, unsigned int width, bool copyData = false);
157  virtual ~vpImage();
158 
161 
162  // destructor
163  void destroy();
164 
165  // Returns a new image that's double size of the current image
167 
175  inline unsigned int getCols() const { return width; }
184  inline unsigned int getHeight() const { return height; }
185 
186  // Return the maximum value within the bitmap
187  Type getMaxValue(bool onlyFiniteVal = true) const;
188  // Return the mean value of the bitmap
189  double getMeanValue() const;
190  double getMeanValue(const vpImage<bool> *p_mask) const;
191  double getMeanValue(const vpImage<bool> *p_mask, unsigned int &nbValidPoints) const;
192  double getStdev() const;
193  double getStdev(const vpImage<bool> *p_mask) const;
194  double getStdev(const double &mean) const;
195  double getStdev(const double &mean, const unsigned int &nbValidPoints, const vpImage<bool> *p_mask) const;
196  // Return the minumum value within the bitmap
197  Type getMinValue(bool onlyFiniteVal = true) const;
198  // Look for the minumum and the maximum value within the bitmap
199  void getMinMaxValue(Type &min, Type &max, bool onlyFiniteVal = true) const;
200  // Look for the minumum and the maximum value within the bitmap and get their location
201  void getMinMaxLoc(vpImagePoint *minLoc, vpImagePoint *maxLoc, Type *minVal = nullptr, Type *maxVal = nullptr) const;
202 
211  inline unsigned int getNumberOfPixel() const { return npixels; }
212 
220  inline unsigned int getRows() const { return height; }
221 
229  inline unsigned int getSize() const { return width * height; }
230 
231  // Gets the value of a pixel at a location.
232  Type getValue(unsigned int i, unsigned int j) const;
233  // Gets the value of a pixel at a location with bilinear interpolation.
234  Type getValue(double i, double j) const;
235  // Gets the value of a pixel at a location with bilinear interpolation.
236  Type getValue(const vpImagePoint &ip) const;
237 
238  // Get image pixels sum
239  double getSum() const;
240  double getSum(const vpImage<bool> *p_mask, unsigned int &nbValidPoints) const;
241 
249  inline unsigned int getWidth() const { return width; }
250 
251  // Returns a new image that's half size of the current image
252  void halfSizeImage(vpImage<Type> &res) const;
253 
255  void init(unsigned int height, unsigned int width);
257  void init(unsigned int height, unsigned int width, Type value);
259  void init(Type *const array, unsigned int height, unsigned int width, bool copyData = false);
260  void insert(const vpImage<Type> &src, const vpImagePoint &topLeft);
261 
262  //------------------------------------------------------------------
263  // Access to the image
264 
266  inline Type *operator[](unsigned int i) { return row[i]; }
267  inline Type *operator[](int i) { return row[i]; }
268 
270  inline const Type *operator[](unsigned int i) const { return row[i]; }
271  inline const Type *operator[](int i) const { return row[i]; }
272 
279  inline Type operator()(unsigned int i, unsigned int j) const { return bitmap[i * width + j]; }
280 
285  inline void operator()(unsigned int i, unsigned int j, const Type &v) { bitmap[i * width + j] = v; }
286 
297  inline Type operator()(const vpImagePoint &ip) const
298  {
299  unsigned int i = (unsigned int)ip.get_i();
300  unsigned int j = (unsigned int)ip.get_j();
301 
302  return bitmap[i * width + j];
303  }
304 
313  inline void operator()(const vpImagePoint &ip, const Type &v)
314  {
315  unsigned int i = (unsigned int)ip.get_i();
316  unsigned int j = (unsigned int)ip.get_j();
317 
318  bitmap[i * width + j] = v;
319  }
320 
322 
325 
326  vpImage<Type> &operator=(const Type &v);
327  bool operator==(const vpImage<Type> &I) const;
328  bool operator!=(const vpImage<Type> &I) const;
329  friend std::ostream &operator<< <>(std::ostream &s, const vpImage<Type> &I);
330  friend std::ostream &operator<<(std::ostream &s, const vpImage<unsigned char> &I);
331  friend std::ostream &operator<<(std::ostream &s, const vpImage<char> &I);
332  friend std::ostream &operator<<(std::ostream &s, const vpImage<float> &I);
333  friend std::ostream &operator<<(std::ostream &s, const vpImage<double> &I);
334 
335  // Perform a look-up table transformation
336  void performLut(const Type(&lut)[256], unsigned int nbThreads = 1);
337 
338  // Returns a new image that's a quarter size of the current image
339  void quarterSizeImage(vpImage<Type> &res) const;
340 
341  // set the size of the image without initializing it.
342  void resize(unsigned int h, unsigned int w);
343  // set the size of the image and initialize it.
344  void resize(unsigned int h, unsigned int w, const Type &val);
345 
346  void sub(const vpImage<Type> &B, vpImage<Type> &C) const;
347  void sub(const vpImage<Type> &A, const vpImage<Type> &B, vpImage<Type> &C) const;
348  void subsample(unsigned int v_scale, unsigned int h_scale, vpImage<Type> &sampled) const;
349 
350  friend void swap<>(vpImage<Type> &first, vpImage<Type> &second);
351 
353 
354 private:
355  unsigned int npixels;
356  unsigned int width;
357  unsigned int height;
358  Type **row;
359  bool hasOwnership;
360 };
361 
362 template <class Type> std::ostream &operator<<(std::ostream &s, const vpImage<Type> &I)
363 {
364  if (I.bitmap == nullptr) {
365  return s;
366  }
367 
368  for (unsigned int i = 0; i < I.getHeight(); i++) {
369  for (unsigned int j = 0; j < I.getWidth() - 1; j++) {
370  s << I[i][j] << " ";
371  }
372 
373  // We don't add " " after the last column element
374  s << I[i][I.getWidth() - 1];
375 
376  // We don't add a \n character at the end of the last row line
377  if (i < I.getHeight() - 1) {
378  s << std::endl;
379  }
380  }
381 
382  return s;
383 }
384 
385 inline std::ostream &operator<<(std::ostream &s, const vpImage<unsigned char> &I)
386 {
387  if (I.bitmap == nullptr) {
388  return s;
389  }
390 
391  std::ios_base::fmtflags original_flags = s.flags();
392 
393  for (unsigned int i = 0; i < I.getHeight(); i++) {
394  for (unsigned int j = 0; j < I.getWidth() - 1; j++) {
395  s << std::setw(3) << static_cast<unsigned>(I[i][j]) << " ";
396  }
397 
398  // We don't add " " after the last column element
399  s << std::setw(3) << static_cast<unsigned>(I[i][I.getWidth() - 1]);
400 
401  // We don't add a \n character at the end of the last row line
402  if (i < I.getHeight() - 1) {
403  s << std::endl;
404  }
405  }
406 
407  s.flags(original_flags); // restore s to standard state
408  return s;
409 }
410 
411 inline std::ostream &operator<<(std::ostream &s, const vpImage<char> &I)
412 {
413  if (I.bitmap == nullptr) {
414  return s;
415  }
416 
417  std::ios_base::fmtflags original_flags = s.flags();
418 
419  for (unsigned int i = 0; i < I.getHeight(); i++) {
420  for (unsigned int j = 0; j < I.getWidth() - 1; j++) {
421  s << std::setw(4) << static_cast<int>(I[i][j]) << " ";
422  }
423 
424  // We don't add " " after the last column element
425  s << std::setw(4) << static_cast<int>(I[i][I.getWidth() - 1]);
426 
427  // We don't add a \n character at the end of the last row line
428  if (i < I.getHeight() - 1) {
429  s << std::endl;
430  }
431  }
432 
433  s.flags(original_flags); // restore s to standard state
434  return s;
435 }
436 
437 inline std::ostream &operator<<(std::ostream &s, const vpImage<float> &I)
438 {
439  if (I.bitmap == nullptr) {
440  return s;
441  }
442 
443  std::ios_base::fmtflags original_flags = s.flags();
444  s.precision(9); // http://en.cppreference.com/w/cpp/types/numeric_limits/max_digits10
445 
446  for (unsigned int i = 0; i < I.getHeight(); i++) {
447  for (unsigned int j = 0; j < I.getWidth() - 1; j++) {
448  s << I[i][j] << " ";
449  }
450 
451  // We don't add " " after the last column element
452  s << I[i][I.getWidth() - 1];
453 
454  // We don't add a \n character at the end of the last row line
455  if (i < I.getHeight() - 1) {
456  s << std::endl;
457  }
458  }
459 
460  s.flags(original_flags); // restore s to standard state
461  return s;
462 }
463 
464 inline std::ostream &operator<<(std::ostream &s, const vpImage<double> &I)
465 {
466  if (I.bitmap == nullptr) {
467  return s;
468  }
469 
470  std::ios_base::fmtflags original_flags = s.flags();
471  s.precision(17); // http://en.cppreference.com/w/cpp/types/numeric_limits/max_digits10
472 
473  for (unsigned int i = 0; i < I.getHeight(); i++) {
474  for (unsigned int j = 0; j < I.getWidth() - 1; j++) {
475  s << I[i][j] << " ";
476  }
477 
478  // We don't add " " after the last column element
479  s << I[i][I.getWidth() - 1];
480 
481  // We don't add a \n character at the end of the last row line
482  if (i < I.getHeight() - 1) {
483  s << std::endl;
484  }
485  }
486 
487  s.flags(original_flags); // restore s to standard state
488  return s;
489 }
490 
491 #if defined(VISP_HAVE_THREADS)
492 namespace
493 {
494 struct vpImageLut_Param_t
495 {
496  unsigned int m_start_index;
497  unsigned int m_end_index;
498 
499  unsigned char m_lut[256];
500  unsigned char *m_bitmap;
501 
502  vpImageLut_Param_t() : m_start_index(0), m_end_index(0), m_lut(), m_bitmap(nullptr) { }
503 
504  vpImageLut_Param_t(unsigned int start_index, unsigned int end_index, unsigned char *bitmap)
505  : m_start_index(start_index), m_end_index(end_index), m_lut(), m_bitmap(bitmap)
506  { }
507 };
508 
509 void performLutThread(vpImageLut_Param_t *imageLut_param)
510 {
511  unsigned int start_index = imageLut_param->m_start_index;
512  unsigned int end_index = imageLut_param->m_end_index;
513 
514  unsigned char *bitmap = imageLut_param->m_bitmap;
515 
516  unsigned char *ptrStart = bitmap + start_index;
517  unsigned char *ptrEnd = bitmap + end_index;
518  unsigned char *ptrCurrent = ptrStart;
519 
520  if (end_index - start_index >= 8) {
521  // Unroll loop version
522  for (; ptrCurrent <= ptrEnd - 8;) {
523  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
524  ++ptrCurrent;
525 
526  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
527  ++ptrCurrent;
528 
529  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
530  ++ptrCurrent;
531 
532  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
533  ++ptrCurrent;
534 
535  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
536  ++ptrCurrent;
537 
538  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
539  ++ptrCurrent;
540 
541  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
542  ++ptrCurrent;
543 
544  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
545  ++ptrCurrent;
546  }
547  }
548 
549  for (; ptrCurrent != ptrEnd; ++ptrCurrent) {
550  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
551  }
552 }
553 
554 struct vpImageLutRGBa_Param_t
555 {
556  unsigned int m_start_index;
557  unsigned int m_end_index;
558 
559  vpRGBa m_lut[256];
560  unsigned char *m_bitmap;
561 
562  vpImageLutRGBa_Param_t() : m_start_index(0), m_end_index(0), m_lut(), m_bitmap(nullptr) { }
563 
564  vpImageLutRGBa_Param_t(unsigned int start_index, unsigned int end_index, unsigned char *bitmap)
565  : m_start_index(start_index), m_end_index(end_index), m_lut(), m_bitmap(bitmap)
566  { }
567 };
568 
569 void performLutRGBaThread(vpImageLutRGBa_Param_t *imageLut_param)
570 {
571  unsigned int start_index = imageLut_param->m_start_index;
572  unsigned int end_index = imageLut_param->m_end_index;
573 
574  unsigned char *bitmap = imageLut_param->m_bitmap;
575 
576  unsigned char *ptrStart = bitmap + start_index * 4;
577  unsigned char *ptrEnd = bitmap + end_index * 4;
578  unsigned char *ptrCurrent = ptrStart;
579 
580  if (end_index - start_index >= 4 * 2) {
581  // Unroll loop version
582  for (; ptrCurrent <= ptrEnd - 4 * 2;) {
583  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].R;
584  ptrCurrent++;
585  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].G;
586  ptrCurrent++;
587  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].B;
588  ptrCurrent++;
589  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].A;
590  ptrCurrent++;
591 
592  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].R;
593  ptrCurrent++;
594  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].G;
595  ptrCurrent++;
596  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].B;
597  ptrCurrent++;
598  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].A;
599  ptrCurrent++;
600  }
601  }
602 
603  while (ptrCurrent != ptrEnd) {
604  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].R;
605  ptrCurrent++;
606 
607  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].G;
608  ptrCurrent++;
609 
610  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].B;
611  ptrCurrent++;
612 
613  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].A;
614  ptrCurrent++;
615  }
616 }
617 } // namespace
618 #endif
619 
623 template <class Type> void vpImage<Type>::init(unsigned int h, unsigned int w, Type value)
624 {
625  init(h, w);
626 
627  // for (unsigned int i = 0; i < npixels; i++)
628  // bitmap[i] = value;
629  std::fill(bitmap, bitmap + npixels, value);
630 }
631 
635 template <class Type> void vpImage<Type>::init(unsigned int h, unsigned int w)
636 {
637  if (h != this->height) {
638  if (row != nullptr) {
639  delete[] row;
640  row = nullptr;
641  }
642  }
643 
644  if ((h != this->height) || (w != this->width)) {
645  if (bitmap != nullptr) {
646  if (hasOwnership) {
647  delete[] bitmap;
648  }
649  bitmap = nullptr;
650  }
651  }
652 
653  this->width = w;
654  this->height = h;
655 
656  npixels = width * height;
657 
658  if (bitmap == nullptr) {
659  bitmap = new Type[npixels];
660  hasOwnership = true;
661  }
662  if (bitmap == nullptr) {
663  throw(vpException(vpException::memoryAllocationError, "cannot allocate bitmap "));
664  }
665  if (row == nullptr)
666  row = new Type *[height];
667  if (row == nullptr) {
668  throw(vpException(vpException::memoryAllocationError, "cannot allocate row "));
669  }
670 
671  for (unsigned int i = 0; i < height; i++)
672  row[i] = bitmap + i * width;
673 }
674 
678 template <class Type> void vpImage<Type>::init(Type *const array, unsigned int h, unsigned int w, bool copyData)
679 {
680  if (h != this->height) {
681  if (row != nullptr) {
682  delete[] row;
683  row = nullptr;
684  }
685  }
686 
687  // Delete bitmap if copyData==false, otherwise only if the dimension differs
688  if ((copyData && ((h != this->height) || (w != this->width))) || !copyData) {
689  if (bitmap != nullptr) {
690  if (hasOwnership) {
691  delete[] bitmap;
692  }
693  bitmap = nullptr;
694  }
695  }
696 
697  hasOwnership = copyData;
698  this->width = w;
699  this->height = h;
700 
701  npixels = width * height;
702 
703  if (copyData) {
704  if (bitmap == nullptr)
705  bitmap = new Type[npixels];
706 
707  if (bitmap == nullptr) {
708  throw(vpException(vpException::memoryAllocationError, "cannot allocate bitmap "));
709  }
710 
711  // Copy the image data
712  memcpy(static_cast<void *>(bitmap), static_cast<void *>(array), (size_t)(npixels * sizeof(Type)));
713  }
714  else {
715  // Copy the address of the array in the bitmap
716  bitmap = array;
717  }
718 
719  if (row == nullptr)
720  row = new Type *[height];
721  if (row == nullptr) {
722  throw(vpException(vpException::memoryAllocationError, "cannot allocate row "));
723  }
724 
725  for (unsigned int i = 0; i < height; i++) {
726  row[i] = bitmap + i * width;
727  }
728 }
729 
733 template <class Type>
734 vpImage<Type>::vpImage(unsigned int h, unsigned int w)
735  : bitmap(nullptr), display(nullptr), npixels(0), width(0), height(0), row(nullptr), hasOwnership(true)
736 {
737  init(h, w, 0);
738 }
739 
743 template <class Type>
744 vpImage<Type>::vpImage(unsigned int h, unsigned int w, Type value)
745  : bitmap(nullptr), display(nullptr), npixels(0), width(0), height(0), row(nullptr), hasOwnership(true)
746 {
747  init(h, w, value);
748 }
749 
753 template <class Type>
754 vpImage<Type>::vpImage(Type *const array, unsigned int h, unsigned int w, bool copyData)
755  : bitmap(nullptr), display(nullptr), npixels(0), width(0), height(0), row(nullptr), hasOwnership(true)
756 {
757  init(array, h, w, copyData);
758 }
759 
763 template <class Type>
764 vpImage<Type>::vpImage() : bitmap(nullptr), display(nullptr), npixels(0), width(0), height(0), row(nullptr), hasOwnership(true)
765 { }
766 
787 template <class Type> void vpImage<Type>::resize(unsigned int h, unsigned int w) { init(h, w); }
788 
808 template <class Type> void vpImage<Type>::resize(unsigned int h, unsigned int w, const Type &val) { init(h, w, val); }
809 
816 template <class Type> void vpImage<Type>::destroy()
817 {
818  if (bitmap != nullptr) {
819  if (hasOwnership) {
820  delete[] bitmap;
821  }
822  bitmap = nullptr;
823  }
824 
825  if (row != nullptr) {
826  delete[] row;
827  row = nullptr;
828  }
829 }
830 
837 template <class Type> vpImage<Type>::~vpImage() { destroy(); }
838 
842 template <class Type>
844  : bitmap(nullptr), display(nullptr), npixels(0), width(0), height(0), row(nullptr), hasOwnership(true)
845 {
846  resize(I.getHeight(), I.getWidth());
847  if (bitmap) {
848  memcpy(static_cast<void *>(bitmap), static_cast<void *>(I.bitmap), I.npixels * sizeof(Type));
849  }
850 }
851 
852 #if ((__cplusplus >= 201103L) || (defined(_MSVC_LANG) && (_MSVC_LANG >= 201103L))) // Check if cxx11 or higher
856 template <class Type>
858  : bitmap(I.bitmap), display(I.display), npixels(I.npixels), width(I.width), height(I.height), row(I.row),
859  hasOwnership(I.hasOwnership)
860 {
861  I.bitmap = nullptr;
862  I.display = nullptr;
863  I.npixels = 0;
864  I.width = 0;
865  I.height = 0;
866  I.row = nullptr;
867  I.hasOwnership = false;
868 }
869 #endif
870 
878 template <class Type> Type vpImage<Type>::getMaxValue(bool onlyFiniteVal) const
879 {
880  if (npixels == 0)
881  throw(vpException(vpException::fatalError, "Cannot compute maximum value of an empty image"));
882  Type m = bitmap[0];
883  for (unsigned int i = 0; i < npixels; i++) {
884  if (bitmap[i] > m) {
885  m = bitmap[i];
886  }
887  }
888  (void)onlyFiniteVal;
889  return m;
890 }
891 
900 template <> inline double vpImage<double>::getMaxValue(bool onlyFiniteVal) const
901 {
902  if (npixels == 0)
903  throw(vpException(vpException::fatalError, "Cannot compute maximum value of an empty image"));
904  double m = bitmap[0];
905  if (onlyFiniteVal) {
906  for (unsigned int i = 0; i < npixels; i++) {
907  if (bitmap[i] > m && vpMath::isFinite(bitmap[i]))
908  m = bitmap[i];
909  }
910  }
911  else {
912  for (unsigned int i = 0; i < npixels; i++) {
913  if (bitmap[i] > m)
914  m = bitmap[i];
915  }
916  }
917  return m;
918 }
919 
928 template <> inline float vpImage<float>::getMaxValue(bool onlyFiniteVal) const
929 {
930  if (npixels == 0)
931  throw(vpException(vpException::fatalError, "Cannot compute maximum value of an empty image"));
932  float m = bitmap[0];
933  if (onlyFiniteVal) {
934  for (unsigned int i = 0; i < npixels; i++) {
935  if (bitmap[i] > m && vpMath::isFinite(bitmap[i]))
936  m = bitmap[i];
937  }
938  }
939  else {
940  for (unsigned int i = 0; i < npixels; i++) {
941  if (bitmap[i] > m)
942  m = bitmap[i];
943  }
944  }
945  return m;
946 }
947 
951 template <class Type> double vpImage<Type>::getMeanValue() const
952 {
953  if ((height == 0) || (width == 0)) {
954  return 0.0;
955  }
956 
957  return getSum() / (height * width);
958 }
959 
965 template <class Type> double vpImage<Type>::getMeanValue(const vpImage<bool> *p_mask) const
966 {
967  unsigned int nbValidPoints = 0;
968  return getMeanValue(p_mask, nbValidPoints);
969 }
970 
977 template <class Type> double vpImage<Type>::getMeanValue(const vpImage<bool> *p_mask, unsigned int &nbValidPoints) const
978 {
979  nbValidPoints = 0;
980  if ((height == 0) || (width == 0)) {
981  return 0.0;
982  }
983 
984  double sum = getSum(p_mask, nbValidPoints);
985  return sum / nbValidPoints;
986 }
987 
991 template <class Type> double vpImage<Type>::getStdev() const
992 {
993  double mean = getMeanValue();
994  return getStdev(mean);
995 }
996 
1002 template <class Type> double vpImage<Type>::getStdev(const vpImage<bool> *p_mask) const
1003 {
1004  unsigned int nbValidPoints = 0;
1005  double mean = getMeanValue(p_mask, nbValidPoints);
1006  return getStdev(mean, nbValidPoints, p_mask);
1007 }
1008 
1020 template <class Type> double vpImage<Type>::getStdev(const double &mean) const
1021 {
1022  const unsigned int size = width * height;
1023  double sum = 0.;
1024  for (unsigned int i = 0; i < size; ++i) {
1025  sum += (bitmap[i] - mean) * (bitmap[i] - mean);
1026  }
1027  sum /= static_cast<double>(size);
1028  return std::sqrt(sum);
1029 }
1030 
1045 template <class Type> double vpImage<Type>::getStdev(const double &mean, const unsigned int &nbValidPoints, const vpImage<bool> *p_mask) const
1046 {
1047  if (p_mask == nullptr) {
1048  return getStdev(mean);
1049  }
1050  const unsigned int size = width * height;
1051  double sum = 0.;
1052  for (unsigned int i = 0; i < size; ++i) {
1053  if (p_mask->bitmap[i]) {
1054  sum += (bitmap[i] - mean) * (bitmap[i] - mean);
1055  }
1056  }
1057  sum /= static_cast<double>(nbValidPoints);
1058  return std::sqrt(sum);
1059 }
1060 
1061 /*
1062 /!\ Did not use Doxygen for this method because it does not handle template specialization
1063 * Return the standard deviation of the bitmap
1064 *
1065 * For a vpRGBa or a vpRGBf image, we compute the standard deviation as follow:
1066 *
1067 * \f$ stdev = \sqrt{\frac{1}{width * height} \sum_{r = 0}^{height-1} \sum_{c = 0}^{width-1} (I[r][c].R + I[r][c].G + I[r][c].B - \mu)^2}\f$
1068 *
1069 * where \f$ \mu \f$ is the mean of the image as computed by \b vpImage::getMeanValue() .
1070 *
1071 * param[in] mean The mean of the image.
1072 * return The standard deviation.
1073 */
1074 template <> inline double vpImage<vpRGBa>::getStdev(const double &mean) const
1075 {
1076  if ((height == 0) || (width == 0)) {
1077  return 0.0;
1078  }
1079 
1080  double res = 0.0;
1081  const unsigned int size = height * width;
1082  for (unsigned int i = 0; i < size; ++i) {
1083  double val = static_cast<double>(bitmap[i].R) + static_cast<double>(bitmap[i].G) + static_cast<double>(bitmap[i].B);
1084  res += (val - mean) * (val - mean);
1085  }
1086  res /= static_cast<double>(size);
1087  return std::sqrt(res);
1088 }
1089 
1090 /*
1091 /!\ Did not use Doxygen for this method because it does not handle template specialization
1092 * Return the standard deviation of the bitmap
1093 *
1094 * For a vpRGBa or a vpRGBf image, we compute the standard deviation as follow:
1095 *
1096 * \f$ stdev = \sqrt{\frac{1}{nbValidPoints} \sum_{r = 0}^{height-1} \sum_{c = 0}^{width-1} (I[r][c].R + I[r][c].G + I[r][c].B - \mu)^2 \delta(r,c)} where \delta(r,c) = 1 if p_mask[r][c], 0 otherwise\f$
1097 *
1098 * where \f$ \mu \f$ is the mean of the image as computed by \b vpImage::getMeanValue() .
1099 *
1100 * param[in] mean The mean of the image.
1101 * param[in] nbValidPoints Number of points that are valid according to the boolean mask.
1102 * param[in] p_mask A boolean mask that indicates which points must be considered, if set.
1103 * return The standard deviation taking into account only the points for which the mask is true.The standard deviation taking into account only the points for which the mask is true.
1104 */
1105 template <> inline double vpImage<vpRGBa>::getStdev(const double &mean, const unsigned int &nbValidPoints, const vpImage<bool> *p_mask) const
1106 {
1107  if ((height == 0) || (width == 0)) {
1108  return 0.0;
1109  }
1110 
1111  if (p_mask == nullptr) {
1112  return getStdev(mean);
1113  }
1114 
1115  const unsigned int size = width * height;
1116  double sum = 0.;
1117  for (unsigned int i = 0; i < size; ++i) {
1118  if (p_mask->bitmap[i]) {
1119  double val = static_cast<double>(bitmap[i].R) + static_cast<double>(bitmap[i].G) + static_cast<double>(bitmap[i].B);
1120  sum += (val - mean) * (val - mean);
1121  }
1122  }
1123  sum /= static_cast<double>(nbValidPoints);
1124  return std::sqrt(sum);
1125 }
1126 
1127 /*
1128 /!\ Did not use Doxygen for this method because it does not handle template specialization
1129 * Return the standard deviation of the bitmap
1130 *
1131 * For a vpRGBa or a vpRGBf image, we compute the standard deviation as follow:
1132 *
1133 * \f$ stdev = \sqrt{\frac{1}{width * height} \sum_{r = 0}^{height-1} \sum_{c = 0}^{width-1} (I[r][c].R + I[r][c].G + I[r][c].B - \mu)^2}\f$
1134 *
1135 * where \f$ \mu \f$ is the mean of the image as computed by \b vpImage::getMeanValue() .
1136 *
1137 * param[in] mean The mean of the image.
1138 * return The standard deviation.
1139 */
1143 template <> inline double vpImage<vpRGBf>::getStdev(const double &mean) const
1144 {
1145  if ((height == 0) || (width == 0)) {
1146  return 0.0;
1147  }
1148 
1149  double res = 0.0;
1150  const unsigned int size = height * width;
1151  for (unsigned int i = 0; i < size; ++i) {
1152  double val = static_cast<double>(bitmap[i].R) + static_cast<double>(bitmap[i].G) + static_cast<double>(bitmap[i].B);
1153  res += (val - mean) * (val - mean);
1154  }
1155  res /= static_cast<double>(size);
1156  return std::sqrt(res);
1157 }
1158 
1159 /*
1160 /!\ Did not use Doxygen for this method because it does not handle template specialization
1161 * Return the standard deviation of the bitmap
1162 *
1163 * For a vpRGBa or a vpRGBf image, we compute the standard deviation as follow:
1164 *
1165 * \f$ stdev = \sqrt{\frac{1}{nbValidPoints} \sum_{r = 0}^{height-1} \sum_{c = 0}^{width-1} (I[r][c].R + I[r][c].G + I[r][c].B - \mu)^2 \delta(r,c)} where \delta(r,c) = 1 if p_mask[r][c], 0 otherwise\f$
1166 *
1167 * where \f$ \mu \f$ is the mean of the image as computed by \b vpImage::getMeanValue() .
1168 *
1169 * param[in] mean The mean of the image.
1170 * param[in] nbValidPoints Number of points that are valid according to the boolean mask.
1171 * param[in] p_mask A boolean mask that indicates which points must be considered, if set.
1172 * return The standard deviation taking into account only the points for which the mask is true.
1173 */
1177 template <> inline double vpImage<vpRGBf>::getStdev(const double &mean, const unsigned int &nbValidPoints, const vpImage<bool> *p_mask) const
1178 {
1179  if ((height == 0) || (width == 0)) {
1180  return 0.0;
1181  }
1182 
1183  if (p_mask == nullptr) {
1184  return getStdev(mean);
1185  }
1186 
1187  const unsigned int size = width * height;
1188  double sum = 0.;
1189  for (unsigned int i = 0; i < size; ++i) {
1190  if (p_mask->bitmap[i]) {
1191  double val = static_cast<double>(bitmap[i].R) + static_cast<double>(bitmap[i].G) + static_cast<double>(bitmap[i].B);
1192  sum += (val - mean) * (val - mean);
1193  }
1194  }
1195  sum /= static_cast<double>(nbValidPoints);
1196  return std::sqrt(sum);
1197 }
1198 
1206 template <class Type> Type vpImage<Type>::getMinValue(bool onlyFiniteVal) const
1207 {
1208  if (npixels == 0)
1209  throw(vpException(vpException::fatalError, "Cannot compute minimum value of an empty image"));
1210  Type m = bitmap[0];
1211  for (unsigned int i = 0; i < npixels; i++) {
1212  if (bitmap[i] < m) {
1213  m = bitmap[i];
1214  }
1215  }
1216  (void)onlyFiniteVal;
1217  return m;
1218 }
1219 
1228 template <> inline double vpImage<double>::getMinValue(bool onlyFiniteVal) const
1229 {
1230  if (npixels == 0)
1231  throw(vpException(vpException::fatalError, "Cannot compute minimum value of an empty image"));
1232  double m = bitmap[0];
1233  if (onlyFiniteVal) {
1234  for (unsigned int i = 0; i < npixels; i++)
1235  if (bitmap[i] < m && vpMath::isFinite(bitmap[i]))
1236  m = bitmap[i];
1237  }
1238  else {
1239  for (unsigned int i = 0; i < npixels; i++)
1240  if (bitmap[i] < m)
1241  m = bitmap[i];
1242  }
1243  return m;
1244 }
1245 
1254 template <> inline float vpImage<float>::getMinValue(bool onlyFiniteVal) const
1255 {
1256  if (npixels == 0)
1257  throw(vpException(vpException::fatalError, "Cannot compute minimum value of an empty image"));
1258  float m = bitmap[0];
1259  if (onlyFiniteVal) {
1260  for (unsigned int i = 0; i < npixels; i++)
1261  if (bitmap[i] < m && vpMath::isFinite(bitmap[i]))
1262  m = bitmap[i];
1263  }
1264  else {
1265  for (unsigned int i = 0; i < npixels; i++)
1266  if (bitmap[i] < m)
1267  m = bitmap[i];
1268  }
1269  return m;
1270 }
1271 
1282 template <class Type> void vpImage<Type>::getMinMaxValue(Type &min, Type &max, bool onlyFiniteVal) const
1283 {
1284  if (npixels == 0)
1285  throw(vpException(vpException::fatalError, "Cannot get minimum/maximum values of an empty image"));
1286 
1287  min = max = bitmap[0];
1288  for (unsigned int i = 0; i < npixels; i++) {
1289  if (bitmap[i] < min)
1290  min = bitmap[i];
1291  if (bitmap[i] > max)
1292  max = bitmap[i];
1293  }
1294  (void)onlyFiniteVal;
1295 }
1296 
1308 template <> inline void vpImage<double>::getMinMaxValue(double &min, double &max, bool onlyFiniteVal) const
1309 {
1310  if (npixels == 0)
1311  throw(vpException(vpException::fatalError, "Cannot get minimum/maximum values of an empty image"));
1312 
1313  min = max = bitmap[0];
1314  if (onlyFiniteVal) {
1315  for (unsigned int i = 0; i < npixels; i++) {
1316  if (vpMath::isFinite(bitmap[i])) {
1317  if (bitmap[i] < min)
1318  min = bitmap[i];
1319  if (bitmap[i] > max)
1320  max = bitmap[i];
1321  }
1322  }
1323  }
1324  else {
1325  for (unsigned int i = 0; i < npixels; i++) {
1326  if (bitmap[i] < min)
1327  min = bitmap[i];
1328  if (bitmap[i] > max)
1329  max = bitmap[i];
1330  }
1331  }
1332 }
1333 
1345 template <> inline void vpImage<float>::getMinMaxValue(float &min, float &max, bool onlyFiniteVal) const
1346 {
1347  if (npixels == 0)
1348  throw(vpException(vpException::fatalError, "Cannot get minimum/maximum values of an empty image"));
1349 
1350  min = max = bitmap[0];
1351  if (onlyFiniteVal) {
1352  for (unsigned int i = 0; i < npixels; i++) {
1353  if (vpMath::isFinite(bitmap[i])) {
1354  if (bitmap[i] < min)
1355  min = bitmap[i];
1356  if (bitmap[i] > max)
1357  max = bitmap[i];
1358  }
1359  }
1360  }
1361  else {
1362  for (unsigned int i = 0; i < npixels; i++) {
1363  if (bitmap[i] < min)
1364  min = bitmap[i];
1365  if (bitmap[i] > max)
1366  max = bitmap[i];
1367  }
1368  }
1369 }
1370 
1381 template <> inline void vpImage<vpRGBf>::getMinMaxValue(vpRGBf &min, vpRGBf &max, bool onlyFiniteVal) const
1382 {
1383  if (npixels == 0)
1384  throw(vpException(vpException::fatalError, "Cannot get minimum/maximum values of an empty image"));
1385 
1386  min = max = bitmap[0];
1387  if (onlyFiniteVal) {
1388  for (unsigned int i = 0; i < npixels; i++) {
1389  if (vpMath::isFinite(bitmap[i].R)) {
1390  if (bitmap[i].R < min.R)
1391  min.R = bitmap[i].R;
1392  if (bitmap[i].R > max.R)
1393  max.R = bitmap[i].R;
1394  }
1395  if (vpMath::isFinite(bitmap[i].G)) {
1396  if (bitmap[i].G < min.G)
1397  min.G = bitmap[i].G;
1398  if (bitmap[i].G > max.G)
1399  max.G = bitmap[i].G;
1400  }
1401  if (vpMath::isFinite(bitmap[i].B)) {
1402  if (bitmap[i].B < min.B)
1403  min.B = bitmap[i].B;
1404  if (bitmap[i].B > max.B)
1405  max.B = bitmap[i].B;
1406  }
1407  }
1408  }
1409  else {
1410  for (unsigned int i = 0; i < npixels; i++) {
1411  if (bitmap[i].R < min.R)
1412  min.R = bitmap[i].R;
1413  if (bitmap[i].R > max.R)
1414  max.R = bitmap[i].R;
1415 
1416  if (bitmap[i].G < min.G)
1417  min.G = bitmap[i].G;
1418  if (bitmap[i].G > max.G)
1419  max.G = bitmap[i].G;
1420 
1421  if (bitmap[i].B < min.B)
1422  min.B = bitmap[i].B;
1423  if (bitmap[i].B > max.B)
1424  max.B = bitmap[i].B;
1425  }
1426  }
1427 }
1428 
1450 template <class Type>
1451 void vpImage<Type>::getMinMaxLoc(vpImagePoint *minLoc, vpImagePoint *maxLoc, Type *minVal, Type *maxVal) const
1452 {
1453  if (npixels == 0)
1454  throw(vpException(vpException::fatalError, "Cannot get location of minimum/maximum "
1455  "values of an empty image"));
1456 
1457  Type min = bitmap[0], max = bitmap[0];
1458  vpImagePoint minLoc_, maxLoc_;
1459  for (unsigned int i = 0; i < height; i++) {
1460  for (unsigned int j = 0; j < width; j++) {
1461  if (row[i][j] < min) {
1462  min = row[i][j];
1463  minLoc_.set_ij(i, j);
1464  }
1465 
1466  if (row[i][j] > max) {
1467  max = row[i][j];
1468  maxLoc_.set_ij(i, j);
1469  }
1470  }
1471  }
1472 
1473  if (minLoc != nullptr)
1474  *minLoc = minLoc_;
1475 
1476  if (maxLoc != nullptr)
1477  *maxLoc = maxLoc_;
1478 
1479  if (minVal != nullptr)
1480  *minVal = min;
1481 
1482  if (maxVal != nullptr)
1483  *maxVal = max;
1484 }
1485 
1490 {
1491  swap(*this, other);
1492  if (other.display != nullptr)
1493  display = other.display;
1494 
1495  return *this;
1496 }
1497 
1504 template <class Type> vpImage<Type> &vpImage<Type>::operator=(const Type &v)
1505 {
1506  for (unsigned int i = 0; i < npixels; i++)
1507  bitmap[i] = v;
1508 
1509  return *this;
1510 }
1511 
1517 template <class Type> bool vpImage<Type>::operator==(const vpImage<Type> &I) const
1518 {
1519  if (this->width != I.getWidth())
1520  return false;
1521  if (this->height != I.getHeight())
1522  return false;
1523 
1524  // printf("wxh: %dx%d bitmap: %p I.bitmap %p\n", width, height, bitmap,
1525  // I.bitmap);
1526  for (unsigned int i = 0; i < npixels; i++) {
1527  if (bitmap[i] != I.bitmap[i]) {
1528  // std::cout << "differ for pixel " << i << " (" << i%this->height
1529  // << ", " << i - i%this->height << ")" << std::endl;
1530  return false;
1531  }
1532  }
1533  return true;
1534 }
1540 template <class Type> bool vpImage<Type>::operator!=(const vpImage<Type> &I) const { return !(*this == I); }
1541 
1567 template <class Type> vpImage<Type> vpImage<Type>::operator-(const vpImage<Type> &B) const
1568 {
1569  vpImage<Type> C;
1570  sub(*this, B, C);
1571  return C;
1572 }
1573 
1585 template <class Type> void vpImage<Type>::insert(const vpImage<Type> &src, const vpImagePoint &topLeft)
1586 {
1587  int itl = (int)topLeft.get_i();
1588  int jtl = (int)topLeft.get_j();
1589 
1590  int dest_ibegin = 0;
1591  int dest_jbegin = 0;
1592  int src_ibegin = 0;
1593  int src_jbegin = 0;
1594  int dest_w = (int)this->getWidth();
1595  int dest_h = (int)this->getHeight();
1596  int src_w = (int)src.getWidth();
1597  int src_h = (int)src.getHeight();
1598  int wsize = (int)src.getWidth();
1599  int hsize = (int)src.getHeight();
1600 
1601  if (itl >= dest_h || jtl >= dest_w)
1602  return;
1603 
1604  if (itl < 0)
1605  src_ibegin = -itl;
1606  else
1607  dest_ibegin = itl;
1608 
1609  if (jtl < 0)
1610  src_jbegin = -jtl;
1611  else
1612  dest_jbegin = jtl;
1613 
1614  if (src_w - src_jbegin > dest_w - dest_jbegin)
1615  wsize = dest_w - dest_jbegin;
1616  else
1617  wsize = src_w - src_jbegin;
1618 
1619  if (src_h - src_ibegin > dest_h - dest_ibegin)
1620  hsize = dest_h - dest_ibegin;
1621  else
1622  hsize = src_h - src_ibegin;
1623 
1624  for (int i = 0; i < hsize; i++) {
1625  Type *srcBitmap = src.bitmap + ((src_ibegin + i) * src_w + src_jbegin);
1626  Type *destBitmap = this->bitmap + ((dest_ibegin + i) * dest_w + dest_jbegin);
1627 
1628  memcpy(static_cast<void *>(destBitmap), static_cast<void *>(srcBitmap), (size_t)wsize * sizeof(Type));
1629  }
1630 }
1631 
1662 template <class Type> void vpImage<Type>::halfSizeImage(vpImage<Type> &res) const
1663 {
1664  unsigned int h = height / 2;
1665  unsigned int w = width / 2;
1666  res.resize(h, w);
1667  for (unsigned int i = 0; i < h; i++)
1668  for (unsigned int j = 0; j < w; j++)
1669  res[i][j] = (*this)[i << 1][j << 1];
1670 }
1671 
1689 template <class Type>
1690 void vpImage<Type>::subsample(unsigned int v_scale, unsigned int h_scale, vpImage<Type> &sampled) const
1691 {
1692  if (v_scale == 1 && h_scale == 1) {
1693  sampled = (*this);
1694  return;
1695  }
1696  unsigned int h = height / v_scale;
1697  unsigned int w = width / h_scale;
1698  sampled.resize(h, w);
1699  for (unsigned int i = 0; i < h; i++)
1700  for (unsigned int j = 0; j < w; j++)
1701  sampled[i][j] = (*this)[i * v_scale][j * h_scale];
1702 }
1703 
1726 template <class Type> void vpImage<Type>::quarterSizeImage(vpImage<Type> &res) const
1727 {
1728  unsigned int h = height / 4;
1729  unsigned int w = width / 4;
1730  res.resize(h, w);
1731  for (unsigned int i = 0; i < h; i++)
1732  for (unsigned int j = 0; j < w; j++)
1733  res[i][j] = (*this)[i << 2][j << 2];
1734 }
1735 
1768 template <class Type> void vpImage<Type>::doubleSizeImage(vpImage<Type> &res)
1769 {
1770  int h = height * 2;
1771  int w = width * 2;
1772 
1773  res.resize(h, w);
1774 
1775  for (int i = 0; i < h; i++)
1776  for (int j = 0; j < w; j++)
1777  res[i][j] = (*this)[i >> 1][j >> 1];
1778 
1779  /*
1780  A B C
1781  E F G
1782  H I J
1783  A C H J are pixels from original image
1784  B E G I are interpolated pixels
1785  */
1786 
1787  // interpolate pixels B and I
1788  for (int i = 0; i < h; i += 2)
1789  for (int j = 1; j < w - 1; j += 2)
1790  res[i][j] = (Type)(0.5 * ((*this)[i >> 1][j >> 1] + (*this)[i >> 1][(j >> 1) + 1]));
1791 
1792  // interpolate pixels E and G
1793  for (int i = 1; i < h - 1; i += 2)
1794  for (int j = 0; j < w; j += 2)
1795  res[i][j] = (Type)(0.5 * ((*this)[i >> 1][j >> 1] + (*this)[(i >> 1) + 1][j >> 1]));
1796 
1797  // interpolate pixel F
1798  for (int i = 1; i < h - 1; i += 2)
1799  for (int j = 1; j < w - 1; j += 2)
1800  res[i][j] = (Type)(0.25 * ((*this)[i >> 1][j >> 1] + (*this)[i >> 1][(j >> 1) + 1] +
1801  (*this)[(i >> 1) + 1][j >> 1] + (*this)[(i >> 1) + 1][(j >> 1) + 1]));
1802 }
1803 
1816 template <class Type> inline Type vpImage<Type>::getValue(unsigned int i, unsigned int j) const
1817 {
1818  if (i >= height || j >= width) {
1819  throw(vpException(vpImageException::notInTheImage, "Pixel outside the image"));
1820  }
1821 
1822  return row[i][j];
1823 }
1824 
1841 template <class Type> Type vpImage<Type>::getValue(double i, double j) const
1842 {
1843  if (i < 0 || j < 0 || i + 1 > height || j + 1 > width) {
1844  throw(vpException(vpImageException::notInTheImage, "Pixel outside of the image"));
1845  }
1846  if (height * width == 0) {
1847  throw vpException(vpImageException::notInitializedError, "Empty image!");
1848  }
1849 
1850  unsigned int iround = static_cast<unsigned int>(floor(i));
1851  unsigned int jround = static_cast<unsigned int>(floor(j));
1852 
1853  double rratio = i - static_cast<double>(iround);
1854  double cratio = j - static_cast<double>(jround);
1855 
1856  double rfrac = 1.0 - rratio;
1857  double cfrac = 1.0 - cratio;
1858 
1859  unsigned int iround_1 = std::min<unsigned int>(height - 1, iround + 1);
1860  unsigned int jround_1 = std::min<unsigned int>(width - 1, jround + 1);
1861 
1862  double value =
1863  (static_cast<double>(row[iround][jround]) * rfrac + static_cast<double>(row[iround_1][jround]) * rratio) * cfrac +
1864  (static_cast<double>(row[iround][jround_1]) * rfrac + static_cast<double>(row[iround_1][jround_1]) * rratio) *
1865  cratio;
1866 
1867  return static_cast<Type>(vpMath::round(value));
1868 }
1869 
1873 template <> inline double vpImage<double>::getValue(double i, double j) const
1874 {
1875  if (i < 0 || j < 0 || i + 1 > height || j + 1 > width) {
1876  throw(vpException(vpImageException::notInTheImage, "Pixel outside of the image"));
1877  }
1878  if (height * width == 0) {
1879  throw vpException(vpImageException::notInitializedError, "Empty image!");
1880  }
1881 
1882  unsigned int iround = static_cast<unsigned int>(floor(i));
1883  unsigned int jround = static_cast<unsigned int>(floor(j));
1884 
1885  double rratio = i - static_cast<double>(iround);
1886  double cratio = j - static_cast<double>(jround);
1887 
1888  double rfrac = 1.0 - rratio;
1889  double cfrac = 1.0 - cratio;
1890 
1891  unsigned int iround_1 = std::min<unsigned int>(height - 1, iround + 1);
1892  unsigned int jround_1 = std::min<unsigned int>(width - 1, jround + 1);
1893 
1894  return (row[iround][jround] * rfrac + row[iround_1][jround] * rratio) * cfrac +
1895  (row[iround][jround_1] * rfrac + row[iround_1][jround_1] * rratio) * cratio;
1896 }
1897 
1901 template <> inline unsigned char vpImage<unsigned char>::getValue(double i, double j) const
1902 {
1903  if (i < 0 || j < 0 || i + 1 > height || j + 1 > width) {
1904  throw(vpException(vpImageException::notInTheImage, "Pixel outside of the image"));
1905  }
1906  if (height * width == 0) {
1907  throw vpException(vpImageException::notInitializedError, "Empty image!");
1908  }
1909 
1910  // alpha architecture is bi-endianness. The following optimization makes testImageGetValue failing
1911 #if (defined(VISP_LITTLE_ENDIAN) || defined(VISP_BIG_ENDIAN)) && !(defined(__alpha__) || defined(_M_ALPHA))
1912  // Fixed-point arithmetic
1913  const int32_t precision = 1 << 16;
1914  int64_t y = static_cast<int64_t>(i * precision);
1915  int64_t x = static_cast<int64_t>(j * precision);
1916 
1917  int64_t iround = y & (~0xFFFF);
1918  int64_t jround = x & (~0xFFFF);
1919 
1920  int64_t rratio = y - iround;
1921  int64_t cratio = x - jround;
1922 
1923  int64_t rfrac = precision - rratio;
1924  int64_t cfrac = precision - cratio;
1925 
1926  int64_t x_ = x >> 16;
1927  int64_t y_ = y >> 16;
1928 
1929  if (y_ + 1 < height && x_ + 1 < width) {
1930  uint16_t up = vpEndian::reinterpret_cast_uchar_to_uint16_LE(bitmap + y_ * width + x_);
1931  uint16_t down = vpEndian::reinterpret_cast_uchar_to_uint16_LE(bitmap + (y_ + 1) * width + x_);
1932 
1933  return static_cast<unsigned char>((((up & 0x00FF) * rfrac + (down & 0x00FF) * rratio) * cfrac +
1934  ((up >> 8) * rfrac + (down >> 8) * rratio) * cratio) >>
1935  32);
1936  }
1937  else if (y_ + 1 < height) {
1938  return static_cast<unsigned char>(((row[y_][x_] * rfrac + row[y_ + 1][x_] * rratio)) >> 16);
1939  }
1940  else if (x_ + 1 < width) {
1941  uint16_t up = vpEndian::reinterpret_cast_uchar_to_uint16_LE(bitmap + y_ * width + x_);
1942  return static_cast<unsigned char>(((up & 0x00FF) * cfrac + (up >> 8) * cratio) >> 16);
1943  }
1944  else {
1945  return row[y_][x_];
1946  }
1947 #else
1948  unsigned int iround = static_cast<unsigned int>(floor(i));
1949  unsigned int jround = static_cast<unsigned int>(floor(j));
1950 
1951  if (iround >= height || jround >= width) {
1952  vpERROR_TRACE("Pixel outside the image");
1953  throw(vpException(vpImageException::notInTheImage, "Pixel outside the image"));
1954  }
1955 
1956  double rratio = i - static_cast<double>(iround);
1957  double cratio = j - static_cast<double>(jround);
1958 
1959  double rfrac = 1.0 - rratio;
1960  double cfrac = 1.0 - cratio;
1961 
1962  unsigned int iround_1 = std::min<unsigned int>(height - 1, iround + 1);
1963  unsigned int jround_1 = std::min<unsigned int>(width - 1, jround + 1);
1964 
1965  double value =
1966  (static_cast<double>(row[iround][jround]) * rfrac + static_cast<double>(row[iround_1][jround]) * rratio) * cfrac +
1967  (static_cast<double>(row[iround][jround_1]) * rfrac + static_cast<double>(row[iround_1][jround_1]) * rratio) *
1968  cratio;
1969  return static_cast<unsigned char>(vpMath::round(value));
1970 #endif
1971 }
1972 
1976 template <> inline vpRGBa vpImage<vpRGBa>::getValue(double i, double j) const
1977 {
1978  if (i < 0 || j < 0 || i + 1 > height || j + 1 > width) {
1979  throw(vpException(vpImageException::notInTheImage, "Pixel outside of the image"));
1980  }
1981  if (height * width == 0) {
1982  throw vpException(vpImageException::notInitializedError, "Empty image!");
1983  }
1984 
1985  unsigned int iround = static_cast<unsigned int>(floor(i));
1986  unsigned int jround = static_cast<unsigned int>(floor(j));
1987 
1988  double rratio = i - static_cast<double>(iround);
1989  double cratio = j - static_cast<double>(jround);
1990 
1991  double rfrac = 1.0 - rratio;
1992  double cfrac = 1.0 - cratio;
1993 
1994  unsigned int iround_1 = std::min<unsigned int>(height - 1, iround + 1);
1995  unsigned int jround_1 = std::min<unsigned int>(width - 1, jround + 1);
1996 
1997  double valueR =
1998  (static_cast<double>(row[iround][jround].R) * rfrac + static_cast<double>(row[iround_1][jround].R) * rratio) *
1999  cfrac +
2000  (static_cast<double>(row[iround][jround_1].R) * rfrac + static_cast<double>(row[iround_1][jround_1].R) * rratio) *
2001  cratio;
2002  double valueG =
2003  (static_cast<double>(row[iround][jround].G) * rfrac + static_cast<double>(row[iround_1][jround].G) * rratio) *
2004  cfrac +
2005  (static_cast<double>(row[iround][jround_1].G) * rfrac + static_cast<double>(row[iround_1][jround_1].G) * rratio) *
2006  cratio;
2007  double valueB =
2008  (static_cast<double>(row[iround][jround].B) * rfrac + static_cast<double>(row[iround_1][jround].B) * rratio) *
2009  cfrac +
2010  (static_cast<double>(row[iround][jround_1].B) * rfrac + static_cast<double>(row[iround_1][jround_1].B) * rratio) *
2011  cratio;
2012 
2013  return vpRGBa(static_cast<unsigned char>(vpMath::round(valueR)), static_cast<unsigned char>(vpMath::round(valueG)),
2014  static_cast<unsigned char>(vpMath::round(valueB)));
2015 }
2016 
2020 template <> inline vpRGBf vpImage<vpRGBf>::getValue(double i, double j) const
2021 {
2022  if (i < 0 || j < 0 || i + 1 > height || j + 1 > width) {
2023  throw(vpException(vpImageException::notInTheImage, "Pixel outside of the image"));
2024  }
2025  if (height * width == 0) {
2026  throw vpException(vpImageException::notInitializedError, "Empty image!");
2027  }
2028 
2029  unsigned int iround = static_cast<unsigned int>(floor(i));
2030  unsigned int jround = static_cast<unsigned int>(floor(j));
2031 
2032  double rratio = i - static_cast<double>(iround);
2033  double cratio = j - static_cast<double>(jround);
2034 
2035  double rfrac = 1.0 - rratio;
2036  double cfrac = 1.0 - cratio;
2037 
2038  unsigned int iround_1 = std::min<unsigned int>(height - 1, iround + 1);
2039  unsigned int jround_1 = std::min<unsigned int>(width - 1, jround + 1);
2040 
2041  double valueR =
2042  (static_cast<double>(row[iround][jround].R) * rfrac + static_cast<double>(row[iround_1][jround].R) * rratio) *
2043  cfrac +
2044  (static_cast<double>(row[iround][jround_1].R) * rfrac + static_cast<double>(row[iround_1][jround_1].R) * rratio) *
2045  cratio;
2046  double valueG =
2047  (static_cast<double>(row[iround][jround].G) * rfrac + static_cast<double>(row[iround_1][jround].G) * rratio) *
2048  cfrac +
2049  (static_cast<double>(row[iround][jround_1].G) * rfrac + static_cast<double>(row[iround_1][jround_1].G) * rratio) *
2050  cratio;
2051  double valueB =
2052  (static_cast<double>(row[iround][jround].B) * rfrac + static_cast<double>(row[iround_1][jround].B) * rratio) *
2053  cfrac +
2054  (static_cast<double>(row[iround][jround_1].B) * rfrac + static_cast<double>(row[iround_1][jround_1].B) * rratio) *
2055  cratio;
2056 
2057  return vpRGBf(static_cast<float>(valueR), static_cast<float>(valueG), static_cast<float>(valueB));
2058 }
2059 
2076 template <class Type> inline Type vpImage<Type>::getValue(const vpImagePoint &ip) const
2077 {
2078  return getValue(ip.get_i(), ip.get_j());
2079 }
2080 
2084 template <> inline double vpImage<double>::getValue(const vpImagePoint &ip) const
2085 {
2086  return getValue(ip.get_i(), ip.get_j());
2087 }
2088 
2092 template <> inline unsigned char vpImage<unsigned char>::getValue(const vpImagePoint &ip) const
2093 {
2094  return getValue(ip.get_i(), ip.get_j());
2095 }
2096 
2100 template <> inline vpRGBa vpImage<vpRGBa>::getValue(const vpImagePoint &ip) const
2101 {
2102  return getValue(ip.get_i(), ip.get_j());
2103 }
2104 
2109 template <class Type> inline double vpImage<Type>::getSum() const
2110 {
2111  if ((height == 0) || (width == 0))
2112  return 0.0;
2113 
2114  double res = 0.0;
2115  for (unsigned int i = 0; i < height * width; ++i) {
2116  res += static_cast<double>(bitmap[i]);
2117  }
2118  return res;
2119 }
2120 
2128 template <class Type> inline double vpImage<Type>::getSum(const vpImage<bool> *p_mask, unsigned int &nbValidPoints) const
2129 {
2130  if ((height == 0) || (width == 0))
2131  return 0.0;
2132  if (p_mask == nullptr) {
2133  nbValidPoints = height * width;
2134  return getSum();
2135  }
2136 
2137  double res = 0.0;
2138  nbValidPoints = 0;
2139  unsigned int size = height * width;
2140  for (unsigned int i = 0; i < size; ++i) {
2141  if (p_mask->bitmap[i]) {
2142  res += static_cast<double>(bitmap[i]);
2143  ++nbValidPoints;
2144  }
2145  }
2146  return res;
2147 }
2148 
2157 template <> inline double vpImage<vpRGBa>::getSum() const
2158 {
2159  if ((height == 0) || (width == 0))
2160  return 0.0;
2161 
2162  double res = 0.0;
2163  for (unsigned int i = 0; i < height * width; ++i) {
2164  res += static_cast<double>(bitmap[i].R) + static_cast<double>(bitmap[i].G) + static_cast<double>(bitmap[i].B);
2165  }
2166  return res;
2167 }
2168 
2180 template <> inline double vpImage<vpRGBa>::getSum(const vpImage<bool> *p_mask, unsigned int &nbValidPoints) const
2181 {
2182  if ((height == 0) || (width == 0)) {
2183  return 0.0;
2184  }
2185 
2186  if (p_mask == nullptr) {
2187  nbValidPoints = height * width;
2188  return getSum();
2189  }
2190 
2191  double res = 0.0;
2192  nbValidPoints = 0;
2193  unsigned int size = height * width;
2194  for (unsigned int i = 0; i < size; ++i) {
2195  if (p_mask->bitmap[i]) {
2196  res += static_cast<double>(bitmap[i].R) + static_cast<double>(bitmap[i].G) + static_cast<double>(bitmap[i].B);
2197  ++nbValidPoints;
2198  }
2199  }
2200  return res;
2201 }
2202 
2210 template <> inline double vpImage<vpRGBf>::getSum() const
2211 {
2212  if ((height == 0) || (width == 0))
2213  return 0.0;
2214 
2215  double res = 0.0;
2216  for (unsigned int i = 0; i < height * width; ++i) {
2217  res += static_cast<double>(bitmap[i].R) + static_cast<double>(bitmap[i].G) + static_cast<double>(bitmap[i].B);
2218  }
2219  return res;
2220 }
2221 
2233 template <> inline double vpImage<vpRGBf>::getSum(const vpImage<bool> *p_mask, unsigned int &nbValidPoints) const
2234 {
2235  if ((height == 0) || (width == 0)) {
2236  return 0.0;
2237  }
2238  if (p_mask == nullptr) {
2239  nbValidPoints = height * width;
2240  return getSum();
2241  }
2242 
2243  double res = 0.0;
2244  nbValidPoints = 0;
2245  unsigned int size = height * width;
2246  for (unsigned int i = 0; i < size; ++i) {
2247  if (p_mask->bitmap[i]) {
2248  res += static_cast<double>(bitmap[i].R) + static_cast<double>(bitmap[i].G) + static_cast<double>(bitmap[i].B);
2249  ++nbValidPoints;
2250  }
2251  }
2252  return res;
2253 }
2254 
2284 template <class Type> void vpImage<Type>::sub(const vpImage<Type> &B, vpImage<Type> &C) const
2285 {
2286 
2287  try {
2288  if ((this->getHeight() != C.getHeight()) || (this->getWidth() != C.getWidth()))
2289  C.resize(this->getHeight(), this->getWidth());
2290  }
2291  catch (const vpException &me) {
2292  std::cout << me << std::endl;
2293  throw;
2294  }
2295 
2296  if ((this->getWidth() != B.getWidth()) || (this->getHeight() != B.getHeight())) {
2297  throw(vpException(vpException::memoryAllocationError, "vpImage mismatch in vpImage/vpImage subtraction"));
2298  }
2299 
2300  for (unsigned int i = 0; i < this->getWidth() * this->getHeight(); i++) {
2301  *(C.bitmap + i) = *(bitmap + i) - *(B.bitmap + i);
2302  }
2303 }
2304 
2316 template <class Type> void vpImage<Type>::sub(const vpImage<Type> &A, const vpImage<Type> &B, vpImage<Type> &C) const
2317 {
2318 
2319  try {
2320  if ((A.getHeight() != C.getHeight()) || (A.getWidth() != C.getWidth()))
2321  C.resize(A.getHeight(), A.getWidth());
2322  }
2323  catch (const vpException &me) {
2324  std::cout << me << std::endl;
2325  throw;
2326  }
2327 
2328  if ((A.getWidth() != B.getWidth()) || (A.getHeight() != B.getHeight())) {
2329  throw(vpException(vpException::memoryAllocationError, "vpImage mismatch in vpImage/vpImage subtraction "));
2330  }
2331 
2332  for (unsigned int i = 0; i < A.getWidth() * A.getHeight(); i++) {
2333  *(C.bitmap + i) = *(A.bitmap + i) - *(B.bitmap + i);
2334  }
2335 }
2336 
2345 template <class Type> void vpImage<Type>::performLut(const Type(&)[256], unsigned int)
2346 {
2347  std::cerr << "Not implemented !" << std::endl;
2348 }
2349 
2360 template <> inline void vpImage<unsigned char>::performLut(const unsigned char(&lut)[256], unsigned int nbThreads)
2361 {
2362  unsigned int size = getWidth() * getHeight();
2363  unsigned char *ptrStart = (unsigned char *)bitmap;
2364  unsigned char *ptrEnd = ptrStart + size;
2365  unsigned char *ptrCurrent = ptrStart;
2366 
2367  bool use_single_thread = (nbThreads == 0 || nbThreads == 1);
2368 #if !defined(VISP_HAVE_THREADS)
2369  use_single_thread = true;
2370 #endif
2371 
2372  if (!use_single_thread && getSize() <= nbThreads) {
2373  use_single_thread = true;
2374  }
2375 
2376  if (use_single_thread) {
2377  // Single thread
2378 
2379  while (ptrCurrent != ptrEnd) {
2380  *ptrCurrent = lut[*ptrCurrent];
2381  ++ptrCurrent;
2382  }
2383  }
2384  else {
2385 #if defined(VISP_HAVE_THREADS)
2386  // Multi-threads
2387  std::vector<std::thread *> threadpool;
2388  std::vector<vpImageLut_Param_t *> imageLutParams;
2389 
2390  unsigned int image_size = getSize();
2391  unsigned int step = image_size / nbThreads;
2392  unsigned int last_step = image_size - step * (nbThreads - 1);
2393 
2394  for (unsigned int index = 0; index < nbThreads; index++) {
2395  unsigned int start_index = index * step;
2396  unsigned int end_index = (index + 1) * step;
2397 
2398  if (index == nbThreads - 1) {
2399  end_index = start_index + last_step;
2400  }
2401 
2402  vpImageLut_Param_t *imageLut_param = new vpImageLut_Param_t(start_index, end_index, bitmap);
2403  memcpy(imageLut_param->m_lut, lut, 256 * sizeof(unsigned char));
2404 
2405  imageLutParams.push_back(imageLut_param);
2406 
2407  // Start the threads
2408  std::thread *imageLut_thread = new std::thread(&performLutThread, imageLut_param);
2409  threadpool.push_back(imageLut_thread);
2410  }
2411 
2412  for (size_t cpt = 0; cpt < threadpool.size(); cpt++) {
2413  // Wait until thread ends up
2414  threadpool[cpt]->join();
2415  }
2416 
2417  // Delete
2418  for (size_t cpt = 0; cpt < threadpool.size(); cpt++) {
2419  delete threadpool[cpt];
2420  }
2421 
2422  for (size_t cpt = 0; cpt < imageLutParams.size(); cpt++) {
2423  delete imageLutParams[cpt];
2424  }
2425 #endif
2426  }
2427 }
2428 
2439 template <> inline void vpImage<vpRGBa>::performLut(const vpRGBa(&lut)[256], unsigned int nbThreads)
2440 {
2441  unsigned int size = getWidth() * getHeight();
2442  unsigned char *ptrStart = (unsigned char *)bitmap;
2443  unsigned char *ptrEnd = ptrStart + size * 4;
2444  unsigned char *ptrCurrent = ptrStart;
2445 
2446  bool use_single_thread = (nbThreads == 0 || nbThreads == 1);
2447 #if !defined(VISP_HAVE_THREADS)
2448  use_single_thread = true;
2449 #endif
2450 
2451  if (!use_single_thread && getSize() <= nbThreads) {
2452  use_single_thread = true;
2453  }
2454 
2455  if (use_single_thread) {
2456  // Single thread
2457  while (ptrCurrent != ptrEnd) {
2458  *ptrCurrent = lut[*ptrCurrent].R;
2459  ++ptrCurrent;
2460 
2461  *ptrCurrent = lut[*ptrCurrent].G;
2462  ++ptrCurrent;
2463 
2464  *ptrCurrent = lut[*ptrCurrent].B;
2465  ++ptrCurrent;
2466 
2467  *ptrCurrent = lut[*ptrCurrent].A;
2468  ++ptrCurrent;
2469  }
2470  }
2471  else {
2472 #if defined(VISP_HAVE_THREADS)
2473  // Multi-threads
2474  std::vector<std::thread *> threadpool;
2475  std::vector<vpImageLutRGBa_Param_t *> imageLutParams;
2476 
2477  unsigned int image_size = getSize();
2478  unsigned int step = image_size / nbThreads;
2479  unsigned int last_step = image_size - step * (nbThreads - 1);
2480 
2481  for (unsigned int index = 0; index < nbThreads; index++) {
2482  unsigned int start_index = index * step;
2483  unsigned int end_index = (index + 1) * step;
2484 
2485  if (index == nbThreads - 1) {
2486  end_index = start_index + last_step;
2487  }
2488 
2489  vpImageLutRGBa_Param_t *imageLut_param = new vpImageLutRGBa_Param_t(start_index, end_index, (unsigned char *)bitmap);
2490  memcpy(static_cast<void *>(imageLut_param->m_lut), lut, 256 * sizeof(vpRGBa));
2491 
2492  imageLutParams.push_back(imageLut_param);
2493 
2494  // Start the threads
2495  std::thread *imageLut_thread = new std::thread(&performLutRGBaThread, imageLut_param);
2496  threadpool.push_back(imageLut_thread);
2497  }
2498 
2499  for (size_t cpt = 0; cpt < threadpool.size(); cpt++) {
2500  // Wait until thread ends up
2501  threadpool[cpt]->join();
2502  }
2503 
2504  // Delete
2505  for (size_t cpt = 0; cpt < threadpool.size(); cpt++) {
2506  delete threadpool[cpt];
2507  }
2508 
2509  for (size_t cpt = 0; cpt < imageLutParams.size(); cpt++) {
2510  delete imageLutParams[cpt];
2511  }
2512 #endif
2513  }
2514 }
2515 
2516 template <class Type> void swap(vpImage<Type> &first, vpImage<Type> &second)
2517 {
2518  using std::swap;
2519  swap(first.bitmap, second.bitmap);
2520  swap(first.display, second.display);
2521  swap(first.npixels, second.npixels);
2522  swap(first.width, second.width);
2523  swap(first.height, second.height);
2524  swap(first.row, second.row);
2525 }
2526 
2527 #endif
friend std::ostream & operator<<(std::ostream &s, const vpArray2D< Type > &A)
Definition: vpArray2D.h:547
Class that defines generic functionalities for display.
Definition: vpDisplay.h:173
error that can be emitted by ViSP classes.
Definition: vpException.h:59
@ memoryAllocationError
Memory allocation error.
Definition: vpException.h:76
@ fatalError
Fatal error.
Definition: vpException.h:84
@ notInitializedError
Image not initialized.
@ notInTheImage
Pixel not in the image.
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:82
double get_j() const
Definition: vpImagePoint.h:125
void set_ij(double ii, double jj)
Definition: vpImagePoint.h:315
double get_i() const
Definition: vpImagePoint.h:114
Definition of the vpImage class member functions.
Definition: vpImage.h:69
Type operator()(const vpImagePoint &ip) const
Definition: vpImage.h:297
void destroy()
Destructor : Memory de-allocation.
Definition: vpImage.h:816
void subsample(unsigned int v_scale, unsigned int h_scale, vpImage< Type > &sampled) const
Definition: vpImage.h:1690
void halfSizeImage(vpImage< Type > &res) const
Definition: vpImage.h:1662
vpImage< Type > & operator=(vpImage< Type > other)
Copy operator.
Definition: vpImage.h:1489
Type * operator[](int i)
Definition: vpImage.h:267
Type getMinValue(bool onlyFiniteVal=true) const
Return the minimum value within the bitmap.
Definition: vpImage.h:1206
void quarterSizeImage(vpImage< Type > &res) const
Definition: vpImage.h:1726
void getMinMaxLoc(vpImagePoint *minLoc, vpImagePoint *maxLoc, Type *minVal=nullptr, Type *maxVal=nullptr) const
Get the position of the minimum and/or the maximum pixel value within the bitmap and the correspondin...
Definition: vpImage.h:1451
void init(unsigned int height, unsigned int width)
Set the size of the image.
Definition: vpImage.h:635
Type * operator[](unsigned int i)
operator[] allows operation like I[i] = x.
Definition: vpImage.h:266
void resize(unsigned int h, unsigned int w, const Type &val)
resize the image : Image initialization
Definition: vpImage.h:808
unsigned int getWidth() const
Definition: vpImage.h:249
friend std::ostream & operator<<(std::ostream &s, const vpImage< unsigned char > &I)
Definition: vpImage.h:385
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:787
double getMeanValue(const vpImage< bool > *p_mask, unsigned int &nbValidPoints) const
Return the mean value of the bitmap.
Definition: vpImage.h:977
unsigned int getNumberOfPixel() const
Definition: vpImage.h:211
double getSum() const
Get the sum of the image. For a vpRGBf image, we takes the sum of the R, G and B components.
Definition: vpImage.h:2157
Type getValue(double i, double j) const
Definition: vpImage.h:1841
void doubleSizeImage(vpImage< Type > &res)
Definition: vpImage.h:1768
vpImage(unsigned int height, unsigned int width, Type value)
constructor set the size of the image and init all the pixel
Definition: vpImage.h:744
void performLut(const Type(&lut)[256], unsigned int nbThreads=1)
Definition: vpImage.h:2345
const Type * operator[](int i) const
Definition: vpImage.h:271
double getMeanValue() const
Return the mean value of the bitmap.
Definition: vpImage.h:951
friend std::ostream & operator<<(std::ostream &s, const vpImage< float > &I)
Definition: vpImage.h:437
bool operator==(const vpImage< Type > &I) const
Definition: vpImage.h:1517
void insert(const vpImage< Type > &src, const vpImagePoint &topLeft)
Definition: vpImage.h:1585
void sub(const vpImage< Type > &A, const vpImage< Type > &B, vpImage< Type > &C) const
Definition: vpImage.h:2316
Type getValue(unsigned int i, unsigned int j) const
Definition: vpImage.h:1816
double getValue(double i, double j) const
Definition: vpImage.h:1873
double getStdev() const
Return the standard deviation of the bitmap.
Definition: vpImage.h:991
double getSum() const
Compute the sum of image intensities. For vpRGBa image type, compute the sum (R+G+B) of image intensi...
Definition: vpImage.h:2109
vpImage< Type > operator-(const vpImage< Type > &B) const
Definition: vpImage.h:1567
void init(unsigned int height, unsigned int width, Type value)
Set the size of the image.
Definition: vpImage.h:623
unsigned int getSize() const
Definition: vpImage.h:229
friend void swap(vpImage< Type > &first, vpImage< Type > &second)
Definition: vpImage.h:2516
unsigned int getCols() const
Definition: vpImage.h:175
Type * bitmap
points toward the bitmap
Definition: vpImage.h:139
const Type * operator[](unsigned int i) const
operator[] allows operation like x = I[i]
Definition: vpImage.h:270
double getMeanValue(const vpImage< bool > *p_mask) const
Return the mean value of the bitmap.
Definition: vpImage.h:965
Type getValue(const vpImagePoint &ip) const
Definition: vpImage.h:2076
void sub(const vpImage< Type > &B, vpImage< Type > &C) const
Definition: vpImage.h:2284
vpImage(Type *const array, unsigned int height, unsigned int width, bool copyData=false)
constructor from an image stored as a continuous array in memory
Definition: vpImage.h:754
void init(Type *const array, unsigned int height, unsigned int width, bool copyData=false)
init from an image stored as a continuous array in memory
Definition: vpImage.h:678
Type getMaxValue(bool onlyFiniteVal=true) const
Return the maximum value within the bitmap.
Definition: vpImage.h:878
virtual ~vpImage()
destructor
Definition: vpImage.h:837
unsigned int getHeight() const
Definition: vpImage.h:184
double getStdev(const double &mean, const unsigned int &nbValidPoints, const vpImage< bool > *p_mask) const
Return the standard deviation of the bitmap.
Definition: vpImage.h:1045
unsigned int getRows() const
Definition: vpImage.h:220
friend std::ostream & operator<<(std::ostream &s, const vpImage< double > &I)
Definition: vpImage.h:464
void getMinMaxValue(Type &min, Type &max, bool onlyFiniteVal=true) const
Look for the minimum and the maximum value within the bitmap.
Definition: vpImage.h:1282
vpImage< Type > & operator=(const Type &v)
= operator : Set all the element of the bitmap to a given value v.
Definition: vpImage.h:1504
vpDisplay * display
Definition: vpImage.h:140
vpImage()
constructor
Definition: vpImage.h:764
friend std::ostream & operator<<(std::ostream &s, const vpImage< char > &I)
Definition: vpImage.h:411
void operator()(const vpImagePoint &ip, const Type &v)
Definition: vpImage.h:313
Type operator()(unsigned int i, unsigned int j) const
Definition: vpImage.h:279
bool operator!=(const vpImage< Type > &I) const
Definition: vpImage.h:1540
double getSum(const vpImage< bool > *p_mask, unsigned int &nbValidPoints) const
Compute the sum of image intensities. For vpRGBa image type, compute the sum (R+G+B) of image intensi...
Definition: vpImage.h:2128
void init(unsigned int h, unsigned int w, Type value)
Definition: vpImage.h:623
vpImage(const vpImage< Type > &)
copy constructor
Definition: vpImage.h:843
vpImage(unsigned int height, unsigned int width)
constructor set the size of the image
Definition: vpImage.h:734
double getStdev(const double &mean) const
Return the standard deviation of the bitmap For a vpRGBa or a vpRGBf image, we compute the standard d...
Definition: vpImage.h:1020
double getStdev(const vpImage< bool > *p_mask) const
Return the standard deviation of the bitmap.
Definition: vpImage.h:1002
void operator()(unsigned int i, unsigned int j, const Type &v)
Definition: vpImage.h:285
static int round(double x)
Definition: vpMath.h:403
static bool isFinite(double value)
Definition: vpMath.cpp:178
Definition: vpRGBa.h:61
Definition: vpRGBf.h:57
float B
Blue component.
Definition: vpRGBf.h:126
float G
Green component.
Definition: vpRGBf.h:125
float R
Red component.
Definition: vpRGBf.h:124
#define vpERROR_TRACE
Definition: vpDebug.h:382
VISP_EXPORT uint16_t reinterpret_cast_uchar_to_uint16_LE(unsigned char *const ptr)
Definition: vpEndian.cpp:108