예제 #1
0
        public static float GetDistanceSq(LABColor c1, LABColor c2)
        {
            float da = c2.af - c1.af;
            float db = c2.bf - c1.bf;

            return(da * da + db * db);
        }
예제 #2
0
        public static LABColor[] PickKMeansCentroids(int numCentroids, LABColor[] dataPoints)
        {
            LABColor[] centroids = new LABColor[numCentroids];

            //Use K-means++ to choose initial centroid values

            //Choose one center uniformly at random from among the data points.
            centroids[0] = dataPoints[(int)(rand.NextDouble() * numCentroids)];

            //For each data point x, compute D(x), the distance between x and the nearest center that has already been chosen.

            float highestD      = 0;
            int   highestDIndex = 0;

            float[] D = new float[dataPoints.Length];
            for (int d = 0; d < dataPoints.Length; ++d)
            {
                D[d] = GetDistanceSq(centroids[0], dataPoints[d]);
                if (D[d] > highestD)
                {
                    highestD      = D[d];
                    highestDIndex = d;
                }
            }


            //Choose one new data point at random as a new center, using a weighted probability distribution where a point x is chosen with probability proportional to D(x)^2.
            //Repeat until k centers have been chosen.

            //Note: for now, just choose the datapoint with highest D

            for (int c = 1; c < centroids.Length; ++c)
            {
                centroids[c] = dataPoints[highestDIndex];

                //recalculate D's
                highestD      = 0;
                highestDIndex = 0;

                for (int d = 0; d < dataPoints.Length; ++d)
                {
                    float currD = GetDistanceSq(centroids[c], dataPoints[d]);
                    if (currD < D[d])
                    {
                        D[d] = currD;
                        if (D[d] > highestD)
                        {
                            highestD      = D[d];
                            highestDIndex = d;
                        }
                    }
                }
            }

            return(centroids);
        }
예제 #3
0
 public static LABColor[] GenerateRandomLABColors(int numColors)
 {
     LABColor[] colors = new LABColor[numColors];
     for (int i = 0; i < numColors; ++i)
     {
         colors[i]    = new LABColor();
         colors[i].Lf = (float)rand.NextDouble() * 100f;
         colors[i].af = -128f + (float)rand.NextDouble() * 256f;
         colors[i].bf = -128f + (float)rand.NextDouble() * 256f;
     }
     return(colors);
 }
예제 #4
0
        public static LABColor[] GetLABPixelData(Bitmap bmp)
        {
            LABColor[] labPixelData = new LABColor[bmp.Width * bmp.Height];

            FastBitmap fastBmp = new FastBitmap(bmp);

            fastBmp.LockImage();

            for (int i = 0; i < labPixelData.Length; ++i)
            {
                labPixelData[i] = RGBToLAB(fastBmp.GetPixel());
                fastBmp.NextPixel();
            }

            fastBmp.UnlockImage();
            return(labPixelData);
        }
예제 #5
0
        public static LABColor RGBToLAB(Color rgb)
        {
            LABColor labColor = new LABColor();

            // RGB to XYZ
            // http://www.brucelindbloom.com/index.html?Eqn_RGB_to_XYZ.html

            //Normalize rgb to [0,1]
            float Vr = rgb.R / 255f;
            float Vg = rgb.G / 255f;
            float Vb = rgb.B / 255f;

            //Inverse sRGB Companding
            // (sRGB (V) to linear RGB (v))
            float vr = Vr;
            float vg = Vg;
            float vb = Vb;

            if (vr <= 0.04045)
            {
                vr = vr / 12.92f;
            }
            else
            {
                vr = (float)Math.Pow((vr + 0.055) / 1.055, 2.4);
            }

            if (vg <= 0.04045)
            {
                vg = vg / 12.92f;
            }
            else
            {
                vg = (float)Math.Pow((vg + 0.055) / 1.055, 2.4);
            }

            if (vb <= 0.04045)
            {
                vb = vb / 12.92f;
            }
            else
            {
                vb = (float)Math.Pow((vb + 0.055) / 1.055, 2.4);
            }

            // Linear RGB to XYZ
            // [X,Y,Z] = [M][v]
            // [M]: sRGB to XYZ matrix (with D50 ref white):
            //http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
            float X = 0.4360747f * vr + 0.3850649f * vg + 0.1430804f * vb;
            float Y = 0.2225045f * vr + 0.7168786f * vg + 0.0606169f * vb;
            float Z = 0.0139322f * vr + 0.0971045f * vg + 0.7141733f * vb;

            // XYZ to Lab
            // http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_Lab.html
            float xr = X / Xr;
            float yr = Y / Yr;
            float zr = Z / Zr;

            float fx, fy, fz;

            if (xr > epsilon)
            {
                fx = (float)Math.Pow(xr, 1 / 3f);
            }
            else
            {
                fx = (k * xr + 16f) / 116f;
            }

            if (yr > epsilon)
            {
                fy = (float)Math.Pow(yr, 1 / 3f);
            }
            else
            {
                fy = (k * yr + 16f) / 116f;
            }

            if (zr > epsilon)
            {
                fz = (float)Math.Pow(zr, 1 / 3f);
            }
            else
            {
                fz = (k * zr + 16f) / 116f;
            }

            labColor.Lf = (116 * fy) - 16;
            labColor.af = 500 * (fx - fy);
            labColor.bf = 200 * (fy - fz);

            return(labColor);
        }
예제 #6
0
        public static Color LABToRGB(LABColor lab)
        {
            int R, G, B;

            // Lab to XYZ
            // http://www.brucelindbloom.com/index.html?Eqn_Lab_to_XYZ.html

            float fy = (lab.Lf + 16) / 116;
            float fz = fy - (lab.bf / 200);
            float fx = (lab.af / 500) + fy;

            float xr = (float)Math.Pow(fx, 3);
            float yr;
            float zr = (float)Math.Pow(fz, 3);

            if (!(xr > epsilon))
            {
                xr = (116 * fx - 16) / k;
            }

            if (lab.Lf > (k * epsilon))
            {
                yr = (float)Math.Pow((lab.Lf + 16) / 116, 3);
            }
            else
            {
                yr = lab.Lf / k;
            }

            if (!(zr > epsilon))
            {
                xr = (116 * fz - 16) / k;
            }

            float X = xr * Xr;
            float Y = yr * Yr;
            float Z = zr * Zr;

            // XYZ to RGB
            // http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_RGB.html

            // XYZ to Linear RGB (v)
            // [v] = [M]^-1[X,Y,Z]
            // [M]^-1: XYZ to sRGB matrix (with D50 ref white):
            // http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html

            float vr = 3.1338561f * X - 1.6168667f * Y - 0.4906146f * Z;
            float vg = -0.9787684f * X + 1.9161415f * Y + 0.0334540f * Z;
            float vb = 0.0719453f * X - 0.2289914f * Y + 1.4052427f * Z;

            // sRGB Companding
            // (linear RGB (v) to sRGB (V))
            float Vr, Vg, Vb;

            if (vr <= 0.0031308)
            {
                Vr = 12.92f * vr;
            }
            else
            {
                Vr = 1.055f * (float)Math.Pow(vr, 1 / 2.4f) - 0.055f;
            }

            if (vg <= 0.0031308)
            {
                Vg = 12.92f * vg;
            }
            else
            {
                Vg = 1.055f * (float)Math.Pow(vg, 1 / 2.4f) - 0.055f;
            }

            if (vb <= 0.0031308)
            {
                Vb = 12.92f * vb;
            }
            else
            {
                Vb = 1.055f * (float)Math.Pow(vb, 1 / 2.4f) - 0.055f;
            }

            //Normalize rgb to [0,255]
            R = (int)(Vr * 255);
            G = (int)(Vg * 255);
            B = (int)(Vb * 255);

            if (R > 255)
            {
                R = 255;
            }
            else if (R < 0)
            {
                R = 0;
            }

            if (G > 255)
            {
                G = 255;
            }
            else if (G < 0)
            {
                G = 0;
            }

            if (B > 255)
            {
                B = 255;
            }
            else if (B < 0)
            {
                B = 0;
            }

            return(Color.FromArgb(255, R, G, B));
        }