3

I´m trying to make some kind of image ranking depending on histogram similarities. I take an image, and need to compare its histogram with a database of images ordering them depending in how similar are to the source image. This should work like a filter, taking a subgroup with the most similar images and then compare them with other methods more accurate and computing expensive (Pattern match, SURF, etc...).

The idea behind this is that some images have, for example, lots of blue, and in the library there are 6 images with lots of blue, so it would rank those images the higher. Other images have lots of yellow (blue and green)...

At this point my code is this:

Image<Bgr, byte> colorCard = frame.Copy();

DenseHistogram histBlue = new DenseHistogram(256, new RangeF(0.0f, 255.0f));
DenseHistogram histRed = new DenseHistogram(256, new RangeF(0.0f, 255.0f));
DenseHistogram histGreen = new DenseHistogram(256, new RangeF(0.0f, 255.0f));

Image<Gray, byte> imgBlue = colorCard[0];
Image<Gray, byte> imgRed = colorCard[1];
Image<Gray, byte> imgGreen = colorCard[2];
imgBlue._EqualizeHist();
imgRed._EqualizeHist();
imgGreen._EqualizeHist();
//Also tried whithout equalizing histograms

histBlue.Calculate(new Image<Gray, byte>[] { imgBlue }, true, null);
histRed.Calculate(new Image<Gray, byte>[] { imgRed }, true, null);
histGreen.Calculate(new Image<Gray, byte>[] { imgGreen }, true, null);

List<Match> matchList = new List<Match>();

foreach (String filename in image_paths)
{
    Image<Bgr, byte> imgToCompare = new Image<Bgr, byte>(filename);
    imgToCompare = imgToCompare.PyrDown().PyrUp().PyrDown().PyrUp();

    DenseHistogram histBlueToCompare = new DenseHistogram(256, new RangeF(0.0f, 255.0f));
    DenseHistogram histRedToCompare = new DenseHistogram(256, new RangeF(0.0f, 255.0f));
    DenseHistogram histGreenToCompare = new DenseHistogram(256, new RangeF(0.0f, 255.0f));

    Image<Gray, byte> imgBlueToCompare = colorCard[0];
    Image<Gray, byte> imgRedToCompare = colorCard[1];
    Image<Gray, byte> imgGreenToCompare = colorCard[2];
    imgBlueToCompare._EqualizeHist();
    imgRedToCompare._EqualizeHist();
    imgGreenToCompare._EqualizeHist();

    histBlueToCompare.Calculate(new Image<Gray, byte>[] { imgBlueToCompare }, true, null);
    histRedToCompare.Calculate(new Image<Gray, byte>[] { imgRedToCompare }, true, null);
    histGreenToCompare.Calculate(new Image<Gray, byte>[] { imgGreenToCompare }, true, null);

    double cBlue = CvInvoke.cvCompareHist(histBlue, histBlueToCompare, Emgu.CV.CvEnum.HISTOGRAM_COMP_METHOD.CV_COMP_CORREL);
    double cRed = CvInvoke.cvCompareHist(histRed, histRedToCompare, Emgu.CV.CvEnum.HISTOGRAM_COMP_METHOD.CV_COMP_CORREL);
    double cGreen = CvInvoke.cvCompareHist(histGreen, histGreenToCompare, Emgu.CV.CvEnum.HISTOGRAM_COMP_METHOD.CV_COMP_CORREL);

    double matchValue = (cBlue + cGreen + cRed) / 3.0;

    matchList.Add(new Match(matchValue, Path.GetFileNameWithoutExtension(filename)));
}

matchList = matchList.OrderBy(X => X.MatchValue).ToList<Match>();
foreach (Match m in matchList)
{
    Logger.Log(m.Card + ": " + m.MatchValue);
}

I can compare each color histogram, but don't know how to merge this comparisons to get a single value. Witch (cBlue + cGreen + cRed) / 3.0 I don't get good results.

I read a method to do this is the Earth Mover Distance (EMD). EmguCV has a function called cvCalcEMD2, but I have no idea how to use (what do the parameters mean) it and can't find an example of its usage.

Evans
  • 1,589
  • 1
  • 14
  • 25

2 Answers2

1

If you want the average histogram, you could also directly calculate it on the gray image, like so:

https://stackoverflow.com/a/4906403/586754

Perhaps in your sample

(cBlue + cGreen + cRed) / 3.0

The range is cropped since it calculates in bytes? But also, you should say how it is not adequate to better understand the problem.

Community
  • 1
  • 1
Andreas Reiff
  • 7,961
  • 10
  • 50
  • 104
0

Instead of computing the intensity as

(cBlue + cGreen + cRed) / 3.0

you may want to use the relative luminance, that takes in account the eye sensitivity when combine the three color components to get the "gray level".

Y = 0.2126 * cRed + 0.7152 * cGreen + 0.0722 * cBlue

You can find more about relative luminance here