private static Bitmap CropColor(Bitmap bmp) { var forbiddenColors = new List <Color> { Color.FromArgb(37, 24, 15) }; Bitmap newBitmap = new Bitmap(bmp.Width, bmp.Height); for (var x = 0; x < bmp.Width; x++) { for (var y = 0; y < bmp.Height; y++) { var firstColor = bmp.GetPixel(x, y); var firstLab = CIELab.FromRGB(firstColor); foreach (var secondColor in forbiddenColors) { var secondLab = CIELab.FromRGB(secondColor); var score = Math.Sqrt(Math.Pow(secondLab.L - firstLab.L, 2) + Math.Pow(secondLab.a - firstLab.a, 2) + Math.Pow(secondLab.b - firstLab.b, 2)); if (score > 0.5f) { newBitmap.SetPixel(x, y, firstColor); } } } } return(newBitmap); }
public List <double> LabToRGB(CIELab cielab) { var y = (cielab.L + 16) / 116; var x = cielab.A / 500 + y; var z = y - cielab.B / 200; double r, g, b; x = 0.95047 * ((x * x * x > 0.008856) ? x * x * x : (x - 16 / 116) / 7.787); y = 1.00000 * ((y * y * y > 0.008856) ? y * y * y : (y - 16 / 116) / 7.787); z = 1.08883 * ((z * z * z > 0.008856) ? z * z * z : (z - 16 / 116) / 7.787); r = x * 3.2406 + y * -1.5372 + z * -0.4986; g = x * -0.9689 + y * 1.8758 + z * 0.0415; b = x * 0.0557 + y * -0.2040 + z * 1.0570; r = (r > 0.0031308) ? (1.055 * Math.Pow(r, 1 / 2.4) - 0.055) : 12.92 * r; g = (g > 0.0031308) ? (1.055 * Math.Pow(g, 1 / 2.4) - 0.055) : 12.92 * g; b = (b > 0.0031308) ? (1.055 * Math.Pow(b, 1 / 2.4) - 0.055) : 12.92 * b; return(new List <double>() { Math.Max(0, Math.Min(1, r)) * 255, Math.Max(0, Math.Min(1, g)) * 255, Math.Max(0, Math.Min(1, b)) * 255 }); }
public static CIELab XYZtoLab(double x, double y, double z) { CIELab lab = CIELab.Empty; lab.L = 116.0 * Fxyz(y / CIEXYZ.D65.Y) - 16; lab.A = 500.0 * (Fxyz(x / CIEXYZ.D65.X) - Fxyz(y / CIEXYZ.D65.Y)); lab.B = 200.0 * (Fxyz(y / CIEXYZ.D65.Y) - Fxyz(z / CIEXYZ.D65.Z)); return(lab); }
/// <summary> /// Converts CIEXYZ to CIELab. /// </summary> public static CIELab XYZtoLab(CIEXYZ ciexyz) { CIELab lab = CIELab.Empty; double x = ciexyz.X; double y = ciexyz.Y; double z = ciexyz.Z; lab.L = 116.0 * Fxyz(y / CIEXYZ.D65.Y) - 16; lab.A = 500.0 * (Fxyz(x / CIEXYZ.D65.X) - Fxyz(y / CIEXYZ.D65.Y)); lab.B = 200.0 * (Fxyz(y / CIEXYZ.D65.Y) - Fxyz(z / CIEXYZ.D65.Z)); return(lab); }
public void DesaturateTest() { // Arrange CIELab lab = new CIELab { L = 97.4, a = 62.3, b = 81.2 }; double aMax = 55, aMin = -55, bMax = 75, bMin = -75; // Act bool desaturated = Colorimetric.Desaturate(ref lab, aMax, aMin, bMax, bMin); // Assert Assert.IsTrue(desaturated); }
public static XYZ CIELabToXYZ(CIELab Color) { float P = (Color.L + 16) / 116.0f; float Xn = 0.95f; float Yn = 1.0f; float Zn = 1.09f; XYZ result = new XYZ(Xn * (float)Math.Pow(P + Color.a / 500.0f, 3.0f), Yn * (float)Math.Pow(P, 3.0f), Zn * (float)Math.Pow(P - Color.b / 200.0f, 3.0f)); return(result); }
public void LCh2LabTest() { // Arrange CIELCh lch = new CIELCh { L = 100.0, C = 0.0, h = 0.0 }; // Act CIELab lab = Colorimetric.LCh2Lab(lch); // Assert Assert.AreEqual(100.0, lab.L); Assert.AreEqual(0.0, lab.a); Assert.AreEqual(0.0, lab.b); }
public void Lab2LChTest() { // Arrange CIELab lab = new CIELab { L = 100.0, a = 0.0, b = 0.0 }; // Act CIELCh lch = Colorimetric.Lab2LCh(lab); // Assert Assert.AreEqual(100.0, lch.L); Assert.AreEqual(0.0, lch.C); Assert.AreEqual(0.0, lch.h); }
public void CIELab_operatorCIELChTest() { // Arrange CIELab lab = new CIELab { L = 100.0, a = 0.0, b = 0.0 }; // Act CIELCh lch = lab; // Assert Assert.AreEqual(100.0, lch.L); Assert.AreEqual(0.0, lch.C); Assert.AreEqual(0.0, lch.h); }
public void CIEDE2000Test() { // Arrange CIELab lab1 = new CIELab { L = 100.0, a = 0.0, b = 0.0 }; CIELab lab2 = new CIELab { L = 87.5, a = 3.21, b = -16.7 }; // Act var actual = DeltaE.CIEDE2000(lab1, lab2); // Assert }
public void CIELCh_operatorCIELabTest() { // Arrange CIELCh lch = new CIELCh { L = 100.0, C = 0.0, h = 0.0 }; // Act CIELab lab = lch; // Assert Assert.AreEqual(100.0, lab.L); Assert.AreEqual(0.0, lab.a); Assert.AreEqual(0.0, lab.b); }
public void LabV2EncodingTest() { ushort[] inWLab = new ushort[3]; for (ushort u = 0; u < ushort.MaxValue; u++) { inWLab[0] = inWLab[1] = inWLab[2] = u; CIELab lab = Colorimetric.LabEncoded2FloatV2(inWLab); ushort[] outWLab = Colorimetric.Float2LabEncodedV2(lab); for (int i = 0; i < 3; i++) { Assert.AreEqual(u, outWLab[i]); } } }
public void CheckPointTest() { // Arrange IntPtr plugin = IntPtr.Zero; IntPtr userData = IntPtr.Zero; using (var context = Context.Create(plugin, userData)) using (var gbd = GamutBoundaryDescriptor.Create(context)) { CIELab add = new CIELab { }; for (int L = 0; L <= 100; L += 10) { for (int a = -128; a <= 128; a += 5) { for (int b = -128; b <= 128; b += 5) { add.L = L; add.a = a; add.b = b; gbd.AddPoint(add); } } } gbd.Compute(); // Act CIELab check = new CIELab { }; for (int L = 10; L <= 90; L += 25) { for (int a = -120; a <= 120; a += 25) { for (int b = -120; b <= 120; b += 25) { check.L = L; check.a = a; check.b = b; // Assert Assert.IsTrue(gbd.CheckPoint(check)); } } } } }
public void CMCTest() { // Arrange CIELab lab1 = new CIELab { L = 100.0, a = 0.0, b = 0.0 }; CIELab lab2 = new CIELab { L = 87.5, a = 3.21, b = -16.7 }; double l = 2.0; double c = 1.0; // Act var actual = DeltaE.CMC(lab1, lab2, l, c); // Assert }
public void CIEXYZ_ToLabTest() { // Arrange CIEXYZ whitePoint = new CIEXYZ { X = 0.9642, Y = 1.0, Z = 0.8249 }; // D50 XYZ normalized to Y = 1.0 CIEXYZ xyz = new CIEXYZ { X = 0.9642, Y = 1.0, Z = 0.8249 }; // Act CIELab lab = xyz.ToLab(whitePoint); // Assert Assert.AreEqual(100.0, lab.L); Assert.AreEqual(0.0, lab.a); Assert.AreEqual(0.0, lab.b); }
public void XYZ2LabTest() { // Arrange CIEXYZ whitePoint = new CIEXYZ { X = 0.9642, Y = 1.0, Z = 0.8249 }; // D50 XYZ normalized to Y = 1.0 CIEXYZ xyz = new CIEXYZ { X = 0.9642, Y = 1.0, Z = 0.8249 }; // Act CIELab lab = Colorimetric.XYZ2Lab(whitePoint, xyz); // Assert Assert.AreEqual(100.0, lab.L); Assert.AreEqual(0.0, lab.a); Assert.AreEqual(0.0, lab.b); }
public void Lab2XYZTest() { // Arrange CIEXYZ whitePoint = new CIEXYZ { X = 0.9642, Y = 1.0, Z = 0.8249 }; // D50 XYZ normalized to Y = 1.0 CIELab lab = new CIELab { L = 100.0, a = 0.0, b = 0.0 }; // Act CIEXYZ xyz = Colorimetric.Lab2XYZ(whitePoint, lab); // Assert Assert.AreEqual(0.9642, xyz.X); Assert.AreEqual(1.0, xyz.Y); Assert.AreEqual(0.8249, xyz.Z); }
public static CIELab XYZToCIELab(XYZ Color) { CIELab lab = new CIELab(); // from wikipedia, the only source that actually states useable values for those "constants" float Xn = 0.95f; float Yn = 1.0f; float Zn = 1.09f; float xFactor = Color.X / Xn; float yFactor = Color.Y / Yn; float zFactor = Color.Z / Zn; if (yFactor > 0.008856) { yFactor = (float)Math.Pow(yFactor, 1.0 / 3.0); lab.L = (float)(116 * yFactor - 16); } else { lab.L = 903.3f * yFactor; yFactor = 7.787f * yFactor + 16.0f / 116.0f; } if (xFactor > 0.008856f) { xFactor = (float)Math.Pow(xFactor, 1.0 / 3.0); } else { xFactor = 7.787f * xFactor + 16.0f / 116.0f; } if (zFactor > 0.008856f) { zFactor = (float)Math.Pow(zFactor, 1.0 / 3.0); } else { zFactor = 7.787f * zFactor + 16.0f / 116.0f; } lab.a = 500.0f * (xFactor - yFactor); lab.b = 200.0f * (yFactor - zFactor); return(lab); }
public void AddPointTest() { // Arrange IntPtr plugin = IntPtr.Zero; IntPtr userData = IntPtr.Zero; CIELab lab = new CIELab { L = 99.3, a = 12.6, b = 14.2 }; using (var context = Context.Create(plugin, userData)) using (var gbd = GamutBoundaryDescriptor.Create(context)) { // Act bool added = gbd.AddPoint(lab); // Assert Assert.IsTrue(added); } }
public static int ClosestColor(Color col, int type) { if (type == AVERAGE_COLOR) { int error = 196609; int ret = -1; for (int i = 0; i < Exist.Count; i++) { int rgb = Exist.ElementAt(i); int r = (rgb & 0xff0000) / 65536; int g = (rgb & 0xff00) / 256; int b = (rgb & 0xff) / 1; int R = (col.R - r); int G = (col.G - g); int B = (col.B - b); int RGB = R * R + G * G + B * B; if (error > RGB) { error = RGB; ret = ExistID.ElementAt(i); } } return(ret); } else if (type == AVERAGE_COLOR_WITH_WEIGHT) { double error = 100000000; int ret = -1; for (int i = 0; i < Exist.Count; i++) { int rgb = Exist.ElementAt(i); int r = (rgb & 0xff0000) / 65536; int g = (rgb & 0xff00) / 256; int b = (rgb & 0xff) / 1; double R = (col.R - r) * 0.30; double G = (col.G - g) * 0.59; double B = (col.B - b) * 0.11; double er = R * R + G * G + B * B; if (error > er) { error = er; ret = ExistID.ElementAt(i); } } return(ret); } else if (type == AVERAGE_LAB) { double error = 1000000000; int ret = -1; CIELab lab_c = ColorConverter.RGBtoLab(col.ToArgb() & 0xffffff); for (int i = 0; i < Exist.Count; i++) { int rgb = Exist.ElementAt(i); CIELab lab = ColorConverter.RGBtoLab(rgb); double L = (lab_c.L - lab.L); double A = (lab_c.A - lab.A); double B = (lab_c.B - lab.B); double er = L * L + A * A + B * B; if (error > er) { error = er; ret = ExistID.ElementAt(i); } } return(ret); } return(-1); }
public static RGB CIELabToRGB(CIELab Color) { return(XYZToRGB(CIELabToXYZ(Color))); }
static void Main(string[] args) { string inputDirectory = args[0]; string inputFilelist = args[1]; string outputFile = args[2]; int resizeWidth = int.Parse(args[3]); int resizeHeight = int.Parse(args[4]); if (resizeWidth != resizeHeight) { throw new NotImplementedException(); } // load filelist List <string> filelist = new List <string>(); using (StreamReader reader = new StreamReader(inputFilelist)) { while (!reader.EndOfStream) { filelist.Add(inputDirectory + reader.ReadLine()); } } ResizeExtractor extractor = new ResizeExtractor(); // compute and write the result //const int batchSize = 1000; using (BinaryWriter writer = new BinaryWriter(new FileStream(outputFile, FileMode.Create))) { writer.Write(filelist.Count); // feature count writer.Write(resizeWidth * resizeHeight * 3); // feature dimension for (int i = 0; i < filelist.Count; i++) { Bitmap inputImage = new Bitmap(filelist[i]); Bitmap resizedImage = ResizeExtractor.ResizeImage(inputImage, resizeWidth, resizeHeight); //writer.Write(resizeWidth * resizeHeight); // centroid count for (int iRow = 0; iRow < resizeHeight; iRow++) // each centroid { for (int iCol = 0; iCol < resizeWidth; iCol++) { Color color = resizedImage.GetPixel(iRow, iCol); CIELab lab = ColorTransform.ColorTransform.RGBtoLab(color.R, color.G, color.B); //writer.Write((float)1); // weight in [0, 1] //writer.Write((float)gaussKernel[iRow, iCol]); //writer.Write((float)((iCol + 0.5) / resizeWidth)); // XY in [0, 1] //writer.Write((float)((iRow + 0.5) / resizeHeight)); writer.Write((float)(lab.L / lab.lMaxValue)); // Lab in [-1, 1] writer.Write((float)(lab.A / lab.aMaxValueAbs)); writer.Write((float)(lab.B / lab.bMaxValueAbs)); //writer.Write((float)0); //writer.Write((float)0); } } if ((i + 1) % 100 == 0) { Console.WriteLine("Extracted " + (i + 1) + "/" + filelist.Count + " signatures."); } } } }
/// <summary> /// Converts CIELab to CIEXYZ. /// </summary> public static CIEXYZ LabtoXYZ(CIELab lab) { return(LabtoXYZ(lab.L, lab.A, lab.B)); }
/// <summary> /// Converts CIELab to RGB. /// </summary> public static RGB LabtoRGB(CIELab lab) { return(XYZtoRGB(LabtoXYZ(lab))); }
public static void Initialize(int type) { if (type == BLEND_COLOR) { for (int i = 0; i < 2; i++) { for (int xy = 0; xy < 256; xy++) { int rgb1 = LIST_RGB_COLOR[xy & 15]; int rgb2 = LIST_RGB_COLOR[xy / 16]; int r1 = (rgb1 & 0xff0000) / 65536; int g1 = (rgb1 & 0xff00) / 256; int b1 = (rgb1 & 0xff) / 1; int r2 = (rgb2 & 0xff0000) / 65536; int g2 = (rgb2 & 0xff00) / 256; int b2 = (rgb2 & 0xff) / 1; if (i == 0) // 75% Foreground 25% Background { double r = (r1 * 3 + r2) / 4.0; double g = (g1 * 3 + g2) / 4.0; double b = (b1 * 3 + b2) / 4.0; r = (r > 255 ? 255 : (r < 0 ? 0 : r)); g = (g > 255 ? 255 : (g < 0 ? 0 : g)); b = (b > 255 ? 255 : (b < 0 ? 0 : b)); int rgb = (int)r * 0x10000 + (int)g * 0x100 + (int)b; if (!Exist.Contains(rgb)) { Exist.Add(rgb); ExistID.Add(i * 256 + xy); } } else // 50% Foreground 50% Background { double r = (r1 + r2) / 2.0; double g = (g1 + g2) / 2.0; double b = (b1 + b2) / 2.0; //r = Math.Sqrt(r1 * r1 + r2 * r2); //g = Math.Sqrt(g1 * g1 + g2 * g2); //b = Math.Sqrt(b1 * b1 + b2 * b2); r = (r > 255 ? 255 : (r < 0 ? 0 : r)); g = (g > 255 ? 255 : (g < 0 ? 0 : g)); b = (b > 255 ? 255 : (b < 0 ? 0 : b)); int rgb = (int)r * 0x10000 + (int)g * 0x100 + (int)b; if (!Exist.Contains(rgb)) { Exist.Add(rgb); ExistID.Add(i * 256 + xy); } } } } } else if (type == PERCEIVED_COLOR) { for (int i = 0; i < 2; i++) { for (int xy = 0; xy < 256; xy++) { int rgb1 = LIST_RGB_COLOR[xy & 15]; int rgb2 = LIST_RGB_COLOR[xy / 16]; CIELab lab1 = ColorConverter.RGBtoLab(rgb1); CIELab lab2 = ColorConverter.RGBtoLab(rgb2); if (i == 0) // 75% Foreground 25% Background { double l = (lab1.L * 3 + lab2.L) / 4.0; double a = (lab1.A * 3 + lab2.A) / 4.0; double b = (lab1.B * 3 + lab2.B) / 4.0; CIELab lab = new CIELab(l, a, b); int rgb = ColorConverter.LabtoRGB(lab); if (!Exist.Contains(rgb)) { Exist.Add(rgb); ExistID.Add(i * 256 + xy); } } else // 50% Foreground 50% Background { double l = (lab1.L + lab2.L) / 2.0; double a = (lab1.A + lab2.A) / 2.0; double b = (lab1.B + lab2.B) / 2.0; CIELab lab = new CIELab(l, a, b); int rgb = ColorConverter.LabtoRGB(lab); if (!Exist.Contains(rgb)) { Exist.Add(rgb); ExistID.Add(i * 256 + xy); } } } } } }
public double DeltaE(CIELab c1, CIELab c2) { double xC1, xC2, xCX, xGX, xNN, xH1, xH2, xDL, xDC, xDH, xLX, xCY, xHX, xTX, xPH, xRC, xSL, xSC, xSH, xRT, WHT_L = 1, WHT_C = 1, WHT_H = 1; xC1 = Math.Sqrt(c1.a * c1.a + c1.b * c1.b); xC2 = Math.Sqrt(c2.a * c2.a + c2.b * c2.b); xCX = (xC1 + xC2) / 2; xGX = 0.5 * (1 - Math.Sqrt(Math.Pow(xCX, 7) / (Math.Pow(xCX, 7) + Math.Pow(25, 7)))); xNN = (1 + xGX) * c1.a; xC1 = Math.Sqrt(xNN * xNN + c1.b * c1.b); xH1 = CieLab2Hue(xNN, c1.b); xNN = (1 + xGX) * c2.a; xC2 = Math.Sqrt(xNN * xNN + c2.b * c2.b); xH2 = CieLab2Hue(xNN, c2.b); xDL = c2.L - c1.L; xDC = xC2 - xC1; if ((xC1 * xC2) == 0) { xDH = 0; } else { xNN = Math.Round(xH2 - xH1, 12); if (Math.Abs(xNN) <= 180) { xDH = xH2 - xH1; } else { if (xNN > 180) { xDH = xH2 - xH1 - 360; } else { xDH = xH2 - xH1 + 360; } } } xDH = 2 * Math.Sqrt(xC1 * xC2) * Math.Sin(deg2rad(xDH / 2)); xLX = (c1.L + c2.L) / 2; xCY = (xC1 + xC2) / 2; if ((xC1 * xC2) == 0) { xHX = xH1 + xH2; } else { xNN = Math.Abs(Math.Round(xH1 - xH2, 12)); if (xNN > 180) { if ((xH2 + xH1) < 360) { xHX = xH1 + xH2 + 360; } else { xHX = xH1 + xH2 - 360; } } else { xHX = xH1 + xH2; } xHX /= 2; } xTX = 1 - 0.17 * Math.Cos(deg2rad(xHX - 30)) + 0.24 * Math.Cos(deg2rad(2 * xHX)) + 0.32 * Math.Cos(deg2rad(3 * xHX + 6)) - 0.20 * Math.Cos(deg2rad(4 * xHX - 63)); xPH = 30 * Math.Exp(-((xHX - 275) / 25) * ((xHX - 275) / 25)); xRC = 2 * Math.Sqrt(Math.Pow(xCY, 7) / (Math.Pow(xCY, 7) + Math.Pow(25, 7))); xSL = 1 + ((0.015 * ((xLX - 50) * (xLX - 50))) / Math.Sqrt(20 + ((xLX - 50) * (xLX - 50)))); xSC = 1 + 0.045 * xCY; xSH = 1 + 0.015 * xCY * xTX; xRT = -1 * Math.Sin(deg2rad(2 * xPH)) * xRC; xDL /= (WHT_L * xSL); xDC /= (WHT_C * xSC); xDH /= (WHT_H * xSH); return(Math.Sqrt(Math.Pow(xDL, 2) + Math.Pow(xDC, 2) + Math.Pow(xDH, 2) + xRT * xDC * xDH)); }
// LAB & XYZ -> RGB public static int LabtoRGB(CIELab lab) { CIEXYZ xyz = LabtoXYZ(lab.L, lab.A, lab.B); return(XYZtoRGB(xyz.X, xyz.Y, xyz.Z)); }