Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenCV - Confusion using calcHist

I've read the documentation for calcHist() many times, but I think my inexperience with OpenCV and rusty programming skills are completely precluding me from understanding it.

I'm looking to count pixels in one channel of an HSV image (Hue, or channel[0]) for segmentation purposes using 10 bins that closely approximate color according to something like (let's use this as an example, I stole the ranges off the web - fwiw, it seems erroneous to omit purple-red):

Red: 0-19 & 330-360 Red-Yellow (RY): 20-49 Yellow: 50-69 YG: 70-84 Green: 85-170 GB: 171-191 Blue: 192-264 BP: 265-289 Purple: 290-329

And so on...

So how do I do this with calcHist?

I'm as far as:

#include <opencv2/opencv.hpp>
#include <vector>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>

using namespace std;
using namespace cv;

int main(int argc, char *argv[])
{
    Mat scene, sceneHSV, dest, histo;
    int numImages = 1, histChannel[] = {0}, dims = 1, histSize[] = {10};

    float redRange[] = {0, 10};
    float roRange[] = {10, 25};
    float orangeRange[] = {25, 35};
    float oyRange[] = {35, 42};
    float yellowRange[] = {42, 85};
    float ygRange[] = {85, 96};
    float greenRange[] = {96, 132};
    float gbRange[] = {132, 145};
    float blueRange[] = {145, 160};
    float bpRange[] = {160, 165};
    float purpleRange[] = {165, 180};

    const float* ranges[] = {redRange, roRange, orangeRange, oyRange, yellowRange, ygRange, greenRange, gbRange, blueRange, bpRange, purpleRange};

    vector<Mat> channels;

    scene = imread("Apple.jpg", 1);
    if (scene.data == NULL)
    {
        cout<<"FAIL"<<endl;
        cin.get();
    }

    cvtColor(scene, sceneHSV, CV_BGR2HSV);
    dilate(sceneHSV, sceneHSV, Mat(), Point(-1, -1), 1, BORDER_CONSTANT, 1);
    pyrMeanShiftFiltering(sceneHSV, dest, 2, 50, 3);
    split(sceneHSV, channels); 

    calcHist(&scene, 1, histChannel, Mat(), histo, dims, histSize, ranges, false, false); 

    cout<<histo<<endl;

    waitKey(0);

    return 0;
}

Now what? What would the arguments to calcHist look like in this case, and what does the output histogram look like? Simply a 1x9 array full of ints?

Thanks very much.

like image 800
TonyRo Avatar asked Mar 04 '13 21:03

TonyRo


1 Answers

I modified the code from here

You might also want to take a look at the documentation of cvtColor here

Note that I have not tried to compile or run this code so I do not guarantee that it will work. But nonetheless, it might be useful as a reference.

Mat hist;
int nimages = 1; // Only 1 image, that is the Mat scene.
int channels[] = {0} // Index for hue channel
int dims = 1 // Only 1 channel, the hue channel
int histSize[] = {9} // 9 bins, 1 each for Red, RY, Yellow, YG etc.
float hranges[] = { 0, 180 }; // hue varies from 0 to 179, see cvtColor
const float *ranges[] = {hranges};

// Compute the histogram.
calcHist(&scene, 
nimages, 
channels, 
Mat(), // No mask
hist, dims, histSize, ranges, uniform=true)

// Now hist will contain the counts in each bin.
// Lets just print out the values. Note that you can output Mat using std::cout
cout << "Histogram: " << endl << hist << endl;

// To access the individual bins, you can either iterate over them
// or use hist.at<uchar>(i, j); Note that one of the index should be 0
// because hist is 1D histogram. Print out hist.rows and hist.cols to see if hist is a N x 1 or 1 x N matrix.
/*
MatIterator_<uchar> it, end;
int binIndex = 0;
for( it = hist.begin<uchar>(), end = hist.end<uchar>(); it != end; ++it)
{
  printf("Count in %d bin: %d\n", binIndex, *it);
  ++binIndex;
}
*/
like image 93
lightalchemist Avatar answered Oct 22 '22 20:10

lightalchemist