1. ## Histogram Equalization

Greetings everybody.
i have an assigment on image proccesing and amongst other question one of them specifies:calculate the equalized histogram of a grayscale
image and show statistical data of your choice between the input and output images.
I am having trouble equalizing the histogram.I have googled around for a couple of days now and i think i could use some help, either im missing the whole picture or minor details that cause problems.
my code is below:
Code:
//                          original histogram
for (i=0; i<lines; i++)
for (j=0; j<columns; j++)
hist[image_in[i][j]]++;

//histogram max and min
int hmax=-1,hmin=257;
for(int i=0;i<256;i++)
{
if (hist[i]>hmax)
hmax=hist[i];
if (hist[i]<hmin)
hmin=hist[i];
}

//                    Probability table
float prt[256];
int pixels=lines*columns;
for(int i=0;i<256;i++);
prt[i]=hist[i]/pixels;

//                            CumulativeDistributionFunction
float cdfmax=-1,cdfmin=257;
float cdf[256];
cdf[0]=prt[0];
for(int i=1;i<256;i++)
{
cdf[i]=prt[i]+cdf[i-1];
if(cdf[i]>cdfmax)
cdfmax=cdf[i];
if(cdf[i]<cdfmin)
cdfmin=cdf[i];
}

// final image
for (int i=0;i<lines;i++)
{
for(int j=0;j<columns;j++)
{
image_out[i][j]=(unsigned char)(((cdf[image_in[i][j]]-cdfmin)/(pixels-cdfmin))*255);
}
}
can anyone point out anything that might help?
im thinking that my equalization formula is wrong, i might have incorrectly translated the mathematical formula from wikipedia to C code but i cant figure out why.

2. you don't show us all your data types. what types are hmax,hmin,hist[]? it looks like all variables should be floats except the images themselves.

is the loop computing cfg[i] supposed to go 0..255 or 0..number of pixels. wikipedia isn't clear

3. hmax hmin and hist are integers. as for the later i am not sure...

4. A greyscale image has 256 separate greyscale levels. So that trivially gives you a 256 bin histogram of colour counts.
Now we want to reassign colour values to the histogram so that all the levels are as equally occupied as possible. There's no way of doing this without losing some information (assuming that every bin is occupied). Basically we want to unite low-occupied regions of the histogram, and spread out the highly-occupied regions.

An easy way to do it is to define a cumulative distribution function, between 0 and 1, for each greyscale value 0-255. This represents the proportion of pixels in the range 0-x for that value.

When we've got 256 cdf values (all incrementing) for the original histogram, the new value becomes cdf * 255. Because we round to the nearest integer, some bins will now have equal values, whilst other values won't be represented at all.

histogram - very easy to write, just declare an array of 256 integers, set to zero to begin with, and go through the image summing.
cumulative distribution function - again very easy to write. decare an array of 256 floats. Then step through the histogram keeping a running sum, and divide by the total number of pixels.
equalisation step - very easy to write. Simply go throught he 256 cdf values and assign the new value to the old value.

Histogram equalisation function - not easy to write in one go, but
very easy once you have those three functions debugged and working.

5. after some testing i see that prt[i] values are 0.000000 for all indexes. am i doing something wrong? hist[i] is an int, pixels are int and prt is float.
hist is full of values, theyr sum is equal to pixels so everything is fine with that. Why
hist[i]/pixels gives no result to prt[i]?

6. Originally Posted by Cursius
after some testing i see that prt[i] values are 0.000000 for all indexes. am i doing something wrong? hist[i] is an int, pixels are int and prt is float.
hist is full of values, theyr sum is equal to pixels so everything is fine with that. Why
hist[i]/pixels gives no result to prt[i]?
C-FAQ - Question 3.15

Bye, Andreas

7. i have already tried casting and i still dont get any results

8. Code:
//                    Probability table
float prt[256];
int pixels=lines*columns;
for(int i=0;i<256;i++);
prt[i]=hist[i]/pixels;
Do you know how to use a debugger?
Single stepping through the code would have shown you that your loop doesn't do anything except incrementing "i";

Bye, Andreas

9. aaahh thank you mate, i had gone through the code a million times and i never noticed that ;....

10. as my first contribution to this site i present you the code.It needs an input of a grayscale image and it will produce an output of the enchanced image, along with basic statistical values such as average color and dispersion of both images.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
main()
{
int i,j,k,l, lines, columns;

unsigned char	*image_in[2048], *image_out[2048];
int hist[256];

char	inp_fn[30],
out_fn[30];

FILE *inp, *out;

printf ("Enter input file name : ");
gets( inp_fn );

printf ("Enter output file name : ");
gets( out_fn );

printf ("Enter no. of lines : ");
scanf("%d", &lines);

printf ("Enter no. of columns : ");
scanf("%d", &columns);

for  (i=0;i<lines;i++)
image_in[i]=(unsigned char*)malloc((columns) * sizeof(unsigned char));

for  (i=0;i<lines;i++)
image_out[i]=(unsigned char*)malloc((columns) * sizeof(unsigned char));

for(int i=0;i<256;i++)
hist[i]=0;

int pixels=lines*columns;
printf("\nTotal pixels: %d",pixels);
if ( ((inp=fopen (inp_fn,"rb")) == NULL))
printf ("Not a valid input file\n");
else
{

for  (i=0;i<lines;i++)

fclose(inp);
}
//************************************************************************************/

//                          original histogram
for (i=0; i<lines; i++)
{  for (j=0; j<columns; j++)
{
hist[image_in[i][j]]++;
}
}

//                          Histogram stats
// min max avg

int hsum=0;
float avg;
int hmax=-1,hmin=257;
for(int i=0;i<256;i++)
{
if (hist[i]>hmax)
hmax=hist[i];
if (hist[i]<hmin)
hmin=hist[i];
}

for(int i=0;i<256;i++)
hsum+=hist[i]*i;

avg=(float)hsum/pixels;
//                   Dispersion of data for original image (Standar Deviation)
float cSum=0;
float cTable[256];
float avgDev=0;
for(int i=0;i<256;i++)
{
cTable[i]=(abs((i-(int)avg)))*(abs((i-(int)avg)));
cTable[i]=hist[i]*cTable[i];
cSum+=cTable[i];
}
cSum=cSum/pixels;

avgDev=sqrt(cSum);

printf("\nOriginal Histogram statistics");
printf("\n ~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
printf("\nHistogram sum: %d \n Histogram Max: %d\n Histogram Min: %d \n Histogram Avg: %f \n Standar Deviation: %f",hsum,hmax,hmin,avg,avgDev);

//                                           Probability table

float prt[256];
for(int i=0;i<256;i++)
prt[i]=(float)hist[i]/pixels;

//                                 Cumulative Distribution Function
float cdfmax=-1,cdfmin=257;
float cdf[256];
cdf[0]=prt[0];
for(int i=1;i<256;i++)
{
cdf[i]=prt[i]+cdf[i-1];
if(cdf[i]>cdfmax)
cdfmax=cdf[i];
if(cdf[i]<cdfmin)
cdfmin=cdf[i];
}

//                                            Final Image
for (int i=0;i<lines;i++)
{
for(int j=0;j<columns;j++)
{
image_out[i][j]=cdf[image_in[i][j]]*255;
}
}

//                                       Equalized Histogram
int eHist[256];
for(int i=0;i<256;i++)
for(int j=0;j<256;j++)
eHist[image_out[i][j]]++;

//                                 Equalized Histogram stats
int ehsum=0;
float eavg;
int ehmax=-1,ehmin=257;
for(int i=0;i<256;i++)
{
if (eHist[i]>ehmax)
ehmax=eHist[i];
if (eHist[i]<ehmin)
ehmin=eHist[i];
}

for(int i=0;i<256;i++)
ehsum+=eHist[i]*i;

eavg=(float)ehsum/pixels;
//                             Dispersion of data for Equalised Histogram
float ecSum=0;
float ecTable[256];
float eavgDev=0;
for(int i=0;i<256;i++)
{
ecTable[i]=(abs((i-(int)eavg)))*(abs((i-(int)eavg)));
ecTable[i]=eHist[i]*ecTable[i];
ecSum+=ecTable[i];
}
ecSum=ecSum/pixels;

eavgDev=sqrt(ecSum);

printf("\n\n Equalised Histogram statistics");
printf("\n ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
printf("\n EqHistogram sum: %d \n EqHistogram Max: %d \n EqHistogram Min: %d \n EqHistogram Avg: %f \n Standar Deviation: %f",ehsum,ehmax,ehmin,eavg,eavgDev);

//*********************WRITE IMAGE ****************************************************
out=fopen (out_fn, "wb");

for  (i=0;i<lines;i++)
fwrite(image_out[i], sizeof(unsigned char), columns, out);

fclose(out);

for (i=0;i<lines;i++)
free(image_in[i]);
for (i=0;i<lines;i++)
free(image_out[i]);
printf("\n");
system("pause");
}
it is not really refined or optimized as i have more work to do for an other project.there are basic comments that should be enough though