Visual Servoing Platform  version 3.6.1 under development (2025-01-21)
vpImage_getters.h
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2024 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 
34 #ifndef VP_IMAGE_GETTERS_H
35 #define VP_IMAGE_GETTERS_H
36 
37 // Warning: this file shouldn't be included by the user. Internal usage only to reduce length of vpImage.h
38 
51 template <class Type> inline Type vpImage<Type>::getValue(unsigned int i, unsigned int j) const
52 {
53  if ((i >= height) || (j >= width)) {
54  throw(vpException(vpImageException::notInTheImage, "Pixel outside the image"));
55  }
56 
57  return row[i][j];
58 }
59 
76 template <class Type> Type vpImage<Type>::getValue(double i, double j) const
77 {
78  if ((i < 0) || (j < 0) || ((i + 1) > height) || ((j + 1) > width)) {
79  throw(vpException(vpImageException::notInTheImage, "Pixel outside of the image"));
80  }
81  if ((height * width) == 0) {
83  }
84 
85  unsigned int iround = static_cast<unsigned int>(floor(i));
86  unsigned int jround = static_cast<unsigned int>(floor(j));
87 
88  double rratio = i - static_cast<double>(iround);
89  double cratio = j - static_cast<double>(jround);
90 
91  double rfrac = 1.0 - rratio;
92  double cfrac = 1.0 - cratio;
93 
94  unsigned int iround_1 = std::min<unsigned int>(height - 1, iround + 1);
95  unsigned int jround_1 = std::min<unsigned int>(width - 1, jround + 1);
96 
97  double value =
98  (((static_cast<double>(row[iround][jround]) * rfrac) + (static_cast<double>(row[iround_1][jround]) * rratio)) * cfrac) +
99  (((static_cast<double>(row[iround][jround_1]) * rfrac) + (static_cast<double>(row[iround_1][jround_1]) * rratio)) *
100  cratio);
101 
102  return static_cast<Type>(vpMath::round(value));
103 }
104 
108 template <> inline double vpImage<double>::getValue(double i, double j) const
109 {
110  if ((i < 0) || (j < 0) || ((i + 1) > height) || ((j + 1) > width)) {
111  throw(vpException(vpImageException::notInTheImage, "Pixel outside of the image"));
112  }
113  if ((height * width) == 0) {
114  throw vpException(vpImageException::notInitializedError, "Empty image!");
115  }
116 
117  unsigned int iround = static_cast<unsigned int>(floor(i));
118  unsigned int jround = static_cast<unsigned int>(floor(j));
119 
120  double rratio = i - static_cast<double>(iround);
121  double cratio = j - static_cast<double>(jround);
122 
123  double rfrac = 1.0 - rratio;
124  double cfrac = 1.0 - cratio;
125 
126  unsigned int iround_1 = std::min<unsigned int>(height - 1, iround + 1);
127  unsigned int jround_1 = std::min<unsigned int>(width - 1, jround + 1);
128 
129  return (((row[iround][jround] * rfrac) + (row[iround_1][jround] * rratio)) * cfrac) +
130  (((row[iround][jround_1] * rfrac) + (row[iround_1][jround_1] * rratio)) * cratio);
131 }
132 
136 template <> inline unsigned char vpImage<unsigned char>::getValue(double i, double j) const
137 {
138  if ((i < 0) || (j < 0) || ((i + 1) > height) || ((j + 1) > width)) {
139  throw(vpException(vpImageException::notInTheImage, "Pixel outside of the image"));
140  }
141  if ((height * width) == 0) {
142  throw vpException(vpImageException::notInitializedError, "Empty image!");
143  }
144 
145  // alpha architecture is bi-endianness. The following optimization makes testImageGetValue failing
146 #if (defined(VISP_LITTLE_ENDIAN) || defined(VISP_BIG_ENDIAN)) && !(defined(__alpha__) || defined(_M_ALPHA))
147  // Fixed-point arithmetic
148  const uint32_t magic_8 = 8;
149  const uint32_t magic_16 = 16;
150  const uint32_t magic_32 = 32;
151  const uint32_t magic_0x00FF = 0x00FF;
152  const uint32_t precision = 1U << magic_16;
153  uint64_t y = static_cast<uint64_t>(i * precision);
154  uint64_t x = static_cast<uint64_t>(j * precision);
155 
156  uint64_t iround = y & (~0xFFFFU);
157  uint64_t jround = x & (~0xFFFFU);
158 
159  uint64_t rratio = y - iround;
160  uint64_t cratio = x - jround;
161 
162  uint64_t rfrac = precision - rratio;
163  uint64_t cfrac = precision - cratio;
164 
165  uint64_t x_ = x >> magic_16;
166  uint64_t y_ = y >> magic_16;
167 
168  if (((y_ + 1) < height) && ((x_ + 1) < width)) {
169  uint16_t up = vpEndian::reinterpret_cast_uchar_to_uint16_LE(bitmap + (y_ * width) + x_);
170  uint16_t down = vpEndian::reinterpret_cast_uchar_to_uint16_LE(bitmap + ((y_ + 1) * width) + x_);
171 
172  return static_cast<unsigned char>((((((up & magic_0x00FF) * rfrac) + ((down & magic_0x00FF) * rratio)) * cfrac)
173  + (((up >> magic_8) * rfrac) + ((down >> magic_8) * rratio)) * cratio) >> magic_32);
174  }
175  else if ((y_ + 1) < height) {
176  return static_cast<unsigned char>(((row[y_][x_] * rfrac) + (row[y_ + 1][x_] * rratio)) >> magic_16);
177  }
178  else if ((x_ + 1) < width) {
179  uint16_t up = vpEndian::reinterpret_cast_uchar_to_uint16_LE(bitmap + (y_ * width) + x_);
180  return static_cast<unsigned char>((((up & magic_0x00FF) * cfrac) + ((up >> magic_8) * cratio)) >> magic_16);
181  }
182  else {
183  return row[y_][x_];
184  }
185 #else
186  unsigned int iround = static_cast<unsigned int>(floor(i));
187  unsigned int jround = static_cast<unsigned int>(floor(j));
188 
189  if (iround >= height || jround >= width) {
190  throw(vpException(vpImageException::notInTheImage, "Pixel outside the image"));
191  }
192 
193  double rratio = i - static_cast<double>(iround);
194  double cratio = j - static_cast<double>(jround);
195 
196  double rfrac = 1.0 - rratio;
197  double cfrac = 1.0 - cratio;
198 
199  unsigned int iround_1 = std::min<unsigned int>(height - 1, iround + 1);
200  unsigned int jround_1 = std::min<unsigned int>(width - 1, jround + 1);
201 
202  double value =
203  (static_cast<double>(row[iround][jround]) * rfrac + static_cast<double>(row[iround_1][jround]) * rratio) * cfrac +
204  (static_cast<double>(row[iround][jround_1]) * rfrac + static_cast<double>(row[iround_1][jround_1]) * rratio) *
205  cratio;
206  return static_cast<unsigned char>(vpMath::round(value));
207 #endif
208 }
209 
213 template <> inline vpRGBa vpImage<vpRGBa>::getValue(double i, double j) const
214 {
215  if ((i < 0) || (j < 0) || ((i + 1) > height) || ((j + 1) > width)) {
216  throw(vpException(vpImageException::notInTheImage, "Pixel outside of the image"));
217  }
218  if ((height * width) == 0) {
219  throw vpException(vpImageException::notInitializedError, "Empty image!");
220  }
221 
222  unsigned int iround = static_cast<unsigned int>(floor(i));
223  unsigned int jround = static_cast<unsigned int>(floor(j));
224 
225  double rratio = i - static_cast<double>(iround);
226  double cratio = j - static_cast<double>(jround);
227 
228  double rfrac = 1.0 - rratio;
229  double cfrac = 1.0 - cratio;
230 
231  unsigned int iround_1 = std::min<unsigned int>(height - 1, iround + 1);
232  unsigned int jround_1 = std::min<unsigned int>(width - 1, jround + 1);
233 
234  double valueR =
235  (((static_cast<double>(row[iround][jround].R) * rfrac) + (static_cast<double>(row[iround_1][jround].R) * rratio)) *
236  cfrac) +
237  (((static_cast<double>(row[iround][jround_1].R) * rfrac) + (static_cast<double>(row[iround_1][jround_1].R) * rratio)) *
238  cratio);
239  double valueG =
240  (((static_cast<double>(row[iround][jround].G) * rfrac) + (static_cast<double>(row[iround_1][jround].G) * rratio)) *
241  cfrac) +
242  (((static_cast<double>(row[iround][jround_1].G) * rfrac) + (static_cast<double>(row[iround_1][jround_1].G) * rratio)) *
243  cratio);
244  double valueB =
245  (((static_cast<double>(row[iround][jround].B) * rfrac) + (static_cast<double>(row[iround_1][jround].B) * rratio)) *
246  cfrac) +
247  (((static_cast<double>(row[iround][jround_1].B) * rfrac) + (static_cast<double>(row[iround_1][jround_1].B) * rratio)) *
248  cratio);
249 
250  return vpRGBa(static_cast<unsigned char>(vpMath::round(valueR)), static_cast<unsigned char>(vpMath::round(valueG)),
251  static_cast<unsigned char>(vpMath::round(valueB)));
252 }
253 
257 template <> inline vpRGBf vpImage<vpRGBf>::getValue(double i, double j) const
258 {
259  if ((i < 0) || (j < 0) || ((i + 1) > height) || ((j + 1) > width)) {
260  throw(vpException(vpImageException::notInTheImage, "Pixel outside of the image"));
261  }
262  if ((height * width) == 0) {
263  throw vpException(vpImageException::notInitializedError, "Empty image!");
264  }
265 
266  unsigned int iround = static_cast<unsigned int>(floor(i));
267  unsigned int jround = static_cast<unsigned int>(floor(j));
268 
269  double rratio = i - static_cast<double>(iround);
270  double cratio = j - static_cast<double>(jround);
271 
272  double rfrac = 1.0 - rratio;
273  double cfrac = 1.0 - cratio;
274 
275  unsigned int iround_1 = std::min<unsigned int>(height - 1, iround + 1);
276  unsigned int jround_1 = std::min<unsigned int>(width - 1, jround + 1);
277 
278  double valueR =
279  (((static_cast<double>(row[iround][jround].R) * rfrac) + (static_cast<double>(row[iround_1][jround].R) * rratio)) *
280  cfrac) +
281  (((static_cast<double>(row[iround][jround_1].R) * rfrac) + (static_cast<double>(row[iround_1][jround_1].R) * rratio)) *
282  cratio);
283  double valueG =
284  (((static_cast<double>(row[iround][jround].G) * rfrac) + (static_cast<double>(row[iround_1][jround].G) * rratio)) *
285  cfrac) +
286  (((static_cast<double>(row[iround][jround_1].G) * rfrac) + (static_cast<double>(row[iround_1][jround_1].G) * rratio)) *
287  cratio);
288  double valueB =
289  (((static_cast<double>(row[iround][jround].B) * rfrac) + (static_cast<double>(row[iround_1][jround].B) * rratio)) *
290  cfrac) +
291  (((static_cast<double>(row[iround][jround_1].B) * rfrac) + (static_cast<double>(row[iround_1][jround_1].B) * rratio)) *
292  cratio);
293 
294  return vpRGBf(static_cast<float>(valueR), static_cast<float>(valueG), static_cast<float>(valueB));
295 }
296 
313 template <class Type> inline Type vpImage<Type>::getValue(const vpImagePoint &ip) const
314 {
315  return getValue(ip.get_i(), ip.get_j());
316 }
317 
321 template <> inline double vpImage<double>::getValue(const vpImagePoint &ip) const
322 {
323  return getValue(ip.get_i(), ip.get_j());
324 }
325 
329 template <> inline unsigned char vpImage<unsigned char>::getValue(const vpImagePoint &ip) const
330 {
331  return getValue(ip.get_i(), ip.get_j());
332 }
333 
337 template <> inline vpRGBa vpImage<vpRGBa>::getValue(const vpImagePoint &ip) const
338 {
339  return getValue(ip.get_i(), ip.get_j());
340 }
341 
349 template <class Type> Type vpImage<Type>::getMaxValue(bool onlyFiniteVal) const
350 {
351  if (npixels == 0) {
352  throw(vpException(vpException::fatalError, "Cannot compute maximum value of an empty image"));
353  }
354  Type m = bitmap[0];
355  for (unsigned int i = 0; i < npixels; ++i) {
356  if (bitmap[i] > m) {
357  m = bitmap[i];
358  }
359  }
360  (void)onlyFiniteVal;
361  return m;
362 }
363 
372 template <> inline double vpImage<double>::getMaxValue(bool onlyFiniteVal) const
373 {
374  if (npixels == 0) {
375  throw(vpException(vpException::fatalError, "Cannot compute maximum value of an empty image"));
376  }
377  double m = bitmap[0];
378  if (onlyFiniteVal) {
379  for (unsigned int i = 0; i < npixels; ++i) {
380  if ((bitmap[i] > m) && (vpMath::isFinite(bitmap[i]))) {
381  m = bitmap[i];
382  }
383  }
384  }
385  else {
386  for (unsigned int i = 0; i < npixels; ++i) {
387  if (bitmap[i] > m) {
388  m = bitmap[i];
389  }
390  }
391  }
392  return m;
393 }
394 
403 template <> inline float vpImage<float>::getMaxValue(bool onlyFiniteVal) const
404 {
405  if (npixels == 0) {
406  throw(vpException(vpException::fatalError, "Cannot compute maximum value of an empty image"));
407  }
408  float m = bitmap[0];
409  if (onlyFiniteVal) {
410  for (unsigned int i = 0; i < npixels; ++i) {
411  if ((bitmap[i] > m) && (vpMath::isFinite(bitmap[i]))) {
412  m = bitmap[i];
413  }
414  }
415  }
416  else {
417  for (unsigned int i = 0; i < npixels; ++i) {
418  if (bitmap[i] > m) {
419  m = bitmap[i];
420  }
421  }
422  }
423  return m;
424 }
425 
433 template <class Type> Type vpImage<Type>::getMinValue(bool onlyFiniteVal) const
434 {
435  if (npixels == 0) {
436  throw(vpException(vpException::fatalError, "Cannot compute minimum value of an empty image"));
437  }
438  Type m = bitmap[0];
439  for (unsigned int i = 0; i < npixels; ++i) {
440  if (bitmap[i] < m) {
441  m = bitmap[i];
442  }
443  }
444  (void)onlyFiniteVal;
445  return m;
446 }
447 
456 template <> inline double vpImage<double>::getMinValue(bool onlyFiniteVal) const
457 {
458  if (npixels == 0) {
459  throw(vpException(vpException::fatalError, "Cannot compute minimum value of an empty image"));
460  }
461  double m = bitmap[0];
462  if (onlyFiniteVal) {
463  for (unsigned int i = 0; i < npixels; ++i) {
464  if ((bitmap[i] < m) && (vpMath::isFinite(bitmap[i]))) {
465  m = bitmap[i];
466  }
467  }
468  }
469  else {
470  for (unsigned int i = 0; i < npixels; ++i) {
471  if (bitmap[i] < m) {
472  m = bitmap[i];
473  }
474  }
475  }
476  return m;
477 }
478 
487 template <> inline float vpImage<float>::getMinValue(bool onlyFiniteVal) const
488 {
489  if (npixels == 0) {
490  throw(vpException(vpException::fatalError, "Cannot compute minimum value of an empty image"));
491  }
492  float m = bitmap[0];
493  if (onlyFiniteVal) {
494  for (unsigned int i = 0; i < npixels; ++i) {
495  if ((bitmap[i] < m) && (vpMath::isFinite(bitmap[i]))) {
496  m = bitmap[i];
497  }
498  }
499  }
500  else {
501  for (unsigned int i = 0; i < npixels; ++i) {
502  if (bitmap[i] < m) {
503  m = bitmap[i];
504  }
505  }
506  }
507  return m;
508 }
509 
520 template <class Type> void vpImage<Type>::getMinMaxValue(Type &min, Type &max, bool onlyFiniteVal) const
521 {
522  if (npixels == 0) {
523  throw(vpException(vpException::fatalError, "Cannot get minimum/maximum values of an empty image"));
524  }
525 
526  min = bitmap[0];
527  max = bitmap[0];
528  for (unsigned int i = 0; i < npixels; ++i) {
529  if (bitmap[i] < min) {
530  min = bitmap[i];
531  }
532  if (bitmap[i] > max) {
533  max = bitmap[i];
534  }
535  }
536  (void)onlyFiniteVal;
537 }
538 
550 template <> inline void vpImage<double>::getMinMaxValue(double &min, double &max, bool onlyFiniteVal) const
551 {
552  if (npixels == 0) {
553  throw(vpException(vpException::fatalError, "Cannot get minimum/maximum values of an empty image"));
554  }
555 
556  min = bitmap[0];
557  max = bitmap[0];
558  if (onlyFiniteVal) {
559  for (unsigned int i = 0; i < npixels; ++i) {
560  if (vpMath::isFinite(bitmap[i])) {
561  if (bitmap[i] < min) {
562  min = bitmap[i];
563  }
564  if (bitmap[i] > max) {
565  max = bitmap[i];
566  }
567  }
568  }
569  }
570  else {
571  for (unsigned int i = 0; i < npixels; ++i) {
572  if (bitmap[i] < min) {
573  min = bitmap[i];
574  }
575  if (bitmap[i] > max) {
576  max = bitmap[i];
577  }
578  }
579  }
580 }
581 
593 template <> inline void vpImage<float>::getMinMaxValue(float &min, float &max, bool onlyFiniteVal) const
594 {
595  if (npixels == 0) {
596  throw(vpException(vpException::fatalError, "Cannot get minimum/maximum values of an empty image"));
597  }
598 
599  min = bitmap[0];
600  max = bitmap[0];
601  if (onlyFiniteVal) {
602  for (unsigned int i = 0; i < npixels; ++i) {
603  if (vpMath::isFinite(bitmap[i])) {
604  if (bitmap[i] < min) {
605  min = bitmap[i];
606  }
607  if (bitmap[i] > max) {
608  max = bitmap[i];
609  }
610  }
611  }
612  }
613  else {
614  for (unsigned int i = 0; i < npixels; ++i) {
615  if (bitmap[i] < min) {
616  min = bitmap[i];
617  }
618  if (bitmap[i] > max) {
619  max = bitmap[i];
620  }
621  }
622  }
623 }
624 
636 template <> inline void vpImage<vpRGBf>::getMinMaxValue(vpRGBf &min, vpRGBf &max, bool onlyFiniteVal) const
637 {
638  if (npixels == 0) {
639  throw(vpException(vpException::fatalError, "Cannot get minimum/maximum values of an empty image"));
640  }
641 
642  min = bitmap[0];
643  max = bitmap[0];
644  if (onlyFiniteVal) {
645  for (unsigned int i = 0; i < npixels; ++i) {
646  if (vpMath::isFinite(bitmap[i].R)) {
647  if (bitmap[i].R < min.R) {
648  min.R = bitmap[i].R;
649  }
650  if (bitmap[i].R > max.R) {
651  max.R = bitmap[i].R;
652  }
653  }
654  if (vpMath::isFinite(bitmap[i].G)) {
655  if (bitmap[i].G < min.G) {
656  min.G = bitmap[i].G;
657  }
658  if (bitmap[i].G > max.G) {
659  max.G = bitmap[i].G;
660  }
661  }
662  if (vpMath::isFinite(bitmap[i].B)) {
663  if (bitmap[i].B < min.B) {
664  min.B = bitmap[i].B;
665  }
666  if (bitmap[i].B > max.B) {
667  max.B = bitmap[i].B;
668  }
669  }
670  }
671  }
672  else {
673  for (unsigned int i = 0; i < npixels; ++i) {
674  if (bitmap[i].R < min.R) {
675  min.R = bitmap[i].R;
676  }
677  if (bitmap[i].R > max.R) {
678  max.R = bitmap[i].R;
679  }
680 
681  if (bitmap[i].G < min.G) {
682  min.G = bitmap[i].G;
683  }
684  if (bitmap[i].G > max.G) {
685  max.G = bitmap[i].G;
686  }
687 
688  if (bitmap[i].B < min.B) {
689  min.B = bitmap[i].B;
690  }
691  if (bitmap[i].B > max.B) {
692  max.B = bitmap[i].B;
693  }
694  }
695  }
696 }
697 
719 template <class Type>
720 void vpImage<Type>::getMinMaxLoc(vpImagePoint *minLoc, vpImagePoint *maxLoc, Type *minVal, Type *maxVal) const
721 {
722  if (npixels == 0) {
723  throw(vpException(vpException::fatalError, "Cannot get location of minimum/maximum "
724  "values of an empty image"));
725  }
726 
727  Type min = bitmap[0], max = bitmap[0];
728  vpImagePoint minLoc_, maxLoc_;
729  for (unsigned int i = 0; i < height; ++i) {
730  for (unsigned int j = 0; j < width; ++j) {
731  if (row[i][j] < min) {
732  min = row[i][j];
733  minLoc_.set_ij(i, j);
734  }
735 
736  if (row[i][j] > max) {
737  max = row[i][j];
738  maxLoc_.set_ij(i, j);
739  }
740  }
741  }
742 
743  if (minLoc != nullptr) {
744  *minLoc = minLoc_;
745  }
746 
747  if (maxLoc != nullptr) {
748  *maxLoc = maxLoc_;
749  }
750 
751  if (minVal != nullptr) {
752  *minVal = min;
753  }
754 
755  if (maxVal != nullptr) {
756  *maxVal = max;
757  }
758 }
759 
770 template <class Type> double vpImage<Type>::getMeanValue(const vpImage<bool> *p_mask, unsigned int *nbValidPoints) const
771 {
772  if ((height == 0) || (width == 0)) {
773  return 0.0;
774  }
775  unsigned int nbPointsInMask = 0;
776  double sum = getSum(p_mask, &nbPointsInMask);
777  if (nbPointsInMask == 0) {
778  throw(vpException(vpException::divideByZeroError, "Division by zero in vpImage::getMeanValue()"));
779  }
780  if (nbValidPoints) {
781  *nbValidPoints = nbPointsInMask;
782  }
783  return sum / nbPointsInMask;
784 }
785 
801 template <class Type> double vpImage<Type>::getStdev(const vpImage<bool> *p_mask, unsigned int *nbValidPoints) const
802 {
803  double mean = getMeanValue(p_mask, nbValidPoints);
804  return getStdev(mean, p_mask);
805 }
806 
825 template <class Type> double vpImage<Type>::getStdev(const double &mean, const vpImage<bool> *p_mask, unsigned int *nbValidPoints) const
826 {
827  if ((height == 0) || (width == 0)) {
828  return 0.0;
829  }
830  const unsigned int size = width * height;
831  double sum = 0.;
832  unsigned int nbPointsInMask = 0;
833  if (p_mask) {
834  if ((p_mask->getWidth() != width) || (p_mask->getHeight() != height)) {
835  throw(vpException(vpException::fatalError, "Cannot compute standard deviation: image and mask size differ"));
836  }
837  for (unsigned int i = 0; i < size; ++i) {
838  if (p_mask->bitmap[i]) {
839  sum += (bitmap[i] - mean) * (bitmap[i] - mean);
840  ++nbPointsInMask;
841  }
842  }
843  }
844  else {
845  for (unsigned int i = 0; i < size; ++i) {
846  sum += (bitmap[i] - mean) * (bitmap[i] - mean);
847  }
848  nbPointsInMask = size;
849  }
850  sum /= static_cast<double>(nbPointsInMask);
851  if (nbValidPoints) {
852  *nbValidPoints = nbPointsInMask;
853  }
854  return std::sqrt(sum);
855 }
856 
857 #ifndef DOXYGEN_SHOULD_SKIP_THIS
876 template <> inline double vpImage<vpRGBa>::getStdev(const double &mean, const vpImage<bool> *p_mask, unsigned int *nbValidPoints) const
877 {
878  if ((height == 0) || (width == 0)) {
879  return 0.0;
880  }
881  const unsigned int size = width * height;
882  double sum = 0.;
883  unsigned int nbPointsInMask = 0;
884  if (p_mask) {
885  if ((p_mask->getWidth() != width) || (p_mask->getHeight() != height)) {
886  throw(vpException(vpException::fatalError, "Cannot compute standard deviation: image and mask size differ"));
887  }
888  for (unsigned int i = 0; i < size; ++i) {
889  if (p_mask->bitmap[i]) {
890  double val = static_cast<double>(bitmap[i].R) + static_cast<double>(bitmap[i].G) + static_cast<double>(bitmap[i].B);
891  sum += (val - mean) * (val - mean);
892  ++nbPointsInMask;
893  }
894  }
895  }
896  else {
897  for (unsigned int i = 0; i < size; ++i) {
898  double val = static_cast<double>(bitmap[i].R) + static_cast<double>(bitmap[i].G) + static_cast<double>(bitmap[i].B);
899  sum += (val - mean) * (val - mean);
900  }
901  nbPointsInMask = size;
902  }
903  sum /= static_cast<double>(nbPointsInMask);
904  if (nbValidPoints) {
905  *nbValidPoints = nbPointsInMask;
906  }
907  return std::sqrt(sum);
908 }
909 
928 template <> inline double vpImage<vpRGBf>::getStdev(const double &mean, const vpImage<bool> *p_mask, unsigned int *nbValidPoints) const
929 {
930  if ((height == 0) || (width == 0)) {
931  return 0.0;
932  }
933  const unsigned int size = width * height;
934  double sum = 0.;
935  unsigned int nbPointsInMask = 0;
936  if (p_mask) {
937  if ((p_mask->getWidth() != width) || (p_mask->getHeight() != height)) {
938  throw(vpException(vpException::fatalError, "Cannot compute standard deviation: image and mask size differ"));
939  }
940  for (unsigned int i = 0; i < size; ++i) {
941  if (p_mask->bitmap[i]) {
942  double val = static_cast<double>(bitmap[i].R) + static_cast<double>(bitmap[i].G) + static_cast<double>(bitmap[i].B);
943  sum += (val - mean) * (val - mean);
944  ++nbPointsInMask;
945  }
946  }
947  }
948  else {
949  for (unsigned int i = 0; i < size; ++i) {
950  double val = static_cast<double>(bitmap[i].R) + static_cast<double>(bitmap[i].G) + static_cast<double>(bitmap[i].B);
951  sum += (val - mean) * (val - mean);
952  }
953  nbPointsInMask = size;
954  }
955  sum /= static_cast<double>(nbPointsInMask);
956  if (nbValidPoints) {
957  *nbValidPoints = nbPointsInMask;
958  }
959  return std::sqrt(sum);
960 }
961 #endif // DOXYGEN_SHOULD_SKIP_THIS
962 
974 template <class Type> inline double vpImage<Type>::getSum(const vpImage<bool> *p_mask, unsigned int *nbValidPoints) const
975 {
976  if ((height == 0) || (width == 0)) {
977  if (nbValidPoints) {
978  *nbValidPoints = 0;
979  }
980  return 0.0;
981  }
982  if (p_mask) {
983  if ((p_mask->getWidth() != width) || (p_mask->getHeight() != height)) {
984  throw(vpException(vpException::fatalError, "Cannot compute sum: image and mask size differ"));
985  }
986  }
987  double res = 0.0;
988  unsigned int nbPointsInMask = 0;
989  unsigned int size = height * width;
990  if (p_mask) {
991  for (unsigned int i = 0; i < size; ++i) {
992  if (p_mask->bitmap[i]) {
993  res += static_cast<double>(bitmap[i]);
994  ++nbPointsInMask;
995  }
996  }
997  }
998  else {
999  for (unsigned int i = 0; i < size; ++i) {
1000  res += static_cast<double>(bitmap[i]);
1001  }
1002  nbPointsInMask = size;
1003  }
1004  if (nbValidPoints) {
1005  *nbValidPoints = nbPointsInMask;
1006  }
1007 
1008  return res;
1009 }
1010 
1011 #ifndef DOXYGEN_SHOULD_SKIP_THIS
1023 template <> inline double vpImage<vpRGBa>::getSum(const vpImage<bool> *p_mask, unsigned int *nbValidPoints) const
1024 {
1025  if ((height == 0) || (width == 0)) {
1026  return 0.0;
1027  }
1028  double res = 0.0;
1029  unsigned int nbPointsInMask = 0;
1030  unsigned int size = height * width;
1031  if (p_mask) {
1032  if ((p_mask->getWidth() != width) || (p_mask->getHeight() != height)) {
1033  throw(vpException(vpException::fatalError, "Cannot compute sum: image and mask size differ"));
1034  }
1035  for (unsigned int i = 0; i < size; ++i) {
1036  if (p_mask->bitmap[i]) {
1037  res += static_cast<double>(bitmap[i].R) + static_cast<double>(bitmap[i].G) + static_cast<double>(bitmap[i].B);
1038  ++nbPointsInMask;
1039  }
1040  }
1041  }
1042  else {
1043  for (unsigned int i = 0; i < (height * width); ++i) {
1044  res += static_cast<double>(bitmap[i].R) + static_cast<double>(bitmap[i].G) + static_cast<double>(bitmap[i].B);
1045  }
1046  nbPointsInMask = size;
1047  }
1048  if (nbValidPoints) {
1049  *nbValidPoints = nbPointsInMask;
1050  }
1051  return res;
1052 }
1053 
1065 template <> inline double vpImage<vpRGBf>::getSum(const vpImage<bool> *p_mask, unsigned int *nbValidPoints) const
1066 {
1067  if ((height == 0) || (width == 0)) {
1068  return 0.0;
1069  }
1070  double res = 0.0;
1071  unsigned int nbPointsInMask = 0;
1072  unsigned int size = height * width;
1073  if (p_mask) {
1074  if ((p_mask->getWidth() != width) || (p_mask->getHeight() != height)) {
1075  throw(vpException(vpException::fatalError, "Cannot compute sum: image and mask size differ"));
1076  }
1077  for (unsigned int i = 0; i < size; ++i) {
1078  if (p_mask->bitmap[i]) {
1079  res += static_cast<double>(bitmap[i].R) + static_cast<double>(bitmap[i].G) + static_cast<double>(bitmap[i].B);
1080  ++nbPointsInMask;
1081  }
1082  }
1083  }
1084  else {
1085  for (unsigned int i = 0; i < (height * width); ++i) {
1086  res += static_cast<double>(bitmap[i].R) + static_cast<double>(bitmap[i].G) + static_cast<double>(bitmap[i].B);
1087  }
1088  nbPointsInMask = size;
1089  }
1090  if (nbValidPoints) {
1091  *nbValidPoints = nbPointsInMask;
1092  }
1093  return res;
1094 }
1095 #endif // DOXYGEN_SHOULD_SKIP_THIS
1096 
1097 #endif
error that can be emitted by ViSP classes.
Definition: vpException.h:60
@ fatalError
Fatal error.
Definition: vpException.h:72
@ divideByZeroError
Division by zero.
Definition: vpException.h:70
@ 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:320
double get_i() const
Definition: vpImagePoint.h:114
double getSum(const vpImage< bool > *p_mask=nullptr, unsigned int *nbValidPoints=nullptr) const
Compute the sum of image intensities.
Type getMinValue(bool onlyFiniteVal=true) const
Return the minimum value within the bitmap.
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...
unsigned int getWidth() const
Definition: vpImage.h:242
Type getValue(unsigned int i, unsigned int j) const
double getValue(double i, double j) const
Type * bitmap
points toward the bitmap
Definition: vpImage.h:135
double getStdev(const vpImage< bool > *p_mask=nullptr, unsigned int *nbValidPoints=nullptr) const
Return the standard deviation of the bitmap.
Type getMaxValue(bool onlyFiniteVal=true) const
Return the maximum value within the bitmap.
unsigned int getHeight() const
Definition: vpImage.h:181
void getMinMaxValue(Type &min, Type &max, bool onlyFiniteVal=true) const
Look for the minimum and the maximum value within the bitmap.
double getMeanValue(const vpImage< bool > *p_mask=nullptr, unsigned int *nbValidPoints=nullptr) const
Return the mean value of the bitmap.
static int round(double x)
Definition: vpMath.h:410
static bool isFinite(double value)
Definition: vpMath.cpp:177
Definition: vpRGBa.h:70
Definition: vpRGBf.h:64
float B
Blue component.
Definition: vpRGBf.h:157
float G
Green component.
Definition: vpRGBf.h:156
float R
Red component.
Definition: vpRGBf.h:155
VISP_EXPORT uint16_t reinterpret_cast_uchar_to_uint16_LE(unsigned char *const ptr)
Definition: vpEndian.cpp:134