Exemplo n.º 1
0
        public static IntField BackgroundFilterSmall(IntField image, int areaThresh)
        {
            image = image.Clone();
            IntField processed = image.Clone();

            // 0..3 - original unprocessed colors
            // -1   - accepted as background
            // -2   - trial fill / kept for later elimination
            for (int y = 0; y < image.Height; y++)
            {
                for (int x = 0; x < image.Width; x++)
                {
                    if (processed[x, y] >= 0)
                    {
                        // Do trial fill
                        processed.Floodfill(x, y, -2);
                        // Accept as background?
                        if (processed.Counter_Floodfill_TotalPixels > areaThresh)
                        {
                            processed.Floodfill(x, y, -1);
                        }
                    }
                }
            }

            for (int p = 0; p < image.Data.Length; p++)
            {
                if (processed.Data[p] == -2)
                {
                    image.Data[p] = -2;
                }
            }

            for (int y = 0; y < image.Height; y++)
            {
                for (int x = 0; x < image.Width; x++)
                {
                    if (processed[x, y] == -2)
                    {
                        if (x > 0 && processed[x - 1, y] == -1)
                        {
                            image.Floodfill(x, y, image[x - 1, y]);
                            processed.Floodfill(x, y, -3);
                        }
                        else if (y > 0 && processed[x, y - 1] == -1)
                        {
                            image.Floodfill(x, y, image[x, y - 1]);
                            processed.Floodfill(x, y, -3);
                        }
                        else if (x < image.Width - 1 && processed[x + 1, y] == -1)
                        {
                            image.Floodfill(x, y, image[x + 1, y]);
                            processed.Floodfill(x, y, -3);
                        }
                        else if (y < image.Height - 1 && processed[x, y + 1] == -1)
                        {
                            image.Floodfill(x, y, image[x, y + 1]);
                            processed.Floodfill(x, y, -3);
                        }
                    }
                }
            }

            return(image);
        }
Exemplo n.º 2
0
        private void backgroundSplit(IntField image, out IntField backgr, out IntField foregr)
        {
            IntField largeBackgrMap;

            // First pass: all large areas are always backgrounds
            {
                IntField vis_hitpoints = image.Clone();
                largeBackgrMap = image.Clone();
                int    x = 0, y = 0, xfr = 0;
                double yd      = 0;
                double ystep   = _backgrLargeStepSize * 0.866 / ((double)image.Width / _backgrLargeStepSize);
                int    curfill = -2;
                while (true)
                {
                    y = (int)yd;
                    if (y >= image.Height)
                    {
                        break;
                    }

                    vis_hitpoints[x, y] = 10;
                    if (largeBackgrMap[x, y] >= 0)
                    {
                        largeBackgrMap.Floodfill(x, y, curfill);
                        curfill--;
                        if (largeBackgrMap.Counter_Floodfill_TotalPixels > _backgrLargeAreaThresh)
                        {
                            largeBackgrMap.Floodfill(x, y, -1);
                        }
                    }

                    yd += ystep;
                    x  += _backgrLargeStepSize;
                    if (x >= image.Width)
                    {
                        xfr += _backgrLargeStepSize / 3;
                        if (xfr > _backgrLargeStepSize)
                        {
                            xfr -= _backgrLargeStepSize;
                        }
                        x = xfr;
                    }
                }

                largeBackgrMap.Map(pix => pix == -1 ? 1 : 0);
                AddImageGrayscale(vis_hitpoints, "10-bkg-large-hitpoints");
                AddImageGrayscale(largeBackgrMap, "11-bkg-large-map");
            }

            // TODO: also background if perfectly rectangular and larger than 4 area

            // Second pass - background continuation
            {
                // Prepare image
                backgr = image.Clone();
                for (int p = 0; p < image.Data.Length; p++)
                {
                    if (largeBackgrMap.Data[p] == 0)
                    {
                        backgr.Data[p] = -1;
                    }
                }
                AddImageGrayscale(backgr, -1, 3, "12-bkg-cont-before");

                // Horizontal continuation
                for (int y = 0; y < backgr.Height; y++)
                {
                    int lastbg      = -1;
                    int lastfgstart = -1;  // -1 means not in a foreground run
                    int x           = 0;
                    while (true)
                    {
                        if (lastfgstart != -1 && (x == backgr.Width || backgr[x, y] != -1))
                        {   // in a fg run and either end of image or end of run (no longer foreground)
                            if (lastbg == -1 || x == backgr.Width || lastbg == backgr[x, y])
                            {
                                int clr = x == backgr.Width ? lastbg : backgr[x, y];
                                for (int fx = lastfgstart; fx < x; fx++)
                                {
                                    backgr[fx, y] = clr;
                                }
                            }
                            lastfgstart = -1;
                        }
                        if (x == backgr.Width)
                        {
                            break;
                        }
                        if (lastfgstart == -1 && backgr[x, y] == -1)
                        {
                            lastfgstart = x;
                            lastbg      = x == 0 ? -1 : backgr[x - 1, y];
                        }
                        x++;
                    }
                }
                AddImageGrayscale(backgr, -1, 3, "13-bkg-cont-horz");

                // Vertical continuation
                for (int x = 0; x < backgr.Width; x++)
                {
                    int lastbg      = -1;
                    int lastfgstart = -1;  // -1 means not in a foreground run
                    int y           = 0;
                    while (true)
                    {
                        if (lastfgstart != -1 && (y == backgr.Height || backgr[x, y] != -1))
                        {   // in a fg run and either end of image or end of run (no longer foreground)
                            if (lastbg == -1 || y == backgr.Height || lastbg == backgr[x, y])
                            {
                                int clr = y == backgr.Height ? lastbg : backgr[x, y];
                                for (int fy = lastfgstart; fy < y; fy++)
                                {
                                    backgr[x, fy] = clr;
                                }
                            }
                            lastfgstart = -1;
                        }
                        if (y == backgr.Height)
                        {
                            break;
                        }
                        if (lastfgstart == -1 && backgr[x, y] == -1)
                        {
                            lastfgstart = y;
                            lastbg      = y == 0 ? -1 : backgr[x, y - 1];
                        }
                        y++;
                    }
                }
                AddImageGrayscale(backgr, -1, 3, "14-bkg-cont-vert");

                // Continuation of leftover areas
                int lastc = -1;
                for (int p = 0; p < backgr.Data.Length; p++)
                {
                    if (backgr.Data[p] == -1 && lastc != -1)
                    {
                        backgr.Floodfill(p % backgr.Width, p / backgr.Width, lastc);
                    }
                    else if (p > 0 && backgr.Data[p - 1] == -1 && backgr.Data[p] != -1)
                    {
                        backgr.Floodfill((p - 1) % backgr.Width, (p - 1) / backgr.Width, backgr.Data[p]);
                    }
                    if (backgr.Data[p] != -1)
                    {
                        lastc = backgr.Data[p];
                    }
                }

                // TODO: remove anything that's highly non-rect

                AddImageGrayscale(backgr, 0, 3, "15-final-bkg");
            }

            // Final pass - extract foreground
            {
                foregr = image.Clone();
                for (int p = 0; p < image.Data.Length; p++)
                {
                    foregr.Data[p] ^= backgr.Data[p];
                }
                AddImageGrayscale(foregr, 0, 3, "16-final-fgr");
            }
        }