Exemple #1
0
        private void NormalizeToPalette()
        {
            try
            {
                using (Bitmap originalImage = new Bitmap(picOriginal.Image))
                {
                    // Can't generate the rendered image here in a using statement as the image will be null in future repaints of the picturebox
                    Bitmap renderedImage = new Bitmap(originalImage.Width, originalImage.Height);
                    for (int x = 0; x < originalImage.Width; x++)
                    {
                        for (int y = 0; y < originalImage.Height; y++)
                        {
                            Color color = originalImage.GetPixel(x, y);

                            // Skip transparent
                            if (color.A == 0)
                            {
                                renderedImage.SetPixel(x, y, color);
                            }
                            else
                            {
                                ColorTuple tup = color.ClosestColor(palette);
                                renderedImage.SetPixel(x, y, tup.ColorValue);
                            }
                        }
                    }
                    picRendered.Image = renderedImage;
                }
            }
            catch (Exception ex)
            {
            }
        }
 public CustomPanel(int x, int y, ColorTuple tuple)
 {
     X           = x;
     Y           = y;
     PaletteItem = tuple;
     //BackColor = tuple.ColorValue;
     BorderStyle = BorderStyle.FixedSingle;
 }
Exemple #3
0
    public ColorTuple getRandomColor()
    {
        int        idx = Random.Range(0, 10);
        ColorTuple T   = new ColorTuple();

        T.color = possibleColors[idx];
        T.index = idx;
        return(T);
    }
Exemple #4
0
 public void ChangeColor()
 {
     colorIndex    = ((colorIndex < colors.Count - 1) ? colorIndex + 1 : 0);
     selectedColor = colors [colorIndex];
     GetComponent <MeshRenderer> ().sharedMaterial.mainTexture = gradientTexture;
     for (int i = 0; i < gradientTexture.width; i++)
     {
         //Debug.Log (i / (float)gradientTexture.width);
         gradientTexture.SetPixel(i, 0, Color.Lerp(selectedColor.colorL, selectedColor.colorR, i / (float)gradientTexture.width));
     }
     gradientTexture.Apply();
     //Camera.main.backgroundColor = selectedColor.colorL;
 }
        /// <summary>
        /// 将颜色相近的像素连接成连通分量,根据每个联通分量的性质判断是否是文字
        /// 默认假设浅色文字周围有深色的边框,否则需要反转
        /// </summary>
        /// <param name="b"></param>
        /// <param name="reversed">false:浅色文字,深色边框/背景,true:深色文字,浅色边框/背景</param>
        /// <returns></returns>
        public static Bitmap Process(Bitmap b, bool reversed)
        {
            int width  = b.Width;
            int height = b.Height;

            float[,,] pixel = new float[width, height, 3];
            int[,] selected = new int[width, height];
            //把像素值转换成0-1之间的浮点数,存入pixel
            NormalizeBitmap(b, pixel, reversed);
            //将颜色相近的像素合并成色块,并去掉和图片边缘相邻的所有色块(假设文字在图片内部)
            //注:此时还不知道文字是什么颜色的
            //将那些最有可能是文字的色块所包含的像素坐标存入textPixels
            int[,] components = new int[width, height];
            List <(int, int)> textPixels  = new List <(int, int)>();
            List <int>        validLevels = new List <int>();
            int cur = 1;

            //先遍历边缘,再遍历中间
            for (int x = 0; x < width; x++)
            {
                if (components[x, 0] == 0)
                {
                    VisitComponent(x, 0, cur, components, pixel, textPixels, validLevels, true);
                }
                if (components[x, height - 1] == 0)
                {
                    VisitComponent(x, height - 1, cur, components, pixel, textPixels, validLevels, true);
                }
            }
            for (int y = 1; y < height - 1; y++)
            {
                if (components[0, y] == 0)
                {
                    VisitComponent(0, y, cur, components, pixel, textPixels, validLevels, true);
                }
                if (components[width - 1, y] == 0)
                {
                    VisitComponent(width - 1, y, cur, components, pixel, textPixels, validLevels, true);
                }
            }
            ++cur;
            for (int x = 1; x < width - 1; x++)
            {
                for (int y = 1; y < height - 1; y++)
                {
                    if (components[x, y] == 0)
                    {
                        VisitComponent(x, y, cur, components, pixel, textPixels, validLevels, false);
                        ++cur;
                    }
                }
            }

            //判断文字宽度的范围
            double meanLevel = validLevels.Average(), levelDistSum = 0;

            foreach (var lv in validLevels)
            {
                levelDistSum += (lv - meanLevel) * (lv - meanLevel);
            }
            double levelStddev = Math.Sqrt(levelDistSum / Math.Max(1, validLevels.Count));
            int    minLevel = 2, maxLevel = 3, levelThresh = (int)Math.Round(meanLevel + 2.5 * levelStddev);

            foreach (var lv in validLevels)
            {
                if (lv <= levelThresh)
                {
                    maxLevel = Math.Max(maxLevel, lv + 2);
                }
            }
            int minSize = 5;

            //假设上一步找到的像素中大部分都属于文字
            //由于第一轮寻找的条件相对苛刻,很难保证找到所有文字像素,所以我们需要第二轮寻找
            //找出这些像素颜色的近似(加权)几何中位数,以及标准差
            //我们猜测这个几何中位数就是文字的颜色
            float      stddiv;
            ColorTuple median = GeometricMedian(textPixels, pixel, out stddiv);
            float      radius = Math.Min(1.1f * stddiv, 0.3f);

            radius = Math.Max(radius, 0.1f);
            //把颜色接近几何中位数的所有像素标记为疑似文字像素(标为1),去除其他像素(标为0)
            //标为1的像素之间互相是联通的
            Relabel(pixel, components, median, radius);
            for (int x = 0; x < width; x++)
            {
                for (int y = 0; y < height; y++)
                {
                    //遍历所有可能是文字的色块
                    if (components[x, y] == 1)
                    {
                        List <(int, int)> visited  = new List <(int, int)>();
                        bool isBorder              = false;
                        List <(int, int)> boundary = ComputeBoundary(median, x, y, 2,
                                                                     pixel, components, visited, out isBorder);
                        //如果当前色块与边界接壤,则舍弃
                        if (!isBorder)
                        {
                            int level = ComputeLevelWithBoundary(boundary, components[x, y], maxLevel, components);
                            //如果当前色块的宽度/大小符合要求,则记录,否则舍弃
                            if ((visited.Count >= minSize || level >= minLevel) && level <= maxLevel)
                            {
                                foreach (var t in visited)
                                {
                                    selected[t.Item1, t.Item2] = 1;
                                }
                            }
                        }
                    }
                }
            }
            //将记录下来的色块标为白色,其他标为黑色
            return(SelectedThreshold(b, selected));
        }
        //TODO : Add commandline args handling
        static void Main(string[] args)
        {
            /*
             * 1. Open the palette and create a dictionary of name, color
             * 2. Open image and iterate over all pixels, across columns, then rows
             * 3. For each pixel, resolve into nearest color from palette and add to the order sheet
             * NOTE : Transparent pixels don't enter into the count
             */

            string srcImage   = "test.png";
            string srcPalette = "colours.csv";
            string outImage   = "paletteAdjusted.png";

            Dictionary <string, Color> palette    = PaletteProcessor.CreatePalette(srcPalette);
            Dictionary <string, int>   orderSheet = new Dictionary <string, int>();

            using (Bitmap src = new Bitmap(srcImage))
            {
                using (Bitmap tar = new Bitmap(src.Width, src.Height))
                {
                    for (int x = 0; x < src.Width; x++)
                    {
                        for (int y = 0; y < src.Height; y++)
                        {
                            Color color = src.GetPixel(x, y);

                            // Skip transparent
                            if (color.A == 0)
                            {
                                tar.SetPixel(x, y, color);
                            }
                            else
                            {
                                ColorTuple tup = color.ClosestColor(palette);

                                if (!orderSheet.ContainsKey(tup.Name))
                                {
                                    orderSheet.Add(tup.Name, 1);
                                }
                                else
                                {
                                    orderSheet[tup.Name]++;
                                }

                                tar.SetPixel(x, y, tup.ColorValue);
                            }
                        }
                    }

                    //Dump the ordersheet
                    StringBuilder sb = new StringBuilder();
                    foreach (string name in orderSheet.Keys)
                    {
                        sb.AppendFormat("{0}: {1}\r\n", name, orderSheet[name]);
                    }

                    File.WriteAllText("OrderSheet.txt", sb.ToString());
                    tar.Save(outImage, src.RawFormat);
                }
            }
        }