예제 #1
0
        private void KMeansCPU(bool async = false)
        {
            DoubleColor[,] LABImageArray = new DoubleColor[SourceImageColorArray.GetLength(0), SourceImageColorArray.GetLength(1)];
            var cp = SourceImageColorProfile;

            var start1 = DateTime.Now;

            ColorProfileConverter.ConvertImageToLAB(SourceImageColorArray, LABImageArray, cp);
            DoubleColor[,] result;
            if (async == false)
            {
                result = KMeansCalc.CalculateKMeans(LABImageArray, KMeansParam, Globals.max_iter, Globals.eps);
            }
            else
            {
                result = KMeansCalc.CalculateKMeansAsync(LABImageArray, KMeansParam, Globals.max_iter, Globals.eps);
            }
            ColorProfileConverter.ConvertImageFromLAB(result, DestImageColorArray, cp);

            var end = DateTime.Now;

            string s = "";

            if (async == true)
            {
                s = "[ASYNC]";
            }

            Debug.WriteLine($"CPU TIME{s}: {end - start1}");

            Dispatcher.Invoke(() =>
            {
                Paint.CopyToWriteableBitmap(DestImageWB, DestImageColorArray);
            });
        }
예제 #2
0
        public static double Distance(DoubleColor c1, DoubleColor c2)
        {
            double dL = c1.R - c2.R;
            double da = c1.G - c2.G;
            double db = c1.B - c2.B;

            return(Math.Sqrt(dL * dL + da * da + db * db));
        }
예제 #3
0
        public static DoubleColor ConvertColorToXYZ(DoubleColor color, ColorProfile src)
        {
            color.InverseGammaCorrection(src.Gamma);
            var         v   = src.RGBtoXYZ.MultiplyByVectorRight(color.R, color.G, color.B);
            DoubleColor XYZ = new DoubleColor(v.X, v.Y, v.Z);

            return(XYZ);
        }
예제 #4
0
        public static DoubleColor ConvertColorToXYZ(DoubleColor color, ColorProfileEnum from)
        {
            ColorProfile cp = null;

            switch (from)
            {
            case ColorProfileEnum.sRGB:
            {
                cp = ColorProfileFactory.GetFactory().sRBGcolorProfile;
            }
            break;

            case ColorProfileEnum.adobeRGB:
            {
                cp = ColorProfileFactory.GetFactory().adobeRBGcolorProfile;
            }
            break;

            case ColorProfileEnum.appleRGB:
            {
                cp = ColorProfileFactory.GetFactory().appleRBGcolorProfile;
            }
            break;

            case ColorProfileEnum.CIE_RGB:
            {
                cp = ColorProfileFactory.GetFactory().CIE_RBGcolorProfile;
            }
            break;

            case ColorProfileEnum.WideGamut:
            {
                cp = ColorProfileFactory.GetFactory().WideGamutcolorProfile;
            }
            break;

            case ColorProfileEnum.PAL:
            {
                cp = ColorProfileFactory.GetFactory().PALcolorProfile;
            }
            break;

            default:
                break;
            }

            color.InverseGammaCorrection(cp.Gamma);
            var         v   = cp.RGBtoXYZ.MultiplyByVectorRight(color.R, color.G, color.B);
            DoubleColor XYZ = new DoubleColor(v.X, v.Y, v.Z);

            //XYZ.ToXYZ();
            return(XYZ);



            //return new DoubleColor(-1, -1, -1);
        }
예제 #5
0
 public static void ConvertImageToDoubleColor(SimpleColor[,] imageSource, DoubleColor[,] imageDest)
 {
     Parallel.For(0, imageSource.GetLength(0), i =>
     {
         for (int j = 0; j < imageSource.GetLength(1); j++)
         {
             imageDest[i, j] = new DoubleColor(imageSource[i, j]);
         }
     });
 }
예제 #6
0
        public static DoubleColor ConvertColorFromXYZ(DoubleColor color, ColorProfile dest, MyMatrix bradfordMatrix = null)
        {
            if (bradfordMatrix != null)
            {
                (color.R, color.G, color.B) = bradfordMatrix.MultiplyByVectorRight(color.R, color.G, color.B);
            }
            var         v   = dest.XYZtoRGB.MultiplyByVectorRight(color.R, color.G, color.B);
            DoubleColor XYZ = new DoubleColor(v.X, v.Y, v.Z);

            XYZ.GammaCorrection(dest.Gamma);
            return(XYZ);
        }
예제 #7
0
 public static void ConvertImageToLAB(SimpleColor[,] imageSource, DoubleColor[,] imageDest, ColorProfile from)
 {
     Parallel.For(0, imageSource.GetLength(0), i =>
     {
         for (int j = 0; j < imageSource.GetLength(1); j++)
         {
             DoubleColor color = new DoubleColor(imageSource[i, j]);
             var c1            = ConvertColorToXYZ(color, from);
             var c2            = ConvertColorFromXYZToLAB(c1, from);
             imageDest[i, j]   = c2;
         }
     });
 }
예제 #8
0
        public static DoubleColor ConvertColorFromXYZToLAB(DoubleColor color, ColorProfile cp)
        {
            //var cp = ColorProfileFactory.GetFactory().GetColorProfile(from);
            double YR = 100d;
            double XR = cp.White_X * YR / cp.White_Y;
            double ZR = cp.White_Z * YR / cp.White_Y;

            double xr = color.R / XR;
            double yr = color.G / YR;
            double zr = color.B / ZR;

            double k_modifier   = 903.3;
            double eps_modifier = 0.008856;

            double fx;
            double fy;
            double fz;

            if (xr > eps_modifier)
            {
                fx = Math.Pow(xr, 1d / 3d);
            }
            else
            {
                fx = (k_modifier * xr + 16d) / 116d;
            }

            if (yr > eps_modifier)
            {
                fy = Math.Pow(yr, 1d / 3d);
            }
            else
            {
                fy = (k_modifier * yr + 16d) / 116d;
            }

            if (zr > eps_modifier)
            {
                fz = Math.Pow(zr, 1d / 3d);
            }
            else
            {
                fz = (k_modifier * zr + 16d) / 116d;
            }

            double L = 116d * fy - 16d;
            double a = 500d * (fx - fy);
            double b = 200d * (fy - fz);

            return(new DoubleColor(L, a, b));
        }
예제 #9
0
        public static void ConvertImage(SimpleColor[,] imageSource, SimpleColor[,] imageDest, ColorProfile from, ColorProfile to)
        {
            var bradfordMatrix = MyMatrix.GenerateBradfordMatrix(from, to);

            Parallel.For(0, imageSource.GetLength(0), i =>
            {
                for (int j = 0; j < imageSource.GetLength(1); j++)
                {
                    DoubleColor color = new DoubleColor(imageSource[i, j]);
                    var c1            = ConvertColorToXYZ(color, from);
                    var c2            = ConvertColorFromXYZ(c1, to, bradfordMatrix);
                    imageDest[i, j]   = c2.ToSimpleColor();
                }
            });
        }
예제 #10
0
        public static DoubleColor ConvertColorFromLABToXYZ(DoubleColor color, ColorProfile cp)
        {
            //var cp = ColorProfileFactory.GetFactory().GetColorProfile(from);
            double YR = 100d;
            double XR = cp.White_X * YR / cp.White_Y;
            double ZR = cp.White_Z * YR / cp.White_Y;

            double xr;
            double yr;
            double zr;

            double k_modifier   = 903.3;
            double eps_modifier = 0.008856;


            double fy = (color.R + 16d) / 116d;
            double fx = color.G / 500d + fy;
            double fz = fy - color.B / 200d;

            xr = Math.Pow(fx, 3);
            if (xr <= eps_modifier)
            {
                xr = (116d * fx - 16d) / k_modifier;
            }

            if (color.R > k_modifier * eps_modifier)
            {
                yr = Math.Pow((color.R + 16d) / 116d, 3);
            }
            else
            {
                yr = color.R / k_modifier;
            }

            zr = Math.Pow(fz, 3);
            if (zr <= eps_modifier)
            {
                zr = (116d * fz - 16d) / k_modifier;
            }


            double X = xr * XR;
            double Y = yr * YR;
            double Z = zr * ZR;

            return(new DoubleColor(X, Y, Z));
        }
예제 #11
0
        public static DoubleColor[,] CalculateKMeansAsync(DoubleColor[,] array, int k_means, int max_iter, double eps)
        {
            double[,] distances = new double[array.GetLength(0), array.GetLength(1)];
            int[,] clusters     = new int[array.GetLength(0), array.GetLength(1)];
            DoubleColor[]     centroids       = new DoubleColor[k_means];
            List <(int, int)> centroids_cords = new List <(int, int)>();
            Random            rand            = new Random();

            for (int i = 0; i < centroids.Length; i++)
            {
                int x = rand.Next(0, array.GetLength(0));
                int y = rand.Next(0, array.GetLength(1));

                int iters = 0;
                while (centroids_cords.Exists(a => DoubleColor.Distance(array[a.Item1, a.Item2], array[x, y]) < eps) == true || iters > max_iter)
                {
                    x = rand.Next(0, array.GetLength(0));
                    y = rand.Next(0, array.GetLength(1));
                    iters++;
                }

                centroids[i] = array[x, y];
            }

            for (int iter_number = 0; iter_number < max_iter; iter_number++)
            {
                //Phase Distance Calculation
                Parallel.For(0, array.GetLength(0), x =>
                {
                    for (int y = 0; y < array.GetLength(1); y++)
                    {
                        var minDist = double.MaxValue;
                        int index   = -1;
                        for (int k = 0; k < centroids.Length; k++)
                        {
                            //if(x==0&&y==0)
                            //{
                            //    ;
                            //}
                            var cur_dist = DoubleColor.Distance(centroids[k], array[x, y]);
                            if (cur_dist < minDist)
                            {
                                minDist = cur_dist;
                                index   = k;
                            }
                        }
                        //if (index == -1)
                        //    ;
                        clusters[x, y] = index;
                    }
                });

                //Phase Centroid Recalculation
                bool hasCentroidChanged = false;


                Parallel.For(0, centroids.Length, k =>
                {
                    int count             = 0;
                    DoubleColor color_sum = new DoubleColor(0d, 0d, 0d);
                    for (int x = 0; x < array.GetLength(0); x++)
                    {
                        for (int y = 0; y < array.GetLength(1); y++)
                        {
                            if (clusters[x, y] == k)
                            {
                                count++;
                                color_sum.R += array[x, y].R;
                                color_sum.G += array[x, y].G;
                                color_sum.B += array[x, y].B;
                            }
                        }
                    }
                    if (count != 0)
                    {
                        color_sum.R /= (double)count;
                        color_sum.G /= (double)count;
                        color_sum.B /= (double)count;
                    }

                    var centroid_dist = DoubleColor.Distance(centroids[k], color_sum);
                    if (centroid_dist > eps)
                    {
                        centroids[k]       = color_sum;
                        hasCentroidChanged = true;
                    }
                });

                if (hasCentroidChanged == false)
                {
                    break;
                }
            }

            DoubleColor[,] resultArray = new DoubleColor[array.GetLength(0), array.GetLength(1)];
            Parallel.For(0, array.GetLength(0), x =>
            {
                for (int y = 0; y < array.GetLength(1); y++)
                {
                    resultArray[x, y] = centroids[clusters[x, y]];
                }
            });

            return(resultArray);
        }
예제 #12
0
        public static DoubleColor ConvertColorFromXYZ(DoubleColor color, ColorProfileEnum from, ColorProfileEnum to)
        {
            ColorProfile cp = null;

            switch (to)
            {
            case ColorProfileEnum.sRGB:
            {
                cp = ColorProfileFactory.GetFactory().sRBGcolorProfile;
            }
            break;

            case ColorProfileEnum.adobeRGB:
            {
                cp = ColorProfileFactory.GetFactory().adobeRBGcolorProfile;
            }
            break;

            case ColorProfileEnum.appleRGB:
            {
                cp = ColorProfileFactory.GetFactory().appleRBGcolorProfile;
            }
            break;

            case ColorProfileEnum.CIE_RGB:
            {
                cp = ColorProfileFactory.GetFactory().CIE_RBGcolorProfile;
            }
            break;

            case ColorProfileEnum.WideGamut:
            {
                cp = ColorProfileFactory.GetFactory().WideGamutcolorProfile;
            }
            break;

            case ColorProfileEnum.PAL:
            {
                cp = ColorProfileFactory.GetFactory().PALcolorProfile;
            }
            break;

            default:
                break;
            }


            //color.InverseGammaCorrection(cp.Gamma);
            MyMatrix bradford = MyMatrix.GenerateBradfordMatrix(from, to);

            if (bradford != null)
            {
                (color.R, color.G, color.B) = bradford.MultiplyByVectorRight(color.R, color.G, color.B);
            }
            var         v   = cp.XYZtoRGB.MultiplyByVectorRight(color.R, color.G, color.B);
            DoubleColor XYZ = new DoubleColor(v.X, v.Y, v.Z);

            XYZ.GammaCorrection(cp.Gamma);
            return(XYZ);


            //return new DoubleColor(-1, -1, -1);
        }
예제 #13
0
        public static void CreateHSVBitmap(SimpleColor[,] pixels)
        {
            int middle_x = pixels.GetLength(1) / 2;
            int middle_y = pixels.GetLength(0) / 2;

            for (int y = 0; y < pixels.GetLength(0); y++)
            {
                for (int x = 0; x < pixels.GetLength(1); x++)
                {
                    if (y < Globals.BorderWidth || y > pixels.GetLength(0) - Globals.BorderWidth ||
                        x < Globals.BorderWidth || x > pixels.GetLength(1) - Globals.BorderWidth)
                    {
                        pixels[y, x] = new SimpleColor(0, 0, 0);
                    }
                    else
                    {
                        pixels[y, x] = new SimpleColor(255, 255, 255);
                        double dist = Distance(middle_x, middle_y, x, y);
                        if (dist <= Globals.Radius)
                        {
                            //calculate HSV
                            //double V = 1;
                            double C   = dist / (double)Globals.Radius;
                            double m   = 1 - C;
                            double cos = Cosinus(middle_x, middle_y, x, y, dist);
                            if (y <= middle_y)// angle between 0 and pi
                            {
                                double H      = Math.Acos(cos);
                                double angleH = H * 180d / Math.PI;
                                double int_H  = (angleH / 60d);
                                //C to dist
                                double X = C * (1 - Math.Abs((int_H % 2) - 1));
                                if (int_H <= 1)
                                {
                                    var color       = new DoubleColor(C + m, X + m, m);
                                    var simpleColor = color.ToSimpleColor();
                                    //double R = 0.5 + C * Math.Cos(angleH) / Math.Cos(60 - H);
                                    //double B = 0.5 - C;
                                    //double G = 1.5 - B - R;
                                    //color = new DoubleColor(R, G, B);
                                    //simpleColor = color.ToSimpleColor();

                                    pixels[y, x] = simpleColor;
                                }
                                else if (int_H <= 2)
                                {
                                    var color = new DoubleColor(X + m, C + m, m);
                                    pixels[y, x] = color.ToSimpleColor();
                                }
                                else
                                {
                                    var color = new DoubleColor(m, C + m, X + m);
                                    pixels[y, x] = color.ToSimpleColor();
                                }
                            }
                            else // angle between pi and 2 pi
                            {
                                double H      = Math.Acos(cos);
                                double angleH = 360d - H * 180 / Math.PI;
                                double int_H  = (angleH / 60);
                                //C to dist
                                double X = C * (1 - Math.Abs((int_H % 2) - 1));
                                if (int_H <= 4)
                                {
                                    var color = new DoubleColor(m, X + m, C + m);
                                    pixels[y, x] = color.ToSimpleColor();
                                }
                                else if (int_H <= 5)
                                {
                                    var color = new DoubleColor(X + m, m, C + m);
                                    pixels[y, x] = color.ToSimpleColor();
                                }
                                else
                                {
                                    var color = new DoubleColor(C + m, m, X + m);
                                    pixels[y, x] = color.ToSimpleColor();
                                }
                            }
                        }
                    }
                }
            }
        }
예제 #14
0
        private void TestButtonRadioButton_Click(object sender, RoutedEventArgs e)
        {
            var tab1 = new float[2];
            var tab2 = new float[2];
            var tab3 = new float[2];

            for (int i = 0; i < tab1.Length; i++)
            {
                if (i == 0)
                {
                    tab1[i] = 1f;
                    tab2[i] = 1f;
                    tab3[i] = 1f;
                }
                else
                {
                    tab1[i] = 2f;
                    tab2[i] = 2f;
                    tab3[i] = 2f;
                }
            }

            var inttab1 = new int[10];
            var inttab2 = new int[10];

            for (int i = 0; i < inttab1.Length; i++)
            {
                inttab1[i] = 3;
                inttab2[i] = 7;
            }

            DoubleColor[,] LABImageArray = new DoubleColor[SourceImageColorArray.GetLength(0), SourceImageColorArray.GetLength(1)];
            int from = SourceColorSpaceComboBox.SelectedIndex;

            ColorProfileConverter.ConvertImageToLAB(SourceImageColorArray, LABImageArray, (ColorProfileEnum)from);


            int rows = LABImageArray.GetLength(0);
            int cols = LABImageArray.GetLength(1);

            var vector_x = new float[rows * cols];
            var vector_y = new float[rows * cols];
            var vector_z = new float[rows * cols];

            for (int x = 0; x < rows; x++)
            {
                for (int y = 0; y < cols; y++)
                {
                    vector_x[y + x * cols] = (float)LABImageArray[x, y].R;
                    vector_y[y + x * cols] = (float)LABImageArray[x, y].G;
                    vector_z[y + x * cols] = (float)LABImageArray[x, y].B;
                }
            }

            using (var wrapper = new Logic())
            {
                //var result = wrapper.addParallelVectors(inttab1, inttab2, inttab1.Length);

                //for (int i = 0; i < result.Length; i++)
                //{
                //    Debug.Write($"{result[i]}, ");
                //}
                //Debug.WriteLine("");
                var iters = wrapper.KMeansGather(tab1, tab2, tab3, tab1.Length, 1, MaxIter);
                Debug.WriteLine($"KMEANS: Iters: {iters}");
                for (int i = 0; i < tab1.Length; i++)
                {
                    Debug.WriteLine($"X: {tab1[i]} Y: {tab2[i]} Z: {tab3[i]}");
                }


                var img_iters = wrapper.KMeansGather(vector_x, vector_y, vector_z, vector_x.Length, KMeansParam, MaxIter);
                Debug.WriteLine($"Image iterations: {img_iters}");
            }

            for (int x = 0; x < rows; x++)
            {
                for (int y = 0; y < cols; y++)
                {
                    LABImageArray[x, y].R = vector_x[y + x * cols];
                    LABImageArray[x, y].G = vector_y[y + x * cols];
                    LABImageArray[x, y].B = vector_z[y + x * cols];
                }
            }

            ColorProfileConverter.ConvertImageFromLAB(LABImageArray, DestImageColorArray, (ColorProfileEnum)from);

            Paint.CopyToWriteableBitmap(DestImageWB, DestImageColorArray);
        }