public override void Charseg(ref Intarray result_segmentation, Bytearray orig_image)
        {
            Logger.Default.Image("segmenting", orig_image);

            int PADDING = 3;

            OcrRoutine.optional_check_background_is_lighter(orig_image);
            Bytearray     image  = new Bytearray();
            Narray <byte> bimage = image;

            image.Copy(orig_image);
            OcrRoutine.binarize_simple(image);
            OcrRoutine.Invert(image);
            ImgOps.pad_by(ref bimage, PADDING, PADDING);
            // pass image to segmenter
            segmenter.SetImage(image);
            // find all cuts in the image
            segmenter.FindAllCuts();
            // choose the best of all cuts
            segmenter.FindBestCuts();

            Intarray segmentation = new Intarray();

            segmentation.Resize(image.Dim(0), image.Dim(1));
            for (int i = 0; i < image.Dim(0); i++)
            {
                for (int j = 0; j < image.Dim(1); j++)
                {
                    segmentation[i, j] = image[i, j] > 0 ? 1 : 0;
                }
            }

            for (int r = 0; r < segmenter.bestcuts.Length(); r++)
            {
                int            c   = segmenter.bestcuts[r];
                Narray <Point> cut = segmenter.cuts[c];
                for (int y = 0; y < image.Dim(1); y++)
                {
                    for (int x = cut[y].X; x < image.Dim(0); x++)
                    {
                        if (segmentation[x, y] > 0)
                        {
                            segmentation[x, y]++;
                        }
                    }
                }
            }
            ImgOps.extract_subimage(result_segmentation, segmentation, PADDING, PADDING,
                                    segmentation.Dim(0) - PADDING, segmentation.Dim(1) - PADDING);

            if (small_merge_threshold > 0)
            {
                SegmRoutine.line_segmentation_merge_small_components(ref result_segmentation, small_merge_threshold);
                SegmRoutine.line_segmentation_sort_x(result_segmentation);
            }

            SegmRoutine.make_line_segmentation_white(result_segmentation);
            // set_line_number(segmentation, 1);
            Logger.Default.Image("resulting segmentation", result_segmentation);
        }
Exemple #2
0
        /// <summary>
        /// Return the segmentation-derived mask for the character.
        /// This may optionally be grown by some pixels.
        /// </summary>
        public override void GetMask(out Rect r, ref Bytearray outmask, int index, int grow)
        {
            r = boxes.At1d(index).Grow(grow);
            r.Intersect(new Rect(0, 0, labels.Dim(0), labels.Dim(1)));
            if (fullheight)
            {
                r.y0 = 0;
                r.y1 = labels.Dim(1);
            }
            int      x = r.x0, y = r.y0, w = r.Width(), h = r.Height();
            Intarray segs = segments.At1d(index);

            outmask.Resize(w, h);
            outmask.Fill(0);
            for (int i = 0; i < w; i++)
            {
                for (int j = 0; j < h; j++)
                {
                    int label = labels[x + i, y + j];
                    if (NarrayUtil.first_index_of(segs, label) >= 0)
                    {
                        outmask[i, j] = (byte)255;
                    }
                }
            }
            if (grow > 0)
            {
                Morph.binary_dilate_circle(outmask, grow);
            }
        }
Exemple #3
0
 /// <summary>
 /// Label the connected components of an image.
 /// </summary>
 public static int label_components(ref Intarray image, bool four_connected = false)
 {
     int w = image.Dim(0), h = image.Dim(1);
     // We slice the image into columns and call make_set()
     // for every continuous segment within each column.
     // Maximal number of segments per column is (h + 1) / 2.
     // We do it `w' times, so it's w * (h + 1) / 2.
     // We also need to add 1 because index 0 is not used, but counted.
     UnionFind uf = new UnionFind(w * (h + 1) / 2 + 1);
     uf.make_set(0);
     int top = 1;
     for(int i=0; i<image.Length1d(); i++) image.Put1d(i, (image.At1d(i) > 0 ? 1 : 0));
     //for(int i=0;i<w;i++) {image(i,0) = 0; image(i,h-1) = 0;}
     //for(int j=0;j<h;j++) {image(0,j) = 0; image(w-1,j) = 0;}
     for(int i=0; i<w; i++) {
         int current_label = 0;
         for(int j=0; j<h; j++) {
             int pixel = image[i,j];
             int range = four_connected ? 0 : 1;
             for(int delta=-range; delta<=range; delta++) {
                 int adj_label = NarrayUtil.Bat(image, i-1, j+delta, 0);
                 if(pixel == 0) {
                     current_label = 0;
                     continue;
                 }
                 if(current_label == 0) {
                     current_label = top;
                     uf.make_set(top);
                     top++;
                 }
                 if(adj_label > 0) {
                     current_label = uf.find_set(current_label);
                     adj_label = uf.find_set(adj_label);
                     if(current_label != adj_label) {
                         uf.make_union(current_label, adj_label);
                         current_label = uf.find_set(current_label);
                         adj_label = uf.find_set(adj_label);
                     }
                 }
                 image[i,j] = current_label;
             }
         }
     }
     for(int i=0;i<image.Length1d();i++) {
         if(image.At1d(i) == 0) continue;
         image.Put1d(i, uf.find_set(image.At1d(i)));
     }
     return renumber_labels(image, 1);
 }
Exemple #4
0
 /// <summary>
 /// Compute the bounding boxes for the pixels in the image.
 /// </summary>
 public static void bounding_boxes(ref Narray<Rect> result, Intarray image)
 {
     result.Clear();
     int n = NarrayUtil.Max(image);
     if (n < 1) return;
     result.Resize(n + 1);
     result.Fill(Rect.CreateEmpty());
     for (int i = 0; i < image.Dim(0); i++)
         for (int j = 0; j < image.Dim(1); j++)
         {
             int value = image[i, j];
             Rect r = result[value];
             r.Include(i, j);
             result[value] = r;
             //original: result(value).include(i, j);
         }
 }
Exemple #5
0
        public void RunTest()
        {
            IBookStore bstore = new SmartBookStore();
            bstore.SetPrefix(@"data2");

            Console.WriteLine("Pages in bookstore: {0}", bstore.NumberOfPages());
            Console.WriteLine("List pages..");
            for (int i = 0; i < bstore.NumberOfPages(); i++)
            {
                Console.WriteLine("page {0:0000}\t->\t{1,6} lines", i, bstore.LinesOnPage(i));
            }
            Bytearray line = new Bytearray();
            bstore.GetLine(line, 1, 5);
            Console.WriteLine("line{0}      [{1},{2}]", 5, line.Dim(0), line.Dim(1));
            Intarray cline = new Intarray();
            bstore.GetCharSegmentation(cline, 1, 5);
            Console.WriteLine("line{0}.cseg [{1},{2}]", 5, cline.Dim(0), cline.Dim(1));
        }
Exemple #6
0
        public void Init(params string[] books)
        {
            bool   retrain    = PGetb("retrain");
            bool   randomize  = PGetb("randomize");
            string cbookstore = PGet("cbookstore");

            bookstores.Clear();
            all_lines.Clear();
            cseg_variant = "cseg.gt";
            text_variant = "gt";
            if (retrain)
            {
                cseg_variant = "cseg";
                text_variant = "";
            }

            int nbooks = books.Length;

            bookstores.Resize(nbooks);
            int totalNumberOfPages = 0;

            for (int i = 0; i < nbooks; i++)
            {
                bookstores[i] = ComponentCreator.MakeComponent <IBookStore>(cbookstore);
                bookstores[i].SetPrefix(books[i].Trim());
                Global.Debugf("info", "{0}: {1} pages", books[i], bookstores[i].NumberOfPages());
                totalNumberOfPages += bookstores[i].NumberOfPages();
            }
            //CHECK_ARG(totalNumberOfPages > 0, "totalNumberOfPages > 0");

            // compute a list of all lines
            Intarray triple = new Intarray(3);

            for (int i = 0; i < nbooks; i++)
            {
                for (int j = 0; j < bookstores[i].NumberOfPages(); j++)
                {
                    for (int k = 0; k < bookstores[i].LinesOnPage(j); k++)
                    {
                        triple[0] = i;
                        triple[1] = j;
                        triple[2] = k;
                        NarrayRowUtil.RowPush(all_lines, triple);
                    }
                }
            }
            Global.Debugf("info", "got {0} lines", all_lines.Dim(0));

            // randomly permute it so that we train in random order
            if (randomize)
            {
                Shuffle();
            }

            index = 0;
        }
Exemple #7
0
        public void RunTest()
        {
            IBookStore bstore = new SmartBookStore();

            bstore.SetPrefix(@"data2");

            Console.WriteLine("Pages in bookstore: {0}", bstore.NumberOfPages());
            Console.WriteLine("List pages..");
            for (int i = 0; i < bstore.NumberOfPages(); i++)
            {
                Console.WriteLine("page {0:0000}\t->\t{1,6} lines", i, bstore.LinesOnPage(i));
            }
            Bytearray line = new Bytearray();

            bstore.GetLine(line, 1, 5);
            Console.WriteLine("line{0}      [{1},{2}]", 5, line.Dim(0), line.Dim(1));
            Intarray cline = new Intarray();

            bstore.GetCharSegmentation(cline, 1, 5);
            Console.WriteLine("line{0}.cseg [{1},{2}]", 5, cline.Dim(0), cline.Dim(1));
        }
Exemple #8
0
        public static void extract_holes(ref Bytearray holes, Bytearray binarized)
        {
            Intarray temp = new Intarray();

            temp.Copy(binarized);
            NarrayUtil.Sub(255, temp);
            ImgLabels.label_components(ref temp);
            int background = -1;

            for (int i = 0; i < temp.Dim(0); i++)
            {
                if (temp[i, 0] != 0)
                {
                    background = temp[i, 0];
                    break;
                }
            }
            holes.MakeLike(temp);
            holes.Fill((byte)0);
            if (background <= 0)
            {
                throw new Exception("extract_holes: background must be more 0");
            }
            for (int i = 0; i < temp.Dim(0); i++)
            {
                for (int j = 0; j < temp.Dim(1); j++)
                {
                    if (temp[i, j] > 0 && temp[i, j] != background)
                    {
                        holes[i, j] = 255;
                    }
                }
            }

            /*fprintf(stderr, "segholes\n");
             * dsection("segholes");
             * dshow(holes, "y");*/
        }
Exemple #9
0
        public static void remove_dontcares(ref Intarray image)
        {
            Floatarray     dist   = new Floatarray();
            Narray <Point> source = new Narray <Point>();

            dist.Resize(image.Dim(0), image.Dim(1));
            for (int i = 0; i < dist.Length1d(); i++)
            {
                if (!dontcare(image.At1d(i)))
                {
                    dist.Put1d(i, (image.At1d(i) > 0 ? 1 : 0));
                }
            }
            BrushFire.brushfire_2(ref dist, ref source, 1000000);
            for (int i = 0; i < dist.Length1d(); i++)
            {
                Point p = source.At1d(i);
                if (dontcare(image.At1d(i)))
                {
                    image.Put1d(i, image[p.X, p.Y]);
                }
            }
        }
Exemple #10
0
        /// <summary>
        /// Compute the bounding boxes for the pixels in the image.
        /// </summary>
        public static void bounding_boxes(ref Narray <Rect> result, Intarray image)
        {
            result.Clear();
            int n = NarrayUtil.Max(image);

            if (n < 1)
            {
                return;
            }
            result.Resize(n + 1);
            result.Fill(Rect.CreateEmpty());
            for (int i = 0; i < image.Dim(0); i++)
            {
                for (int j = 0; j < image.Dim(1); j++)
                {
                    int  value = image[i, j];
                    Rect r     = result[value];
                    r.Include(i, j);
                    result[value] = r;
                    //original: result(value).include(i, j);
                }
            }
        }
Exemple #11
0
        public override void Charseg(ref Intarray segmentation, Bytearray inraw)
        {
            Logger.Default.Image("segmenting", inraw);

            OcrRoutine.optional_check_background_is_lighter(inraw);
            Bytearray image = new Bytearray();

            image.Copy(inraw);
            OcrRoutine.binarize_simple(image);
            OcrRoutine.Invert(image);

            segmenter.SetImage(image);
            segmenter.FindAllCuts();
            segmenter.FindBestCuts();

            Intarray seg = new Intarray();

            seg.Copy(image);

            for (int r = 0; r < segmenter.bestcuts.Length(); r++)
            {
                int            w   = seg.Dim(0);
                int            c   = segmenter.bestcuts[r];
                Narray <Point> cut = segmenter.cuts[c];
                for (int y = 0; y < image.Dim(1); y++)
                {
                    for (int i = -1; i <= 1; i++)
                    {
                        int x = cut[y].X;
                        if (x < 1 || x >= w - 1)
                        {
                            continue;
                        }
                        seg[x + i, y] = 0;
                    }
                }
            }
            ImgLabels.label_components(ref seg);
            // dshowr(seg,"YY"); dwait();
            segmentation.Copy(image);
            ImgLabels.propagate_labels_to(ref segmentation, seg);

            SegmRoutine.line_segmentation_merge_small_components(ref segmentation, small_merge_threshold);
            SegmRoutine.line_segmentation_sort_x(segmentation);

            SegmRoutine.make_line_segmentation_white(segmentation);
            // set_line_number(segmentation, 1);
            Logger.Default.Image("resulting segmentation", segmentation);
        }
        public override void Charseg(ref Intarray segmentation, Bytearray inraw)
        {
            Logger.Default.Image("segmenting", inraw);

            OcrRoutine.optional_check_background_is_lighter(inraw);
            Bytearray image = new Bytearray();
            image.Copy(inraw);
            OcrRoutine.binarize_simple(image);
            OcrRoutine.Invert(image);

            segmenter.SetImage(image);
            segmenter.FindAllCuts();
            segmenter.FindBestCuts();

            Intarray seg = new Intarray();
            seg.Copy(image);

            for (int r = 0; r < segmenter.bestcuts.Length(); r++)
            {
                int w = seg.Dim(0);
                int c = segmenter.bestcuts[r];
                Narray<Point> cut = segmenter.cuts[c];
                for (int y = 0; y < image.Dim(1); y++)
                {
                    for (int i = -1; i <= 1; i++)
                    {
                        int x = cut[y].X;
                        if (x < 1 || x >= w - 1) continue;
                        seg[x + i, y] = 0;
                    }
                }
            }
            ImgLabels.label_components(ref seg);
            // dshowr(seg,"YY"); dwait();
            segmentation.Copy(image);
            ImgLabels.propagate_labels_to(ref segmentation, seg);

            SegmRoutine.line_segmentation_merge_small_components(ref segmentation, small_merge_threshold);
            SegmRoutine.line_segmentation_sort_x(segmentation);

            SegmRoutine.make_line_segmentation_white(segmentation);
            // set_line_number(segmentation, 1);
            Logger.Default.Image("resulting segmentation", segmentation);
        }
Exemple #13
0
        public override void SetImage(Bytearray image)
        {
            dimage.Copy(image);
            int w = image.Dim(0), h = image.Dim(1);

            wimage.Resize(w, h);
            wimage.Fill(0);
            float s1 = 0.0f, sy = 0.0f;

            for (int i = 1; i < w; i++)
            {
                for (int j = 0; j < h; j++)
                {
                    if (image[i, j] > 0)
                    {
                        s1++; sy += j;
                    }
                    if (image[i - 1, j] == 0 && image[i, j] > 0)
                    {
                        wimage[i, j] = boundary_weight;
                    }
                    else if (image[i, j] > 0)
                    {
                        wimage[i, j] = inside_weight;
                    }
                    else
                    {
                        wimage[i, j] = outside_weight;
                    }
                }
            }
            where = (int)(sy / s1);
            for (int i = 0; i < dimage.Dim(0); i++)
            {
                dimage[i, where] = 0x008000;
            }
        }
Exemple #14
0
        protected void Step(int x0, int x1, int y)
        {
            int           w = wimage.Dim(0), h = wimage.Dim(1);
            Queue <Point> queue = new Queue <Point>(w * h);

            for (int i = x0; i < x1; i++)
            {
                queue.Enqueue(new Point(i, y));
            }
            int low  = 1;
            int high = wimage.Dim(0) - 1;

            while (queue.Count > 0)
            {
                Point p = queue.Dequeue();
                int   i = p.X, j = p.Y;
                int   cost  = costs[i, j];
                int   ncost = cost + wimage[i, j] + down_cost;
                if (costs[i, j + direction] > ncost)
                {
                    costs[i, j + direction]   = ncost;
                    sources[i, j + direction] = i;
                    if (j + direction != limit)
                    {
                        queue.Enqueue(new Point(i, j + direction));
                    }
                }
                if (i > low)
                {
                    if (wimage[i, j] == 0)
                    {
                        ncost = cost + wimage[i, j] + outside_diagonal_cost;
                    }
                    else if (wimage[i, j] > 0)
                    {
                        ncost = cost + wimage[i, j] + inside_diagonal_cost;
                    }
                    else if (wimage[i, j] < 0)
                    {
                        ncost = cost + wimage[i, j] + boundary_diagonal_cost;
                    }
                    if (costs[i - 1, j + direction] > ncost)
                    {
                        costs[i - 1, j + direction]   = ncost;
                        sources[i - 1, j + direction] = i;
                        if (j + direction != limit)
                        {
                            queue.Enqueue(new Point(i - 1, j + direction));
                        }
                    }
                }
                if (i < high)
                {
                    if (wimage[i, j] == 0)
                    {
                        ncost = cost + wimage[i, j] + outside_diagonal_cost;
                    }
                    else if (wimage[i, j] > 0)
                    {
                        ncost = cost + wimage[i, j] + inside_diagonal_cost;
                    }
                    else if (wimage[i, j] < 0)
                    {
                        ncost = cost + wimage[i, j] + boundary_diagonal_cost;
                    }
                    if (costs[i + 1, j + direction] > ncost)
                    {
                        costs[i + 1, j + direction]   = ncost;
                        sources[i + 1, j + direction] = i;
                        if (j + direction != limit)
                        {
                            queue.Enqueue(new Point(i + 1, j + direction));
                        }
                    }
                }
            }
        }
Exemple #15
0
        public override void Charseg(ref Intarray segmentation, Bytearray inraw)
        {
            setParams();
            //Logger.Default.Image("segmenting", inraw);

            int PADDING = 3;

            OcrRoutine.optional_check_background_is_lighter(inraw);
            Bytearray image = new Bytearray();

            image.Copy(inraw);
            OcrRoutine.binarize_simple(image);
            OcrRoutine.Invert(image);

            SetImage(image);
            FindAllCuts();
            FindBestCuts();

            Intarray seg = new Intarray();

            seg.MakeLike(image);
            seg.Fill(255);

            for (int r = 0; r < bestcuts.Length(); r++)
            {
                int            w   = seg.Dim(0);
                int            c   = bestcuts[r];
                Narray <Point> cut = cuts[c];
                for (int y = 0; y < image.Dim(1); y++)
                {
                    for (int i = -1; i <= 1; i++)
                    {
                        int x = cut[y].X;
                        if (x < 1 || x >= w - 1)
                        {
                            continue;
                        }
                        seg[x + i, y] = 0;
                    }
                }
            }
            ImgLabels.label_components(ref seg);
            // dshowr(seg,"YY"); dwait();
            segmentation.Copy(image);

            for (int i = 0; i < seg.Length1d(); i++)
            {
                if (segmentation.At1d(i) == 0)
                {
                    seg.Put1d(i, 0);
                }
            }

            ImgLabels.propagate_labels_to(ref segmentation, seg);

            if (PGeti("component_segmentation") > 0)
            {
                Intarray ccseg = new Intarray();
                ccseg.Copy(image);
                ImgLabels.label_components(ref ccseg);
                SegmRoutine.combine_segmentations(ref segmentation, ccseg);
                if (PGeti("fix_diacritics") > 0)
                {
                    SegmRoutine.fix_diacritics(segmentation);
                }
            }
#if false
            SegmRoutine.line_segmentation_merge_small_components(ref segmentation, small_merge_threshold);
            SegmRoutine.line_segmentation_sort_x(segmentation);
#endif

            SegmRoutine.make_line_segmentation_white(segmentation);
            // set_line_number(segmentation, 1);
            //Logger.Default.Image("resulting segmentation", segmentation);
        }
Exemple #16
0
        public override void Charseg(ref Intarray segmentation, Bytearray inraw)
        {
            setParams();
            //Logger.Default.Image("segmenting", inraw);

            int PADDING = 3;
            OcrRoutine.optional_check_background_is_lighter(inraw);
            Bytearray image = new Bytearray();
            image.Copy(inraw);
            OcrRoutine.binarize_simple(image);
            OcrRoutine.Invert(image);

            SetImage(image);
            FindAllCuts();
            FindBestCuts();

            Intarray seg = new Intarray();
            seg.MakeLike(image);
            seg.Fill(255);

            for (int r = 0; r < bestcuts.Length(); r++)
            {
                int w = seg.Dim(0);
                int c = bestcuts[r];
                Narray<Point> cut = cuts[c];
                for (int y = 0; y < image.Dim(1); y++)
                {
                    for (int i = -1; i <= 1; i++)
                    {
                        int x = cut[y].X;
                        if (x < 1 || x >= w - 1) continue;
                        seg[x + i, y] = 0;
                    }
                }
            }
            ImgLabels.label_components(ref seg);
            // dshowr(seg,"YY"); dwait();
            segmentation.Copy(image);

            for (int i = 0; i < seg.Length1d(); i++)
                if (segmentation.At1d(i) == 0) seg.Put1d(i, 0);

            ImgLabels.propagate_labels_to(ref segmentation, seg);

            if (PGeti("component_segmentation") > 0)
            {
                Intarray ccseg = new Intarray();
                ccseg.Copy(image);
                ImgLabels.label_components(ref ccseg);
                SegmRoutine.combine_segmentations(ref segmentation, ccseg);
                if (PGeti("fix_diacritics") > 0)
                {
                    SegmRoutine.fix_diacritics(segmentation);
                }
            }
            #if false
            SegmRoutine.line_segmentation_merge_small_components(ref segmentation, small_merge_threshold);
            SegmRoutine.line_segmentation_sort_x(segmentation);
            #endif

            SegmRoutine.make_line_segmentation_white(segmentation);
            // set_line_number(segmentation, 1);
            //Logger.Default.Image("resulting segmentation", segmentation);
        }
Exemple #17
0
        /// <summary>
        /// Train on a text line, given a segmentation.
        /// <remarks>This is analogous to addTrainingLine(bytearray,nustring) except that
        /// it takes the "ground truth" line segmentation.</remarks>
        /// </summary>
        public override bool AddTrainingLine(Intarray cseg, Bytearray image_grayscale, string tr)
        {
            Bytearray image = new Bytearray();
            image.Copy(image_grayscale);
            if (String.IsNullOrEmpty(tr))
            {
                Global.Debugf("error", "input transcript is empty");
                return false;
            }
            if (image.Dim(0) < PGeti("minheight"))
            {
                Global.Debugf("error", "input line too small ({0} x {1})", image.Dim(0), image.Dim(1));
                return false;
            }
            if (image.Dim(1) > PGeti("maxheight"))
            {
                Global.Debugf("error", "input line too high ({0} x {1})", image.Dim(0), image.Dim(1));
                return false;
            }
            if (image.Dim(1) * 1.0 / image.Dim(0) > PGetf("maxaspect"))
            {
                Global.Debugf("warn", "input line has bad aspect ratio ({0} x {1})", image.Dim(0), image.Dim(1));
                return false;
            }
            CHECK_ARG(image.Dim(0) == cseg.Dim(0) && image.Dim(1) == cseg.Dim(1),
                "image.Dim(0) == cseg.Dim(0) && image.Dim(1) == cseg.Dim(1)");

            bool use_reject = PGetb("use_reject") && !DisableJunk;

            // check and set the transcript
            transcript = tr;
            SetLine(image_grayscale);
            if (PGeti("invert") > 0)
                NarrayUtil.Sub(NarrayUtil.Max(image), image);
            for (int i = 0; i < transcript.Length; i++)
                CHECK_ARG((int)transcript[i] >= 32, "(int)transcript[i] >= 32");

            // compute correspondences between actual segmentation and
            // ground truth segmentation
            Narray<Intarray> segments = new Narray<Intarray>();
            GrouperRoutine.segmentation_correspondences(segments, segmentation, cseg);

            // now iterate through all the hypothesis segments and
            // train the classifier with them
            int total = 0;
            int junk = 0;
            for (int i = 0; i < grouper.Object.Length(); i++)
            {
                Intarray segs = new Intarray();
                grouper.Object.GetSegments(segs, i);

                // see whether this is a ground truth segment
                int match = -1;
                for (int j = 0; j < segments.Length(); j++)
                {
                    if (GrouperRoutine.Equals(segments[j], segs))
                    {
                        match = j;
                        break;
                    }
                }
                match -= 1;         // segments are numbered starting at 1
                int c = reject_class;
                if (match >= 0)
                {
                    if (match >= transcript.Length)
                    {
                        Global.Debugf("error", "mismatch between transcript and cseg: {0}", transcript);
                        continue;
                    }
                    else
                    {
                        c = (int)transcript[match];
                        Global.Debugf("debugmismatch", "index {0} position {1} char {2} [{3}]", i, match, (char)c, c);
                    }
                }

                if (c == reject_class)
                    junk++;

                // extract the character and add it to the classifier
                Rect b;
                Bytearray mask = new Bytearray();
                grouper.Object.GetMask(out b, ref mask, i, 0);
                Bytearray cv = new Bytearray();
                grouper.Object.ExtractWithMask(cv, mask, image, i, 0);
                Floatarray v = new Floatarray();
                v.Copy(cv);
                v /= 255.0;
                Global.Debugf("cdim", "character dimensions ({0},{1})", v.Dim(0), v.Dim(1));
                total++;
                if (use_reject)
                {
                    classifier.Object.XAdd(v, c);
                }
                else
                {
                    if (c != reject_class)
                        classifier.Object.XAdd(v, c);
                }
                if (c != reject_class)
                    IncClass(c);
                ntrained++;
            }
            Global.Debugf("detail", "AddTrainingLine trained {0} chars, {1} junk", total - junk, junk);
            return true;
        }
Exemple #18
0
 public void Image(string description, Intarray a, float zoom = 100f)
 {
     if (verbose)
     {
         writer.WriteLine(String.Format("image {0} w:{1}, h:{2}", description, a.Dim(0), a.Dim(1)));
     }
 }
Exemple #19
0
        public override void Charseg(ref Intarray result_segmentation, Bytearray orig_image)
        {
            Logger.Default.Image("segmenting", orig_image);

            int PADDING = 3;
            OcrRoutine.optional_check_background_is_lighter(orig_image);
            Bytearray image = new Bytearray();
            Narray<byte> bimage = image;
            image.Copy(orig_image);
            OcrRoutine.binarize_simple(image);
            OcrRoutine.Invert(image);
            ImgOps.pad_by(ref bimage, PADDING, PADDING);
            // pass image to segmenter
            segmenter.SetImage(image);
            // find all cuts in the image
            segmenter.FindAllCuts();
            // choose the best of all cuts
            segmenter.FindBestCuts();

            Intarray segmentation = new Intarray();
            segmentation.Resize(image.Dim(0), image.Dim(1));
            for (int i = 0; i < image.Dim(0); i++)
                for (int j = 0; j < image.Dim(1); j++)
                    segmentation[i, j] = image[i, j] > 0 ? 1 : 0;

            for (int r = 0; r < segmenter.bestcuts.Length(); r++)
            {
                int c = segmenter.bestcuts[r];
                Narray<Point> cut = segmenter.cuts[c];
                for (int y = 0; y < image.Dim(1); y++)
                {
                    for (int x = cut[y].X; x < image.Dim(0); x++)
                    {
                        if (segmentation[x, y] > 0) segmentation[x, y]++;
                    }
                }
            }
            ImgOps.extract_subimage(result_segmentation, segmentation, PADDING, PADDING,
                             segmentation.Dim(0) - PADDING, segmentation.Dim(1) - PADDING);

            if (small_merge_threshold > 0)
            {
                SegmRoutine.line_segmentation_merge_small_components(ref result_segmentation, small_merge_threshold);
                SegmRoutine.line_segmentation_sort_x(result_segmentation);
            }

            SegmRoutine.make_line_segmentation_white(result_segmentation);
            // set_line_number(segmentation, 1);
            Logger.Default.Image("resulting segmentation", result_segmentation);
        }
Exemple #20
0
 public void Image(string description, Intarray a, float zoom = 100f)
 {
     if (verbose)
         writer.WriteLine(String.Format("image {0} w:{1}, h:{2}", description, a.Dim(0), a.Dim(1)));
 }
Exemple #21
0
        /// <summary>
        /// Train on a text line, given a segmentation.
        /// <remarks>This is analogous to addTrainingLine(bytearray,nustring) except that
        /// it takes the "ground truth" line segmentation.</remarks>
        /// </summary>
        public override bool AddTrainingLine(Intarray cseg, Bytearray image_grayscale, string tr)
        {
            Bytearray image = new Bytearray();

            image.Copy(image_grayscale);
            if (String.IsNullOrEmpty(tr))
            {
                Global.Debugf("error", "input transcript is empty");
                return(false);
            }
            if (image.Dim(0) < PGeti("minheight"))
            {
                Global.Debugf("error", "input line too small ({0} x {1})", image.Dim(0), image.Dim(1));
                return(false);
            }
            if (image.Dim(1) > PGeti("maxheight"))
            {
                Global.Debugf("error", "input line too high ({0} x {1})", image.Dim(0), image.Dim(1));
                return(false);
            }
            if (image.Dim(1) * 1.0 / image.Dim(0) > PGetf("maxaspect"))
            {
                Global.Debugf("warn", "input line has bad aspect ratio ({0} x {1})", image.Dim(0), image.Dim(1));
                return(false);
            }
            CHECK_ARG(image.Dim(0) == cseg.Dim(0) && image.Dim(1) == cseg.Dim(1),
                      "image.Dim(0) == cseg.Dim(0) && image.Dim(1) == cseg.Dim(1)");

            bool use_reject = PGetb("use_reject") && !DisableJunk;

            // check and set the transcript
            transcript = tr;
            SetLine(image_grayscale);
            if (PGeti("invert") > 0)
            {
                NarrayUtil.Sub(NarrayUtil.Max(image), image);
            }
            for (int i = 0; i < transcript.Length; i++)
            {
                CHECK_ARG((int)transcript[i] >= 32, "(int)transcript[i] >= 32");
            }

            // compute correspondences between actual segmentation and
            // ground truth segmentation
            Narray <Intarray> segments = new Narray <Intarray>();

            GrouperRoutine.segmentation_correspondences(segments, segmentation, cseg);

            // now iterate through all the hypothesis segments and
            // train the classifier with them
            int total = 0;
            int junk  = 0;

            for (int i = 0; i < grouper.Object.Length(); i++)
            {
                Intarray segs = new Intarray();
                grouper.Object.GetSegments(segs, i);

                // see whether this is a ground truth segment
                int match = -1;
                for (int j = 0; j < segments.Length(); j++)
                {
                    if (GrouperRoutine.Equals(segments[j], segs))
                    {
                        match = j;
                        break;
                    }
                }
                match -= 1;         // segments are numbered starting at 1
                int c = reject_class;
                if (match >= 0)
                {
                    if (match >= transcript.Length)
                    {
                        Global.Debugf("error", "mismatch between transcript and cseg: {0}", transcript);
                        continue;
                    }
                    else
                    {
                        c = (int)transcript[match];
                        Global.Debugf("debugmismatch", "index {0} position {1} char {2} [{3}]", i, match, (char)c, c);
                    }
                }

                if (c == reject_class)
                {
                    junk++;
                }

                // extract the character and add it to the classifier
                Rect      b;
                Bytearray mask = new Bytearray();
                grouper.Object.GetMask(out b, ref mask, i, 0);
                Bytearray cv = new Bytearray();
                grouper.Object.ExtractWithMask(cv, mask, image, i, 0);
                Floatarray v = new Floatarray();
                v.Copy(cv);
                v /= 255.0;
                Global.Debugf("cdim", "character dimensions ({0},{1})", v.Dim(0), v.Dim(1));
                total++;
                if (use_reject)
                {
                    classifier.Object.XAdd(v, c);
                }
                else
                {
                    if (c != reject_class)
                    {
                        classifier.Object.XAdd(v, c);
                    }
                }
                if (c != reject_class)
                {
                    IncClass(c);
                }
                ntrained++;
            }
            Global.Debugf("detail", "AddTrainingLine trained {0} chars, {1} junk", total - junk, junk);
            return(true);
        }
Exemple #22
0
        /// <summary>
        /// Label the connected components of an image.
        /// </summary>
        public static int label_components(ref Intarray image, bool four_connected = false)
        {
            int w = image.Dim(0), h = image.Dim(1);
            // We slice the image into columns and call make_set()
            // for every continuous segment within each column.
            // Maximal number of segments per column is (h + 1) / 2.
            // We do it `w' times, so it's w * (h + 1) / 2.
            // We also need to add 1 because index 0 is not used, but counted.
            UnionFind uf = new UnionFind(w * (h + 1) / 2 + 1);

            uf.make_set(0);
            int top = 1;

            for (int i = 0; i < image.Length1d(); i++)
            {
                image.Put1d(i, (image.At1d(i) > 0 ? 1 : 0));
            }
            //for(int i=0;i<w;i++) {image(i,0) = 0; image(i,h-1) = 0;}
            //for(int j=0;j<h;j++) {image(0,j) = 0; image(w-1,j) = 0;}
            for (int i = 0; i < w; i++)
            {
                int current_label = 0;
                for (int j = 0; j < h; j++)
                {
                    int pixel = image[i, j];
                    int range = four_connected ? 0 : 1;
                    for (int delta = -range; delta <= range; delta++)
                    {
                        int adj_label = NarrayUtil.Bat(image, i - 1, j + delta, 0);
                        if (pixel == 0)
                        {
                            current_label = 0;
                            continue;
                        }
                        if (current_label == 0)
                        {
                            current_label = top;
                            uf.make_set(top);
                            top++;
                        }
                        if (adj_label > 0)
                        {
                            current_label = uf.find_set(current_label);
                            adj_label     = uf.find_set(adj_label);
                            if (current_label != adj_label)
                            {
                                uf.make_union(current_label, adj_label);
                                current_label = uf.find_set(current_label);
                                adj_label     = uf.find_set(adj_label);
                            }
                        }
                        image[i, j] = current_label;
                    }
                }
            }
            for (int i = 0; i < image.Length1d(); i++)
            {
                if (image.At1d(i) == 0)
                {
                    continue;
                }
                image.Put1d(i, uf.find_set(image.At1d(i)));
            }
            return(renumber_labels(image, 1));
        }
Exemple #23
0
 public static void remove_dontcares(ref Intarray image)
 {
     Floatarray dist = new Floatarray();
     Narray<Point> source = new Narray<Point>();
     dist.Resize(image.Dim(0), image.Dim(1));
     for (int i = 0; i < dist.Length1d(); i++)
         if (!dontcare(image.At1d(i))) dist.Put1d(i, (image.At1d(i) > 0 ? 1 : 0));
     BrushFire.brushfire_2(ref dist, ref source, 1000000);
     for (int i = 0; i < dist.Length1d(); i++)
     {
         Point p = source.At1d(i);
         if (dontcare(image.At1d(i))) image.Put1d(i, image[p.X, p.Y]);
     }
 }
Exemple #24
0
        public static void line_segmentation_merge_small_components(ref Intarray segmentation, int r = 10)
        {
            if (NarrayUtil.Max(segmentation) > 100000)
            {
                throw new Exception("line_segmentation_merge_small_components: to many segments");
            }
            make_line_segmentation_black(segmentation);
            Narray <Rect> bboxes = new Narray <Rect>();

            ImgLabels.bounding_boxes(ref bboxes, segmentation);
            bboxes[0] = Rect.CreateEmpty();
            bool changed;

            do
            {
                changed = false;
                for (int i = 1; i < bboxes.Length(); i++)
                {
                    Rect b = bboxes[i];
                    if (b.Empty())
                    {
                        continue;
                    }
                    if (b.Width() >= r || b.Height() >= r)
                    {
                        continue;
                    }
                    // merge small components only with touching components
                    int  closest = 0;
                    Rect b1      = b.Grow(1);
                    b1.Intersect(new Rect(0, 0, segmentation.Dim(0), segmentation.Dim(1)));
                    for (int x = b1.x0; x < b1.x1; x++)
                    {
                        for (int y = b1.y0; y < b1.y1; y++)
                        {
                            int value = segmentation[x, y];
                            if (value == 0)
                            {
                                continue;
                            }
                            if (value == i)
                            {
                                continue;
                            }
                            closest = value;
                            break;
                        }
                    }
                    if (closest == 0)
                    {
                        continue;
                    }
                    for (int x = b.x0; x < b.x1; x++)
                    {
                        for (int y = b.y0; y < b.y1; y++)
                        {
                            if (segmentation[x, y] == i)
                            {
                                segmentation[x, y] = closest;
                            }
                        }
                    }
                    bboxes[i] = Rect.CreateEmpty();
                    changed   = true;
                }
            } while (changed);
        }