Isis 3 Programmer Reference
ImageHistogram.cpp
1 
6 /* SPDX-License-Identifier: CC0-1.0 */
7 #include "ImageHistogram.h"
8 
9 #include "Brick.h"
10 #include "ControlNet.h"
11 #include "ControlMeasure.h"
12 
13 #include <iostream>
14 #include <math.h>
15 #include <stdio.h>
16 #include <string>
17 
18 using namespace std;
19 
20 namespace Isis {
21 
30  ImageHistogram::ImageHistogram(double minimum, double maximum, int nbins) :
31  Histogram(minimum, maximum, nbins) {
32  }
33 
34 
56  ImageHistogram::ImageHistogram(Cube &cube, int statsBand, Progress *progress,
57  double startSample, double startLine,
58  double endSample, double endLine,
59  int bins, bool addCubeData) {
60  InitializeFromCube(cube, statsBand, progress, bins, startSample, startLine,
61  endSample, endLine);
62 
63  if (addCubeData) {
64  Brick cubeDataBrick((int)(endSample - startSample + 1),
65  1, 1, cube.pixelType());
66 
67  // if band == 0, then we're gathering data for all bands.
68  int startBand = statsBand;
69  int endBand = statsBand;
70 
71  if (statsBand == 0) {
72  startBand = 1;
73  endBand = cube.bandCount();
74  }
75 
76  if (progress != NULL) {
77  progress->SetText("Gathering histogram");
78  progress->SetMaximumSteps(
79  (int)(endLine - startLine + 1) * (int)(endBand - startBand + 1));
80  progress->CheckStatus();
81  }
82 
83  for (int band = startBand; band <= endBand; band++) {
84  for (int line = (int)startLine; line <= endLine; line++) {
85  cubeDataBrick.SetBasePosition(qRound(startSample), line, band);
86  cube.read(cubeDataBrick);
87  AddData(cubeDataBrick.DoubleBuffer(), cubeDataBrick.size());
88  if (progress != NULL) {
89  progress->CheckStatus();
90  }
91  }
92  }
93  }
94  }
95 
96  void ImageHistogram::InitializeFromCube(Cube &cube, int statsBand,
97  Progress *progress, int nbins, double startSample, double startLine,
98  double endSample, double endLine) {
99  // Make sure band is valid, 0 is valid (means all bands)
100  if ( (statsBand < 0) || (statsBand > cube.bandCount() ) ) {
101  string msg = "Cannot gather histogram for band [" + IString(statsBand) +
102  "]";
103  throw IException(IException::Programmer, msg, _FILEINFO_);
104  }
105 
106  // We need to find the min/max DN value for our histogram bins to be the
107  // correct size.
108  double minDnValue = Null;
109  double maxDnValue = Null;
110 
111  if (cube.pixelType() == UnsignedByte) {
112  // If we can discretely store every data point, then we can use the
113  // possible extent of the data range as our min/max dn values.
114  if (nbins == 0) {
115  minDnValue = 0.0 * cube.multiplier() + cube.base();
116  maxDnValue = 255.0 * cube.multiplier() + cube.base();
117  nbins = 256;
118  }
119  }
120  else if (cube.pixelType() == UnsignedWord) {
121  if (nbins == 0) {
122  minDnValue = 0.0 * cube.multiplier() + cube.base();
123  maxDnValue = 65535.0 * cube.multiplier() + cube.base();
124  nbins = 65536;
125  }
126  }
127  else if (cube.pixelType() == SignedWord) {
128  if (nbins == 0) {
129  minDnValue = -32768.0 * cube.multiplier() + cube.base();
130  maxDnValue = 32767.0 * cube.multiplier() + cube.base();
131  nbins = 65536;
132  }
133  }
134  // 32-bit data covers too big of a range of values to use
135  // the min and max possible values to set our value range.
136  // So, just set the number of bins and then later we will
137  // compute the min and max value in the actual cube.
138  else if (cube.pixelType() == UnsignedInteger ||
139  cube.pixelType() == SignedInteger ||
140  cube.pixelType() == Real) {
141  if (nbins == 0) {
142  nbins = 65536;
143  }
144  }
145  else {
146  IString msg = "Unsupported pixel type";
147  throw IException(IException::Programmer, msg, _FILEINFO_);
148  }
149 
150  if (startSample == Null)
151  startSample = 1.0;
152 
153  if (endSample == Null)
154  endSample = cube.sampleCount();
155 
156  if (startLine == Null)
157  startLine = 1.0;
158 
159  if (endLine == Null)
160  endLine = cube.lineCount();
161 
162  // If we still need our min/max DN values, find them.
163  if (minDnValue == Null || maxDnValue == Null) {
164 
165  Brick cubeDataBrick((int)(endSample - startSample + 1),
166  1, 1, cube.pixelType() );
167  Statistics stats;
168 
169  // if band == 0, then we're gathering stats for all bands. I'm really
170  // not sure that this is correct, a good idea or called from anywhere...
171  // but I don't have time to track down the use case.
172  int startBand = statsBand;
173  int endBand = statsBand;
174 
175  if (statsBand == 0) {
176  startBand = 1;
177  endBand = cube.bandCount();
178  }
179 
180  if (progress != NULL) {
181 
182  progress->SetText("Computing min/max for histogram");
183  progress->SetMaximumSteps(
184  (int)(endLine - startLine + 1) * (int)(endBand - startBand + 1) );
185  progress->CheckStatus();
186  }
187 
188  for (int band = startBand; band <= endBand; band++) {
189  for (int line = (int)startLine; line <= endLine; line++) {
190 
191  cubeDataBrick.SetBasePosition(qRound(startSample), line, band);
192  cube.read(cubeDataBrick);
193  stats.AddData(cubeDataBrick.DoubleBuffer(), cubeDataBrick.size());
194 
195  if (progress != NULL) {
196  progress->CheckStatus();
197  }
198  }
199  }
200 
201  if (stats.ValidPixels() == 0) {
202  minDnValue = 0.0;
203  maxDnValue = 1.0;
204  }
205  else {
206  minDnValue = stats.Minimum();
207  maxDnValue = stats.Maximum();
208  }
209  }
210 
211  // Set the bins and range
212  SetValidRange(minDnValue, maxDnValue);
213  SetBins(nbins);
214  }
215 
218  }
219 
228  void ImageHistogram::AddData(const double *data,
229  const unsigned int count) {
230  Statistics::AddData(data, count);
231 
232  int nbins = p_bins.size();
233  int index;
234  for (unsigned int i = 0; i < count; i++) {
235  if (IsValidPixel(data[i]) && InRange(data[i]) ) {
236  if (BinRangeStart() == BinRangeEnd() ) {
237  index = 0;
238  }
239  else {
240  index = (int) floor((double)(nbins - 1) / (BinRangeEnd() - BinRangeStart()) *
241  (data[i] - BinRangeStart() ) + 0.5);
242  }
243  if (index < 0) index = 0;
244  if (index >= nbins) index = nbins - 1;
245  p_bins[index] += 1;
246  }
247  }
248  }
249 
256  void ImageHistogram::AddData(const double data) {
257  Statistics::AddData(data);
258 
259  int nbins = p_bins.size();
260  int index;
261  if (IsValidPixel(data) && InRange(data) ) {
262  if (BinRangeStart() == BinRangeEnd() ) {
263  index = 0;
264  }
265  else {
266  index = (int) floor((double)(nbins - 1) / (BinRangeEnd() - BinRangeStart() ) *
267  (data - BinRangeStart() ) + 0.5);
268  }
269  if (index < 0) index = 0;
270  if (index >= nbins) index = nbins - 1;
271  p_bins[index] += 1;
272  }
273  }
274 
284  void ImageHistogram::RemoveData(const double *data,
285  const unsigned int count) {
286  Statistics::RemoveData(data, count);
287 
288  int nbins = p_bins.size();
289  int index;
290  for (unsigned int i = 0; i < count; i++) {
291  if (IsValidPixel(data[i]) ) {
292 
293  if (BinRangeStart() == BinRangeEnd() ) {
294  index = 0;
295  }
296  else {
297  index = (int) floor((double)(nbins - 1) / (BinRangeEnd() - BinRangeStart()) *
298  (data[i] - BinRangeStart()) + 0.5);
299  }
300  if (index < 0) index = 0;
301  if (index >= nbins) index = nbins - 1;
302  p_bins[index] -= 1;
303  }
304  }
305  }
306 
318  void ImageHistogram::BinRange(const int index,
319  double &low, double &high) const {
320  if ( (index < 0) || (index >= (int)p_bins.size() ) ) {
321 
322  QString message = Message::ArraySubscriptNotInRange(index);
323  throw IException(IException::Programmer, message, _FILEINFO_);
324  }
325 
326  double binSize = (BinRangeEnd() - BinRangeStart()) / (double)(p_bins.size() - 1);
327  low = BinRangeStart() - binSize / 2.0 + binSize * (double) index;
328  high = low + binSize;
329  }
330 }
Isis::Brick::SetBasePosition
void SetBasePosition(const int start_sample, const int start_line, const int start_band)
This method is used to set the base position of the shape buffer.
Definition: Brick.h:120
Isis::Cube::base
double base() const
Returns the base value for converting 8-bit/16-bit pixels to 32-bit.
Definition: Cube.cpp:1427
Isis::Statistics::AddData
void AddData(const double *data, const unsigned int count)
Add an array of doubles to the accumulators and counters.
Definition: Statistics.cpp:141
Isis::ImageHistogram::AddData
virtual void AddData(const double *data, const unsigned int count)
Add an array of doubles to the histogram counters.
Definition: ImageHistogram.cpp:228
Isis::Progress::CheckStatus
void CheckStatus()
Checks and updates the status.
Definition: Progress.cpp:105
Isis::Cube::read
void read(Blob &blob, const std::vector< PvlKeyword > keywords=std::vector< PvlKeyword >()) const
This method will read data from the specified Blob object.
Definition: Cube.cpp:807
Isis::Histogram::SetBins
void SetBins(const int bins)
Change the number of bins in the histogram and reset counters.
Definition: Histogram.cpp:219
Isis::Progress::SetMaximumSteps
void SetMaximumSteps(const int steps)
This sets the maximum number of steps in the process.
Definition: Progress.cpp:85
Isis::Buffer::DoubleBuffer
double * DoubleBuffer() const
Returns the value of the shape buffer.
Definition: Buffer.h:138
Isis::Brick
Buffer for containing a three dimensional section of an image.
Definition: Brick.h:45
Isis::ImageHistogram::ImageHistogram
ImageHistogram(double minimum, double maximum, int bins=1024)
Constructs a histogram object.
Definition: ImageHistogram.cpp:30
Isis::Statistics::RemoveData
void RemoveData(const double *data, const unsigned int count)
Remove an array of doubles from the accumulators and counters.
Definition: Statistics.cpp:206
Isis::ImageHistogram::RemoveData
virtual void RemoveData(const double *data, const unsigned int count)
Remove an array of doubles from the histogram counters.
Definition: ImageHistogram.cpp:284
Isis::Cube::multiplier
double multiplier() const
Returns the multiplier value for converting 8-bit/16-bit pixels to 32-bit.
Definition: Cube.cpp:1748
Isis::Cube::lineCount
int lineCount() const
Definition: Cube.cpp:1734
Isis::Histogram::SetValidRange
void SetValidRange(const double minimum=Isis::ValidMinimum, const double maximum=Isis::ValidMaximum)
Changes the range of the bins.
Definition: Histogram.cpp:192
Isis::Progress::SetText
void SetText(const QString &text)
Changes the value of the text string reported just before 0% processed.
Definition: Progress.cpp:61
Isis::Histogram::p_bins
std::vector< BigInt > p_bins
The array of counts.
Definition: Histogram.h:121
Isis::Cube::sampleCount
int sampleCount() const
Definition: Cube.cpp:1807
Isis::Cube
IO Handler for Isis Cubes.
Definition: Cube.h:167
Isis::IException
Isis exception class.
Definition: IException.h:91
Isis::Cube::bandCount
virtual int bandCount() const
Returns the number of virtual bands for the cube.
Definition: Cube.cpp:1410
Isis::ImageHistogram::~ImageHistogram
~ImageHistogram()
Destructs a histogram object.
Definition: ImageHistogram.cpp:217
Isis::Progress
Program progress reporter.
Definition: Progress.h:42
Isis::Null
const double Null
Value for an Isis Null pixel.
Definition: SpecialPixel.h:95
Isis::IException::Programmer
@ Programmer
This error is for when a programmer made an API call that was illegal.
Definition: IException.h:146
std
Namespace for the standard library.
Isis::Cube::pixelType
PixelType pixelType() const
Definition: Cube.cpp:1758
Isis::Histogram
Container of a cube histogram.
Definition: Histogram.h:74
Isis::IsValidPixel
bool IsValidPixel(const double d)
Returns if the input pixel is valid.
Definition: SpecialPixel.h:223
Isis::Statistics::Statistics
Statistics(QObject *parent=0)
Constructs an IsisStats object with accumulators and counters set to zero.
Definition: Statistics.cpp:28
Isis::Buffer::size
int size() const
Returns the total number of pixels in the shape buffer.
Definition: Buffer.h:97
Isis::IString
Adds specific functionality to C++ strings.
Definition: IString.h:165
Isis::Message::ArraySubscriptNotInRange
QString ArraySubscriptNotInRange(int index)
This error should be used when an Isis object or application is checking array bounds and the legal r...
Definition: ArraySubscriptNotInRange.cpp:31
Isis::ImageHistogram::BinRange
virtual void BinRange(const int index, double &low, double &high) const
Returns the left edge and right edge values of a bin.
Definition: ImageHistogram.cpp:318
Isis
This is free and unencumbered software released into the public domain.
Definition: Apollo.h:16