0
votes

I am using EmguCV(c#) histogram to compare two HSV images. But sometimes I get negative values. I assumed that when I compare 2 histogram values, the value will be in the interval <0 and 1>. However, some of the values of hue or saturation are sometimes negative numbers like -0.145.

Firstly, I get byte image array, which I convert into Image<Hsv, Byte> - img1.

Image<Hsv, Byte> img1 = null;
Mat byteImageMat = new Mat();
Mat hsvMat = new Mat();
CvInvoke.Imdecode(request.ByteImage, Emgu.CV.CvEnum.ImreadModes.AnyColor, byteImageMat);
CvInvoke.CvtColor(byteImageMat, hsvMat, ColorConversion.Bgr2Hsv);
img1 = hsvMat.ToImage<Hsv, Byte>();

Then I create DenseHistogram and spliting individual channels.

DenseHistogram ComparedHistoHue = new DenseHistogram(180, new RangeF(0, 180));
DenseHistogram ComparedHistoSaturation = new DenseHistogram(256, new RangeF(0, 256));
DenseHistogram ComparedHistoBrightness = new DenseHistogram(256, new RangeF(0, 256));
Image<Gray, Byte> hueChannel = img1[0];
Image<Gray, Byte> saturationChannel = img1[1];
Image<Gray, Byte> brightnessChannel = img1[2];

After that I calculate histograms

ComparedHistoHue.Calculate(new Image<Gray, Byte>[] { hueChannel }, false, null);
ComparedHistoSaturation.Calculate(new Image<Gray, Byte>[] { saturationChannel }, false, null);
ComparedHistoBrightness.Calculate(new Image<Gray, Byte>[] { brightnessChannel }, false, null);

At this point, I loaded histogram from file which I created before and assign it into Mat (loadedMatHue, loadedMatSaturation and loadedMatBrightness).

double hue = CvInvoke.CompareHist(loadedMatHue, ComparedHistoHue, Emgu.CV.CvEnum.HistogramCompMethod.Correl);
double satuation = CvInvoke.CompareHist(loadedMatSaturation, ComparedHistoSaturation, Emgu.CV.CvEnum.HistogramCompMethod.Correl);
double brightnes = CvInvoke.CompareHist(loadedMatBrightness, ComparedHistoBrightness, Emgu.CV.CvEnum.HistogramCompMethod.Correl);

Can somebody tell me, why is in hue or saturation variable negative value? In my opinion and tests, there is always only one negative value at one momemnt across the double variables.

1

1 Answers

1
votes

For HSV, the idea that the numbers would be between 0 and 1 is incorrect. If you want your image to have values between 0 and 1, then that image would have to be in grayscale.

In HSV, you split it up into three definitions, Hue, Saturation, and Value.

Hue is stored from 0 to 360 degrees, but can become negative if you rotate the hue past 0.

Saturation is considered from 0 to 1, i.e grayscale values. If you have negative values in this channel, disregard them, as the lowest that this value should be is 0. The same can be said for the highest value, which will be 1 since the highest value of a grayscale channel can only be one. Like I said before, its best to think of this channel in terms of grayscale from 0 to 1.

Value is very similar to saturation, the only difference being that value is considered the "lightness of the color, by the given S[saturation]" This value also can only be between 0 and 1, and any values outside of this space should be clipped.

If you want a more in depth explanation, you can check out this Stack post, which is very detailed and I thought it should be credited in this post.

If you do have to clip these values, you can always access the pixel values for each channel using some sample code below.

Image<Hsv,Byte> sampleImage = new Image<Hsv,Byte>("path\to\image");

//X and y are the pixel coordinates on an image
//Hue channel
byte hue = sampleImage.Data[y,x,0];
//Saturation channel
byte sat = sampleImage.Data[y,x,1];
//Value channel
byte val = sampleImage.Data[y,x,2];

You can throw these values inside of a loop and check if a pixel is outside the boundaries, and if it is replace it with the high or low value respectively.