Пример #1
0
        /// <summary>
        /// Train on a text line.
        /// <remarks>Usage is: call addTrainingLine with training data, then call finishTraining
        /// The state of the object is undefined between calling addTrainingLine and finishTraining, and it is
        /// an error to call recognizeLine before finishTraining completes.  This allows both batch
        /// and incemental training.
        /// NB: you might train on length 1 strings for single character training
        /// and might train on words if line alignment is not working
        /// (well, for some training data)</remarks>
        /// </summary>
        public void AddTrainingLine(Intarray cseg, string tr)
        {
            Bytearray gimage = new Bytearray();

            ClassifierUtil.segmentation_as_bitmap(gimage, cseg);
            AddTrainingLine(cseg, gimage, tr);
        }
Пример #2
0
        public static void write_image_gray(string path, Bytearray image)
        {
            Bitmap bitmap = ImgRoutine.NarrayToRgbBitmap(image);

            bitmap.Save(path);
            bitmap.Dispose();
        }
Пример #3
0
 public static void binary_close_circle(Bytearray image, int r)
 {
     if (r == 0)
         return;
     binary_dilate_circle(image, r);
     binary_erode_circle(image, r);
 }
Пример #4
0
 public override bool GetLine(Bytearray image, int page, int line, string variant = null)
 {
     string s = PathFile(page, line, variant, "png");
     if (!File.Exists(s)) return false;
     ImgIo.read_image_gray(image, s);
     return true;
 }
Пример #5
0
 public static Bitmap read_image_gray(Bytearray image, string path)
 {
     Bitmap bitmap = LoadBitmapFromFile(path);
     image.Resize(bitmap.Width, bitmap.Height);
     ImgRoutine.NarrayFromBitmap(image, bitmap);
     return bitmap;
 }
Пример #6
0
 public static void make_binary(Bytearray image)
 {
     for (int i = 0; i < image.Length1d(); i++)
     {
         image.Put1d(i, (byte)(image.At1d(i) > 0 ? 255 : 0));
     }
 }
Пример #7
0
        /// <summary>
        /// Extract the character by bounding rectangle (no masking).
        /// </summary>
        void extractSlicedWithBackground <T>(Narray <T> outa, Narray <T> source, T dflt, int index, int grow = 0)
        {
            if (!labels.SameDims(source))
            {
                throw new Exception("ASSERT: labels.SameDims(source)");
            }
            Bytearray mask = new Bytearray();
            Rect      r;

            GetMask(out r, ref mask, index, grow);
            int x = r.x0, y = r.y0, w = r.Width(), h = r.Height();

            outa.Resize(w, source.Dim(1));
            outa.Fill(dflt);
            for (int i = 0; i < w; i++)
            {
                for (int j = 0; j < h; j++)
                {
                    if (mask[i, j] > 0)
                    {
                        outa[i, j + y] = source[i + x, j + y];
                    }
                }
            }
        }
Пример #8
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);
            }
        }
Пример #9
0
        public override void Charseg(ref Intarray outimage, Bytearray inimage)
        {
            int       swidth  = PGeti("swidth");
            int       sheight = PGeti("sheight");
            Bytearray image   = new Bytearray();

            image.Copy(inimage);
            OcrRoutine.binarize_simple(image);
            OcrRoutine.Invert(image);
            outimage.Copy(image);
            if (swidth > 0 || sheight > 0)
            {
                Morph.binary_close_rect(image, swidth, sheight);
            }
            Intarray labels = new Intarray();

            labels.Copy(image);
            ImgLabels.label_components(ref labels);
            for (int i = 0; i < outimage.Length1d(); i++)
            {
                if (outimage.At1d(i) > 0)
                {
                    outimage.Put1d(i, SegmRoutine.cseg_pixel(labels.At1d(i)));
                }
            }
            SegmRoutine.make_line_segmentation_white(outimage);
            SegmRoutine.check_line_segmentation(outimage);
        }
Пример #10
0
        public void Binarize(Bytearray outarray, Floatarray inarray)
        {
            Bytearray image = new Bytearray();

            image.Copy(inarray);
            Binarize(outarray, image);
        }
Пример #11
0
 public override void Binarize(Bytearray outa, Bytearray ina_)
 {
     fraction = (float)PGetf("f");
     Floatarray ina = new Floatarray();
     ina.Copy(ina_);
     binarize_by_range(outa, ina, fraction);
 }
Пример #12
0
 public static void binary_close_rect(Bytearray image, int rw, int rh)
 {
     if (rw == 0 && rh == 0)
         return;
     binary_dilate_rect(image, rw, rh);
     binary_erode_rect(image, rw, rh);
 }
Пример #13
0
 public void Image(string description, Bytearray a, float zoom = 100f)
 {
     if (verbose)
     {
         writer.WriteLine(String.Format("image {0} w:{1}, h:{2}", description, a.Dim(0), a.Dim(1)));
     }
 }
Пример #14
0
        public void SetLine(Bytearray image)
        {
            CHECK_ARG(image.Dim(1) < PGeti("maxheight"), "image.Dim(1) < PGeti(\"maxheight\")");

            // run the segmenter

            /*Narray<Rect> bboxes = new Narray<Rect>();
             * Intarray iar = new Intarray();
             * iar.Copy(image);
             * ImgLabels.bounding_boxes(ref bboxes, iar);*/
            //Console.WriteLine("IMG SETLINE: imin:{0} imax:{1}", NarrayUtil.ArgMin(iar), NarrayUtil.ArgMax(iar));
            //Console.WriteLine("INDEX_BLACK:{0} {1} {2} {3}", bboxes[0].x0, bboxes[0].y0, bboxes[0].x1, bboxes[0].y1);
            //ImgIo.write_image_gray("image.png", image);
            OcrRoutine.binarize_simple(binarized, image);
            segmenter.Object.Charseg(ref segmentation, binarized);

            /*Intarray segm = new Intarray();
             * segm.Copy(segmentation);
             * ImgLabels.simple_recolor(segm);
             * ImgIo.write_image_packed("segm_image.png", segm);*/

            //NarrayUtil.Sub(255, binarized);

            SegmRoutine.make_line_segmentation_black(segmentation);
            SegmRoutine.remove_small_components(segmentation, 3, 3);       // i add this line
            ImgLabels.renumber_labels(segmentation, 1);

            // set up the grouper
            grouper.Object.SetSegmentation(segmentation);
        }
Пример #15
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);
        }
Пример #16
0
        public void TestArrays()
        {
            string imgfn = "test-c3.png";

            // load Bytearray
            Bytearray ba = new Bytearray(1, 1);

            ImgIo.read_image_gray(ba, imgfn);
            OcrRoutine.Invert(ba);
            //NarrayUtil.Sub((byte)255, image);
            byte[] bytes1 = ba.To1DArray();
            NarrayShow.ShowConsole(ba);
            StdInput linput1 = new StdInput(ba);

            Console.WriteLine();

            // load StdInput
            Bitmap   bitmap  = ImgIo.LoadBitmapFromFile(imgfn);
            StdInput linput2 = StdInput.FromBitmap(bitmap);
            //NarrayShow.ShowConsole(linput2);

            // test convert
            Floatarray fa      = linput2.ToFloatarray();
            StdInput   linput3 = new StdInput(fa);

            Console.WriteLine("Arrays is identical? {0}", Equals(linput1.GetDataBuffer(), linput2.GetDataBuffer()));
            Console.WriteLine("Arrays is identical? {0}", Equals(linput2.GetDataBuffer(), linput3.GetDataBuffer()));
        }
Пример #17
0
        public void TestArrays()
        {
            string imgfn = "test-c3.png";

            // load Bytearray
            Bytearray ba = new Bytearray(1, 1);
            ImgIo.read_image_gray(ba, imgfn);
            OcrRoutine.Invert(ba);
            //NarrayUtil.Sub((byte)255, image);
            byte[] bytes1 = ba.To1DArray();
            NarrayShow.ShowConsole(ba);
            StdInput linput1 = new StdInput(ba);
            Console.WriteLine();

            // load StdInput
            Bitmap bitmap = ImgIo.LoadBitmapFromFile(imgfn);
            StdInput linput2 = StdInput.FromBitmap(bitmap);
            //NarrayShow.ShowConsole(linput2);

            // test convert
            Floatarray fa = linput2.ToFloatarray();
            StdInput linput3 = new StdInput(fa);

            Console.WriteLine("Arrays is identical? {0}", Equals(linput1.GetDataBuffer(), linput2.GetDataBuffer()));
            Console.WriteLine("Arrays is identical? {0}", Equals(linput2.GetDataBuffer(), linput3.GetDataBuffer()));
        }
Пример #18
0
        private void ProcessSegmentationMethod(object sender, RoutedEventArgs e)
        {
            string       strSermenterName = (sender as Control).Tag.ToString();
            ISegmentLine segmenter        = ComponentCreator.MakeComponent <ISegmentLine>(strSermenterName);

            if (segmenter == null || currBookLine == null)
            {
                return;
            }

            // приведем к чернобелому
            Bytearray image = currBookLine.ImageBytearray;

            //IBinarize binarizer = new BinarizeByOtsu();
            //binarizer.Binarize(image, image);
            OcrRoutine.binarize_simple(image, image);
            // сегментация
            Intarray charseg = new Intarray();

            segmenter.Charseg(ref charseg, image);
            // фон равен 0
            SegmRoutine.make_line_segmentation_black(charseg);
            // удалим маленькие сегменты
            SegmRoutine.remove_small_components(charseg, 3, 3);
            ImgLabels.renumber_labels(charseg, 1);

            currBookLine.CharsegIntarray = charseg;
            CurrSegmentsCount            = NarrayUtil.Max(charseg);
            // Show segmented image
            ShowCharsegImage(charseg,
                             (currBookLine.HaveTranscript && CurrSegmentsCount == currBookLine.Transcript.Length) ?
                             currBookLine.Transcript : "");
            // to enable save button
            EnableCharsegCmdButtons();
        }
Пример #19
0
        public static void threshold_frac(Bytearray thresholded, Floatarray input, float frac)
        {
            float minofinput = NarrayUtil.Min(input);
            float theta      = frac * (NarrayUtil.Max(input) - minofinput) + minofinput;

            binarize_with_threshold(thresholded, input, theta);
        }
Пример #20
0
        public static int average_on_border(Bytearray a)
        {
            int sum   = 0;
            int right = a.Dim(0) - 1;
            int top   = a.Dim(1) - 1;

            for (int x = 0; x < a.Dim(0); x++)
            {
                sum += a[x, 0];
            }
            for (int x = 0; x < a.Dim(0); x++)
            {
                sum += a[x, top];
            }
            for (int y = 1; y < top; y++)
            {
                sum += a[0, y];
            }
            for (int y = 1; y < top; y++)
            {
                sum += a[right, y];
            }
            // If average border intensity is between 127-128, inverting the
            // image does not work correctly
            float average_border_intensity = sum / ((right + top) * 2.0f);

            if (!(average_border_intensity <= 127 || average_border_intensity >= 128))
            {
                Console.WriteLine("average border intensity is between 127-128, inverting the image does not work correctly");
            }
            return(sum / ((right + top) * 2));
        }
Пример #21
0
        public void TestSimple()
        {
            Global.SetEnv("debug", Global.GetEnv("debug") + "");
            // image file name to recognize
            string imgFileName           = "line.png";
            string imgCsegFileName       = "line.cseg.png";
            string imgTranscriptFileName = "line.txt";

            // line recognizer
            Linerec lrec = (Linerec)Linerec.LoadLinerec("default.model");

            //Linerec lrec = (Linerec)Linerec.LoadLinerec("2m2-reject.cmodel");
            //Linerec lrec = (Linerec)Linerec.LoadLinerec("multi3.cmodel");
            //Linerec lrec = (Linerec)Linerec.LoadLinerec("latin-ascii.model");
            lrec.Info();

            // language model
            OcroFST default_lmodel = OcroFST.MakeOcroFst();

            default_lmodel.Load("default.fst");
            OcroFST lmodel = default_lmodel;

            // read image
            Bytearray image = new Bytearray(1, 1);

            ImgIo.read_image_gray(image, imgFileName);

            // recognize!
            OcroFST  fst  = OcroFST.MakeOcroFst();
            Intarray rseg = new Intarray();

            lrec.RecognizeLine(rseg, fst, image);

            // show result 1
            string resStr;

            fst.BestPath(out resStr);
            Console.WriteLine("Fst BestPath:   {0}", resStr);

            // find result 2
            Intarray   v1   = new Intarray();
            Intarray   v2   = new Intarray();
            Intarray   inp  = new Intarray();
            Intarray   outp = new Intarray();
            Floatarray c    = new Floatarray();

            BeamSearch.beam_search(v1, v2, inp, outp, c, fst, lmodel, 100);

            FstUtil.remove_epsilons(out resStr, outp);
            Console.WriteLine("Fst BeamSearch: {0}", resStr);

            Intarray cseg = new Intarray();

            SegmRoutine.rseg_to_cseg(cseg, rseg, inp);
            SegmRoutine.make_line_segmentation_white(cseg);
            ImgLabels.simple_recolor(cseg); // for human readable
            ImgIo.write_image_packed(imgCsegFileName, cseg);
            File.WriteAllText(imgTranscriptFileName, resStr.Replace(" ", ""));
        }
Пример #22
0
        public Linerec(string classifier1 = "latin"/*none*/, string extractor1 = "scaledfe",
            string segmenter1 = "DpSegmenter", int use_reject = 1)
        {
            transcript = "";
            //line = new Bytearray();
            segmentation = new Intarray();
            binarized = new Bytearray();

            // component choices
            PDef("classifier", classifier1, "character classifier");
            PDef("extractor", extractor1, "feature extractor");
            PDef("segmenter", segmenter1, "line segmenter");
            PDef("grouper", "SimpleGrouper", "line grouper");
            // retraining
            PDef("cpreload", "none", "classifier to be loaded prior to training");
            // debugging
            PDef("verbose", 0, "verbose output from glinerec");
            // outputs
            PDef("use_priors", 0, "correct the classifier output by priors");
            PDef("use_reject", use_reject, "use a reject class (use posteriors only and train on junk chars)");
            PDef("maxcost", 20.0, "maximum cost of a character to be added to the output");
            PDef("minclass", 32, "minimum output class to be added (default=unicode space)");
            PDef("minprob", 1e-9, "minimum probability for a character to appear in the output at all");
            PDef("invert", 1, "invert the input line prior to char extraction");
            // segmentation
            PDef("maxrange", 5, "maximum number of components that are grouped together");
            // sanity limits on input
            PDef("minheight", 9, "minimum height of input line");
            PDef("maxheight", 300, "maximum height of input line");
            PDef("maxaspect", 2.0, "maximum height/width ratio of input line");
            // space estimation (FIXME factor this out eventually)
            PDef("space_fractile", 0.5, "fractile for space estimation");
            PDef("space_multiplier", 2.0, "multipler for space estimation");
            PDef("space_min", 0.2, "minimum space threshold (in xheight)");
            PDef("space_max", 1.1, "maximum space threshold (in xheight)");
            PDef("space_yes", 1.0, "cost of inserting a space");
            PDef("space_no", 5.0, "cost of not inserting a space");
            // back compability
            PDef("minsize_factor", 0.0, "");

            counts = new Intarray();
            segmenter = new ComponentContainerISegmentLine(ComponentCreator.MakeComponent<ISegmentLine>(PGet("segmenter")));
            grouper = new ComponentContainerIGrouper(ComponentCreator.MakeComponent<IGrouper>(PGet("grouper")));
            classifier = new ComponentContainerIModel(IModel.MakeModel(PGet("classifier")));
            TryAttachClassifierEvent(classifier.Object);

            Persist(classifier, "classifier");
            Persist(counts, "counts");
            Persist(segmenter, "segmenter");
            Persist(grouper, "grouper");

            if (!classifier.IsEmpty)
            {
                classifier.Object.Set("junk", PGeti("use_reject"));
                classifier.Object.SetExtractor(PGet("extractor"));
            }
            ntrained = 0;
            counts_warned = false;
        }
Пример #23
0
        public Linerec(string classifier1 = "latin" /*none*/, string extractor1 = "scaledfe",
                       string segmenter1  = "DpSegmenter", int use_reject       = 1)
        {
            transcript = "";
            //line = new Bytearray();
            segmentation = new Intarray();
            binarized    = new Bytearray();

            // component choices
            PDef("classifier", classifier1, "character classifier");
            PDef("extractor", extractor1, "feature extractor");
            PDef("segmenter", segmenter1, "line segmenter");
            PDef("grouper", "SimpleGrouper", "line grouper");
            // retraining
            PDef("cpreload", "none", "classifier to be loaded prior to training");
            // debugging
            PDef("verbose", 0, "verbose output from glinerec");
            // outputs
            PDef("use_priors", 0, "correct the classifier output by priors");
            PDef("use_reject", use_reject, "use a reject class (use posteriors only and train on junk chars)");
            PDef("maxcost", 20.0, "maximum cost of a character to be added to the output");
            PDef("minclass", 32, "minimum output class to be added (default=unicode space)");
            PDef("minprob", 1e-9, "minimum probability for a character to appear in the output at all");
            PDef("invert", 1, "invert the input line prior to char extraction");
            // segmentation
            PDef("maxrange", 5, "maximum number of components that are grouped together");
            // sanity limits on input
            PDef("minheight", 9, "minimum height of input line");
            PDef("maxheight", 300, "maximum height of input line");
            PDef("maxaspect", 2.0, "maximum height/width ratio of input line");
            // space estimation (FIXME factor this out eventually)
            PDef("space_fractile", 0.5, "fractile for space estimation");
            PDef("space_multiplier", 2.0, "multipler for space estimation");
            PDef("space_min", 0.2, "minimum space threshold (in xheight)");
            PDef("space_max", 1.1, "maximum space threshold (in xheight)");
            PDef("space_yes", 1.0, "cost of inserting a space");
            PDef("space_no", 5.0, "cost of not inserting a space");
            // back compability
            PDef("minsize_factor", 0.0, "");

            counts     = new Intarray();
            segmenter  = new ComponentContainerISegmentLine(ComponentCreator.MakeComponent <ISegmentLine>(PGet("segmenter")));
            grouper    = new ComponentContainerIGrouper(ComponentCreator.MakeComponent <IGrouper>(PGet("grouper")));
            classifier = new ComponentContainerIModel(IModel.MakeModel(PGet("classifier")));
            TryAttachClassifierEvent(classifier.Object);

            Persist(classifier, "classifier");
            Persist(counts, "counts");
            Persist(segmenter, "segmenter");
            Persist(grouper, "grouper");

            if (!classifier.IsEmpty)
            {
                classifier.Object.Set("junk", PGeti("use_reject"));
                classifier.Object.SetExtractor(PGet("extractor"));
            }
            ntrained      = 0;
            counts_warned = false;
        }
Пример #24
0
 public static void binary_and(Bytearray image, Bytearray image2, int dx, int dy)
 {
     int w = image.Dim(0);
     int h = image.Dim(1);
     for (int i = 0; i < w; i++)
         for (int j = 0; j < h; j++)
             image[i, j] = Math.Min(image[i, j], NarrayUtil.Ext(image2, i - dx, j - dy));
 }
Пример #25
0
 public static void binary_invert(Bytearray image)
 {
     check_binary(image);
     for (int i = 0; i < image.Length1d(); i++)
     {
         image.Put1d(i, (byte)(255 - image.At1d(i)));
     }
 }
Пример #26
0
 public virtual void Extract(Bytearray outa, Bytearray ina)
 {
     Floatarray fina = new Floatarray();
     Floatarray fouta = new Floatarray();
     fina.Copy(ina);
     Extract(fouta, fina);
     outa.Copy(fouta);
 }
Пример #27
0
        public static Bitmap read_image_gray(Bytearray image, string path)
        {
            Bitmap bitmap = LoadBitmapFromFile(path);

            image.Resize(bitmap.Width, bitmap.Height);
            ImgRoutine.NarrayFromBitmap(image, bitmap);
            return(bitmap);
        }
Пример #28
0
 public static int binarize_simple(Bytearray result, Bytearray image)
 {
     int threshold = (NarrayUtil.Max(image)/* + NarrayUtil.Min(image)*/) / 2;
     result.MakeLike(image);
     for (int i = 0; i < image.Length1d(); i++)
         result.Put1d(i, image.At1d(i) < threshold ? (byte)0 : (byte)255);
     return threshold;
 }
Пример #29
0
 public static void binarize_with_threshold(Bytearray result, Floatarray image, float threshold)
 {
     result.MakeLike(image);
     for (int i = 0; i < image.Length1d(); i++)
     {
         result.Put1d(i, image.At1d(i) < threshold ? (byte)0 : (byte)255);
     }
 }
Пример #30
0
        public override void Binarize(Bytearray outa, Bytearray ina_)
        {
            fraction = (float)PGetf("f");
            Floatarray ina = new Floatarray();

            ina.Copy(ina_);
            binarize_by_range(outa, ina, fraction);
        }
Пример #31
0
        public List<List<float>> SpaceCosts(List<Candidate> candidates, Bytearray image)
        {
            /*
                Given a list of character recognition candidates and their
                classifications, and an image of the corresponding text line,
                compute a list of pairs of costs for putting/not putting a space
                after each of the candidate characters.

                The basic idea behind this simple algorithm is to try larger
                and larger horizontal closing operations until most of the components
                start having a "wide" aspect ratio; that's when characters have merged
                into words.  The remaining whitespace should be spaces.

                This is just a simple stopgap measure; it will be replaced with
                trainable space modeling.
             */
            int w = image.Dim(0);
            int h = image.Dim(1);

            Bytearray closed = new Bytearray();
            int r;
            for (r = 0; r < maxrange; r++)
            {
                if (r > 0)
                {
                    closed.Copy(image);
                    Morph.binary_close_circle(closed, r);
                }
                else
                    closed.Copy(image);
                Intarray labeled = new Intarray();
                labeled.Copy(closed);
                ImgLabels.label_components(ref labeled);
                Narray<Rect> rects = new Narray<Rect>();
                ImgLabels.bounding_boxes(ref rects, labeled);
                Floatarray aspects = new Floatarray();
                for (int i = 0; i < rects.Length(); i++)
                {
                    Rect rect = rects[i];
                    float aspect = rect.Aspect();
                    aspects.Push(aspect);
                }
                float maspect = NarrayUtil.Median(aspects);
                if (maspect >= this.aspect_threshold)
                    break;
            }

            // close with a little bit of extra space
            closed.Copy(image);
            Morph.binary_close_circle(closed, r+1);

            // compute the remaining aps
            //Morph.binary_dilate_circle();

            // every character box that ends near a cap gets a space appended

            return null;
        }
Пример #32
0
 public static void binary_close_circle(Bytearray image, int r)
 {
     if (r == 0)
     {
         return;
     }
     binary_dilate_circle(image, r);
     binary_erode_circle(image, r);
 }
Пример #33
0
 public static void binary_close_rect(Bytearray image, int rw, int rh)
 {
     if (rw == 0 && rh == 0)
     {
         return;
     }
     binary_dilate_rect(image, rw, rh);
     binary_erode_rect(image, rw, rh);
 }
Пример #34
0
        public override void Charseg(ref Intarray outimage, Bytearray inarray)
        {
            Bytearray image = new Bytearray();

            image.Copy(inarray);
            OcrRoutine.binarize_simple(image);
            OcrRoutine.Invert(image);
            outimage.Copy(image);
            Intarray labels = new Intarray();

            labels.Copy(image);
            ImgLabels.label_components(ref labels);
            Narray <Rect> boxes = new Narray <Rect>();

            ImgLabels.bounding_boxes(ref boxes, labels);
            Intarray equiv = new Intarray(boxes.Length());

            for (int i = 0; i < boxes.Length(); i++)
            {
                equiv[i] = i;
            }
            for (int i = 1; i < boxes.Length(); i++)
            {
                Rect p = boxes[i];
                for (int j = 1; j < boxes.Length(); j++)
                {
                    if (i == j)
                    {
                        continue;
                    }
                    Rect q  = boxes[j];
                    int  x0 = Math.Max(p.x0, q.x0);
                    int  x1 = Math.Min(p.x1, q.x1);
                    int  iw = x1 - x0;
                    if (iw <= 0)
                    {
                        continue;         // no overlap
                    }
                    int   ow   = Math.Min(p.Width(), q.Width());
                    float frac = iw / (float)(ow);
                    if (frac < 0.5f)
                    {
                        continue;             // insufficient overlap
                    }
                    // printf("%d %d : %d %d : %g\n",i,j,iw,ow,frac);
                    equiv.Put1d(Math.Max(i, j), Math.Min(i, j));
                }
            }
            for (int i = 0; i < labels.Length(); i++)
            {
                labels.Put1d(i, equiv.At1d(labels.At1d(i)));
            }
            ImgLabels.renumber_labels(labels, 1);
            outimage.Move(labels);
            SegmRoutine.make_line_segmentation_white(outimage);
            SegmRoutine.check_line_segmentation(outimage);
        }
Пример #35
0
        public static void Invert(Bytearray a)
        {
            int n = a.Length1d();

            for (int i = 0; i < n; i++)
            {
                a.Put1d(i, (byte)(255 - a.At1d(i)));
            }
        }
Пример #36
0
        public virtual void Extract(Bytearray outa, Bytearray ina)
        {
            Floatarray fina  = new Floatarray();
            Floatarray fouta = new Floatarray();

            fina.Copy(ina);
            Extract(fouta, fina);
            outa.Copy(fouta);
        }
Пример #37
0
        public static void Thin(ref Bytearray uci)
        {
            int w = uci.Dim(0) - 1;
            int h = uci.Dim(1) - 1;

            for (int i = 0, n = uci.Length1d(); i < n; i++)
            {
                if (uci.At1d(i) > 0)
                    uci.Put1d(i, ON);
                else
                    uci.Put1d(i, OFF);
            }

            bool flag;
            do
            {
                flag = false;
                for (int j = 0; j < 8; j += 2)
                {
                    for (int x = 1; x < w; x++)
                        for (int y = 1; y < h; y++)
                        {
                            if (uci[x, y] != ON)
                                continue;
                            if (uci[x + nx[j], y + ny[j]] != OFF)
                                continue;
                            int b = 0;
                            for (int i = 7; i >= 0; i--)
                            {
                                b <<= 1;
                                b |= (uci[x + nx[i], y + ny[i]] != OFF ? 1 : 0);
                            }
                            if (ttable[b] > 0)
                                uci[x, y] = SKEL;
                            else
                            {
                                uci[x, y] = DEL;
                                flag = true;
                            }
                        }
                    if (!flag)
                        continue;
                    for (int x = 1; x < w; x++)
                        for (int y = 1; y < h; y++)
                            if (uci[x, y] == DEL)
                                uci[x, y] = OFF;
                }
            } while (flag);

            for (int i = 0, n = uci.Length1d(); i < n; i++)
            {
                if (uci.At1d(i) == SKEL)
                    uci.Put1d(i, 255);
                else
                    uci.Put1d(i, 0);
            }
        }
Пример #38
0
 public static void binary_autoinvert(Bytearray image)
 {
     check_binary(image);
     int count = 0;
     for (int i = 0; i < image.Length1d(); i++)
         if (image.At1d(i) > 0) count++;
     if (count > image.Length1d() / 2)
         binary_invert(image);
 }
Пример #39
0
        public override void PutLine(Bytearray image, int page, int line, string variant = null)
        {
            MaybeMakeDirectory(page);
            FileStream fs = Open(FileMode.Create, page, line, variant, "png");

            ImgIo.write_image_gray(fs, image, System.Drawing.Imaging.ImageFormat.Png);
            fs.Flush();
            fs.Close();
        }
Пример #40
0
        public void SetImage(Bytearray image_)
        {
            Bytearray image = new Bytearray();

            //image = image_;
            image.Copy(image_);
            dimage.Copy(image);
            if (PGeti("fill_holes") > 0)
            {
                Bytearray holes = new Bytearray();
                SegmRoutine.extract_holes(ref holes, image);
                for (int i = 0; i < image.Length(); i++)
                {
                    if (holes.At1d(i) > 0)
                    {
                        image.Put1d(i, 255);
                    }
                }
            }
            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, j] > 0)
                    {
                        wimage[i, j] = inside_weight;
                    }
                    else
                    {
                        wimage[i, j] = outside_weight;
                    }
                }
            }
            if (s1 == 0)
            {
                where = image.Dim(1) / 2;
            }
            else
            {
                where = (int)(sy / s1);
            }
            for (int i = 0; i < dimage.Dim(0); i++)
            {
                dimage[i, where] = 0x008000;
            }
        }
Пример #41
0
        public void PutLineBin(Bytearray image, int page, int line, string variant = null)
        {
            string v = "bin";

            if (!String.IsNullOrEmpty(variant))
            {
                v += "."; v += variant;
            }
            PutLine(image, page, line, v);
        }
Пример #42
0
 public static void optional_check_background_is_darker(Bytearray a)
 {
     if (bgcheck)
     {
         if (!background_seems_black(a))
         {
             throw new Exception("background must be black");
         }
     }
 }
Пример #43
0
 public static Bitmap read_image_binary(Bytearray image, string path)
 {
     Bitmap bitmap = LoadBitmapFromFile(path);
     image.Resize(bitmap.Width, bitmap.Height);
     ImgRoutine.NarrayFromBitmap(image, bitmap);
     double threshold = (NarrayUtil.Min(image) + NarrayUtil.Max(image)) / 2.0;
     for (int i = 0; i < image.Length1d(); i++)
         image.Put1d(i, (byte)((image.At1d(i) < threshold) ? 0 : 255));
     return bitmap;
 }
Пример #44
0
 public static void optional_check_background_is_lighter(Bytearray a)
 {
     if (bgcheck)
     {
         if (!background_seems_white(a))
         {
             throw new Exception("background must be white");
         }
     }
 }
Пример #45
0
 public static void binarize_by_range(Bytearray outa, Floatarray ina, float fraction)
 {
     float imin = NarrayUtil.Min(ina);
     float imax = NarrayUtil.Max(ina);
     float thresh = (int)(imin + (imax - imin) * fraction);
     outa.MakeLike(ina);
     for (int i = 0; i < ina.Length1d(); i++)
     {
         if (ina.At1d(i) > thresh) outa.Put1d(i, 255);
         else outa.Put1d(i, 0);
     }
 }
Пример #46
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);
        }
Пример #47
0
 public static void binary_erode_circle(Bytearray image, int r)
 {
     if (r == 0)
         return;
     Bytearray outa = new Bytearray();
     outa.Copy(image);
     for (int i = -r; i <= r; i++)
         for (int j = -r; j <= r; j++)
         {
             if (i * i + j * j <= r * r)
                 binary_and(outa, image, i, j);
         }
     image.Move(outa);
 }
Пример #48
0
 public static void binary_dilate_rect(Bytearray image, int rw, int rh)
 {
     if(rw==0 && rh==0)
         return;
     Bytearray outa = new Bytearray();
     outa.Copy(image);
     // note that we handle the even cases complementary
     // to erode_rect; this makes open_rect and close_rect
     // do the right thing
     for(int i=0; i<rw; i++)
         binary_or(outa, image, i-(rw-1)/2, 0);
     for(int j=0; j<rh; j++)
         binary_or(image, outa, 0, j-(rh-1)/2);
 }
Пример #49
0
        public override void Charseg(ref Intarray result_segmentation, Bytearray orig_image)
        {
            Bytearray image = new Bytearray();
            image.Copy(orig_image);
            OcrRoutine.optional_check_background_is_lighter(image);
            OcrRoutine.binarize_simple(image);
            OcrRoutine.Invert(image);

            Intarray ccseg = new Intarray();
            ccseg.Copy(image);
            ImgLabels.label_components(ref ccseg);

            base.Charseg(ref result_segmentation, orig_image);
            SegmRoutine.combine_segmentations(ref result_segmentation, ccseg);
        }
Пример #50
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));
        }
Пример #51
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);
        }
Пример #52
0
 public static int average_on_border(Bytearray a)
 {
     int sum = 0;
     int right = a.Dim(0) - 1;
     int top = a.Dim(1) - 1;
     for(int x = 0; x < a.Dim(0); x++)
         sum += a[x, 0];
     for(int x = 0; x < a.Dim(0); x++)
         sum += a[x, top];
     for(int y = 1; y < top; y++)
         sum += a[0, y];
     for(int y = 1; y < top; y++)
         sum += a[right, y];
     // If average border intensity is between 127-128, inverting the
     // image does not work correctly
     float average_border_intensity = sum / ((right + top) * 2.0f);
     if (!(average_border_intensity <= 127 || average_border_intensity >= 128))
         Console.WriteLine("average border intensity is between 127-128, inverting the image does not work correctly");
     return sum / ((right + top) * 2);
 }
Пример #53
0
 public override void Charseg(ref Intarray segmentation, Bytearray image)
 {
     Bytearray timage = new Bytearray();
     timage.Copy(image);
     //for (int i = 0; i < image.Length(); i++) image[i] = (byte)(image[i] > 0 ? 0 : 1);
     OcrRoutine.binarize_simple(timage);
     OcrRoutine.Invert(image);
     Skeleton.Thin(ref timage);
     //ImgIo.write_image_gray("_thinned.png", timage);
     ImgMisc.remove_singular_points(ref timage, 2);
     //ImgIo.write_image_gray("_segmented.png", timage);
     Intarray tsegmentation = new Intarray();
     tsegmentation.Copy(timage);
     ImgLabels.label_components(ref tsegmentation);
     SegmRoutine.remove_small_components(tsegmentation, 4, 4);
     //ImgIo.write_image_packed("_labeled.png", tsegmentation);
     segmentation.Copy(image);
     ImgLabels.propagate_labels_to(ref segmentation, tsegmentation);
     //ImgIo.write_image_packed("_propagated.png", segmentation);
 }
Пример #54
0
 public override void Charseg(ref Intarray outimage, Bytearray inimage)
 {
     int swidth = PGeti("swidth");
     int sheight = PGeti("sheight");
     Bytearray image = new Bytearray();
     image.Copy(inimage);
     OcrRoutine.binarize_simple(image);
     OcrRoutine.Invert(image);
     outimage.Copy(image);
     if (swidth > 0 || sheight > 0)
         Morph.binary_close_rect(image, swidth, sheight);
     Intarray labels = new Intarray();
     labels.Copy(image);
     ImgLabels.label_components(ref labels);
     for(int i=0; i<outimage.Length1d(); i++)
         if (outimage.At1d(i) > 0)
             outimage.Put1d(i, SegmRoutine.cseg_pixel(labels.At1d(i)));
     SegmRoutine.make_line_segmentation_white(outimage);
     SegmRoutine.check_line_segmentation(outimage);
 }
Пример #55
0
 public override void Charseg(ref Intarray outimage, Bytearray inarray)
 {
     Bytearray image = new Bytearray();
     image.Copy(inarray);
     OcrRoutine.binarize_simple(image);
     OcrRoutine.Invert(image);
     outimage.Copy(image);
     Intarray labels = new Intarray();
     labels.Copy(image);
     ImgLabels.label_components(ref labels);
     Narray<Rect> boxes = new Narray<Rect>();
     ImgLabels.bounding_boxes(ref boxes, labels);
     Intarray equiv = new Intarray(boxes.Length());
     for(int i=0; i<boxes.Length(); i++)
         equiv[i] = i;
     for(int i=1; i<boxes.Length(); i++) {
         Rect p = boxes[i];
         for(int j=1;j<boxes.Length();j++) {
             if(i==j) continue;
             Rect q = boxes[j];
             int x0 = Math.Max(p.x0, q.x0);
             int x1 = Math.Min(p.x1, q.x1);
             int iw = x1-x0;
             if(iw <= 0) continue; // no overlap
             int ow = Math.Min(p.Width(), q.Width());
             float frac = iw/(float)(ow);
             if(frac < 0.5f) continue; // insufficient overlap
             // printf("%d %d : %d %d : %g\n",i,j,iw,ow,frac);
             equiv.Put1d(Math.Max(i, j), Math.Min(i, j));
         }
     }
     for(int i=0; i<labels.Length(); i++)
         labels.Put1d(i, equiv.At1d(labels.At1d(i)));
     ImgLabels.renumber_labels(labels, 1);
     outimage.Move(labels);
     SegmRoutine.make_line_segmentation_white(outimage);
     SegmRoutine.check_line_segmentation(outimage);
 }
Пример #56
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;
 }
Пример #57
0
 /// <summary>
 /// Get the mask around a given rectangle.
 /// </summary>
 public abstract void GetMaskAt(ref Bytearray outmask, int index, Rect b);
Пример #58
0
 /// <summary>
 /// Get the bounding rectangle and mask for group "index".
 /// Optionally, expand the mask by the given margin.
 /// </summary>
 public abstract void GetMask(out Rect r, ref Bytearray outmask, int index, int margin);
Пример #59
0
 public abstract void ExtractWithMask(Floatarray outa, Bytearray mask,
                      Floatarray source, int index, int grow = 0);
Пример #60
0
 public abstract void ExtractSliced(Bytearray outa, Bytearray source,
                            byte dflt, int index, int grow=0);