Click here to Skip to main content
15,892,005 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
I'm a newbie on using OpenCV and i urgently need help about an application that i'm doing.

I'm working with a CBIR(Content-based Image Retrieval) project which will draw RGB histogram of images and also calculate the distance between other images with query image.

I'm using VS 2008 - MFC and OpenCV Library. The method i wanted to use for calculating the distance is Euclidean Distance(ED), but somehow i failed to work it out.

I found a function - cvCalcEMD2() that can help me calculate the distance between two histogram. To use this function, i need to create signature for my histogram.

Here is an example for creating signature that i found in Learning OpenCv:
//Convert histograms into signatures for EMD matching
//assume we already have 2D histograms hist1 and hist2
//that are both of dimension h_bins by s_bins (though for EMD,
// histograms don’t have to match in size).
//
CvMat* sig1,sig2;
int numrows = h_bins*s_bins;
//Create matrices to store the signature in
//
sig1 = cvCreateMat(numrows, 3, CV_32FC1); //1 count + 2 coords = 3
sig2 = cvCreateMat(numrows, 3, CV_32FC1); //sigs are of type float.
//Fill signatures for the two histograms
//
for( int h = 0; h < h_bins; h++ ) {
    for( int s = 0; s < s_bins; s++ ) {
        float bin_val = cvQueryHistValue_2D( hist1, h, s );
        cvSet2D(sig1,h*s_bins + s,0,cvScalar(bin_val)); //bin value
        cvSet2D(sig1,h*s_bins + s,1,cvScalar(h));       //Coord 1
        cvSet2D(sig1,h*s_bins + s,2,cvScalar(s));       //Coord 2
bin_val = cvQueryHistValue_2D( hist2, h, s );
        cvSet2D(sig2,h*s_bins + s,0,cvScalar(bin_val)); //bin value
        cvSet2D(sig2,h*s_bins + s,1,cvScalar(h));       //Coord 1
        cvSet2D(sig2,h*s_bins + s,2,cvScalar(s));       //Coord 2
    }
}

and also the link to a page that with an example on calc HSV histogram and create signature using it. (It is exactly the same with the code above but with the code where she create histogram)

in the For loop, there is a line where i need to pass in my histogram:

float bin_val = cvQueryHistValue_2D( hist1, h, s );

and in my function for histogram don't have something like the variable h_bins and s_bins

In my program, i calculate/draw my histogram into R, G and B. means, each image i've 3 histogram. eg: CvHistogram *hist_red, *hist_green, *hist_blue;

the function that i used to draw histogram:
C#
void CMy04Dlg::CalcHistogram(IplImage* img)
{
    IplImage* channel = cvCreateImage( cvGetSize(img), 8, 1 );
    IplImage *hist_img = cvCreateImage(cvSize(100,100), 8, 3);
    cvSet( hist_img, cvScalarAll(255), 0 );
    CvHistogram *hist_red;
    CvHistogram *hist_green;
    CvHistogram *hist_blue;
    int hist_size = 256;
    float range[]={0,256};
    float* ranges[] = { range };
    float max_value = 0.0;
    float max = 0.0;
    float w_scale = 0.0;
    /* Create a 1-D Arrays to hold the histograms */
    hist_red = cvCreateHist(1, &hist_size, CV_HIST_ARRAY, ranges, 1);
    hist_green = cvCreateHist(1, &hist_size, CV_HIST_ARRAY, ranges, 1);
    hist_blue = cvCreateHist(1, &hist_size, CV_HIST_ARRAY, ranges, 1);
    /* Set image to obtain RED as Channel of Interest (COI) */
        cvSetImageCOI(img,3);
        cvCopy(img,channel);
        cvResetImageROI(img);
    /* Calculate histogram of the Image and store it in the array */
        cvCalcHist( &channel, hist_red, 0, NULL );
    /* Calculate and Plot the histograms Green and Blue channels as well */
    /* Green channel */
        cvSetImageCOI(img,2);
        cvCopy(img,channel);
        cvResetImageROI(img);
        cvCalcHist( &channel, hist_green, 0, NULL );
    /* Blue channel */
        cvSetImageCOI(img,1);
        cvCopy(img,channel);
        cvResetImageROI(img);
        cvCalcHist( &channel, hist_blue, 0, NULL );

    /* Find the minimum and maximum values of the histograms */
    cvGetMinMaxHistValue( hist_red, 0, &max_value, 0, 0 );
    cvGetMinMaxHistValue( hist_green, 0, &max, 0, 0 );
    max_value = (max > max_value) ? max : max_value;
    cvGetMinMaxHistValue( hist_blue, 0, &max, 0, 0 );
    max_value = (max > max_value) ? max : max_value;// The variable max_value has the maximum of the three histograms
    /* Using the maximum value, Scale/Squeeze the histogram (to fit the image) */
    cvScale( hist_red->bins, hist_red->bins, ((float)hist_img->height)/max_value, 0 );
    cvScale( hist_green->bins, hist_green->bins, ((float)hist_img->height)/max_value, 0 );
    cvScale( hist_blue->bins, hist_blue->bins, ((float)hist_img->height)/max_value, 0 );
        /* Scale/Squeeze the histogram range to image width */
    w_scale = ((float)hist_img->width)/hist_size;
    /* Plot the Histograms */
    for( int i = 0; i < hist_size; i++ )
    {
        cvRectangle( hist_img, cvPoint((int)i*w_scale , hist_img->height),cvPoint((int)(i+1)*w_scale, hist_img->height - cvRound(cvGetReal1D(hist_red->bins,i))),CV_RGB(255,0,0), -1, 8, 0 );
        cvRectangle( hist_img, cvPoint((int)i*w_scale , hist_img->height),cvPoint((int)(i+1)*w_scale, hist_img->height - cvRound(cvGetReal1D(hist_green->bins,i))),CV_RGB(0,255,0), -1, 8, 0 );
        cvRectangle( hist_img, cvPoint((int)i*w_scale , hist_img->height),cvPoint((int)(i+1)*w_scale, hist_img->height - cvRound(cvGetReal1D(hist_blue->bins,i))),CV_RGB(0,0,255), -1, 8, 0 );
    }
ShowImage( hist_img, IDC_IHist );
cvSaveImage("myoutput.jpg",hist_img);
}


How do i use my histogram to create signature?
anyone can help me?
Posted
Updated 13-Nov-10 0:20am
v3

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900