mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-04-22 19:29:04 -05:00
moved histogram stuff to Histogram class, fixed miscalculated standard deviation
This commit is contained in:
@@ -22,6 +22,7 @@
|
||||
// * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
// ****************************************************************************************/
|
||||
#include <modules/iswa/rendering/dataplane.h>
|
||||
#include <modules/multiresvolume/rendering/histogram.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <ghoul/io/texture/texturereader.h>
|
||||
@@ -77,11 +78,10 @@ DataPlane::DataPlane(const ghoul::Dictionary& dictionary)
|
||||
// _avgBenchmarkTime = 0.0;
|
||||
// _numOfBenchmarks = 0;
|
||||
loadTexture();});
|
||||
_useLog.onChange([this](){loadTexture();});
|
||||
_useHistogram.onChange([this](){loadTexture();});
|
||||
_useLog.onChange([this](){ loadTexture(); });
|
||||
_useHistogram.onChange([this](){ loadTexture(); });
|
||||
_dataOptions.onChange([this](){ loadTexture();} );
|
||||
|
||||
|
||||
_transferFunctionsFile.onChange([this](){
|
||||
setTransferFunctions(_transferFunctionsFile.value());
|
||||
});
|
||||
@@ -307,7 +307,7 @@ std::vector<float*> DataPlane::readData(std::string& dataBuffer){
|
||||
for(int option : selectedOptions){
|
||||
data[option] = new float[_dimensions.x*_dimensions.y]{0.0f};
|
||||
}
|
||||
|
||||
|
||||
int numValues = 0;
|
||||
while(getline(memorystream, line)){
|
||||
if(line.find("#") == 0){ //part of the header
|
||||
@@ -343,7 +343,7 @@ std::vector<float*> DataPlane::readData(std::string& dataBuffer){
|
||||
numValues++;
|
||||
}
|
||||
}
|
||||
std::cout << "Actual size: " << numValues << " Expected: " << _dimensions.x*_dimensions.y << std::endl;
|
||||
|
||||
if(numValues != _dimensions.x*_dimensions.y){
|
||||
LWARNING("Number of values read and expected are not the same");
|
||||
return std::vector<float*>();
|
||||
@@ -383,107 +383,41 @@ std::vector<float*> DataPlane::readData(std::string& dataBuffer){
|
||||
|
||||
void DataPlane::processData(float* outputData, std::vector<float>& inputData, float min, float max,float sum){
|
||||
|
||||
// HISTOGRAM
|
||||
// number of levels/bins/values
|
||||
const int levels = 512;
|
||||
// Normal Histogram where "levels" is the number of steps/bins
|
||||
std::vector<int> histogram = std::vector<int>(levels, 0);
|
||||
// Maps the old levels to new ones.
|
||||
std::vector<float> newLevels = std::vector<float>(levels, 0.0f);
|
||||
|
||||
const int numValues = inputData.size();
|
||||
|
||||
//FOR TESTING ONLY
|
||||
//================
|
||||
// float entropyBefore;
|
||||
// float entropyAfter;
|
||||
// std::vector<int> histogramAfter = std::vector<int>(levels, 0);
|
||||
// auto calulateEntropy = [levels, numValues](std::vector<int> histogram){
|
||||
// float entropy;
|
||||
// for(auto frequency : histogram){
|
||||
// if(frequency != 0)
|
||||
// entropy -= ((float)frequency/numValues) * log2((float)frequency/numValues);
|
||||
// }
|
||||
// return entropy;
|
||||
// };
|
||||
//================
|
||||
|
||||
// maps the data values to the histogram bin/index/level
|
||||
auto mapToHistogram = [levels](float val, float varMin, float varMax) {
|
||||
float probability = (val-varMin)/(varMax-varMin);
|
||||
float mappedValue = probability * levels;
|
||||
return glm::clamp(mappedValue, 0.0f, static_cast<float>(levels - 1));
|
||||
};
|
||||
|
||||
Histogram histogram(min, max, 512);
|
||||
|
||||
//Calculate the mean
|
||||
float mean = (1.0 / numValues) * sum;
|
||||
//Calculate the Standard Deviation
|
||||
float standardDeviation = sqrt (((pow(sum, 2.0)) - ((1.0/numValues) * (pow(sum,2.0)))) / (numValues - 1.0));
|
||||
//calulate log mean
|
||||
// logmean /= numValues;
|
||||
|
||||
//HISTOGRAM FUNCTIONALITY
|
||||
//======================
|
||||
|
||||
//Calculate the Standard Deviation
|
||||
float var = 0;
|
||||
for(auto dataValue : inputData){
|
||||
var += pow(dataValue - mean, 2);
|
||||
}
|
||||
float standardDeviation = sqrt ( var / numValues );
|
||||
|
||||
// Histogram functionality
|
||||
if(_useHistogram.value()){
|
||||
for(int i = 0; i < numValues; i++){
|
||||
float v = inputData[i];
|
||||
float pixelVal = mapToHistogram(v, min, max);
|
||||
histogram[(int)pixelVal]++;
|
||||
inputData[i] = pixelVal;
|
||||
}
|
||||
|
||||
// Map mean and standard deviation to histogram levels
|
||||
mean = mapToHistogram(mean , min, max);
|
||||
// logmean = mapToHistogram(logmean , min, max);
|
||||
standardDeviation = mapToHistogram(standardDeviation, min, max);
|
||||
min = 0.0f;
|
||||
max = levels - 1.0f;
|
||||
|
||||
//FOR TESTING
|
||||
//entropyBefore = calulateEntropy(histogram);
|
||||
|
||||
//Calculate the cumulative distributtion function (CDF)
|
||||
float previousCdf = 0.0f;
|
||||
for(int i = 0; i < levels; i++){
|
||||
|
||||
float probability = histogram[i] / (float)numValues;
|
||||
float cdf = previousCdf + probability;
|
||||
cdf = glm::clamp(cdf, 0.0f, 1.0f); //just in case
|
||||
newLevels[i] = cdf * (levels-1);
|
||||
previousCdf = cdf;
|
||||
for(auto dataValue : inputData){
|
||||
histogram.add(dataValue, 1);
|
||||
}
|
||||
histogram.generateEqualizer();
|
||||
standardDeviation = histogram.equalize(standardDeviation);
|
||||
mean = histogram.equalize(mean);
|
||||
}
|
||||
//======================
|
||||
|
||||
for(int i=0; i< numValues; i++){
|
||||
|
||||
|
||||
// Normalize and equalize
|
||||
for(int i=0; i < numValues; i++){
|
||||
float v = inputData[i];
|
||||
|
||||
// if use histogram get the equalized values
|
||||
if(_useHistogram.value()){
|
||||
v = newLevels[(int)v];
|
||||
|
||||
// FOR TESTING
|
||||
//histogramAfter[(int)v]++;
|
||||
|
||||
// Map mean and standard deviation to new histogram levels
|
||||
mean = newLevels[(int) mean];
|
||||
// logmean = newLevels[(int) logmean];
|
||||
standardDeviation = newLevels[(int) standardDeviation];
|
||||
v = histogram.equalize(v);
|
||||
}
|
||||
|
||||
v = normalizeWithStandardScore(v, mean, standardDeviation);
|
||||
v = normalizeWithStandardScore(v, mean, standardDeviation);
|
||||
outputData[i] += v;
|
||||
|
||||
}
|
||||
|
||||
// FOR TESTING
|
||||
// ===========
|
||||
// entropyAfter = calulateEntropy(histogramAfter);
|
||||
// std::cout << "Entropy Before: "<< entropyBefore << std::endl;
|
||||
// std::cout << "Entropy After: "<< entropyAfter << std::endl;
|
||||
// ===========
|
||||
// Histogram equalized = histogram.equalize();
|
||||
// histogram.print();
|
||||
// equalized.print();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -78,6 +78,7 @@ friend class IswaGroup;
|
||||
|
||||
glm::size3_t _dimensions;
|
||||
std::string _dataBuffer;
|
||||
|
||||
// std::shared_ptr<ColorBar> _colorbar;
|
||||
|
||||
//FOR TESTING
|
||||
|
||||
@@ -38,12 +38,14 @@ Histogram::Histogram()
|
||||
: _minBin(0)
|
||||
, _maxBin(0)
|
||||
, _numBins(-1)
|
||||
, _numValues(0)
|
||||
, _data(nullptr) {}
|
||||
|
||||
Histogram::Histogram(float minBin, float maxBin, int numBins)
|
||||
: _minBin(minBin)
|
||||
, _maxBin(maxBin)
|
||||
, _numBins(numBins)
|
||||
, _numValues(0)
|
||||
, _data(nullptr) {
|
||||
|
||||
_data = new float[numBins];
|
||||
@@ -56,12 +58,14 @@ Histogram::Histogram(float minBin, float maxBin, int numBins, float *data)
|
||||
: _minBin(minBin)
|
||||
, _maxBin(maxBin)
|
||||
, _numBins(numBins)
|
||||
, _numValues(0)
|
||||
, _data(data) {}
|
||||
|
||||
Histogram::Histogram(Histogram&& other) {
|
||||
_minBin = other._minBin;
|
||||
_maxBin = other._maxBin;
|
||||
_numBins = other._numBins;
|
||||
_numValues = other._numValues;
|
||||
_data = other._data;
|
||||
other._data = nullptr;
|
||||
}
|
||||
@@ -70,6 +74,7 @@ Histogram& Histogram::operator=(Histogram&& other) {
|
||||
_minBin = other._minBin;
|
||||
_maxBin = other._maxBin;
|
||||
_numBins = other._numBins;
|
||||
_numValues = other._numValues;
|
||||
_data = other._data;
|
||||
other._data = nullptr;
|
||||
return *this;
|
||||
@@ -111,6 +116,7 @@ bool Histogram::add(float bin, float value) {
|
||||
if (binIndex == _numBins) binIndex--; // [0, _numBins[
|
||||
|
||||
_data[binIndex] += value;
|
||||
_numValues++;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -123,6 +129,7 @@ bool Histogram::add(const Histogram& histogram) {
|
||||
_data[i] += data[i];
|
||||
|
||||
}
|
||||
_numValues += histogram._numValues;
|
||||
return true;
|
||||
} else {
|
||||
LERROR("Dimension mismatch");
|
||||
@@ -207,15 +214,72 @@ void Histogram::normalize() {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Will create an internal array for histogram equalization.
|
||||
* Old histogram value is the index of the array, and the new equalized
|
||||
* value will be the value at the index.
|
||||
*/
|
||||
void Histogram::generateEqualizer(){
|
||||
float previousCdf = 0.0f;
|
||||
_equalizer = std::vector<float>(_numBins, 0.0f);
|
||||
for(int i = 0; i < _numBins; i++){
|
||||
|
||||
float probability = _data[i] / (float)_numValues;
|
||||
float cdf = previousCdf + probability;
|
||||
cdf = std::min(1.0f, cdf);
|
||||
_equalizer[i] = cdf * (_numBins-1);
|
||||
previousCdf = cdf;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Will return a equalized histogram
|
||||
*/
|
||||
Histogram Histogram::equalize(){
|
||||
Histogram equalizedHistogram(_minBin, _maxBin, _numBins);
|
||||
|
||||
for(int i = 0; i < _numBins; i++){
|
||||
equalizedHistogram._data[(int)_equalizer[i]] += _data[i];
|
||||
}
|
||||
equalizedHistogram._numValues = _numValues;
|
||||
return std::move(equalizedHistogram);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a value within the domain of this histogram (_minBin < value < maxBin),
|
||||
* this method will use its equalizer to return a histogram equalized result.
|
||||
*/
|
||||
float Histogram::equalize(float value){
|
||||
if (value < _minBin || value > _maxBin) {
|
||||
LWARNING("value being equalized is is not within min and max of histogram");
|
||||
}
|
||||
float normalizedValue = (value-_minBin)/(_maxBin-_minBin);
|
||||
int bin = floor(normalizedValue * _numBins);
|
||||
// If value == _maxBins then bin == _numBins, which is a invalid index.
|
||||
bin = std::min(_numBins-1, bin);
|
||||
|
||||
return _equalizer[bin];
|
||||
}
|
||||
|
||||
float Histogram::entropy(){
|
||||
float entropy;
|
||||
for(int i = 0; i < _numBins; i++){
|
||||
if(_data[i] != 0)
|
||||
entropy -= ((float)_data[i]/_numValues) * log2((float)_data[i]/_numValues);
|
||||
}
|
||||
return entropy;
|
||||
}
|
||||
|
||||
void Histogram::print() const {
|
||||
std::cout << "number of bins: " << _numBins << std::endl
|
||||
<< "range: " << _minBin << " - " << _maxBin << std::endl << std::endl;
|
||||
for (int i = 0; i < _numBins; i++) {
|
||||
float low = _minBin + float(i) / _numBins * (_maxBin - _minBin);
|
||||
float high = low + (_maxBin - _minBin) / float(_numBins);
|
||||
std::cout << "[" << low << ", " << high << "[" << std::endl
|
||||
std::cout << i << " [" << low << ", " << high << "]"
|
||||
<< " " << _data[i] << std::endl;
|
||||
}
|
||||
std::cout << std::endl << std::endl << std::endl<< "==============" << std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -56,6 +56,10 @@ public:
|
||||
|
||||
void normalize();
|
||||
void print() const;
|
||||
void generateEqualizer();
|
||||
Histogram equalize();
|
||||
float equalize (float);
|
||||
float entropy();
|
||||
|
||||
private:
|
||||
int _numBins;
|
||||
@@ -63,6 +67,8 @@ private:
|
||||
float _maxBin;
|
||||
|
||||
float* _data;
|
||||
std::vector<float> _equalizer;
|
||||
int _numValues;
|
||||
|
||||
}; // class Histogram
|
||||
} // namespace openspace
|
||||
|
||||
Reference in New Issue
Block a user