AloisD
AloisD

Reputation: 23

Trying to compute my own Histogram without opencv calcHist()

What I'm trying to do is writing a function that calculates a Histogram of a greyscale image with a forwarded Number of Bins (anzBin) which the histograms range is divided in. Then I'm running through the Image Pixels compairing their value to the different Bins and in case a value fits, increasing the value of the Bin by 1

   vector<int> calcuHisto(const IplImage *src_pic, int anzBin) 
   {
   CvSize size = cvGetSize(src_pic);
   int binSize = (size.width / 256)*anzBin;
   vector<int> histogram(anzBin,0);

    for (int y = 0; y<size.height; y++) 
    {
         const uchar *src_pic_point =
        (uchar *)(src_pic->imageData + y*src_pic->widthStep);
       for (int x = 0; x<size.width; x++) 
       {
        for (int z = 0; z < anzBin; z++)
        {
            if (src_pic_point[x] <= z*binSize)
            {
                histogram[src_pic_point[x]]++;
            }

        }

    }
}
return histogram;
}

But unfortunately it's not working... What is wrong here? Please help

Upvotes: 2

Views: 3788

Answers (1)

andrew
andrew

Reputation: 2469

There are a few issues I can see

  1. Your binSize calculation is wrong
  2. Your binning algorithm is one sided, and should be two sided
  3. You aren't incrementing the proper bin when you find a match

1. binsize calculation

bin size = your range / number of bins

2. two sided binning

if (src_pic_point[x] <= z*binSize)

you need a two sided range of values, not a one sided inequality. Imagine you have 4 bins and values from 0 to 255. Your bins should have the following ranges

bin     low     high
0       0       63.75
1       63.75   127.5
2       127.5   191.25
3       191.25  255

For example: a value of 57 should go in bin 0. Your code says the value goes in all the bins! Because its always <= z*binsize You need something something with a lower and upper bound.

3. Incrementing the appropriate bin

You are using z to loop over each bin, so when you find a match you should increment bin z, you don't use the actual pixel value except when determining which bin it belongs to

this would likely be buffer overrun imagine again you have 4 bins, and the current pixel has a value of 57. This code says increment bin 57. But you only have 4 bins (0-3)

histogram[src_pic_point[x]]++;

you want to increment only the bin the pixel value falls into

histogram[z]++;

CODE
With that in mind here is revised code (it is untested, but should work)

vector<int> calcuHisto(const IplImage *src_pic, int anzBin) 
{
    CvSize size = cvGetSize(src_pic);
    double binSize = 256.0 / anzBin;        //new definition
    vector<int> histogram(anzBin,0);        //i don't know if this works so I
                                            //so I will leave it

    //goes through all rows
    for (int y = 0; y<size.height; y++) 
    {
        //grabs an entire row of the imageData
        const uchar *src_pic_point = (uchar *)(src_pic->imageData + y*src_pic->widthStep);

        //goes through each column
        for (int x = 0; x<size.width; x++) 
        {
            //for each bin
            for (int z = 0; z < anzBin; z++)
            {
                //check both upper and lower limits
                if (src_pic_point[x] >= z*binSize && src_pic_point[x] < (z+1)*binSize)
                {
                    //increment the index that contains the point
                    histogram[z]++;
                }
            }
        }
    }
    return histogram;
}

Upvotes: 5

Related Questions