示例#1
0
        private void DoTestRecognize(LenetClassifier classifier)
        {
            OutputVector ov = new OutputVector();
            Floatarray   v  = new Floatarray();
            Bytearray    ba = new Bytearray(1, 1);

            ImgIo.read_image_gray(ba, testPngFileName);
            NarrayUtil.Sub(255, ba);
            v.Copy(ba);
            v /= 255.0;
            classifier.XOutputs(ov, v);
            Console.WriteLine("Featured output class '{0}', score '{1}'", (char)ov.Key(ov.BestIndex), ov.Value(ov.BestIndex));
        }
示例#2
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");*/
        }
示例#3
0
        /// <summary>
        /// This is a weird, optional method that exposes character segmentation
        /// for those line recognizers that have it segmentation contains colored pixels,
        /// and a transition in the transducer of the form * --- 1/eps --> * --- 2/a --> *
        /// means that pixels with color 1 and 2 together form the letter "a"
        /// </summary>
        public override double RecognizeLine(Intarray segmentation_, IGenericFst result, Bytearray image_)
        {
            double rate = 0.0;

            CHECK_ARG(image_.Dim(1) < PGeti("maxheight"),
                      String.Format("input line too high ({0} x {1})", image_.Dim(0), image_.Dim(1)));
            CHECK_ARG(image_.Dim(1) * 1.0 / image_.Dim(0) < PGetf("maxaspect"),
                      String.Format("input line has bad aspect ratio ({0} x {1})", image_.Dim(0), image_.Dim(1)));
            bool use_reject = PGetb("use_reject") && !DisableJunk;
            //Console.WriteLine("IMG: imin:{0} imax:{1}", NarrayUtil.ArgMin(image_), NarrayUtil.ArgMax(image_));
            Bytearray image = new Bytearray();

            image.Copy(image_);

            SetLine(image_);

            if (PGeti("invert") > 0)
            {
                NarrayUtil.Sub(NarrayUtil.Max(image), image);
            }
            segmentation_.Copy(segmentation);
            Bytearray    available   = new Bytearray();
            Floatarray   cp          = new Floatarray();
            Floatarray   ccosts      = new Floatarray();
            Floatarray   props       = new Floatarray();
            OutputVector p           = new OutputVector();
            int          ncomponents = grouper.Object.Length();
            int          minclass    = PGeti("minclass");
            float        minprob     = PGetf("minprob");
            float        space_yes   = PGetf("space_yes");
            float        space_no    = PGetf("space_no");
            float        maxcost     = PGetf("maxcost");

            // compute priors if possible; fall back on
            // using no priors if no counts are available
            Floatarray priors     = new Floatarray();
            bool       use_priors = PGeti("use_priors") > 0;

            if (use_priors)
            {
                if (counts.Length() > 0)
                {
                    priors.Copy(counts);
                    priors /= NarrayUtil.Sum(priors);
                }
                else
                {
                    if (!counts_warned)
                    {
                        Global.Debugf("warn", "use_priors specified but priors unavailable (old model)");
                    }
                    use_priors    = false;
                    counts_warned = true;
                }
            }

            EstimateSpaceSize();

            for (int i = 0; i < ncomponents; i++)
            {
                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);
                //ImgIo.write_image_gray("extrmask_image.png", cv);
                Floatarray v = new Floatarray();
                v.Copy(cv);
                v /= 255.0f;
                float ccost = classifier.Object.XOutputs(p, v);
                if (use_reject && classifier.Object.HigherOutputIsBetter)
                {
                    ccost = 0;
                    float total = p.Sum();
                    if (total > 1e-11f)
                    {
                        //p /= total;
                    }
                    else
                    {
                        p.Values.Fill(0.0f);
                    }
                }
                int count = 0;

                Global.Debugf("dcost", "output {0}", p.Keys.Length());
                for (int index = 0; index < p.Keys.Length(); index++)
                {
                    int j = p.Keys[index];
                    if (j < minclass)
                    {
                        continue;
                    }
                    if (j == reject_class)
                    {
                        continue;
                    }
                    float value = p.Values[index];
                    if (value <= 0.0f)
                    {
                        continue;
                    }
                    if (value < minprob)
                    {
                        continue;
                    }
                    float pcost = classifier.Object.HigherOutputIsBetter ? (float)-Math.Log(value) : value;
                    Global.Debugf("dcost", "{0} {1} {2}", j, pcost + ccost, (j > 32 ? (char)j : '_'));
                    float total_cost = pcost + ccost;
                    if (total_cost < maxcost)
                    {
                        if (use_priors)
                        {
                            total_cost -= (float)-Math.Log(priors[j]);
                        }
                        grouper.Object.SetClass(i, j, total_cost);
                        count++;
                    }
                }
                Global.Debugf("dcost", "");

                if (count == 0)
                {
                    float xheight = 10.0f;
                    if (b.Height() < xheight / 2 && b.Width() < xheight / 2)
                    {
                        grouper.Object.SetClass(i, (int)'~', high_cost / 2);
                    }
                    else
                    {
                        grouper.Object.SetClass(i, (int)'#', (b.Width() / xheight) * high_cost);
                    }
                }
                if (grouper.Object.PixelSpace(i) > space_threshold)
                {
                    Global.Debugf("spaces", "space {0}", grouper.Object.PixelSpace(i));
                    grouper.Object.SetSpaceCost(i, space_yes, space_no);
                }
            }

            grouper.Object.GetLattice(result);
            return(rate);
        }
示例#4
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);
        }