예제 #1
0
        // Shrink the color palette.
        public static List <RGB5> ShrinkColorPalette(int numCols, List <RGB5> colors, out List <int> closestIndices)
        {
            //Run the algorithm.
            int bucketsFilled = 1;

            // We must convert to CIELAB first as RGB sucks at representing what the human eye sees.
            List <CIELAB> cols = new List <CIELAB>();

            foreach (var c in colors)
            {
                cols.Add(new CIELAB(c));
            }
            List <List <CIELAB> > buckets = new List <List <CIELAB> >();

            buckets.Add(cols);

            // Run until we get the desired number of colors. What we do here is split the bucket with the most variance.
            while (bucketsFilled < numCols)
            {
                List <CIELAB> largestBucketVar = null;
                double        largestVar       = double.MinValue;
                foreach (var b in buckets)
                {
                    double variance = CIELAB.CalculateVariance(b);
                    if (variance >= largestVar)
                    {
                        largestBucketVar = b;
                        largestVar       = variance;
                    }
                }
                buckets.Remove(largestBucketVar);
                List <CIELAB> v1, v2;
                CIELAB.SplitBucket(largestBucketVar, out v1, out v2);
                buckets.Add(v1);
                buckets.Add(v2);
                bucketsFilled++;
            }

            // Convert each bucket into RGB5.
            List <RGB5>   outputRGB = new List <RGB5>();
            List <CIELAB> outputCIE = new List <CIELAB>();

            foreach (var b in buckets)
            {
                var avg = CIELAB.AverageColor(b);
                outputCIE.Add(avg);
                outputRGB.Add(avg.ToRGB5());
            }

            // Get closest value for RGB indices.
            closestIndices = new List <int>();
            for (int i = 0; i < cols.Count; i++)
            {
                closestIndices.Add(cols[i].ClosestColorIndex(outputCIE));
            }

            // Return the final buckets.
            return(outputRGB);
        }
예제 #2
0
        // The variance of a group of CIELab colors.
        public static double CalculateVariance(List <CIELAB> colors)
        {
            double ret = 0;
            CIELAB avg = AverageColor(colors);

            foreach (var c in colors)
            {
                ret += c.DeltaESquared(avg);  // (x - xBar)^2
            }
            return(ret / (colors.Count - 1)); // Use sample variance instead of population. Stats!
        }
예제 #3
0
        // Distance squared
        public double DeltaESquared(CIELAB other)
        {
            var deltaL = L - other.L;
            var deltaA = A - other.A;
            var deltaB = B - other.B;
            var c1     = Math.Sqrt(A * A + B * B);
            var c2     = Math.Sqrt(other.A * other.A + other.B * other.B);
            var deltaC = c1 - c2;
            var deltaH = deltaA * deltaA + deltaB * deltaB - deltaC * deltaC;

            deltaH = deltaH < 0 ? 0 : Math.Sqrt(deltaH);
            var sc         = 1.0 + 0.045 * c1;
            var sh         = 1.0 + 0.015 * c1;
            var deltaLKlsl = deltaL / (1.0);
            var deltaCkcsc = deltaC / (sc);
            var deltaHkhsh = deltaH / (sh);
            var i          = deltaLKlsl * deltaLKlsl + deltaCkcsc * deltaCkcsc + deltaHkhsh * deltaHkhsh;

            return(i);
        }