/// <summary> /// Gets the CIE-LAB equivalent. If Alpha channel was specified, it will be included. /// </summary> /// <returns></returns> public Color ToColor() { if (!this._color.HasValue) { return(LabColor.ToColor(this)); } return(this._color.Value); }
public LabColor(byte red, byte green, byte blue, byte alpha = 255) { LabColor labColor = LabColor.FromArgb(red, green, blue, alpha); this.L = labColor.L; this.A = labColor.A; this.B = labColor.B; this.Alpha = labColor.Alpha; this._color = Color.FromArgb(alpha, red, green, blue); }
/// <summary> /// This is only for testing. It will create a sample from the image and give it a red hue. /// </summary> /// <param name="bytes"></param> /// <param name="stride"></param> private static void FindTableClothColor(ref byte[] bytes, int stride) { //LabColor labColor1 = new LabColor(51f, 2, 2); //LabColor labColor2 = new LabColor(50f, 0, 0); //float delta = LabColor.FindDeltaE94(labColor1, labColor2); int bytesPerPixel = 4; // each pixel is represented by 4 bytes int imageHeight = bytes.Length / stride; // get the height of the image represented by our bytes int imageWidth = stride / bytesPerPixel; Size quadrantSize = new Size(imageWidth / 2, imageHeight / 2); // split the image into 4 equally and get size of 1 piece // using our quadrant, create a rectangle at the center of the image Rectangle sampleRect = new Rectangle(new Point(quadrantSize.Width / 2, quadrantSize.Height / 2), quadrantSize); // dictionary which will hold the number of occurrences for each color in our quadrant sample Dictionary <Color, int> colorPopularity = new Dictionary <Color, int>(); // since the table cloth will be the most popular color we need not sample the entire image. // to retain some performance we'll sample the center of the image to determine the table cloth color // with such a small sample we shouldn't have to worry too much about the color variance caused by highlights and shadows // ....hopefully for (int yPixelIndex = (sampleRect.Y * stride); yPixelIndex <= (sampleRect.Bottom * stride); yPixelIndex += stride) { for (int xPixelIndex = sampleRect.X * bytesPerPixel; xPixelIndex <= sampleRect.Right * bytesPerPixel; xPixelIndex += (bytesPerPixel)) { int offset = xPixelIndex + yPixelIndex; if (offset >= bytes.Length) { break; // this should never happen } byte blue = bytes[offset]; byte green = bytes[++offset]; byte red = bytes[++offset]; bytes[offset] = 255; byte alpha = bytes[++offset]; Color pixelColor = Color.FromArgb(alpha, red, green, blue); if (!colorPopularity.ContainsKey(pixelColor)) { colorPopularity.Add(pixelColor, 0); } colorPopularity[pixelColor] += 1; } } Color popular = colorPopularity.ToList().OrderByDescending(k => k.Value).First().Key; LabColor labColor = new LabColor(popular); }
/// <summary> /// Finds the Delta E(94) of two LabColors /// </summary> /// <param name="color1"></param> /// <param name="color2"></param> /// <param name="applicationType"></param> /// <remarks> /// formula: /// http://www.brucelindbloom.com/index.html?Eqn_DeltaE_CIE94.html /// summary: /// https://opentextbc.ca/graphicdesign/chapter/4-4-lab-colour-space-and-delta-e-measurements/ /// constants & values breakdown: /// https://www.pac.gr/bcm/uploads/a-guide-of-understanding-color-comunication-part-3.pdf /// </remarks> /// <returns></returns> public static float FindDeltaE94(LabColor color1, LabColor color2, Constants.ApplicationType applicationType = Constants.ApplicationType.GraphicArts) { Constants constants = Constants.Get(applicationType); double K1 = constants.K1; double K2 = constants.K2; double KL = constants.KL; double KC = constants.KC; // 1d; double KH = constants.KH; // 1d; // modifying factor to compensate for perceptual distortions in the color space double ab = 1d; // difference in lightness/darkness value. += lighter | -= darker double delta_L = color1.L - color2.L; double C1 = Math.Sqrt(Math.Pow(color1.A, 2d) + Math.Pow(color1.B, 2d)); double C2 = Math.Sqrt(Math.Pow(color2.A, 2d) + Math.Pow(color2.B, 2d)); // Brightness in chroma. += brighter | -= duller double delta_C = C1 - C2; // difference on red/green axis. += redder | -= greener double delta_a = color1.A - color2.A; // difference on yellow/blue axis. += yellower | -= bluer double delta_b = color1.B - color2.B; double delta_h_radical = (Math.Pow(delta_a, 2d) + Math.Pow(delta_b, 2d) - Math.Pow(delta_C, 2d)); // In the calculation of ΔH, the value inside the radical is, in theory, always greater than or equal to zero. // However in an actual implementation, it may become a very slightly negative value, due to limited arithmetic precision. // Should this occur, the square root will fail. // Difference in hue double delta_H = Math.Sqrt(delta_h_radical < 0 ? 0 : delta_h_radical); double SL = 1d; double SC = 1d + (K1 * C1); double SH = 1d + (K2 * C1); double part1 = Math.Pow(delta_L / (KL * SL), 2d); double part2 = Math.Pow(delta_C / (KC * SC), 2d); // Math.Pow((delta_C * ab) / (KC * SC), 2d); double part3 = Math.Pow(delta_H / (KH * SH), 2d); // Math.Pow((delta_H * ab) / (KH * SH), 2d); // Total color difference value float delta_E = (float)Math.Sqrt(part1 + part2 + part3); return(delta_E); }
private void calculatedPictureBox_MouseMove(object sender, MouseEventArgs e) { if (analyzer == null) { return; } // prevent out of bound coordinates if picture is smaller than our picture box if (e.X > calculatedPictureBox.Image.Width || e.Y > calculatedPictureBox.Image.Height) { return; } Color color = analyzer.GetColorAtCoordinate(e.Location); LabColor labColor = new LabColor(color); // testing and sampling data under mouse cursor while over image. if (previousLabColor.HasValue) { float delta = LabColor.FindDeltaE94(previousLabColor.Value, labColor); // delta of 10 seems to produce good results in finding objects on the table if (delta >= 10) { Console.WriteLine(); Console.WriteLine("--------------------------------"); Console.WriteLine("Color = " + color); Console.WriteLine("Previous Color = " + previousColor); Console.WriteLine("Delta = " + delta); } } Console.WriteLine(); Console.WriteLine(); previousColor = color; previousLabColor = labColor; }
/// <summary> /// Converts a Color to its CIE-LAB color equivalent. /// If Alpha channel is used, it is preserved but not converted. /// </summary> /// <param name="color"></param> /// <returns></returns> public static LabColor FromColor(Color color) { return(LabColor.FromArgb(color.R, color.G, color.B, color.A)); }
/// <summary> /// Converts the CIE-LAB to its Color equivalent. If Alpha channel was specified, it will be included. /// </summary> /// <returns></returns> public static Color ToColor(LabColor labColor) { // implement conversion and return it return(Color.Transparent); }