static public Color[] V1(Color[] llist, int ColorsCount) { List <RGB> list = new List <RGB>(); foreach (Color item in llist) { list.Add(new RGB(item)); } List <List <Color> > Result = new List <List <Color> >(); List <RGB> Part = new List <RGB>(); int maxLength = 0; int emptyListCount = 0; int[] groupLengths = new int[ColorsCount]; list.Sort(delegate(RGB left, RGB right) { return(right.Hue.CompareTo(left.Hue)); }); float lower = (float)list[list.Count - 1].Hue; float upper = (float)list[0].Hue; float KeyStep = (upper - lower) / ColorsCount; upper = KeyStep + lower; for (int i = 0; i < ColorsCount; i++) { if (i == ColorsCount - 1) { upper = (float)list[0].Hue; } foreach (RGB item in list) { if ((float)item.Hue >= (float)lower && (float)item.Hue <= (float)upper) { Part.Add(item); } } if (Part.Count > 2) { Part = ColorPalette.DistrictByHue(Part, true); Part.Sort(delegate(RGB left, RGB right) { return(left.Brightness.CompareTo(right.Brightness)); }); } if (maxLength < Part.Count) { maxLength = Part.Count; } if (Part.Count == 0) { emptyListCount += 1; } groupLengths[i] = Part.Count; List <Color> temp = new List <Color>(); foreach (RGB item in Part) { temp.Add(item.Color); } Result.Add(temp.GetRange(0, temp.Count)); Part.Clear(); lower = lower + KeyStep; upper = upper + KeyStep; } List <Color> maxList = new List <Color>(); List <List <Color> > emptyLists = new List <List <Color> >(); Array.Sort(groupLengths); maxList = Result.Find(group => group.Count == maxLength); emptyLists = Result.FindAll(x => x.Count == 0); if (emptyListCount != 0 && maxLength > 1) { for (int i = 0; i < emptyLists.Count; i++) { int col = 0; int LargestPartIndex = 0; Array.Sort(groupLengths); maxLength = groupLengths[groupLengths.Length - 1]; LargestPartIndex = Result.FindIndex(group => group.Count == maxLength); col = Result[LargestPartIndex].Count / 2; emptyLists[i].AddRange(Result[LargestPartIndex].GetRange(0, col)); Result[LargestPartIndex].RemoveRange(0, col); groupLengths[groupLengths.Length - 1] = groupLengths[groupLengths.Length - 1] / 2; } int cnt = 0; for (int i = 0; i < Result.Count; i++) { if (Result[i].Count == 0) { Result[i] = emptyLists[cnt]; cnt += 1; } } } int index = Result.FindIndex(group => group.Count != 0); for (int i = 0; i < Result.Count; i++) { if (Result[i].Count == 0) { Result[i] = Result[index]; } } return(ColorPalette.GetAverageColors(Result).ToArray()); }
static public Color[] V44(Color[] llist, int ColorsCount) { List <RGB> RGB_AllColors = new List <RGB>(); for (int i = 0; i < llist.Length; i++) { RGB_AllColors.Add(new RGB(llist[i], K_means.AllWeights[i])); } List <List <Color> > Result = new List <List <Color> >(); List <RGB> Part = new List <RGB>(); int maxLength = 0; int emptyListCount = 0; int[] groupLengths = new int[ColorsCount]; RGB_AllColors.Sort(delegate(RGB left, RGB right) { return(right.Hue.CompareTo(left.Hue)); }); for (int i = 0; i < ColorsCount; i++) { float currentHueValue = 0f; if (i < 3) { foreach (RGB item in RGB_AllColors) { // элементы на границах попадают в обе группы currentHueValue = item.Hue; if ((float)currentHueValue >= (float)(120f * (float)i) && (float)currentHueValue <= (float)(120f * (float)(i + 1))) { Part.Add(item); } } } if (Part.Count >= 2) { Part = ColorPalette.DistrictByHue(Part, true); Part.Sort(delegate(RGB left, RGB right) { return(left.Brightness.CompareTo(right.Brightness)); }); } List <Color> temp = new List <Color>(); foreach (RGB item in Part) { for (int f = 0; f < item.Weight; f++) { temp.Add(item.Color); } } if (maxLength < temp.Count) { maxLength = temp.Count; } if (temp.Count == 0) { emptyListCount += 1; } groupLengths[i] = temp.Count; Result.Add(temp.GetRange(0, temp.Count)); Part.Clear(); } List <Color> maxList = new List <Color>(); List <List <Color> > emptyLists = new List <List <Color> >(); Array.Sort(groupLengths); maxList = Result.Find(group => group.Count == maxLength); emptyLists = Result.FindAll(x => x.Count == 0); if (emptyListCount != 0 && maxLength > 1) { for (int i = 0; i < emptyLists.Count; i++) { int col = 0; int LargestPartIndex = 0; Array.Sort(groupLengths); maxLength = groupLengths[groupLengths.Length - 1]; LargestPartIndex = Result.FindIndex(group => group.Count == maxLength); col = Result[LargestPartIndex].Count / 2; emptyLists[i].AddRange(Result[LargestPartIndex].GetRange(0, col)); Result[LargestPartIndex].RemoveRange(0, col); groupLengths[groupLengths.Length - 1] = groupLengths[groupLengths.Length - 1] / 2; } int cnt = 0; for (int i = 0; i < Result.Count; i++) { if (Result[i].Count == 0) { Result[i] = emptyLists[cnt]; cnt += 1; } } } for (int i = 0; i < Result.Count; i++) { if (Result[i].Count == 0) { Result[i].Add(maxList[0]); } } return(ColorPalette.GetAverageColors(Result).ToArray()); }
static public List <List <Color> > RunSingleThread(Color[] RGB_AllColors, int ClasterCount, int InitVersion) { int IterationCount = 0; int ColorsCount; int weight; double var_L, var_a, var_b, count, minE, E; List <List <CIELab> > ResultClasters = new List <List <CIELab> >(); CIELab[] PreviousCentroids = new CIELab[ClasterCount]; CIELab[] CIELab_AllColors = Converter.Array_RGBtoCIELab(RGB_AllColors); AllWeights = ColorPalette.GetColorsWeights(RGB_AllColors); Color[] RGB_AllColorsDistr = ColorPalette.DistrictByRGB(RGB_AllColors); CIELab[] CIELab_AllColorsDistr = Converter.Array_RGBtoCIELab(RGB_AllColorsDistr); ColorsCount = RGB_AllColorsDistr.Length; for (int i = 0; i < ClasterCount; i++) { PreviousCentroids[i] = CIELab_AllColors[0]; ResultClasters.Add(new List <CIELab>()); } switch (InitVersion) { case 1: CurrentCentroids = Converter.Array_RGBtoCIELab(InitializeCentroids.V1(RGB_AllColors, ClasterCount)); break; case 2: CurrentCentroids = Converter.Array_RGBtoCIELab(InitializeCentroids.V2(RGB_AllColors, ClasterCount)); break; case 3: CurrentCentroids = Converter.Array_RGBtoCIELab(InitializeCentroids.V3(RGB_AllColors, ClasterCount)); break; case 4: CurrentCentroids = Converter.Array_RGBtoCIELab(InitializeCentroids.V4(RGB_AllColors, ClasterCount)); break; case 5: CurrentCentroids = Converter.Array_RGBtoCIELab(InitializeCentroids.V5(RGB_AllColors, ClasterCount)); break; default: CurrentCentroids = Converter.Array_RGBtoCIELab(InitializeCentroids.V4(RGB_AllColors, ClasterCount)); break; } while (true) { IterationCount++; double[,] accum = new double[ClasterCount, 4]; CIELab CurrentColor; int NumOfNearestClaster = 0; for (int f = 0; f < ColorsCount; f++) { minE = 1000000d; CurrentColor = CIELab_AllColorsDistr[f]; weight = AllWeights[f]; for (int i = 0; i < ClasterCount; i++) { var_L = CurrentColor.L - CurrentCentroids[i].L; var_a = CurrentColor.a - CurrentCentroids[i].a; var_b = CurrentColor.b - CurrentCentroids[i].b; var_L = var_L * var_L; var_a = var_a * var_a; var_b = var_b * var_b; E = var_L + var_a + var_b; if (E < minE) { minE = E; NumOfNearestClaster = i; } } accum[NumOfNearestClaster, 0] += CurrentColor.L * weight; accum[NumOfNearestClaster, 1] += CurrentColor.a * weight; accum[NumOfNearestClaster, 2] += CurrentColor.b * weight; accum[NumOfNearestClaster, 3] += weight; } CurrentCentroids.CopyTo(PreviousCentroids, 0); for (int f = 0; f < ClasterCount; f++) { count = var_L = var_a = var_b = 0; count += accum[f, 3]; var_L += accum[f, 0]; var_a += accum[f, 1]; var_b += accum[f, 2]; var_L = var_L / count; var_a = var_a / count; var_b = var_b / count; CurrentCentroids[f] = new CIELab(var_L, var_a, var_b); } bool equal = CompareClasters(CurrentCentroids, PreviousCentroids); if (equal || IterationCount >= 500) { Group(CIELab_AllColorsDistr, ResultClasters, ClasterCount); FillEmptyClasters(ResultClasters, ClasterCount); break; } } if (ClasterCount == 20) { ColorPalette.s = IterationCount.ToString() + "\t count"; } return(Converter.GroupList_CIELabtoRBG(ResultClasters)); }
static public Color[] V5(Color[] llist, int ColorsCount) { List <RGB> RGB_AllColors = new List <RGB>(); foreach (Color item in llist) { RGB_AllColors.Add(new RGB(item)); } List <List <Color> > Result = new List <List <Color> >(); List <RGB> Part = new List <RGB>(); int maxLength = 0; int emptyListCount = 0; RGB_AllColors.Sort(delegate(RGB left, RGB right) { return(right.Hue.CompareTo(left.Hue)); }); for (int i = 0; i < ColorsCount; i++) { if (i < 3) { foreach (RGB item in RGB_AllColors) { if ((float)item.Hue >= (float)(120f * (float)i) && (float)item.Hue <= (float)(120f * (float)(i + 1))) { Part.Add(item); } } } if (Part.Count >= 2) { Part = ColorPalette.DistrictByHue(Part, true); Part.Sort(delegate(RGB left, RGB right) { return(left.Hue.CompareTo(right.Hue)); }); } if (maxLength < Part.Count) { maxLength = Part.Count; } if (Part.Count == 0) { emptyListCount += 1; } List <Color> temp = new List <Color>(); foreach (RGB item in Part) { temp.Add(item.Color); } Result.Add(temp.GetRange(0, temp.Count)); Part.Clear(); } if (emptyListCount != 0 && maxLength > 1) { double E_value = 0d; double E_valueMax = 0d; int GroupIndex = 0; while (emptyListCount != 0) { Result.Sort(delegate(List <Color> left, List <Color> right) { return(right.Count.CompareTo(left.Count)); }); E_value = 0d; E_valueMax = 0d; GroupIndex = 0; for (int i = 0; i < ColorsCount; i++) { if (Result[i].Count > 1) { Color left = ColorPalette.GetAverageColor(Result[i].GetRange(0, Result[i].Count / 2)); Color right = ColorPalette.GetAverageColor(Result[i].GetRange(Result[i].Count / 2, Result[i].Count / 2)); CIELab CIE_left = CIELab.RGB_to_CIELab(left); CIELab CIE_right = CIELab.RGB_to_CIELab(right); E_value = CIELab.deltaE76(CIE_left, CIE_right); if (E_value > E_valueMax) { GroupIndex = i; E_valueMax = E_value; } } } maxLength = Result[GroupIndex].Count; if (maxLength == 1) { break; } Result[ColorsCount - 1].AddRange(Result[GroupIndex].GetRange(0, maxLength / 2)); Result[GroupIndex].RemoveRange(0, maxLength / 2); emptyListCount--; } } int index = Result.FindIndex(group => group.Count != 0); for (int i = 0; i < Result.Count; i++) { if (Result[i].Count == 0) { Result[i] = Result[index]; } } return(ColorPalette.GetAverageColors(Result).ToArray()); }
static public List <List <Color> > RunMultiThread(Color[] RGB_AllColors, int ClasterCount, int InitVersion) { int IterationCount = 0; int ThreadCount = 3; int ColorsCount = RGB_AllColors.Length; double var_L, var_a, var_b, count; List <List <CIELab> > ResultClasters = new List <List <CIELab> >(); CIELab[] PreviousCentroids = new CIELab[ClasterCount]; CIELab[] CIELab_AllColors; AccumParts = new List <double[, ]>(); switch (InitVersion) { case 1: CurrentCentroids = Converter.Array_RGBtoCIELab(InitializeCentroids.V1(RGB_AllColors, ClasterCount)); break; case 2: CurrentCentroids = Converter.Array_RGBtoCIELab(InitializeCentroids.V2(RGB_AllColors, ClasterCount)); break; case 3: CurrentCentroids = Converter.Array_RGBtoCIELab(InitializeCentroids.V3(RGB_AllColors, ClasterCount)); break; case 4: CurrentCentroids = Converter.Array_RGBtoCIELab(InitializeCentroids.V4(RGB_AllColors, ClasterCount)); break; case 5: CurrentCentroids = Converter.Array_RGBtoCIELab(InitializeCentroids.V5(RGB_AllColors, ClasterCount)); break; default: CurrentCentroids = Converter.Array_RGBtoCIELab(InitializeCentroids.V4(RGB_AllColors, ClasterCount)); break; } AllWeights = ColorPalette.GetColorsWeights(RGB_AllColors); RGB_AllColors = ColorPalette.DistrictByRGB(RGB_AllColors); CIELab_AllColors = Converter.Array_RGBtoCIELab(RGB_AllColors); WeightsParts = Converter.SplitOnParts(AllWeights, ThreadCount); CIELab_Parts = Converter.SplitOnParts(CIELab_AllColors, ThreadCount); for (int j = 0; j < ThreadCount; j++) { AccumParts.Add(new double[ClasterCount, 4]); for (int i = 0; i < ClasterCount; i++) { PreviousCentroids[i] = CIELab_Parts[0][0]; } } for (int i = 0; i < ClasterCount; i++) { ResultClasters.Add(new List <CIELab>()); } var watch = System.Diagnostics.Stopwatch.StartNew(); while (true) { IterationCount++; using (CountdownEvent complete = new CountdownEvent(ThreadCount)) { ThreadPool.QueueUserWorkItem(delegate { MainAlgorithm(CIELab_Parts[0], ClasterCount, 0); complete.Signal(); }); ThreadPool.QueueUserWorkItem(delegate { MainAlgorithm(CIELab_Parts[1], ClasterCount, 1); complete.Signal(); }); ThreadPool.QueueUserWorkItem(delegate { MainAlgorithm(CIELab_Parts[2], ClasterCount, 2); complete.Signal(); }); complete.Wait(); } CurrentCentroids.CopyTo(PreviousCentroids, 0); for (int f = 0; f < ClasterCount; f++) { count = var_L = var_a = var_b = 0; for (int j = 0; j < ThreadCount; j++) { count += AccumParts[j][f, 3]; var_L += AccumParts[j][f, 0]; var_a += AccumParts[j][f, 1]; var_b += AccumParts[j][f, 2]; } var_L = var_L / count; var_a = var_a / count; var_b = var_b / count; CurrentCentroids[f] = new CIELab(var_L, var_a, var_b); } bool equal = CompareClasters(CurrentCentroids, PreviousCentroids); if (equal || IterationCount >= 500) { Group(CIELab_AllColors, ResultClasters, ClasterCount); FillEmptyClasters(ResultClasters, ClasterCount); break; } } watch.Stop(); var elapsedMs = watch.ElapsedMilliseconds; if (ClasterCount == 20) { ColorPalette.s += IterationCount.ToString() + "\t count\n"; ColorPalette.s += ((float)elapsedMs / 1000).ToString() + "\t mainAlgo"; } return(Converter.GroupList_CIELabtoRBG(ResultClasters)); }