/// <summary> /// see: http://www.songho.ca/dsp/luminance/luminance.html /// </summary> public unsafe static void ConvertBgrToGray_Byte(IImage src, IImage dest) { Bgr8 *srcPtr = (Bgr8 *)src.ImageData; byte *dstPtr = (byte *)dest.ImageData; int width = src.Width; int height = src.Height; int srcShift = src.Stride - width * sizeof(Bgr8); //DO NOT divide with sizeof(Bgr8) as reminder may not be 0!!! int dstShift = dest.Stride - width * sizeof(byte); for (int row = 0; row < height; row++) { for (int col = 0; col < width; col++) { Bgr8.ConvertBgrToGray(srcPtr, dstPtr); srcPtr++; dstPtr++; } srcPtr = (Bgr8 *)((byte *)srcPtr + srcShift); dstPtr = (byte *)((byte *)dstPtr + dstShift); } }
/// <summary> /// Evaluates the function using the provided image. /// </summary> /// <param name="image">Color image.</param> /// <returns>Entropy value. Smaller entropy is preferred.</returns> public unsafe float Evaluate(Bgr <byte>[,] image) { var histogram = new int[HISTOGRAM_SIZE]; using (var uImg = image.Lock()) { Bgr8 *imData = (Bgr8 *)uImg.ImageData; for (int r = 0; r < uImg.Height; r++) { for (int c = 0; c < uImg.Width; c++) { Bgr8 bgr = imData[c]; float intensity = 0.2126f * bgr.R + 0.7152f * bgr.G + 0.0722f * bgr.B; float gain = getGainAt(this, c, r, uImg.Width, uImg.Height); int correction = (int)(gain * intensity); updateHistogram(histogram, correction); } imData = (Bgr8 *)((byte *)imData + uImg.Stride); } } float entropy = calculateEntropy(histogram); return(entropy); }
public unsafe static void ConvertBgrToGray(Bgr8 *bgr, byte *gray) { int val = ((bgr->R << 1) + //2 * red (bgr->G << 2) + bgr->G + //5 * green bgr->B //1 * blue ) >> 3; //divide by 8 *gray = (byte)val; }
public unsafe static void ConvertHsvToBgr(Hsv8 *hsv, Bgr8 *bgr) { if (hsv->S == 0) { bgr->R = hsv->V; bgr->G = hsv->V; bgr->B = hsv->V; return; } int hue = hsv->H * 2; //move to [0-360 range] (only needed for byte!) int hQuadrant = hue / 60; // Hue quadrant 0 - 5 (60deg) int hOffset = hue % 60; // Hue position in quadrant int vs = hsv->V * hsv->S; byte p = (byte)(hsv->V - (vs / 255)); byte q = (byte)(hsv->V - (vs / 255 * hOffset) / 60); byte t = (byte)(hsv->V - (vs / 255 * (60 - hOffset)) / 60); switch (hQuadrant) { case 0: bgr->R = hsv->V; bgr->G = t; bgr->B = p; break; case 1: bgr->R = q; bgr->G = hsv->V; bgr->B = p; break; case 2: bgr->R = p; bgr->G = hsv->V; bgr->B = t; break; case 3: bgr->R = p; bgr->G = q; bgr->B = hsv->V; break; case 4: bgr->R = t; bgr->G = p; bgr->B = hsv->V; break; default: bgr->R = hsv->V; bgr->G = p; bgr->B = q; break; } }
private unsafe static void convertBgrToHsv_Byte(Bgr8 *bgr, Hsv8 *hsv) { byte rgbMin, rgbMax; rgbMin = bgr->R < bgr->G ? (bgr->R < bgr->B ? bgr->R : bgr->B) : (bgr->G < bgr->B ? bgr->G : bgr->B); rgbMax = bgr->R > bgr->G ? (bgr->R > bgr->B ? bgr->R : bgr->B) : (bgr->G > bgr->B ? bgr->G : bgr->B); hsv->V = rgbMax; if (hsv->V == 0) { hsv->H = 0; hsv->S = 0; return; } hsv->S = (byte)(255 * (rgbMax - rgbMin) / rgbMax); if (hsv->S == 0) { hsv->H = 0; return; } int hue = 0; if (rgbMax == bgr->R) { hue = 0 + 60 * (bgr->G - bgr->B) / (rgbMax - rgbMin); if (hue < 0) { hue += 360; } } else if (rgbMax == bgr->G) { hue = 120 + 60 * (bgr->B - bgr->R) / (rgbMax - rgbMin); } else //rgbMax == bgr->B { hue = 240 + 60 * (bgr->R - bgr->G) / (rgbMax - rgbMin); } hsv->H = (byte)(hue / 2); //scale [0-360] -> [0-180] (only needed for byte!) Debug.Assert(hue >= 0 && hue <= 360); }
/// <summary> /// Applies the de-vignetting function to the specified color image. /// </summary> /// <param name="image">Image to correct.</param> public unsafe void Apply(Bgr <byte>[,] image) { using (var uImg = image.Lock()) { Bgr8 *imData = (Bgr8 *)uImg.ImageData; for (int r = 0; r < uImg.Height; r++) { for (int c = 0; c < uImg.Width; c++) { float gain = getGainAt(this, c, r, uImg.Width, uImg.Height); Bgr8 *bgr = &imData[c]; bgr->B = clampToByte((int)(bgr->B * gain)); bgr->G = clampToByte((int)(bgr->G * gain)); bgr->R = clampToByte((int)(bgr->R * gain)); } imData = (Bgr8 *)((byte *)imData + uImg.Stride); } } }