Пример #1
0
        public override void SplitIndices(Intarray result1, Intarray result2, Intarray indices)
        {
            result1.MakeLike(indices);
            result2.MakeLike(indices);
            int k = l2.nStates();

            for (int i = 0; i < indices.Length(); i++)
            {
                result1.Put1d(i, indices.At1d(i) / k);
                result2.Put1d(i, indices.At1d(i) % k);
            }
        }
Пример #2
0
        public static void segmentation_correspondences(Narray<Intarray> outsegments, Intarray seg, Intarray cseg)
        {
            if (NarrayUtil.Max(seg) >= 10000)
                throw new Exception("CHECK_ARG: (max(seg)<10000)");
            if (NarrayUtil.Max(cseg) >= 10000)
                throw new Exception("CHECK_ARG: (max(cseg)<10000)");

            int nseg = NarrayUtil.Max(seg) + 1;
            int ncseg = NarrayUtil.Max(cseg) + 1;
            Intarray overlaps = new Intarray(nseg, ncseg);
            overlaps.Fill(0);
            if (seg.Length() != cseg.Length())
                throw new Exception("CHECK_ARG: (seg.Length()==cseg.Length())");
            for (int i = 0; i < seg.Length(); i++)
                overlaps[seg.At1d(i), cseg.At1d(i)]++;
            outsegments.Clear();
            outsegments.Resize(ncseg);
            for (int i = 0; i < nseg; i++)
            {
                int j = NarrayRowUtil.RowArgMax(overlaps, i);
                if (!(j >= 0 && j < ncseg))
                    throw new Exception("ASSERT: (j>=0 && j<ncseg)");
                if (outsegments[j] == null)
                    outsegments[j] = new Intarray();
                outsegments[j].Push(i);
            }
        }
Пример #3
0
 /// <summary>
 /// A valid line segmentation may contain 0 or 0xffffff as the
 /// background, and otherwise numbers components starting at 1.
 /// The segmentation consists of segmented background pixels
 /// (0x80xxxx) and segmented foreground pixels (0x00xxxx).  The
 /// segmented foreground pixels should constitute a usable
 /// binarization of the original image.
 /// </summary>
 public static void check_line_segmentation(Intarray cseg)
 {
     if (cseg.Length1d() == 0)
     {
         return;
     }
     if (cseg.Rank() != 2)
     {
         throw new Exception("check_line_segmentation: rank must be 2");
     }
     for (int i = 0; i < cseg.Length1d(); i++)
     {
         int value = cseg.At1d(i);
         if (value == 0)
         {
             continue;
         }
         if (value == 0xffffff)
         {
             continue;
         }
         if ((value & 0x800000) > 0)
         {
             if ((value & ~0x800000) > 100000)
             {
                 throw new Exception("check_line_segmentation: (value & ~0x800000) > 100000");
             }
         }
         else
         if (value > 100000)
         {
             throw new Exception("check_line_segmentation: value > 100000");
         }
     }
 }
Пример #4
0
        public static void check_approximately_sorted(Intarray labels)
        {
            for (int i = 0; i < labels.Length1d(); i++)
            {
                if (labels.At1d(i) > 100000)
                {
                    throw new Exception("labels out of range");
                }
            }
            Narray <Rect> rboxes = new Narray <Rect>();

            ImgLabels.bounding_boxes(ref rboxes, labels);
#if false
            // TODO/tmb disabling check until the overseg issue is fixed --tmb
            for (int i = 1; i < rboxes.Length(); i++)
            {
                if (rboxes[i].Right < rboxes[i - 1].Left)
                {
                    /*errors_log("bad segmentation", labels);
                     * errors_log.recolor("bad segmentation (recolored)", labels);
                     * throw_fmt("boxes aren't approximately sorted: "
                     *        "box %d is to the left from box %d", i, i-1);*/
                }
            }
#endif
        }
Пример #5
0
        public static void rseg_to_cseg(Intarray cseg, Intarray rseg, Intarray ids)
        {
            Intarray map = new Intarray(NarrayUtil.Max(rseg) + 1);

            map.Fill(0);
            int color = 0;

            for (int i = 0; i < ids.Length(); i++)
            {
                if (ids[i] == 0)
                {
                    continue;
                }
                color++;
                int start = ids[i] >> 16;
                int end   = ids[i] & 0xFFFF;
                if (start > end)
                {
                    throw new Exception("segmentation encoded in IDs looks seriously broken!");
                }
                if (start >= map.Length() || end >= map.Length())
                {
                    throw new Exception("segmentation encoded in IDs doesn't fit!");
                }
                for (int j = start; j <= end; j++)
                {
                    map[j] = color;
                }
            }
            cseg.MakeLike(rseg);
            for (int i = 0; i < cseg.Length1d(); i++)
            {
                cseg.Put1d(i, map[rseg.At1d(i)]);
            }
        }
Пример #6
0
        /// <summary>
        /// Merge segments from start to end.
        /// </summary>
        /// <param name="cseg">Output</param>
        /// <param name="rseg">Input</param>
        /// <param name="start">start merge position</param>
        /// <param name="end">end merge position</param>
        public static void rseg_to_cseg(Intarray cseg, Intarray rseg, int start, int end)
        {
            int maxSegNum = NarrayUtil.Max(rseg);

            if (start > end)
            {
                throw new Exception("segmentation encoded in IDs looks seriously broken!");
            }
            if (start > maxSegNum || end > maxSegNum)
            {
                throw new Exception("segmentation encoded in IDs doesn't fit!");
            }
            Intarray map = new Intarray(maxSegNum + 1);

            map.Fill(0);

            int color = 1;

            for (int i = 1; i <= maxSegNum; i++)
            {
                map[i] = color;
                if (i < start || i >= end)
                {
                    color++;
                }
            }
            cseg.MakeLike(rseg);
            for (int i = 0; i < cseg.Length1d(); i++)
            {
                cseg.Put1d(i, map[rseg.At1d(i)]);
            }
        }
Пример #7
0
        /// <summary>
        /// Copy one FST to another.
        /// </summary>
        /// <param name="dst">The destination. Will be cleared before copying.</param>
        /// <param name="src">The FST to copy.</param>
        public static void fst_copy(IGenericFst dst, IGenericFst src)
        {
            dst.Clear();
            int n = src.nStates();

            for (int i = 0; i < n; i++)
            {
                dst.NewState();
            }
            dst.SetStart(src.GetStart());
            for (int i = 0; i < n; i++)
            {
                dst.SetAccept(i, src.GetAcceptCost(i));
                Intarray   targets = new Intarray(), outputs = new Intarray(), inputs = new Intarray();
                Floatarray costs = new Floatarray();
                src.Arcs(inputs, targets, outputs, costs, i);
                int inlen = inputs.Length();
                if (inlen != targets.Length())
                {
                    throw new Exception("ASSERT: inputs.length() == targets.length()");
                }
                if (inlen != outputs.Length())
                {
                    throw new Exception("ASSERT: inputs.length() == outputs.length()");
                }
                if (inlen != costs.Length())
                {
                    throw new Exception("ASSERT: inputs.length() == costs.length()");
                }
                for (int j = 0; j < inputs.Length(); j++)
                {
                    dst.AddTransition(i, targets.At1d(j), outputs.At1d(j), costs.At1d(j), inputs.At1d(j));
                }
            }
        }
Пример #8
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);
        }
Пример #9
0
        public static void line_segmentation_sort_x(Intarray segmentation)
        {
            if (NarrayUtil.Max(segmentation) > 100000)
            {
                throw new Exception("line_segmentation_merge_small_components: to many segments");
            }
            Narray <Rect> bboxes = new Narray <Rect>();

            ImgLabels.bounding_boxes(ref bboxes, segmentation);
            Floatarray x0s = new Floatarray();

            unchecked
            {
                x0s.Push((float)-999999);
            }
            for (int i = 1; i < bboxes.Length(); i++)
            {
                if (bboxes[i].Empty())
                {
                    x0s.Push(999999);
                }
                else
                {
                    x0s.Push(bboxes[i].x0);
                }
            }
            // dprint(x0s,1000); printf("\n");
            Narray <int> permutation  = new Intarray();
            Narray <int> rpermutation = new Intarray();

            NarrayUtil.Quicksort(permutation, x0s);
            rpermutation.Resize(permutation.Length());
            for (int i = 0; i < permutation.Length(); i++)
            {
                rpermutation[permutation[i]] = i;
            }
            // dprint(rpermutation,1000); printf("\n");
            for (int i = 0; i < segmentation.Length1d(); i++)
            {
                if (segmentation.At1d(i) == 0)
                {
                    continue;
                }
                segmentation.Put1d(i, rpermutation[segmentation.At1d(i)]);
            }
        }
Пример #10
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);
        }
Пример #11
0
 public static void make_line_segmentation_black(Intarray a)
 {
     check_line_segmentation(a);
     ImgMisc.replace_values(a, 0xFFFFFF, 0);
     for (int i = 0; i < a.Length1d(); i++)
     {
         a.Put1d(i, a.At1d(i) & 0xFFF);
     }
 }
Пример #12
0
        public static void combine_segmentations(ref Intarray dst, Intarray src)
        {
            dst.SameDims(src);
            int n = NarrayUtil.Max(dst) + 1;

            for (int i = 0; i < dst.Length1d(); i++)
            {
                dst.Put1d(i, (dst.At1d(i) + src.At1d(i) * n));
            }
            ImgLabels.renumber_labels(dst, 1);
        }
Пример #13
0
 public static void segmentation_as_bitmap(Bytearray image, Intarray cseg)
 {
     image.MakeLike(cseg);
     for (int i = 0; i < image.Length1d(); i++)
     {
         int value = cseg.At1d(i);
         if (value == 0 || value == 0xffffff)
         {
             image.Put1d(i, 255);
         }
         //if (value == 0xffffff) image.Put1d(i, 255);
     }
 }
Пример #14
0
        public static void check_page_segmentation(Intarray pseg)
        {
            bool          allow_zero = true;
            Narray <bool> used       = new Narray <bool>(5000);

            used.Fill(false);
            int nused = 0;
            int mused = 0;

            for (int i = 0; i < pseg.Length1d(); i++)
            {
                uint pixel = (uint)pseg.At1d(i);
                if (!(allow_zero || pixel != 0))
                {
                    throw new Exception("CHECK_ARG: (allow_zero || pixel != 0)");
                }
                if (pixel == 0 || pixel == 0xffffff)
                {
                    continue;
                }
                int column    = (int)(0xff & (pixel >> 16));
                int paragraph = (int)(0xff & (pixel >> 8));
                int line      = (int)(0xff & pixel);
                if (!((column > 0 && column < 32) || column == 254 || column == 255))
                {
                    throw new Exception("CHECK_ARG: ((column > 0 && column < 32) || column == 254 || column == 255)");
                }
                if (!((paragraph >= 0 && paragraph < 64) || (paragraph >= 250 && paragraph <= 255)))
                {
                    throw new Exception("CHECK_ARG: ((paragraph >= 0 && paragraph < 64) || (paragraph >= 250 && paragraph <= 255))");
                }
                if (column < 32)
                {
                    if (!used[line])
                    {
                        nused++;
                    }
                    used[line] = true;
                    if (line > mused)
                    {
                        mused = line;
                    }
                }
            }
            // character segments need to be numbered sequentially (no gaps)
            // (gaps usually happen when someone passes a binary image instead of a segmentation)
            if (!(nused == mused || nused == mused + 1))
            {
                Global.Debugf("warn", "check_page_segmentation found non-sequentially numbered segments");
            }
        }
Пример #15
0
        public static void remove_small_components <T>(Narray <T> bimage, int mw, int mh)
        {
            Intarray image = new Intarray();

            image.Copy(bimage);
            ImgLabels.label_components(ref image);
            Narray <Rect> rects = new Narray <Rect>();

            ImgLabels.bounding_boxes(ref rects, image);
            Bytearray good = new Bytearray(rects.Length());

            for (int i = 0; i < good.Length(); i++)
            {
                good[i] = 1;
            }
            for (int i = 0; i < rects.Length(); i++)
            {
                if (rects[i].Width() < mw && rects[i].Height() < mh)
                {
                    // printf("*** %d %d %d\n",i,rects[i].width(),rects[i].height());
                    good[i] = 0;
                }
            }
            for (int i = 0; i < image.Length1d(); i++)
            {
                if (good[image.At1d(i)] == 0)
                {
                    image.Put1d(i, 0);
                }
            }
            for (int i = 0; i < image.Length1d(); i++)
            {
                if (image.At1d(i) == 0)
                {
                    bimage.Put1d(i, default(T));                     // default(T) - 0
                }
            }
        }
Пример #16
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]);
                }
            }
        }
Пример #17
0
        /// <summary>
        /// Renumber the non-zero pixels in an image to start with pixel value start.
        /// The numerical order of pixels is preserved.
        /// </summary>
        public static int renumber_labels(Intarray image, int start = 1)
        {
            //SortedList<int, int> translation = new SortedList<int, int>(256);
            Dictionary <int, int> translation = new Dictionary <int, int>(256);
            int n = start;

            for (int i = 0; i < image.Length1d(); i++)
            {
                int pixel = image.At1d(i);
                if (pixel == 0 || pixel == 0xffffff)
                {
                    continue;
                }
                if (!translation.ContainsKey(pixel))
                {
                    translation.Add(pixel, n);
                    n++;
                }
            }
            n = start;
            int[] keys = translation.Keys.ToArray();
            foreach (int key in keys)
            {
                translation[key] = n++;
            }
            for (int i = 0; i < image.Length1d(); i++)
            {
                int pixel = image.At1d(i);
                if (pixel == 0 || pixel == 0xffffff)
                {
                    continue;
                }
                image.Put1d(i, translation[pixel]);
            }
            return(n);
        }
Пример #18
0
        public static void propagate_labels_to(ref Intarray target, Intarray seed)
        {
            Floatarray     dist   = new Floatarray();
            Narray <Point> source = new Narray <Point>();

            dist.Copy(seed);
            BrushFire.brushfire_2(ref dist, ref source, 1000000);
            for (int i = 0; i < dist.Length1d(); i++)
            {
                Point p = source.At1d(i);
                if (target.At1d(i) > 0)
                {
                    target.Put1d(i, seed[p.X, p.Y]);
                }
            }
        }
Пример #19
0
        /// <summary>
        /// Propagate labels across the entire image from a set of non-zero seeds.
        /// </summary>
        public static void propagate_labels(ref Intarray image)
        {
            Floatarray     dist   = new Floatarray();
            Narray <Point> source = new Narray <Point>();

            dist.Copy(image);
            BrushFire.brushfire_2(ref dist, ref source, 1000000);
            for (int i = 0; i < dist.Length1d(); i++)
            {
                Point p = source.At1d(i);
                if (image.At1d(i) == 0)
                {
                    image.Put1d(i, image[p.X, p.Y]);
                }
            }
        }
Пример #20
0
        /// <summary>
        /// Remove segments from start to end.
        /// </summary>
        /// <param name="cseg">Output</param>
        /// <param name="rseg">Input</param>
        /// <param name="start">start remove position</param>
        /// <param name="end">end remove position</param>
        public static void rseg_to_cseg_remove(Intarray cseg, Intarray rseg,
                                               Bytearray outimg, Bytearray img, int start, int end)
        {
            int maxSegNum = NarrayUtil.Max(rseg);

            if (start > end)
            {
                throw new Exception("segmentation encoded in IDs looks seriously broken!");
            }
            if (start > maxSegNum || end > maxSegNum)
            {
                throw new Exception("segmentation encoded in IDs doesn't fit!");
            }
            if (rseg.Length1d() != img.Length1d())
            {
                throw new Exception("rseg and img must have same a dimension!");
            }
            Intarray map = new Intarray(maxSegNum + 1);

            map.Fill(0);

            int color = 1;

            for (int i = 1; i <= maxSegNum; i++)
            {
                map[i] = color;
                if (i < start || i > end)
                {
                    color++;
                }
                else
                {
                    map[i] = 0;
                }
            }
            cseg.MakeLike(rseg);
            outimg.Copy(img);
            for (int i = 0; i < cseg.Length1d(); i++)
            {
                int val = rseg.At1d(i);
                cseg.Put1d(i, map[val]);
                if (val > 0 && map[val] == 0)
                {
                    outimg.Put1d(i, 255);
                }
            }
        }
Пример #21
0
 public static void simple_recolor(Intarray image)
 {
     /*for (int i = 0; i < image.Length1d(); i++)
      * {
      *  if (image.At1d(i) == 0) continue;
      *  image.At1d(i) = enumerator[image.at1d(i)];
      * }*/
     for (int i = 0; i < image.Length1d(); i++)
     {
         int value = image.At1d(i);
         if (value == 0 || value == 0xffffff)
         {
             continue;
         }
         image.Put1d(i, interesting_colors(1 + value % 19));
     }
 }
Пример #22
0
 public static void check_approximately_sorted(Intarray labels)
 {
     for (int i = 0; i < labels.Length1d(); i++)
         if (labels.At1d(i) > 100000)
             throw new Exception("labels out of range");
     Narray<Rect> rboxes = new Narray<Rect>();
     ImgLabels.bounding_boxes(ref rboxes, labels);
     #if false
     // TODO/tmb disabling check until the overseg issue is fixed --tmb
     for(int i=1;i<rboxes.Length();i++) {
         if(rboxes[i].Right<rboxes[i-1].Left) {
             /*errors_log("bad segmentation", labels);
             errors_log.recolor("bad segmentation (recolored)", labels);
             throw_fmt("boxes aren't approximately sorted: "
                       "box %d is to the left from box %d", i, i-1);*/
         }
     }
     #endif
 }
Пример #23
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);
 }
Пример #24
0
        public static void segmentation_correspondences(Narray <Intarray> outsegments, Intarray seg, Intarray cseg)
        {
            if (NarrayUtil.Max(seg) >= 10000)
            {
                throw new Exception("CHECK_ARG: (max(seg)<10000)");
            }
            if (NarrayUtil.Max(cseg) >= 10000)
            {
                throw new Exception("CHECK_ARG: (max(cseg)<10000)");
            }

            int      nseg     = NarrayUtil.Max(seg) + 1;
            int      ncseg    = NarrayUtil.Max(cseg) + 1;
            Intarray overlaps = new Intarray(nseg, ncseg);

            overlaps.Fill(0);
            if (seg.Length() != cseg.Length())
            {
                throw new Exception("CHECK_ARG: (seg.Length()==cseg.Length())");
            }
            for (int i = 0; i < seg.Length(); i++)
            {
                overlaps[seg.At1d(i), cseg.At1d(i)]++;
            }
            outsegments.Clear();
            outsegments.Resize(ncseg);
            for (int i = 0; i < nseg; i++)
            {
                int j = NarrayRowUtil.RowArgMax(overlaps, i);
                if (!(j >= 0 && j < ncseg))
                {
                    throw new Exception("ASSERT: (j>=0 && j<ncseg)");
                }
                if (outsegments[j] == null)
                {
                    outsegments[j] = new Intarray();
                }
                outsegments[j].Push(i);
            }
        }
Пример #25
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);
 }
Пример #26
0
        /// <summary>
        /// Reverse the FST's arcs, adding a new start vertex (former accept).
        /// </summary>
        public static void fst_copy_reverse(IGenericFst dst, IGenericFst src, bool no_accept = false)
        {
            dst.Clear();
            int n = src.nStates();

            for (int i = 0; i <= n; i++)
            {
                dst.NewState();
            }
            if (!no_accept)
            {
                dst.SetAccept(src.GetStart());
            }
            dst.SetStart(n);
            for (int i = 0; i < n; i++)
            {
                dst.AddTransition(n, i, 0, src.GetAcceptCost(i), 0);
                Intarray   targets = new Intarray(), outputs = new Intarray(), inputs = new Intarray();
                Floatarray costs = new Floatarray();
                src.Arcs(inputs, targets, outputs, costs, i);
                if (inputs.Length() != targets.Length())
                {
                    throw new Exception("ASSERT: inputs.length() == targets.length()");
                }
                if (inputs.Length() != outputs.Length())
                {
                    throw new Exception("ASSERT: inputs.length() == outputs.length()");
                }
                if (inputs.Length() != costs.Length())
                {
                    throw new Exception("ASSERT: inputs.length() == costs.length()");
                }
                for (int j = 0; j < inputs.Length(); j++)
                {
                    dst.AddTransition(targets.At1d(j), i, outputs.At1d(j), costs.At1d(j), inputs.At1d(j));
                }
            }
        }
Пример #27
0
 /// <summary>
 /// Copy one FST to another.
 /// </summary>
 /// <param name="dst">The destination. Will be cleared before copying.</param>
 /// <param name="src">The FST to copy.</param>
 public static void fst_copy(IGenericFst dst, IGenericFst src)
 {
     dst.Clear();
     int n = src.nStates();
     for (int i = 0; i < n; i++)
         dst.NewState();
     dst.SetStart(src.GetStart());
     for (int i = 0; i < n; i++)
     {
         dst.SetAccept(i, src.GetAcceptCost(i));
         Intarray targets = new Intarray(), outputs = new Intarray(), inputs = new Intarray();
         Floatarray costs = new Floatarray();
         src.Arcs(inputs, targets, outputs, costs, i);
         int inlen = inputs.Length();
         if (inlen != targets.Length())
             throw new Exception("ASSERT: inputs.length() == targets.length()");
         if (inlen != outputs.Length())
             throw new Exception("ASSERT: inputs.length() == outputs.length()");
         if (inlen != costs.Length())
             throw new Exception("ASSERT: inputs.length() == costs.length()");
         for (int j = 0; j < inputs.Length(); j++)
             dst.AddTransition(i, targets.At1d(j), outputs.At1d(j), costs.At1d(j), inputs.At1d(j));
     }
 }
Пример #28
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);
        }
Пример #29
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);
        }
Пример #30
0
 public int Key(int i)
 {
     return(_keys.At1d(i));
 }
Пример #31
0
 /// <summary>
 /// Reverse the FST's arcs, adding a new start vertex (former accept).
 /// </summary>
 public static void fst_copy_reverse(IGenericFst dst, IGenericFst src, bool no_accept = false)
 {
     dst.Clear();
     int n = src.nStates();
     for (int i = 0; i <= n; i++)
         dst.NewState();
     if (!no_accept)
         dst.SetAccept(src.GetStart());
     dst.SetStart(n);
     for (int i = 0; i < n; i++)
     {
         dst.AddTransition(n, i, 0, src.GetAcceptCost(i), 0);
         Intarray targets = new Intarray(), outputs = new Intarray(), inputs = new Intarray();
         Floatarray costs = new Floatarray();
         src.Arcs(inputs, targets, outputs, costs, i);
         if (inputs.Length() != targets.Length())
             throw new Exception("ASSERT: inputs.length() == targets.length()");
         if (inputs.Length() != outputs.Length())
             throw new Exception("ASSERT: inputs.length() == outputs.length()");
         if (inputs.Length() != costs.Length())
             throw new Exception("ASSERT: inputs.length() == costs.length()");
         for (int j = 0; j < inputs.Length(); j++)
             dst.AddTransition(targets.At1d(j), i, outputs.At1d(j), costs.At1d(j), inputs.At1d(j));
     }
 }
Пример #32
0
 public override void SplitIndices(Intarray result1, Intarray result2, Intarray indices)
 {
     result1.MakeLike(indices);
     result2.MakeLike(indices);
     int k = l2.nStates();
     for (int i = 0; i < indices.Length(); i++)
     {
         result1.Put1d(i, indices.At1d(i) / k);
         result2.Put1d(i, indices.At1d(i) % k);
     }
 }
Пример #33
0
        public override void Arcs(Intarray ids, Intarray targets, Intarray outputs, Floatarray costs, int node)
        {
            int n1 = node / l2.nStates();
            int n2 = node % l2.nStates();
            Intarray ids1 = new Intarray();
            Intarray ids2 = new Intarray();
            Intarray t1 = new Intarray();
            Intarray t2 = new Intarray();
            Intarray o1 = new Intarray();
            Intarray o2 = new Intarray();
            Floatarray c1 = new Floatarray();
            Floatarray c2 = new Floatarray();
            l1.Arcs(ids1, t1, o1, c1, n1);
            l2.Arcs(ids2, t2, o2, c2, n2);

            // sort & permute
            Intarray p1 = new Intarray();
            Intarray p2 = new Intarray();

            NarrayUtil.Quicksort(p1, o1);
            NarrayUtil.Permute(ids1, p1);
            NarrayUtil.Permute(t1, p1);
            NarrayUtil.Permute(o1, p1);
            NarrayUtil.Permute(c1, p1);

            NarrayUtil.Quicksort(p2, ids2);
            NarrayUtil.Permute(ids2, p2);
            NarrayUtil.Permute(t2, p2);
            NarrayUtil.Permute(o2, p2);
            NarrayUtil.Permute(c2, p2);

            int k1, k2;
            // l1 epsilon moves
            for (k1 = 0; k1 < o1.Length() && o1.At1d(k1) == 0; k1++)
            {
                ids.Push(ids1.At1d(k1));
                targets.Push(Combine(t1.At1d(k1), n2));
                outputs.Push(0);
                costs.Push(c1.At1d(k1));
            }
            // l2 epsilon moves
            for (k2 = 0; k2 < o2.Length() && ids2.At1d(k2) == 0; k2++)
            {
                ids.Push(0);
                targets.Push(Combine(n1, t2.At1d(k2)));
                outputs.Push(o2.At1d(k2));
                costs.Push(c2.At1d(k2));
            }
            // non-epsilon moves
            while (k1 < o1.Length() && k2 < ids2.Length())
            {
                while (k1 < o1.Length() && o1.At1d(k1) < ids2.At1d(k2)) k1++;
                if (k1 >= o1.Length()) break;
                while (k2 < ids2.Length() && o1.At1d(k1) > ids2.At1d(k2)) k2++;
                while (k1 < o1.Length() && k2 < ids2.Length() && o1.At1d(k1) == ids2.At1d(k2))
                {
                    for (int j = k2; j < ids2.Length() && o1.At1d(k1) == ids2.At1d(j); j++)
                    {
                        ids.Push(ids1.At1d(k1));
                        targets.Push(Combine(t1.At1d(k1), t2.At1d(j)));
                        outputs.Push(o2.At1d(j));
                        costs.Push(c1.At1d(k1) + c2.At1d(j));
                    }
                    k1++;
                }
            }
        }
Пример #34
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);
 }
Пример #35
0
        public static void fix_diacritics(Intarray segmentation)
        {
            Narray <Rect> bboxes = new Narray <Rect>();

            ImgLabels.bounding_boxes(ref bboxes, segmentation);
            if (bboxes.Length() < 1)
            {
                return;
            }
            Intarray assignments = new Intarray(bboxes.Length());

            for (int i = 0; i < assignments.Length(); i++)
            {
                assignments[i] = i;
            }
            for (int j = 0; j < bboxes.Length(); j++)
            {
                float dist    = 1e38f;
                int   closest = -1;
                for (int i = 0; i < bboxes.Length(); i++)
                {
                    // j should overlap i in the x direction
                    if (bboxes.At1d(j).x1 < bboxes.At1d(i).x0)
                    {
                        continue;
                    }
                    if (bboxes.At1d(j).x0 > bboxes.At1d(i).x1)
                    {
                        continue;
                    }
                    // j should be above i
                    if (!(bboxes.At1d(j).y0 >= bboxes.At1d(i).y1))
                    {
                        continue;
                    }
#if false
                    // j should be smaller than i
                    if (!(bboxes.At1d(j).area() < bboxes.At1d(i).area()))
                    {
                        continue;
                    }
#endif
                    float d = Math.Abs((bboxes[j].x0 + bboxes[j].x1) / 2 - (bboxes[i].x0 + bboxes[i].x1) / 2);
                    if (d >= dist)
                    {
                        continue;
                    }
                    dist    = d;
                    closest = i;
                }
                if (closest < 0)
                {
                    continue;
                }
                assignments[j] = closest;
            }
            for (int i = 0; i < segmentation.Length(); i++)
            {
                segmentation.Put1d(i, assignments[segmentation.At1d(i)]);
            }
            ImgLabels.renumber_labels(segmentation, 1);
        }
Пример #36
0
 /// <summary>
 /// Renumber the non-zero pixels in an image to start with pixel value start.
 /// The numerical order of pixels is preserved.
 /// </summary>
 public static int renumber_labels(Intarray image, int start=1)
 {
     //SortedList<int, int> translation = new SortedList<int, int>(256);
     Dictionary<int, int> translation = new Dictionary<int, int>(256);
     int n = start;
     for(int i=0; i<image.Length1d(); i++) {
         int pixel = image.At1d(i);
         if(pixel==0 || pixel==0xffffff) continue;
         if (!translation.ContainsKey(pixel))
         {
             translation.Add(pixel, n);
             n++;
         }
     }
     n = start;
     int[] keys = translation.Keys.ToArray();
     foreach (int key in keys)
         translation[key] = n++;
     for(int i=0;i<image.Length1d();i++)
     {
         int pixel = image.At1d(i);
         if(pixel==0 || pixel==0xffffff) continue;
         image.Put1d(i, translation[pixel]);
     }
     return n;
 }
Пример #37
0
 public static void simple_recolor(Intarray image)
 {
     /*for (int i = 0; i < image.Length1d(); i++)
     {
         if (image.At1d(i) == 0) continue;
         image.At1d(i) = enumerator[image.at1d(i)];
     }*/
     for (int i = 0; i < image.Length1d(); i++)
     {
         int value = image.At1d(i);
         if (value == 0 || value == 0xffffff) continue;
         image.Put1d(i, interesting_colors(1 + value % 19));
     }
 }
Пример #38
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]);
     }
 }
Пример #39
0
 public static void propagate_labels_to(ref Intarray target, Intarray seed)
 {
     Floatarray dist = new Floatarray();
     Narray<Point> source = new Narray<Point>();
     dist.Copy(seed);
     BrushFire.brushfire_2(ref dist, ref source, 1000000);
     for (int i = 0; i < dist.Length1d(); i++)
     {
         Point p = source.At1d(i);
         if (target.At1d(i) > 0) target.Put1d(i, seed[p.X, p.Y]);
     }
 }
Пример #40
0
 /// <summary>
 /// Propagate labels across the entire image from a set of non-zero seeds.
 /// </summary>
 public static void propagate_labels(ref Intarray image)
 {
     Floatarray dist = new Floatarray();
     Narray<Point> source = new Narray<Point>();
     dist.Copy(image);
     BrushFire.brushfire_2(ref dist, ref source, 1000000);
     for (int i = 0; i < dist.Length1d(); i++)
     {
         Point p = source.At1d(i);
         if (image.At1d(i) == 0) image.Put1d(i, image[p.X, p.Y]);
     }
 }
Пример #41
0
        public override void Arcs(Intarray ids, Intarray targets, Intarray outputs, Floatarray costs, int node)
        {
            int        n1   = node / l2.nStates();
            int        n2   = node % l2.nStates();
            Intarray   ids1 = new Intarray();
            Intarray   ids2 = new Intarray();
            Intarray   t1   = new Intarray();
            Intarray   t2   = new Intarray();
            Intarray   o1   = new Intarray();
            Intarray   o2   = new Intarray();
            Floatarray c1   = new Floatarray();
            Floatarray c2   = new Floatarray();

            l1.Arcs(ids1, t1, o1, c1, n1);
            l2.Arcs(ids2, t2, o2, c2, n2);

            // sort & permute
            Intarray p1 = new Intarray();
            Intarray p2 = new Intarray();

            NarrayUtil.Quicksort(p1, o1);
            NarrayUtil.Permute(ids1, p1);
            NarrayUtil.Permute(t1, p1);
            NarrayUtil.Permute(o1, p1);
            NarrayUtil.Permute(c1, p1);

            NarrayUtil.Quicksort(p2, ids2);
            NarrayUtil.Permute(ids2, p2);
            NarrayUtil.Permute(t2, p2);
            NarrayUtil.Permute(o2, p2);
            NarrayUtil.Permute(c2, p2);

            int k1, k2;

            // l1 epsilon moves
            for (k1 = 0; k1 < o1.Length() && o1.At1d(k1) == 0; k1++)
            {
                ids.Push(ids1.At1d(k1));
                targets.Push(Combine(t1.At1d(k1), n2));
                outputs.Push(0);
                costs.Push(c1.At1d(k1));
            }
            // l2 epsilon moves
            for (k2 = 0; k2 < o2.Length() && ids2.At1d(k2) == 0; k2++)
            {
                ids.Push(0);
                targets.Push(Combine(n1, t2.At1d(k2)));
                outputs.Push(o2.At1d(k2));
                costs.Push(c2.At1d(k2));
            }
            // non-epsilon moves
            while (k1 < o1.Length() && k2 < ids2.Length())
            {
                while (k1 < o1.Length() && o1.At1d(k1) < ids2.At1d(k2))
                {
                    k1++;
                }
                if (k1 >= o1.Length())
                {
                    break;
                }
                while (k2 < ids2.Length() && o1.At1d(k1) > ids2.At1d(k2))
                {
                    k2++;
                }
                while (k1 < o1.Length() && k2 < ids2.Length() && o1.At1d(k1) == ids2.At1d(k2))
                {
                    for (int j = k2; j < ids2.Length() && o1.At1d(k1) == ids2.At1d(j); j++)
                    {
                        ids.Push(ids1.At1d(k1));
                        targets.Push(Combine(t1.At1d(k1), t2.At1d(j)));
                        outputs.Push(o2.At1d(j));
                        costs.Push(c1.At1d(k1) + c2.At1d(j));
                    }
                    k1++;
                }
            }
        }
Пример #42
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));
        }