private unsafe float[] createHistogram(UnmanagedImage frame, Rectangle area)
{
int width = frame.Width;
int height = frame.Height;
int stride = frame.Stride;
int pixelSize = Bitmap.GetPixelFormatSize(frame.PixelFormat) / 8;
int offset = stride - area.Width * pixelSize;
float[] histogram = new float[histogramSize];
// stay inside the image
int areaX = Math.Max(area.X, 0);
int areaY = Math.Max(area.Y, 0);
int areaWidth = Math.Min(area.Width, width - areaX);
int areaHeight = Math.Min(area.Height, height - areaY);
if (mode == CamshiftMode.HSL)
{
// Process as HSL
HSL hsl = new HSL();
RGB rgb = new RGB();
byte* src = (byte*)frame.ImageData.ToPointer() + areaX * pixelSize + areaY * stride;
for (int y = 0; y < areaHeight; y++)
{
for (int x = 0; x < areaWidth; x++, src += 3)
{
rgb.Red = (*(src + RGB.R));
rgb.Green = (*(src + RGB.G));
rgb.Blue = (*(src + RGB.B));
Accord.Imaging.HSL.FromRGB(rgb, hsl);
if ((hsl.Saturation >= hslSaturation.Min) && (hsl.Saturation <= hslSaturation.Max) &&
(hsl.Luminance >= hslLuminance.Min) && (hsl.Luminance <= hslLuminance.Max))
histogram[hsl.Hue] += 1;
}
src += offset;
}
}
else if (mode == CamshiftMode.Mixed)
{
// Process in mixed mode
HSL hsl = new HSL();
RGB rgb = new RGB();
byte* src = (byte*)frame.ImageData.ToPointer() + areaX * pixelSize + areaY * stride;
for (int y = 0; y < areaHeight; y++)
{
for (int x = 0; x < areaWidth; x++, src += 3)
{
rgb.Red = (*(src + RGB.R));
rgb.Green = (*(src + RGB.G));
rgb.Blue = (*(src + RGB.B));
Accord.Imaging.HSL.FromRGB(rgb, hsl);
if ((hsl.Saturation >= hslSaturation.Min) && (hsl.Saturation <= hslSaturation.Max) &&
(hsl.Luminance >= hslLuminance.Min) && (hsl.Luminance <= hslLuminance.Max))
histogram[(int)(hsl.Hue * 10 + hsl.Saturation * 100 + hsl.Luminance * 10)] += 1;
}
src += offset;
}
}
else
{
// Process as RGB
byte* src = (byte*)frame.ImageData.ToPointer() + areaX * pixelSize + areaY * stride;
for (int y = 0; y < areaHeight; y++)
{
for (int x = 0; x < areaWidth; x++, src += 3)
{
// (small values are discarded)
int r = (int)(*(src + RGB.R)) >> 4;
int g = (int)(*(src + RGB.G)) >> 4;
int b = (int)(*(src + RGB.B)) >> 4;
histogram[256 * r + 16 * g + b] += 1;
}
src += offset;
}
}
return histogram;
}