Visual Servoing Platform  version 3.6.1 under development (2024-09-07)
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 
635 template <> inline void vpImage<vpRGBf>::getMinMaxValue(vpRGBf &min, vpRGBf &max, bool onlyFiniteVal) const
636 {
637  if (npixels == 0) {
638  throw(vpException(vpException::fatalError, "Cannot get minimum/maximum values of an empty image"));
639  }
640 
641  min = bitmap[0];
642  max = bitmap[0];
643  if (onlyFiniteVal) {
644  for (unsigned int i = 0; i < npixels; ++i) {
645  if (vpMath::isFinite(bitmap[i].R)) {
646  if (bitmap[i].R < min.R) {
647  min.R = bitmap[i].R;
648  }
649  if (bitmap[i].R > max.R) {
650  max.R = bitmap[i].R;
651  }
652  }
653  if (vpMath::isFinite(bitmap[i].G)) {
654  if (bitmap[i].G < min.G) {
655  min.G = bitmap[i].G;
656  }
657  if (bitmap[i].G > max.G) {
658  max.G = bitmap[i].G;
659  }
660  }
661  if (vpMath::isFinite(bitmap[i].B)) {
662  if (bitmap[i].B < min.B) {
663  min.B = bitmap[i].B;
664  }
665  if (bitmap[i].B > max.B) {
666  max.B = bitmap[i].B;
667  }
668  }
669  }
670  }
671  else {
672  for (unsigned int i = 0; i < npixels; ++i) {
673  if (bitmap[i].R < min.R) {
674  min.R = bitmap[i].R;
675  }
676  if (bitmap[i].R > max.R) {
677  max.R = bitmap[i].R;
678  }
679 
680  if (bitmap[i].G < min.G) {
681  min.G = bitmap[i].G;
682  }
683  if (bitmap[i].G > max.G) {
684  max.G = bitmap[i].G;
685  }
686 
687  if (bitmap[i].B < min.B) {
688  min.B = bitmap[i].B;
689  }
690  if (bitmap[i].B > max.B) {
691  max.B = bitmap[i].B;
692  }
693  }
694  }
695 }
696 
718 template <class Type>
719 void vpImage<Type>::getMinMaxLoc(vpImagePoint *minLoc, vpImagePoint *maxLoc, Type *minVal, Type *maxVal) const
720 {
721  if (npixels == 0) {
722  throw(vpException(vpException::fatalError, "Cannot get location of minimum/maximum "
723  "values of an empty image"));
724  }
725 
726  Type min = bitmap[0], max = bitmap[0];
727  vpImagePoint minLoc_, maxLoc_;
728  for (unsigned int i = 0; i < height; ++i) {
729  for (unsigned int j = 0; j < width; ++j) {
730  if (row[i][j] < min) {
731  min = row[i][j];
732  minLoc_.set_ij(i, j);
733  }
734 
735  if (row[i][j] > max) {
736  max = row[i][j];
737  maxLoc_.set_ij(i, j);
738  }
739  }
740  }
741 
742  if (minLoc != nullptr) {
743  *minLoc = minLoc_;
744  }
745 
746  if (maxLoc != nullptr) {
747  *maxLoc = maxLoc_;
748  }
749 
750  if (minVal != nullptr) {
751  *minVal = min;
752  }
753 
754  if (maxVal != nullptr) {
755  *maxVal = max;
756  }
757 }
758 
769 template <class Type> double vpImage<Type>::getMeanValue(const vpImage<bool> *p_mask, unsigned int *nbValidPoints) const
770 {
771  if ((height == 0) || (width == 0)) {
772  return 0.0;
773  }
774  unsigned int nbPointsInMask = 0;
775  double sum = getSum(p_mask, &nbPointsInMask);
776  if (nbPointsInMask == 0) {
777  throw(vpException(vpException::divideByZeroError, "Division by zero in vpImage::getMeanValue()"));
778  }
779  if (nbValidPoints) {
780  *nbValidPoints = nbPointsInMask;
781  }
782  return sum / nbPointsInMask;
783 }
784 
800 template <class Type> double vpImage<Type>::getStdev(const vpImage<bool> *p_mask, unsigned int *nbValidPoints) const
801 {
802  double mean = getMeanValue(p_mask, nbValidPoints);
803  return getStdev(mean, p_mask);
804 }
805 
824 template <class Type> double vpImage<Type>::getStdev(const double &mean, const vpImage<bool> *p_mask, unsigned int *nbValidPoints) const
825 {
826  if ((height == 0) || (width == 0)) {
827  return 0.0;
828  }
829  const unsigned int size = width * height;
830  double sum = 0.;
831  unsigned int nbPointsInMask = 0;
832  if (p_mask) {
833  if ((p_mask->getWidth() != width) || (p_mask->getHeight() != height)) {
834  throw(vpException(vpException::fatalError, "Cannot compute standard deviation: image and mask size differ"));
835  }
836  for (unsigned int i = 0; i < size; ++i) {
837  if (p_mask->bitmap[i]) {
838  sum += (bitmap[i] - mean) * (bitmap[i] - mean);
839  ++nbPointsInMask;
840  }
841  }
842  }
843  else {
844  for (unsigned int i = 0; i < size; ++i) {
845  sum += (bitmap[i] - mean) * (bitmap[i] - mean);
846  }
847  nbPointsInMask = size;
848  }
849  sum /= static_cast<double>(nbPointsInMask);
850  if (nbValidPoints) {
851  *nbValidPoints = nbPointsInMask;
852  }
853  return std::sqrt(sum);
854 }
855 
856 #ifndef DOXYGEN_SHOULD_SKIP_THIS
875 template <> inline double vpImage<vpRGBa>::getStdev(const double &mean, const vpImage<bool> *p_mask, unsigned int *nbValidPoints) const
876 {
877  if ((height == 0) || (width == 0)) {
878  return 0.0;
879  }
880  const unsigned int size = width * height;
881  double sum = 0.;
882  unsigned int nbPointsInMask = 0;
883  if (p_mask) {
884  if ((p_mask->getWidth() != width) || (p_mask->getHeight() != height)) {
885  throw(vpException(vpException::fatalError, "Cannot compute standard deviation: image and mask size differ"));
886  }
887  for (unsigned int i = 0; i < size; ++i) {
888  if (p_mask->bitmap[i]) {
889  double val = static_cast<double>(bitmap[i].R) + static_cast<double>(bitmap[i].G) + static_cast<double>(bitmap[i].B);
890  sum += (val - mean) * (val - mean);
891  ++nbPointsInMask;
892  }
893  }
894  }
895  else {
896  for (unsigned int i = 0; i < size; ++i) {
897  double val = static_cast<double>(bitmap[i].R) + static_cast<double>(bitmap[i].G) + static_cast<double>(bitmap[i].B);
898  sum += (val - mean) * (val - mean);
899  }
900  nbPointsInMask = size;
901  }
902  sum /= static_cast<double>(nbPointsInMask);
903  if (nbValidPoints) {
904  *nbValidPoints = nbPointsInMask;
905  }
906  return std::sqrt(sum);
907 }
908 
927 template <> inline double vpImage<vpRGBf>::getStdev(const double &mean, const vpImage<bool> *p_mask, unsigned int *nbValidPoints) const
928 {
929  if ((height == 0) || (width == 0)) {
930  return 0.0;
931  }
932  const unsigned int size = width * height;
933  double sum = 0.;
934  unsigned int nbPointsInMask = 0;
935  if (p_mask) {
936  if ((p_mask->getWidth() != width) || (p_mask->getHeight() != height)) {
937  throw(vpException(vpException::fatalError, "Cannot compute standard deviation: image and mask size differ"));
938  }
939  for (unsigned int i = 0; i < size; ++i) {
940  if (p_mask->bitmap[i]) {
941  double val = static_cast<double>(bitmap[i].R) + static_cast<double>(bitmap[i].G) + static_cast<double>(bitmap[i].B);
942  sum += (val - mean) * (val - mean);
943  ++nbPointsInMask;
944  }
945  }
946  }
947  else {
948  for (unsigned int i = 0; i < size; ++i) {
949  double val = static_cast<double>(bitmap[i].R) + static_cast<double>(bitmap[i].G) + static_cast<double>(bitmap[i].B);
950  sum += (val - mean) * (val - mean);
951  }
952  nbPointsInMask = size;
953  }
954  sum /= static_cast<double>(nbPointsInMask);
955  if (nbValidPoints) {
956  *nbValidPoints = nbPointsInMask;
957  }
958  return std::sqrt(sum);
959 }
960 #endif // DOXYGEN_SHOULD_SKIP_THIS
961 
973 template <class Type> inline double vpImage<Type>::getSum(const vpImage<bool> *p_mask, unsigned int *nbValidPoints) const
974 {
975  if ((height == 0) || (width == 0)) {
976  if (nbValidPoints) {
977  *nbValidPoints = 0;
978  }
979  return 0.0;
980  }
981  if (p_mask) {
982  if ((p_mask->getWidth() != width) || (p_mask->getHeight() != height)) {
983  throw(vpException(vpException::fatalError, "Cannot compute sum: image and mask size differ"));
984  }
985  }
986  double res = 0.0;
987  unsigned int nbPointsInMask = 0;
988  unsigned int size = height * width;
989  if (p_mask) {
990  for (unsigned int i = 0; i < size; ++i) {
991  if (p_mask->bitmap[i]) {
992  res += static_cast<double>(bitmap[i]);
993  ++nbPointsInMask;
994  }
995  }
996  }
997  else {
998  for (unsigned int i = 0; i < size; ++i) {
999  res += static_cast<double>(bitmap[i]);
1000  }
1001  nbPointsInMask = size;
1002  }
1003  if (nbValidPoints) {
1004  *nbValidPoints = nbPointsInMask;
1005  }
1006 
1007  return res;
1008 }
1009 
1010 #ifndef DOXYGEN_SHOULD_SKIP_THIS
1022 template <> inline double vpImage<vpRGBa>::getSum(const vpImage<bool> *p_mask, unsigned int *nbValidPoints) const
1023 {
1024  if ((height == 0) || (width == 0)) {
1025  return 0.0;
1026  }
1027  double res = 0.0;
1028  unsigned int nbPointsInMask = 0;
1029  unsigned int size = height * width;
1030  if (p_mask) {
1031  if ((p_mask->getWidth() != width) || (p_mask->getHeight() != height)) {
1032  throw(vpException(vpException::fatalError, "Cannot compute sum: image and mask size differ"));
1033  }
1034  for (unsigned int i = 0; i < size; ++i) {
1035  if (p_mask->bitmap[i]) {
1036  res += static_cast<double>(bitmap[i].R) + static_cast<double>(bitmap[i].G) + static_cast<double>(bitmap[i].B);
1037  ++nbPointsInMask;
1038  }
1039  }
1040  }
1041  else {
1042  for (unsigned int i = 0; i < (height * width); ++i) {
1043  res += static_cast<double>(bitmap[i].R) + static_cast<double>(bitmap[i].G) + static_cast<double>(bitmap[i].B);
1044  }
1045  nbPointsInMask = size;
1046  }
1047  if (nbValidPoints) {
1048  *nbValidPoints = nbPointsInMask;
1049  }
1050  return res;
1051 }
1052 
1064 template <> inline double vpImage<vpRGBf>::getSum(const vpImage<bool> *p_mask, unsigned int *nbValidPoints) const
1065 {
1066  if ((height == 0) || (width == 0)) {
1067  return 0.0;
1068  }
1069  double res = 0.0;
1070  unsigned int nbPointsInMask = 0;
1071  unsigned int size = height * width;
1072  if (p_mask) {
1073  if ((p_mask->getWidth() != width) || (p_mask->getHeight() != height)) {
1074  throw(vpException(vpException::fatalError, "Cannot compute sum: image and mask size differ"));
1075  }
1076  for (unsigned int i = 0; i < size; ++i) {
1077  if (p_mask->bitmap[i]) {
1078  res += static_cast<double>(bitmap[i].R) + static_cast<double>(bitmap[i].G) + static_cast<double>(bitmap[i].B);
1079  ++nbPointsInMask;
1080  }
1081  }
1082  }
1083  else {
1084  for (unsigned int i = 0; i < (height * width); ++i) {
1085  res += static_cast<double>(bitmap[i].R) + static_cast<double>(bitmap[i].G) + static_cast<double>(bitmap[i].B);
1086  }
1087  nbPointsInMask = size;
1088  }
1089  if (nbValidPoints) {
1090  *nbValidPoints = nbPointsInMask;
1091  }
1092  return res;
1093 }
1094 #endif // DOXYGEN_SHOULD_SKIP_THIS
1095 
1096 #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:409
static bool isFinite(double value)
Definition: vpMath.cpp:177
Definition: vpRGBa.h:65
Definition: vpRGBf.h:60
float B
Blue component.
Definition: vpRGBf.h:142
float G
Green component.
Definition: vpRGBf.h:141
float R
Red component.
Definition: vpRGBf.h:140
VISP_EXPORT uint16_t reinterpret_cast_uchar_to_uint16_LE(unsigned char *const ptr)
Definition: vpEndian.cpp:134