It is appeared that in Internet almost impossible to find a Histogram Normalization algorithm. So, here I propose a C++ implementation which uses naive OpenCV data containers. The algorithm is straight-forward but should be easily understandable. I suggest to make a small competition on optimizing it
Code: Select all
void Normalization()
{
register int x, y;
register int i, j;
unsigned int nC[256], n = 0;
double pC[256], pN[256];
double cC[256], cN[256];
for (i=0; i < 256; i++) {
nC[i] = 0;
cC[i] = 0;
}
n = this->cols * this->rows;
//calculate the nubber of occurence
vector<Mat> channels(this->channels());
split(*this, channels);
for (x = 0; x < this->cols; x++)
for (y = 0; y < this->rows; y++) {
int val = 0;
for (i = 0; i < this->channels(); i++) val += channels[i].at<unsigned char>(y, x);
val /= this->channels();
nC[(unsigned char) val]++;
}
//calculating probabilities
for (i=0; i < 256; i++) {
pC[i] = (double) nC[i]/ (double) n;
pN[i] = exp(-pow((double) i - 127, 2) / (2*32*32)) / sqrt(2*Pi*32*32);
//calculatinc cumulative distribution
for (j=0; j<=i; j++) {
cC[i] += pC[j];
cN[i] += pN[j];
}
}
//for (i=0; i < 256; i++) cN[i] = (double ) i / 256; //uncomment this to achieve histogram equalization
for (x = 0; x < this->cols; x++)
for (y = 0; y < this->rows; y++)
for (i = 0; i < this->channels(); i++) {
double arg = cC[channels[i].at<unsigned char>(y,x)];
double Min = abs(cN[0] - arg);
int MinJ = 0;
for (j = 1; j < 256; j++)
if (Min > abs(cN[j] - arg)) {
Min = abs(cN[j] - arg);
MinJ = j;
}
channels[i].at<unsigned char>(y, x) = (unsigned char) MinJ;
}
merge(channels, *this);
channels.clear();
return 0;
}