moved histogram stuff to Histogram class, fixed miscalculated standard deviation

This commit is contained in:
Michael Nilsson
2016-05-13 15:16:43 -04:00
parent c2443a9ee2
commit d37de2e582
4 changed files with 100 additions and 95 deletions
+28 -94
View File
@@ -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();
}
+1
View File
@@ -78,6 +78,7 @@ friend class IswaGroup;
glm::size3_t _dimensions;
std::string _dataBuffer;
// std::shared_ptr<ColorBar> _colorbar;
//FOR TESTING
+65 -1
View File
@@ -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