Example #1
0
        // partition.c (621, 1)
        // boxaPruneSortedOnOverlap(boxas, maxoverlap) as Boxa
        // boxaPruneSortedOnOverlap(BOXA *, l_float32) as BOXA *
        ///  <summary>
        /// (1) This selectively removes smaller boxes when they are overlapped
        /// by any larger box by more than the input 'maxoverlap' fraction.<para/>
        ///
        /// (2) To avoid all pruning, use maxoverlap = 1.0.  To select only
        /// boxes that have no overlap with each other (maximal pruning),
        /// set maxoverlap = 0.0.<para/>
        ///
        /// (3) If there are no boxes in boxas, returns an empty boxa.
        ///  </summary>
        ///  <remarks>
        ///  </remarks>
        ///  <include file="..\CHM_Help\IncludeComments.xml" path="Comments/boxaPruneSortedOnOverlap/*"/>
        ///  <param name="boxas">[in] - sorted by size in decreasing order</param>
        ///  <param name="maxoverlap">[in] - maximum fractional overlap of a box by any of the larger boxes</param>
        ///   <returns>boxad pruned, or NULL on error</returns>
        public static Boxa boxaPruneSortedOnOverlap(
            Boxa boxas,
            Single maxoverlap)
        {
            if (boxas == null)
            {
                throw new ArgumentNullException("boxas cannot be Nothing");
            }

            IntPtr _Result = Natives.boxaPruneSortedOnOverlap(boxas.Pointer, maxoverlap);

            if (_Result == IntPtr.Zero)
            {
                return(null);
            }

            return(new Boxa(_Result));
        }
Example #2
0
        // pageseg.c (1927, 1)
        // pixFindLargeRectangles(pixs, polarity, nrect, pboxa, ppixdb) as int
        // pixFindLargeRectangles(PIX *, l_int32, l_int32, BOXA **, PIX **) as l_ok
        ///  <summary>
        /// (1) This does a greedy search to find the largest rectangles,
        /// either black or white and without overlaps, in %pix.<para/>
        ///
        /// (2) See pixFindLargestRectangle(), which is called multiple
        /// times, for details.  On each call, the largest rectangle
        /// found is painted, so that none of its pixels can be
        /// used later, before calling it again.<para/>
        ///
        /// (3) This function is surprisingly fast.  Although
        /// pixFindLargestRectangle() runs at about 50 MPix/sec, when it
        /// is run multiple times by pixFindLargeRectangles(), it processes
        /// at 150 - 250 MPix/sec, and the time is approximately linear
        /// in %nrect.  For example, for a 1 MPix image, searching for
        /// the largest 50 boxes takes about 0.2 seconds.
        ///  </summary>
        ///  <remarks>
        ///  </remarks>
        ///  <include file="..\CHM_Help\IncludeComments.xml" path="Comments/pixFindLargeRectangles/*"/>
        ///  <param name="pixs">[in] - 1 bpp</param>
        ///  <param name="polarity">[in] - 0 within background, 1 within foreground</param>
        ///  <param name="nrect">[in] - number of rectangles to be found</param>
        ///  <param name="pboxa">[out] - largest rectangles, sorted by decreasing area</param>
        ///  <param name="ppixdb">[in,out] - optional return output with rectangles drawn on it</param>
        ///   <returns>0 if OK, 1 on error</returns>
        public static int pixFindLargeRectangles(
            Pix pixs,
            int polarity,
            int nrect,
            out Boxa pboxa,
            ref Pix ppixdb)
        {
            if (pixs == null)
            {
                throw new ArgumentNullException("pixs cannot be Nothing");
            }

            if ((new List <int> {
                1
            }).Contains((int)pixs.d) == false)
            {
                throw new ArgumentException("1 bpp");
            }
            IntPtr pboxaPtr  = IntPtr.Zero;
            IntPtr ppixdbPtr = IntPtr.Zero;         if (ppixdb != null)
            {
                ppixdbPtr = ppixdb.Pointer;
            }
            int _Result = Natives.pixFindLargeRectangles(pixs.Pointer, polarity, nrect, out pboxaPtr, ref ppixdbPtr);

            if (pboxaPtr == IntPtr.Zero)
            {
                pboxa = null;
            }
            else
            {
                pboxa = new Boxa(pboxaPtr);
            };
            if (ppixdbPtr == IntPtr.Zero)
            {
                ppixdb = null;
            }
            else
            {
                ppixdb = new Pix(ppixdbPtr);
            };

            return(_Result);
        }
Example #3
0
        // morphapp.c (195, 1)
        // pixMorphSequenceByComponent(pixs, sequence, connectivity, minw, minh, pboxa) as Pix
        // pixMorphSequenceByComponent(PIX *, const char *, l_int32, l_int32, l_int32, BOXA **) as PIX *
        ///  <summary>
        /// (1) See pixMorphSequence() for composing operation sequences.<para/>
        ///
        /// (2) This operates separately on each c.c. in the input pix.<para/>
        ///
        /// (3) The dilation does NOT increase the c.c. size it is clipped
        /// to the size of the original c.c. This is necessary to
        /// keep the c.c. independent after the operation.<para/>
        ///
        /// (4) You can specify that the width and/or height must equal
        /// or exceed a minimum size for the operation to take place.<para/>
        ///
        /// (5) Use NULL for boxa to avoid returning the boxa.
        ///  </summary>
        ///  <remarks>
        ///  </remarks>
        ///  <include file="..\CHM_Help\IncludeComments.xml" path="Comments/pixMorphSequenceByComponent/*"/>
        ///  <param name="pixs">[in] - 1 bpp</param>
        ///  <param name="sequence">[in] - string specifying sequence</param>
        ///  <param name="connectivity">[in] - 4 or 8</param>
        ///  <param name="minw">[in] - minimum width to consider use 0 or 1 for any width</param>
        ///  <param name="minh">[in] - minimum height to consider use 0 or 1 for any height</param>
        ///  <param name="pboxa">[out][optional] - return boxa of c.c. in pixs</param>
        ///   <returns>pixd, or NULL on error</returns>
        public static Pix pixMorphSequenceByComponent(
            Pix pixs,
            String sequence,
            int connectivity,
            int minw,
            int minh,
            out Boxa pboxa)
        {
            if (pixs == null)
            {
                throw new ArgumentNullException("pixs cannot be Nothing");
            }

            if (sequence == null)
            {
                throw new ArgumentNullException("sequence cannot be Nothing");
            }

            if ((new List <int> {
                1
            }).Contains((int)pixs.d) == false)
            {
                throw new ArgumentException("1 bpp");
            }
            IntPtr pboxaPtr = IntPtr.Zero;
            IntPtr _Result  = Natives.pixMorphSequenceByComponent(pixs.Pointer, sequence, connectivity, minw, minh, out pboxaPtr);

            if (pboxaPtr == IntPtr.Zero)
            {
                pboxa = null;
            }
            else
            {
                pboxa = new Boxa(pboxaPtr);
            };

            if (_Result == IntPtr.Zero)
            {
                return(null);
            }

            return(new Pix(_Result));
        }
Example #4
0
        // affinecompose.c (358, 1)
        // boxaTranslate(boxas, transx, transy) as Boxa
        // boxaTranslate(BOXA *, l_float32, l_float32) as BOXA *
        ///  <summary>
        /// boxaTranslate()
        ///  </summary>
        ///  <remarks>
        ///  </remarks>
        ///  <include file="..\CHM_Help\IncludeComments.xml" path="Comments/boxaTranslate/*"/>
        ///  <param name="boxas">[in] - </param>
        ///  <param name="transx">[in] - x component of translation wrt. the origin</param>
        ///  <param name="transy">[in] - y component of translation wrt. the origin</param>
        ///   <returns>boxad  translated boxas, or NULL on error Notes: (1) See createMatrix2dTranslate() for details of transform.</returns>
        public static Boxa boxaTranslate(
            Boxa boxas,
            Single transx,
            Single transy)
        {
            if (boxas == null)
            {
                throw new ArgumentNullException("boxas cannot be Nothing");
            }

            IntPtr _Result = Natives.boxaTranslate(boxas.Pointer, transx, transy);

            if (_Result == IntPtr.Zero)
            {
                return(null);
            }

            return(new Boxa(_Result));
        }
Example #5
0
        // affinecompose.c (391, 1)
        // boxaScale(boxas, scalex, scaley) as Boxa
        // boxaScale(BOXA *, l_float32, l_float32) as BOXA *
        ///  <summary>
        /// boxaScale()
        ///  </summary>
        ///  <remarks>
        ///  </remarks>
        ///  <include file="..\CHM_Help\IncludeComments.xml" path="Comments/boxaScale/*"/>
        ///  <param name="boxas">[in] - </param>
        ///  <param name="scalex">[in] - horizontal scale factor</param>
        ///  <param name="scaley">[in] - vertical scale factor</param>
        ///   <returns>boxad  scaled boxas, or NULL on error Notes: (1) See createMatrix2dScale() for details of transform.</returns>
        public static Boxa boxaScale(
            Boxa boxas,
            Single scalex = 1,
            Single scaley = 1)
        {
            if (boxas == null)
            {
                throw new ArgumentNullException("boxas cannot be Nothing");
            }

            IntPtr _Result = Natives.boxaScale(boxas.Pointer, scalex, scaley);

            if (_Result == IntPtr.Zero)
            {
                return(null);
            }

            return(new Boxa(_Result));
        }
Example #6
0
        // boxfunc2.c (1602, 1)
        // boxaEncapsulateAligned(boxa, num, copyflag) as Boxaa
        // boxaEncapsulateAligned(BOXA *, l_int32, l_int32) as BOXAA *
        ///  <summary>
        /// (1) This puts %num boxes from the input %boxa into each of a
        /// set of boxa within an output baa.<para/>
        ///
        /// (2) This assumes that the boxes in %boxa are in sets of %num each.
        ///  </summary>
        ///  <remarks>
        ///  </remarks>
        ///  <include file="..\CHM_Help\IncludeComments.xml" path="Comments/boxaEncapsulateAligned/*"/>
        ///  <param name="boxa">[in] - </param>
        ///  <param name="num">[in] - number put into each boxa in the baa</param>
        ///  <param name="copyflag">[in] - L_COPY or L_CLONE</param>
        ///   <returns>baa, or NULL on error</returns>
        public static Boxaa boxaEncapsulateAligned(
            Boxa boxa,
            int num,
            int copyflag)
        {
            if (boxa == null)
            {
                throw new ArgumentNullException("boxa cannot be Nothing");
            }

            IntPtr _Result = Natives.boxaEncapsulateAligned(boxa.Pointer, num, copyflag);

            if (_Result == IntPtr.Zero)
            {
                return(null);
            }

            return(new Boxaa(_Result));
        }
Example #7
0
        // boxfunc3.c (1573, 1)
        // boxaSelectLargeULBox(boxas, areaslop, yslop) as Box
        // boxaSelectLargeULBox(BOXA *, l_float32, l_int32) as BOX *
        ///  <summary>
        /// (1) See usage notes in pixSelectLargeULComp().
        ///  </summary>
        ///  <remarks>
        ///  </remarks>
        ///  <include file="..\CHM_Help\IncludeComments.xml" path="Comments/boxaSelectLargeULBox/*"/>
        ///  <param name="boxas">[in] - 1 bpp</param>
        ///  <param name="areaslop">[in] - fraction near but less than 1.0</param>
        ///  <param name="yslop">[in] - number of pixels in y direction</param>
        ///   <returns>box, or NULL on error</returns>
        public static Box boxaSelectLargeULBox(
            Boxa boxas,
            Single areaslop,
            int yslop)
        {
            if (boxas == null)
            {
                throw new ArgumentNullException("boxas cannot be Nothing");
            }

            IntPtr _Result = Natives.boxaSelectLargeULBox(boxas.Pointer, areaslop, yslop);

            if (_Result == IntPtr.Zero)
            {
                return(null);
            }

            return(new Box(_Result));
        }
Example #8
0
        // recogident.c (246, 1)
        // recogSplitIntoCharacters(recog, pixs, minh, skipsplit, pboxa, ppixa, debug) as int
        // recogSplitIntoCharacters(L_RECOG *, PIX *, l_int32, l_int32, BOXA **, PIXA **, l_int32) as l_ok
        ///  <summary>
        /// (1) This can be given an image that has an arbitrary number
        /// of text characters.  It optionally splits connected
        /// components based on document image decoding in recogDecode().
        /// The returned pixa includes the boxes from which the
        /// (possibly split) components are extracted.<para/>
        ///
        /// (2) After noise filtering, the resulting components are put in
        /// row-major (2D) order, and the smaller of overlapping
        /// components are removed if they satisfy conditions of
        /// relative size and fractional overlap.<para/>
        ///
        /// (3) Note that the splitting function uses unscaled templates
        /// and does not bother returning the class results and scores.
        /// These are more accurately found later using the scaled templates.
        ///  </summary>
        ///  <remarks>
        ///  </remarks>
        ///  <include file="..\CHM_Help\IncludeComments.xml" path="Comments/recogSplitIntoCharacters/*"/>
        ///  <param name="recog">[in] - </param>
        ///  <param name="pixs">[in] - 1 bpp, contains only mostly deskewed text</param>
        ///  <param name="minh">[in] - remove shorter components use 0 for default</param>
        ///  <param name="skipsplit">[in] - 1 to skip the splitting step</param>
        ///  <param name="pboxa">[out] - character bounding boxes</param>
        ///  <param name="ppixa">[out] - character images</param>
        ///  <param name="debug">[in] - 1 for results written to pixadb_split</param>
        ///   <returns>0 if OK, 1 on error or if no components are returned</returns>
        public static int recogSplitIntoCharacters(
            L_Recog recog,
            Pix pixs,
            int minh,
            int skipsplit,
            out Boxa pboxa,
            out Pixa ppixa,
            Enumerations.DebugOnOff debug = DebugOnOff.DebugOn)
        {
            if (recog == null)
            {
                throw new ArgumentNullException("recog cannot be Nothing");
            }

            if (pixs == null)
            {
                throw new ArgumentNullException("pixs cannot be Nothing");
            }

            IntPtr pboxaPtr = IntPtr.Zero;
            IntPtr ppixaPtr = IntPtr.Zero;
            int    _Result  = Natives.recogSplitIntoCharacters(recog.Pointer, pixs.Pointer, minh, skipsplit, out pboxaPtr, out ppixaPtr, (int)debug);

            if (pboxaPtr == IntPtr.Zero)
            {
                pboxa = null;
            }
            else
            {
                pboxa = new Boxa(pboxaPtr);
            };
            if (ppixaPtr == IntPtr.Zero)
            {
                ppixa = null;
            }
            else
            {
                ppixa = new Pixa(ppixaPtr);
            };

            return(_Result);
        }
Example #9
0
        // affinecompose.c (424, 1)
        // boxaRotate(boxas, xc, yc, angle) as Boxa
        // boxaRotate(BOXA *, l_float32, l_float32, l_float32) as BOXA *
        ///  <summary>
        /// boxaRotate()
        ///  </summary>
        ///  <remarks>
        ///  </remarks>
        ///  <include file="..\CHM_Help\IncludeComments.xml" path="Comments/boxaRotate/*"/>
        ///  <param name="boxas">[in] - </param>
        ///  <param name="xc">[in] - location of center of rotation</param>
        ///  <param name="yc">[in] - location of center of rotation</param>
        ///  <param name="angle">[in] - rotation in radians clockwise is positive</param>
        ///   <returns>boxad  scaled boxas, or NULL on error Notes: (1) See createMatrix2dRotate() for details of transform.</returns>
        public static Boxa boxaRotate(
            Boxa boxas,
            Single xc,
            Single yc,
            Single angle)
        {
            if (boxas == null)
            {
                throw new ArgumentNullException("boxas cannot be Nothing");
            }

            IntPtr _Result = Natives.boxaRotate(boxas.Pointer, xc, yc, angle);

            if (_Result == IntPtr.Zero)
            {
                return(null);
            }

            return(new Boxa(_Result));
        }
Example #10
0
        // boxfunc2.c (454, 1)
        // boxaRotateOrth(boxas, w, h, rotation) as Boxa
        // boxaRotateOrth(BOXA *, l_int32, l_int32, l_int32) as BOXA *
        ///  <summary>
        /// (1) See boxRotateOrth() for details.
        ///  </summary>
        ///  <remarks>
        ///  </remarks>
        ///  <include file="..\CHM_Help\IncludeComments.xml" path="Comments/boxaRotateOrth/*"/>
        ///  <param name="boxas">[in] - </param>
        ///  <param name="w">[in] - of image in which the boxa is embedded</param>
        ///  <param name="h">[in] - of image in which the boxa is embedded</param>
        ///  <param name="rotation">[in] - 0 = noop, 1 = 90 deg, 2 = 180 deg, 3 = 270 deg all rotations are clockwise</param>
        ///   <returns>boxad, or NULL on error</returns>
        public static Boxa boxaRotateOrth(
            Boxa boxas,
            int w,
            int h,
            int rotation)
        {
            if (boxas == null)
            {
                throw new ArgumentNullException("boxas cannot be Nothing");
            }

            IntPtr _Result = Natives.boxaRotateOrth(boxas.Pointer, w, h, rotation);

            if (_Result == IntPtr.Zero)
            {
                return(null);
            }

            return(new Boxa(_Result));
        }
Example #11
0
        // jbclass.c (1312, 1)
        // jbGetComponents(pixs, components, maxwidth, maxheight, pboxad, ppixad) as int
        // jbGetComponents(PIX *, l_int32, l_int32, l_int32, BOXA **, PIXA **) as l_ok
        ///  <summary>
        /// jbGetComponents()
        ///  </summary>
        ///  <remarks>
        ///  </remarks>
        ///  <include file="..\CHM_Help\IncludeComments.xml" path="Comments/jbGetComponents/*"/>
        ///  <param name="pixs">[in] - 1 bpp</param>
        ///  <param name="components">[in] - JB_CONN_COMPS, JB_CHARACTERS, JB_WORDS</param>
        ///  <param name="maxwidth">[in] - of saved components larger are discarded</param>
        ///  <param name="maxheight">[in] - of saved components larger are discarded</param>
        ///   <returns>0 if OK, 1 on error</returns>
        public static int jbGetComponents(
            Pix pixs,
            int components,
            int maxwidth,
            int maxheight,
            Boxa pboxad,
            Pixa ppixad)
        {
            if (pixs == null)
            {
                throw new ArgumentNullException("pixs cannot be Nothing");
            }

            if (pboxad == null)
            {
                throw new ArgumentNullException("pboxad cannot be Nothing");
            }

            if (ppixad == null)
            {
                throw new ArgumentNullException("ppixad cannot be Nothing");
            }

            if ((new List <int> {
                1
            }).Contains((int)pixs.d) == false)
            {
                throw new ArgumentException("1 bpp");
            }
            IntPtr pboxadPtr = IntPtr.Zero;         if (pboxad != null)
            {
                pboxadPtr = pboxad.Pointer;
            }
            IntPtr ppixadPtr = IntPtr.Zero;         if (ppixad != null)
            {
                ppixadPtr = ppixad.Pointer;
            }
            int _Result = Natives.jbGetComponents(pixs.Pointer, components, maxwidth, maxheight, pboxadPtr, ppixadPtr);

            return(_Result);
        }
Example #12
0
        // finditalic.c (110, 1)
        // pixItalicWords(pixs, boxaw, pixw, pboxa, debugflag) as int
        // pixItalicWords(PIX *, BOXA *, PIX *, BOXA **, l_int32) as l_ok
        ///  <summary>
        /// (1) You can input the bounding boxes for the words in one of
        /// two forms: as bounding boxes (%boxaw) or as a word mask with
        /// the word bounding boxes filled (%pixw).  For example,
        /// to compute %pixw, you can use pixWordMaskByDilation().<para/>
        ///
        /// (2) Alternatively, you can set both of these inputs to NULL,
        /// in which case the word mask is generated here.  This is
        /// done by dilating and closing the input image to connect
        /// letters within a word, while leaving the words separated.
        /// The parameters are chosen under the assumption that the
        /// input is 10 to 12 pt text, scanned at about 300 ppi.<para/>
        ///
        /// (3) sel_ital1 and sel_ital2 detect the right edges that are
        /// nearly vertical, at approximately the angle of italic
        /// strokes.  We use the right edge to avoid getting seeds
        /// from lower-case 'y'.  The typical italic slant has a smaller
        /// angle with the vertical than the 'W', so in most cases we
        /// will not trigger on the slanted lines in the 'W'.<para/>
        ///
        /// (4) Note that sel_ital2 is shorter than sel_ital1.  It is
        /// more appropriate for a typical font scanned at 200 ppi.
        ///  </summary>
        ///  <remarks>
        ///  </remarks>
        ///  <include file="..\CHM_Help\IncludeComments.xml" path="Comments/pixItalicWords/*"/>
        ///  <param name="pixs">[in] - 1 bpp</param>
        ///  <param name="boxaw">[in][optional] - word bounding boxes can be NULL</param>
        ///  <param name="pixw">[in][optional] - word box mask can be NULL</param>
        ///  <param name="pboxa">[out] - boxa of italic words</param>
        ///  <param name="debugflag">[in] - 1 for debug output 0 otherwise</param>
        ///   <returns>0 if OK, 1 on error</returns>
        public static int pixItalicWords(
            Pix pixs,
            Boxa boxaw,
            Pix pixw,
            out Boxa pboxa,
            int debugflag)
        {
            if (pixs == null)
            {
                throw new ArgumentNullException("pixs cannot be Nothing");
            }

            if ((new List <int> {
                1
            }).Contains((int)pixs.d) == false)
            {
                throw new ArgumentException("1 bpp");
            }
            IntPtr boxawPtr = IntPtr.Zero;  if (boxaw != null)
            {
                boxawPtr = boxaw.Pointer;
            }
            IntPtr pixwPtr = IntPtr.Zero;   if (pixw != null)
            {
                pixwPtr = pixw.Pointer;
            }
            IntPtr pboxaPtr = IntPtr.Zero;
            int    _Result  = Natives.pixItalicWords(pixs.Pointer, boxawPtr, pixwPtr, out pboxaPtr, debugflag);

            if (pboxaPtr == IntPtr.Zero)
            {
                pboxa = null;
            }
            else
            {
                pboxa = new Boxa(pboxaPtr);
            };

            return(_Result);
        }
Example #13
0
        // dewarp3.c (537, 1)
        // dewarpaApplyDisparityBoxa(dewa, pageno, pixs, boxas, mapdir, x, y, pboxad, debugfile) as int
        // dewarpaApplyDisparityBoxa(L_DEWARPA *, l_int32, PIX *, BOXA *, l_int32, l_int32, l_int32, BOXA **, const char *) as l_ok
        ///  <summary>
        /// (1) This applies the disparity arrays in one of two mapping directions
        /// to the specified boxa.  It can be used in the backward direction
        /// to locate a box in the original coordinates that would have
        /// been dewarped to to the specified image.<para/>
        ///
        /// (2) If there is no model for %pageno, this will use the model for
        /// 'refpage' and put the result in the dew for %pageno.<para/>
        ///
        /// (3) This works with both stripped and full resolution page models.
        /// If the full res disparity array(s) are missing, they are remade.<para/>
        ///
        /// (4) If an error occurs, a copy of the input boxa is returned.
        ///  </summary>
        ///  <remarks>
        ///  </remarks>
        ///  <include file="..\CHM_Help\IncludeComments.xml" path="Comments/dewarpaApplyDisparityBoxa/*"/>
        ///  <param name="dewa">[in] - </param>
        ///  <param name="pageno">[in] - of page model to be used may be a ref model</param>
        ///  <param name="pixs">[in] - initial pix reference for alignment and debugging</param>
        ///  <param name="boxas">[in] - boxa to be mapped</param>
        ///  <param name="mapdir">[in] - 1 if mapping forward from original to dewarped 0 if backward</param>
        ///  <param name="x">[in] - origin for generation of disparity arrays with respect to the source region</param>
        ///  <param name="y">[in] - origin for generation of disparity arrays with respect to the source region</param>
        ///  <param name="pboxad">[out] - disparity corrected boxa</param>
        ///  <param name="debugfile">[in]use NULL to skip - writing this</param>
        ///   <returns>0 if OK, 1 on error no models or ref models available</returns>
        public static int dewarpaApplyDisparityBoxa(
            L_Dewarpa dewa,
            int pageno,
            Pix pixs,
            Boxa boxas,
            int mapdir,
            int x,
            int y,
            out Boxa pboxad,
            String debugfile = "")
        {
            if (dewa == null)
            {
                throw new ArgumentNullException("dewa cannot be Nothing");
            }

            if (pixs == null)
            {
                throw new ArgumentNullException("pixs cannot be Nothing");
            }

            if (boxas == null)
            {
                throw new ArgumentNullException("boxas cannot be Nothing");
            }

            IntPtr pboxadPtr = IntPtr.Zero;
            int    _Result   = Natives.dewarpaApplyDisparityBoxa(dewa.Pointer, pageno, pixs.Pointer, boxas.Pointer, mapdir, x, y, out pboxadPtr, debugfile);

            if (pboxadPtr == IntPtr.Zero)
            {
                pboxad = null;
            }
            else
            {
                pboxad = new Boxa(pboxadPtr);
            };

            return(_Result);
        }
Example #14
0
        // paintcmap.c (219, 1)
        // pixColorGrayRegionsCmap(pixs, boxa, type, rval, gval, bval) as int
        // pixColorGrayRegionsCmap(PIX *, BOXA *, l_int32, l_int32, l_int32, l_int32) as l_ok
        ///  <summary>
        /// (1) This is an in-place operation.<para/>
        ///
        /// (2) If type == L_PAINT_LIGHT, it colorizes non-black pixels,
        /// preserving antialiasing.
        /// If type == L_PAINT_DARK, it colorizes non-white pixels,
        /// preserving antialiasing.  See pixColorGrayCmap() for details.<para/>
        ///
        /// (3) This can also be called through pixColorGrayRegions().<para/>
        ///
        /// (4) This increases the colormap size by the number of
        /// different gray (non-black or non-white) colors in the
        /// selected regions of pixs.  If there is not enough room in
        /// the colormap for this expansion, it returns 1 (error),
        /// and the caller should check the return value.<para/>
        ///
        /// (5) Because two boxes in the boxa can overlap, pixels that
        /// are colorized in the first box must be excluded in the
        /// second because their value exceeds the size of the map.
        ///  </summary>
        ///  <remarks>
        ///  </remarks>
        ///  <include file="..\CHM_Help\IncludeComments.xml" path="Comments/pixColorGrayRegionsCmap/*"/>
        ///  <param name="pixs">[in] - 8 bpp, with colormap</param>
        ///  <param name="boxa">[in] - of regions in which to apply color</param>
        ///  <param name="type">[in] - L_PAINT_LIGHT, L_PAINT_DARK</param>
        ///  <param name="rval">[in] - target color</param>
        ///  <param name="gval">[in] - target color</param>
        ///  <param name="bval">[in] - target color</param>
        ///   <returns>0 if OK, 1 on error</returns>
        public static int pixColorGrayRegionsCmap(
            Pix pixs,
            Boxa boxa,
            int type,
            int rval,
            int gval,
            int bval)
        {
            if (pixs == null)
            {
                throw new ArgumentNullException("pixs cannot be Nothing");
            }

            if (boxa == null)
            {
                throw new ArgumentNullException("boxa cannot be Nothing");
            }

            int _Result = Natives.pixColorGrayRegionsCmap(pixs.Pointer, boxa.Pointer, type, rval, gval, bval);

            return(_Result);
        }
Example #15
0
        // jbclass.c (1597, 1)
        // pixWordBoxesByDilation(pixs, minwidth, minheight, maxwidth, maxheight, pboxa, psize, pixadb) as int
        // pixWordBoxesByDilation(PIX *, l_int32, l_int32, l_int32, l_int32, BOXA **, l_int32 *, PIXA *) as l_ok
        ///  <summary>
        /// (1) Returns a pruned set of word boxes.<para/>
        ///
        /// (2) See pixWordMaskByDilation().
        ///  </summary>
        ///  <remarks>
        ///  </remarks>
        ///  <include file="..\CHM_Help\IncludeComments.xml" path="Comments/pixWordBoxesByDilation/*"/>
        ///  <param name="pixs">[in] - 1 bpp typ. 75 - 200 ppi</param>
        ///  <param name="minwidth">[in] - saved components smaller are discarded</param>
        ///  <param name="minheight">[in] - saved components smaller are discarded</param>
        ///  <param name="maxwidth">[in] - saved components larger are discarded</param>
        ///  <param name="maxheight">[in] - saved components larger are discarded</param>
        ///  <param name="pboxa">[out] - of dilated word mask</param>
        ///  <param name="psize">[out][optional] - size of good horizontal dilation</param>
        ///  <param name="pixadb">[out][optional] - debug: pixa of intermediate steps</param>
        ///   <returns>0 if OK, 1 on error</returns>
        public static int pixWordBoxesByDilation(
            Pix pixs,
            int minwidth,
            int minheight,
            int maxwidth,
            int maxheight,
            out Boxa pboxa,
            out int psize,
            out Pixa pixadb)
        {
            if (pixs == null)
            {
                throw new ArgumentNullException("pixs cannot be Nothing");
            }

            IntPtr pboxaPtr  = IntPtr.Zero;
            IntPtr pixadbPtr = IntPtr.Zero;
            int    _Result   = Natives.pixWordBoxesByDilation(pixs.Pointer, minwidth, minheight, maxwidth, maxheight, out pboxaPtr, out psize, out pixadbPtr);

            if (pboxaPtr == IntPtr.Zero)
            {
                pboxa = null;
            }
            else
            {
                pboxa = new Boxa(pboxaPtr);
            };
            if (pixadbPtr == IntPtr.Zero)
            {
                pixadb = null;
            }
            else
            {
                pixadb = new Pixa(pixadbPtr);
            };

            return(_Result);
        }
Example #16
0
        // classapp.c (515, 1)
        // boxaExtractSortedPattern(boxa, na) as Numaa
        // boxaExtractSortedPattern(BOXA *, NUMA *) as NUMAA *
        ///  <summary>
        /// (1) The input is expected to come from pixGetWordBoxesInTextlines().<para/>
        ///
        /// (2) Each numa in the output consists of an average y coordinate
        /// of the first box in the textline, followed by pairs of
        /// x coordinates representing the left and right edges of each
        /// of the boxes in the textline.
        ///  </summary>
        ///  <remarks>
        ///  </remarks>
        ///  <include file="..\CHM_Help\IncludeComments.xml" path="Comments/boxaExtractSortedPattern/*"/>
        ///  <param name="boxa">[in] - typ. of word bounding boxes, in textline order</param>
        ///  <param name="na">[in] - index of textline for each box in boxa</param>
        ///   <returns>naa NUMAA, where each numa represents one textline, or NULL on error</returns>
        public static Numaa boxaExtractSortedPattern(
            Boxa boxa,
            Numa na)
        {
            if (boxa == null)
            {
                throw new ArgumentNullException("boxa cannot be Nothing");
            }

            if (na == null)
            {
                throw new ArgumentNullException("na cannot be Nothing");
            }

            IntPtr _Result = Natives.boxaExtractSortedPattern(boxa.Pointer, na.Pointer);

            if (_Result == IntPtr.Zero)
            {
                return(null);
            }

            return(new Numaa(_Result));
        }
Example #17
0
        // affinecompose.c (493, 1)
        // boxaAffineTransform(boxas, mat) as Boxa
        // boxaAffineTransform(BOXA *, l_float32 *) as BOXA *
        ///  <summary>
        /// boxaAffineTransform()
        ///  </summary>
        ///  <remarks>
        ///  </remarks>
        ///  <include file="..\CHM_Help\IncludeComments.xml" path="Comments/boxaAffineTransform/*"/>
        ///  <param name="boxas">[in] - </param>
        ///  <param name="mat">[in] - 3x3 transform matrix canonical form</param>
        ///   <returns>boxad  transformed boxas, or NULL on error</returns>
        public static Boxa boxaAffineTransform(
            Boxa boxas,
            Single[] mat)
        {
            if (boxas == null)
            {
                throw new ArgumentNullException("boxas cannot be Nothing");
            }

            if (mat == null)
            {
                throw new ArgumentNullException("mat cannot be Nothing");
            }

            IntPtr _Result = Natives.boxaAffineTransform(boxas.Pointer, mat);

            if (_Result == IntPtr.Zero)
            {
                return(null);
            }

            return(new Boxa(_Result));
        }
Example #18
0
        // boxfunc2.c (1024, 1)
        // boxaSort2dByIndex(boxas, naa) as Boxaa
        // boxaSort2dByIndex(BOXA *, NUMAA *) as BOXAA *
        ///  <summary>
        /// boxaSort2dByIndex()
        ///  </summary>
        ///  <remarks>
        ///  </remarks>
        ///  <include file="..\CHM_Help\IncludeComments.xml" path="Comments/boxaSort2dByIndex/*"/>
        ///  <param name="boxas">[in] - </param>
        ///  <param name="naa">[in] - numaa that maps from the new baa to the input boxa</param>
        ///   <returns>baa sorted boxaa, or NULL on error</returns>
        public static Boxaa boxaSort2dByIndex(
            Boxa boxas,
            Numaa naa)
        {
            if (boxas == null)
            {
                throw new ArgumentNullException("boxas cannot be Nothing");
            }

            if (naa == null)
            {
                throw new ArgumentNullException("naa cannot be Nothing");
            }

            IntPtr _Result = Natives.boxaSort2dByIndex(boxas.Pointer, naa.Pointer);

            if (_Result == IntPtr.Zero)
            {
                return(null);
            }

            return(new Boxaa(_Result));
        }
Example #19
0
        // boxfunc3.c (364, 1)
        // pixPaintBoxaRandom(pixs, boxa) as Pix
        // pixPaintBoxaRandom(PIX *, BOXA *) as PIX *
        ///  <summary>
        /// (1) If pixs is 1 bpp, we paint the boxa using a colormap
        /// otherwise, we convert to 32 bpp.<para/>
        ///
        /// (2) We use up to 254 different colors for painting the regions.<para/>
        ///
        /// (3) If boxes overlap, the later ones paint over earlier ones.
        ///  </summary>
        ///  <remarks>
        ///  </remarks>
        ///  <include file="..\CHM_Help\IncludeComments.xml" path="Comments/pixPaintBoxaRandom/*"/>
        ///  <param name="pixs">[in] - any depth, can be cmapped</param>
        ///  <param name="boxa">[in] - of boxes, to paint</param>
        ///   <returns>pixd with painted boxes, or NULL on error</returns>
        public static Pix pixPaintBoxaRandom(
            Pix pixs,
            Boxa boxa)
        {
            if (pixs == null)
            {
                throw new ArgumentNullException("pixs cannot be Nothing");
            }

            if (boxa == null)
            {
                throw new ArgumentNullException("boxa cannot be Nothing");
            }

            IntPtr _Result = Natives.pixPaintBoxaRandom(pixs.Pointer, boxa.Pointer);

            if (_Result == IntPtr.Zero)
            {
                return(null);
            }

            return(new Pix(_Result));
        }
Example #20
0
        // boxfunc3.c (283, 1)
        // pixSetBlackOrWhiteBoxa(pixs, boxa, op) as Pix
        // pixSetBlackOrWhiteBoxa(PIX *, BOXA *, l_int32) as PIX *
        ///  <summary>
        /// pixSetBlackOrWhiteBoxa()
        ///  </summary>
        ///  <remarks>
        ///  </remarks>
        ///  <include file="..\CHM_Help\IncludeComments.xml" path="Comments/pixSetBlackOrWhiteBoxa/*"/>
        ///  <param name="pixs">[in] - any depth, can be cmapped</param>
        ///  <param name="boxa">[in][optional] - of boxes, to clear or set</param>
        ///  <param name="op">[in] - L_SET_BLACK, L_SET_WHITE</param>
        ///   <returns>pixd with boxes filled with white or black, or NULL on error</returns>
        public static Pix pixSetBlackOrWhiteBoxa(
            Pix pixs,
            Boxa boxa,
            int op)
        {
            if (pixs == null)
            {
                throw new ArgumentNullException("pixs cannot be Nothing");
            }

            IntPtr boxaPtr = IntPtr.Zero;   if (boxa != null)
            {
                boxaPtr = boxa.Pointer;
            }
            IntPtr _Result = Natives.pixSetBlackOrWhiteBoxa(pixs.Pointer, boxaPtr, op);

            if (_Result == IntPtr.Zero)
            {
                return(null);
            }

            return(new Pix(_Result));
        }
Example #21
0
        // classapp.c (453, 1)
        // pixGetWordBoxesInTextlines(pixs, minwidth, minheight, maxwidth, maxheight, pboxad, pnai) as int
        // pixGetWordBoxesInTextlines(PIX *, l_int32, l_int32, l_int32, l_int32, BOXA **, NUMA **) as l_ok
        ///  <summary>
        /// (1) The input should be at a resolution of between 75 and 150 ppi.<para/>
        ///
        /// (2) This is a special version of pixGetWordsInTextlines(), that
        /// just finds the word boxes in line order, with a numa
        /// giving the textline index for each word.
        /// See pixGetWordsInTextlines() for more details.
        ///  </summary>
        ///  <remarks>
        ///  </remarks>
        ///  <include file="..\CHM_Help\IncludeComments.xml" path="Comments/pixGetWordBoxesInTextlines/*"/>
        ///  <param name="pixs">[in] - 1 bpp, typ. 300 ppi</param>
        ///  <param name="minwidth">[in] - of saved components smaller are discarded</param>
        ///  <param name="minheight">[in] - of saved components smaller are discarded</param>
        ///  <param name="maxwidth">[in] - of saved components larger are discarded</param>
        ///  <param name="maxheight">[in] - of saved components larger are discarded</param>
        ///  <param name="pboxad">[out] - word boxes sorted in textline line order</param>
        ///  <param name="pnai">[out][optional] - index of textline for each word</param>
        ///   <returns>0 if OK, 1 on error</returns>
        public static int pixGetWordBoxesInTextlines(
            Pix pixs,
            int minwidth,
            int minheight,
            int maxwidth,
            int maxheight,
            out Boxa pboxad,
            out Numa pnai)
        {
            if (pixs == null)
            {
                throw new ArgumentNullException("pixs cannot be Nothing");
            }

            IntPtr pboxadPtr = IntPtr.Zero;
            IntPtr pnaiPtr   = IntPtr.Zero;
            int    _Result   = Natives.pixGetWordBoxesInTextlines(pixs.Pointer, minwidth, minheight, maxwidth, maxheight, out pboxadPtr, out pnaiPtr);

            if (pboxadPtr == IntPtr.Zero)
            {
                pboxad = null;
            }
            else
            {
                pboxad = new Boxa(pboxadPtr);
            };
            if (pnaiPtr == IntPtr.Zero)
            {
                pnai = null;
            }
            else
            {
                pnai = new Numa(pnaiPtr);
            };

            return(_Result);
        }
Example #22
0
        // boxfunc2.c (1170, 1)
        // boxaExtractAsPta(boxa, pptal, pptat, pptar, pptab, pptaw, pptah, keepinvalid) as int
        // boxaExtractAsPta(BOXA *, PTA **, PTA **, PTA **, PTA **, PTA **, PTA **, l_int32) as l_ok
        ///  <summary>
        /// (1) For most applications, such as counting, sorting, fitting
        /// to some parametrized form, plotting or filtering in general,
        /// you should remove the invalid boxes.  Each pta saves the
        /// box index in the x array, so replacing invalid boxes by
        /// filling with boxaFillSequence(), which is required for
        /// boxaExtractAsNuma(), is not necessary.<para/>
        ///
        /// (2) If invalid boxes are retained, each one will result in
        /// entries (typically 0) in all selected output pta.
        ///  </summary>
        ///  <remarks>
        ///  </remarks>
        ///  <include file="..\CHM_Help\IncludeComments.xml" path="Comments/boxaExtractAsPta/*"/>
        ///  <param name="boxa">[in] - </param>
        ///  <param name="pptal">[out][optional] - array of left locations vs. index</param>
        ///  <param name="pptat">[out][optional] - array of top locations vs. index</param>
        ///  <param name="pptar">[out][optional] - array of right locations vs. index</param>
        ///  <param name="pptab">[out][optional] - array of bottom locations vs. index</param>
        ///  <param name="pptaw">[out][optional] - array of widths vs. index</param>
        ///  <param name="pptah">[out][optional] - array of heights vs. index</param>
        ///  <param name="keepinvalid">[in] - 1 to keep invalid boxes 0 to remove them</param>
        ///   <returns>0 if OK, 1 on error</returns>
        public static int boxaExtractAsPta(
            Boxa boxa,
            out Pta pptal,
            out Pta pptat,
            out Pta pptar,
            out Pta pptab,
            out Pta pptaw,
            out Pta pptah,
            int keepinvalid)
        {
            if (boxa == null)
            {
                throw new ArgumentNullException("boxa cannot be Nothing");
            }

            IntPtr pptalPtr = IntPtr.Zero;
            IntPtr pptatPtr = IntPtr.Zero;
            IntPtr pptarPtr = IntPtr.Zero;
            IntPtr pptabPtr = IntPtr.Zero;
            IntPtr pptawPtr = IntPtr.Zero;
            IntPtr pptahPtr = IntPtr.Zero;
            int    _Result  = Natives.boxaExtractAsPta(boxa.Pointer, out pptalPtr, out pptatPtr, out pptarPtr, out pptabPtr, out pptawPtr, out pptahPtr, keepinvalid);

            if (pptalPtr == IntPtr.Zero)
            {
                pptal = null;
            }
            else
            {
                pptal = new Pta(pptalPtr);
            };
            if (pptatPtr == IntPtr.Zero)
            {
                pptat = null;
            }
            else
            {
                pptat = new Pta(pptatPtr);
            };
            if (pptarPtr == IntPtr.Zero)
            {
                pptar = null;
            }
            else
            {
                pptar = new Pta(pptarPtr);
            };
            if (pptabPtr == IntPtr.Zero)
            {
                pptab = null;
            }
            else
            {
                pptab = new Pta(pptabPtr);
            };
            if (pptawPtr == IntPtr.Zero)
            {
                pptaw = null;
            }
            else
            {
                pptaw = new Pta(pptawPtr);
            };
            if (pptahPtr == IntPtr.Zero)
            {
                pptah = null;
            }
            else
            {
                pptah = new Pta(pptahPtr);
            };

            return(_Result);
        }
Example #23
0
    public string Recognize(Texture2D texture)
    {
        if (_tessHandle.Equals(IntPtr.Zero))
        {
            return(null);
        }

        _highlightedTexture = texture;

        int width  = _highlightedTexture.width;
        int height = _highlightedTexture.height;

        Color32[] colors        = _highlightedTexture.GetPixels32();
        int       count         = width * height;
        int       bytesPerPixel = 4;

        byte[] dataBytes = new byte[count * bytesPerPixel];
        int    bytePtr   = 0;

        for (int y = height - 1; y >= 0; y--)
        {
            for (int x = 0; x < width; x++)
            {
                int colorIdx = y * width + x;
                dataBytes[bytePtr++] = colors[colorIdx].r;
                dataBytes[bytePtr++] = colors[colorIdx].g;
                dataBytes[bytePtr++] = colors[colorIdx].b;
                dataBytes[bytePtr++] = colors[colorIdx].a;
            }
        }

        IntPtr imagePtr = Marshal.AllocHGlobal(count * bytesPerPixel);

        Marshal.Copy(dataBytes, 0, imagePtr, count * bytesPerPixel);

        TessBaseAPISetImage(_tessHandle, imagePtr, width, height, bytesPerPixel, width * bytesPerPixel);

        if (TessBaseAPIRecognize(_tessHandle, IntPtr.Zero) != 0)
        {
            Marshal.FreeHGlobal(imagePtr);
            return(null);
        }

        IntPtr     confidencesPointer = TessBaseAPIAllWordConfidences(_tessHandle);
        int        i          = 0;
        List <int> confidence = new List <int>();

        while (true)
        {
            int tempConfidence = Marshal.ReadInt32(confidencesPointer, i * 4);

            if (tempConfidence == -1)
            {
                break;
            }

            i++;
            confidence.Add(tempConfidence);
        }

        int    pointerSize = Marshal.SizeOf(typeof(IntPtr));
        IntPtr intPtr      = TessBaseAPIGetWords(_tessHandle, IntPtr.Zero);
        Boxa   boxa        = Marshal.PtrToStructure <Boxa>(intPtr);

        Box[] boxes = new Box[boxa.n];


        for (int index = 1; index < boxes.Length; index++)
        {
            if (confidence[index] >= MinimumConfidence)
            {
                IntPtr boxPtr = Marshal.ReadIntPtr(boxa.box, index * pointerSize);
                boxes[index] = Marshal.PtrToStructure <Box>(boxPtr);
                Box box = boxes[index];
                DrawLines(_highlightedTexture,
                          new Rect(box.x, _highlightedTexture.height - box.y - box.h, box.w, box.h),
                          Color.white);
                n         += 1;
                text_size += box.h;
            }
        }
        text_size /= n;

        IntPtr stringPtr = TessBaseAPIGetUTF8Text(_tessHandle);

        Marshal.FreeHGlobal(imagePtr);
        if (stringPtr.Equals(IntPtr.Zero))
        {
            return(null);
        }

#if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN
        string recognizedText = Marshal.PtrToStringAnsi(stringPtr);
#else
        string recognizedText = Marshal.PtrToStringAuto(stringPtr);
#endif

        TessBaseAPIClear(_tessHandle);
        TessDeleteText(stringPtr);

        string[]      words  = recognizedText.Split(new[] { ' ', '\n' }, StringSplitOptions.RemoveEmptyEntries);
        StringBuilder result = new StringBuilder();


        rapport1 = Screen.width / x;
        rapport2 = Screen.height / y;

        // Pour chaque lettre reconnue, on créé un GameObject de type TextMeshPro dans lequel on écrit la lettre reconnue, puis on la place au bon endroit devant l'image.

        for (i = 0; i < boxes.Length; i++)
        {
            //Debug.Log(words[i] + " -> " + confidence[i]);
            if (confidence[i] >= MinimumConfidence)
            {
                Box   box      = boxes[i];
                float decalage = (float)box.w * rapport1 / (float)words[i].Length;
                for (int j = 0; j < words[i].Length; j++)
                {
                    //TextMeshProUGUI te = GameObject.Instantiate(prefab, new Vector3(0, 0, 0), Quaternion.identity);
                    TextMeshProUGUI te = GameObject.Instantiate(prefab, parent.transform);

                    te.transform.SetParent(parent.transform);
                    te.text = words[i][j].ToString();
                    //te.fontSize = box.h;
                    te.rectTransform.sizeDelta = new Vector2(decalage, (float)box.h * rapport2);
                    float a = te.rectTransform.sizeDelta.x > te.rectTransform.sizeDelta.y ? te.rectTransform.sizeDelta.x : te.rectTransform.sizeDelta.y;
                    te.fontSize = a;
                    //te.rectTransform.position = new Vector3((Screen.width / 2 - parent.rectTransform.sizeDelta.x / 2) + box.x + te.rectTransform.sizeDelta.x / 2 + j * decalage, (Screen.height / 2 - parent.rectTransform.sizeDelta.y / 2) + (parent.rectTransform.sizeDelta.y - box.y) - te.rectTransform.sizeDelta.y / 2, 0);
                    te.rectTransform.anchoredPosition = new Vector3(box.x * rapport1 + te.rectTransform.sizeDelta.x / 2 + j * decalage, (parent.rectTransform.sizeDelta.y - box.y * rapport2) - te.rectTransform.sizeDelta.y / 2, 0);
                    //te.rectTransform.anchoredPosition = new Vector3(0, 0, 0);
                }
                result.Append(words[i]);
                result.Append(" ");
            }
        }

        return(result.ToString());
    }
Example #24
0
    public string Recognize(Texture2D texture)
    {
        if (_tessHandle.Equals(IntPtr.Zero))
        {
            return(null);
        }

        _highlightedTexture = texture;

        int width  = _highlightedTexture.width;
        int height = _highlightedTexture.height;

        Color32[] colors        = _highlightedTexture.GetPixels32();
        int       count         = width * height;
        int       bytesPerPixel = 4;

        byte[] dataBytes = new byte[count * bytesPerPixel];
        int    bytePtr   = 0;

        for (int y = height - 1; y >= 0; y--)
        {
            for (int x = 0; x < width; x++)
            {
                int colorIdx = y * width + x;
                dataBytes[bytePtr++] = colors[colorIdx].r;
                dataBytes[bytePtr++] = colors[colorIdx].g;
                dataBytes[bytePtr++] = colors[colorIdx].b;
                dataBytes[bytePtr++] = colors[colorIdx].a;
            }
        }

        IntPtr imagePtr = Marshal.AllocHGlobal(count * bytesPerPixel);

        Marshal.Copy(dataBytes, 0, imagePtr, count * bytesPerPixel);

        TessBaseAPISetImage(_tessHandle, imagePtr, width, height, bytesPerPixel, width * bytesPerPixel);

        if (TessBaseAPIRecognize(_tessHandle, IntPtr.Zero) != 0)
        {
            Marshal.FreeHGlobal(imagePtr);
            return(null);
        }

        IntPtr     confidencesPointer = TessBaseAPIAllWordConfidences(_tessHandle);
        int        i          = 0;
        List <int> confidence = new List <int>();

        while (true)
        {
            int tempConfidence = Marshal.ReadInt32(confidencesPointer, i * 4);

            if (tempConfidence == -1)
            {
                break;
            }

            i++;
            confidence.Add(tempConfidence);
        }

        int    pointerSize = Marshal.SizeOf(typeof(IntPtr));
        IntPtr intPtr      = TessBaseAPIGetWords(_tessHandle, IntPtr.Zero);
        Boxa   boxa        = Marshal.PtrToStructure <Boxa>(intPtr);

        Box[] boxes = new Box[boxa.n];

        for (int index = 0; index < boxes.Length; index++)
        {
            if (confidence[index] >= MinimumConfidence)
            {
                IntPtr boxPtr = Marshal.ReadIntPtr(boxa.box, index * pointerSize);
                boxes[index] = Marshal.PtrToStructure <Box>(boxPtr);
                Box box = boxes[index];
                DrawLines(_highlightedTexture,
                          new Rect(box.x, _highlightedTexture.height - box.y - box.h, box.w, box.h),
                          Color.green);
            }
        }

        IntPtr stringPtr = TessBaseAPIGetUTF8Text(_tessHandle);

        Marshal.FreeHGlobal(imagePtr);
        if (stringPtr.Equals(IntPtr.Zero))
        {
            return(null);
        }

#if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN
        string recognizedText = Marshal.PtrToStringAnsi(str_ptr);
#else
        string recognizedText = Marshal.PtrToStringAuto(stringPtr);
#endif

        TessBaseAPIClear(_tessHandle);
        TessDeleteText(stringPtr);

        string[]      words  = recognizedText.Split(new[] { ' ', '\n' }, StringSplitOptions.RemoveEmptyEntries);
        StringBuilder result = new StringBuilder();

        for (i = 0; i < boxes.Length; i++)
        {
            Debug.Log(words[i] + " -> " + confidence[i]);
            if (confidence[i] >= MinimumConfidence)
            {
                result.Append(words[i]);
                result.Append(" ");
            }
        }

        return(result.ToString());
    }
Example #25
0
    // Recognize the text by feeding it a Texture2D , return a string
    public List <WordList> Recognize(Texture2D texture)
    {
        // Guard in case Tesseract isn't initialized
        if (_tessHandle.Equals(IntPtr.Zero))
        {
            return(null);
        }

        // Set a property to store the texture
        _highlightedTexture = texture;

        // Determine the bytes data
        // First get the texture's dimensions
        int width  = _highlightedTexture.width;
        int height = _highlightedTexture.height;

        //Get the color scape
        // The image texture must have read/write enabled otherwise this function will fail
        Color32[] colors = _highlightedTexture.GetPixels32();

        // Count the total pixels
        int count = width * height;

        //Determine the number of bytes by multiplying the total pixels by the bytes per pixel
        // Four bytes as we're using RGBA (one byte for each element in the byte array
        int bytesPerPixel = 4;

        byte[] dataBytes = new byte[count * bytesPerPixel];

        // Byte Pointer
        int bytePtr = 0;

        // Set up the Byte Stream/Array from the PixelArray
        // For each pixel of Y (height) while it's greater than 0
        for (int y = height - 1; y >= 0; y--)
        {
            // At each Y value, For each pixel of x (width) while X is smaller than the total width
            // Scanning top down like a security guard using a metal detector
            for (int x = 0; x < width; x++)
            {
                // ColorIndex equals current height times total width plus the current width
                int colorIdx = y * width + x;

                // Comprehension of where the data is being placed:
                // dataBytes[0] = First Pixel (Top left), Red Channel
                // dataBytes[1] = First Pixel (Top left), Green Channel
                // dataBytes[2] = Second Pixel (Top Left, one pixel right), Red Channel
                dataBytes[bytePtr++] = colors[colorIdx].r;
                dataBytes[bytePtr++] = colors[colorIdx].g;
                dataBytes[bytePtr++] = colors[colorIdx].b;
                dataBytes[bytePtr++] = colors[colorIdx].a;
            }
        }

        // Method Research:
        // IntPtr is pointer for an integer who's size is platform-specific (32 or 64 bit)
        // The Marshal class provides a collection of methods for allocating and manipulating unmanaged memory

        // AllocHGlobal allocates memory from the unmanaged memory of the process, equal to the size of the image by the number of bytes per pixel
        IntPtr imagePtr = Marshal.AllocHGlobal(count * bytesPerPixel);

        //Copies data from the datastream we set up earlier to our new unmanaged memory pointer
        // We're using overload 16: Copy(Byte[], Int32, IntPtr, Int32): Copies data from a one-dimensional, managed 8-bit unsigned integer array to an unmanaged memory pointer.
        Marshal.Copy(dataBytes, 0, imagePtr, count * bytesPerPixel);

        //  Passing a pointer to the memory of the byte array as a parameter of SetImage
        TessBaseAPISetImage(_tessHandle, imagePtr, width, height,
                            bytesPerPixel, width * bytesPerPixel);

        // See if Tesseract has recognized the image
        if (TessBaseAPIRecognize(_tessHandle, IntPtr.Zero) != 0)
        {
            // If Tesseract has recognized the image, free the memory used for the image data
            Marshal.FreeHGlobal(imagePtr);
            return(null);
        }

        // Determine the confidence level for each word
        IntPtr confidencesPointer = TessBaseAPIAllWordConfidences(_tessHandle);
        int    i = 0;

        // Create a list of the confidence at each byte
        // Note the AllWordConfidences returns a pointer to the 1st element of an Integer32 array ending with -1,
        // so you need to loop through until you get -1
        confidence = new List <int>();

        while (true)
        {
            int tempConfidence = Marshal.ReadInt32(confidencesPointer, i * 4);

            if (tempConfidence == -1)
            {
                break;
            }

            i++;
            confidence.Add(tempConfidence);
        }

        // -------- Determine Boxes for Highlights
        // Get the byte size of the pointer
        int pointerSize = Marshal.SizeOf(typeof(IntPtr));

        // Get the words from Tesseract
        IntPtr intPtr = TessBaseAPIGetWords(_tessHandle, IntPtr.Zero);

        // Put the pointer data into the Boxa structure
        Boxa boxa = Marshal.PtrToStructure <Boxa>(intPtr);

        // Determine the boxes
        boxes = new Box[boxa.n];


        // For Each of the boxes, set it to the read value of the box at the given offset and make it a box structure
        for (int index = 0; index < boxes.Length; index++)
        {
            // If the confidence of the word meets the minimum index
            if (confidence[index] >= MinimumConfidence)
            {
                IntPtr boxPtr = Marshal.ReadIntPtr(boxa.box,
                                                   index * pointerSize);

                boxes[index] = Marshal.PtrToStructure <Box>(boxPtr);
                Box box = boxes[index];

                // draw lines around the box / word
                DrawLines(texture,
                          new Rect(box.x, texture.height - box.y - box.h, box.w, box.h),
                          Color.magenta);
            }
        }
        // --------- End Highlight Section

        // Create a new pointer for the string data and assign it to the result of the method to return UTF8 data.
        IntPtr str_ptr = TessBaseAPIGetUTF8Text(_tessHandle);

        // Free the memory used for the image data
        Marshal.FreeHGlobal(imagePtr);

        // If the string returns null/empty, return null
        if (str_ptr.Equals(IntPtr.Zero))
        {
            return(null);
        }
        //IF we're in windows, convert to an ansi string
        #if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN
        string recognizedText = Marshal.PtrToStringAnsi(str_ptr);
        // Else, convert auto
        #else
        string recognizedText = Marshal.PtrToStringAuto(str_ptr);
        #endif
        // Clear Tesseract
        TessBaseAPIClear(_tessHandle);

        // Clear the text from Tesseract
        TessDeleteText(str_ptr);

        // Filter out the words from the text that are too low in confidence
        words = recognizedText.Split(new[] { ' ', '\n' },
                                     StringSplitOptions.RemoveEmptyEntries);
        StringBuilder result = new StringBuilder();

        for (i = 0; i < boxes.Length; i++)
        {
            // public int Width, Height, X, Y, confidence;
            //  public string Word;
            if (confidence[i] >= MinimumConfidence)
            {
                Box  box      = boxes[i];
                Rect location = new Rect(box.x, texture.height - box.y - box.h, box.w, box.h);
                var  temp     = new WordList();
                temp.box        = location;
                temp.word       = words[i];
                temp.confidence = confidence[i];
                recognizedWords.Add(temp);
                result.Append(words[i]);
                result.Append(" ");
            }
        }

        // Return the filtered words
        return(recognizedWords);
    }
Example #26
0
    public string Recognize(Texture2D texture)
    {
        if (_tessHandle.Equals(IntPtr.Zero))
        {
            return(null);
        }

        _highlightedTexture = texture;

        int width  = _highlightedTexture.width;
        int height = _highlightedTexture.height;

        Color32[] colors        = texture.GetPixels32();
        int       count         = width * height;
        int       bytesPerPixel = 4;

        byte[] dataBytes = new byte[count * bytesPerPixel];

        int bytePtr = 0;

        for (int y = height - 1; y >= 0; y--)
        {
            for (int x = 0; x < width; x++)
            {
                int colorIdx = y * width + x;
                dataBytes[bytePtr++] = colors[colorIdx].r;
                dataBytes[bytePtr++] = colors[colorIdx].g;
                dataBytes[bytePtr++] = colors[colorIdx].b;
                dataBytes[bytePtr++] = colors[colorIdx].a;
            }
        }

        IntPtr imagePtr = Marshal.AllocHGlobal(count * bytesPerPixel);

        Marshal.Copy(dataBytes, 0, imagePtr, count * bytesPerPixel);
        TessBaseAPISetImage(_tessHandle, imagePtr, width, height,
                            bytesPerPixel, width * bytesPerPixel);

        if (TessBaseAPIRecognize(_tessHandle, IntPtr.Zero) != 0)
        {
            Marshal.FreeHGlobal(imagePtr);
            return(null);
        }

        int    pointerSize = Marshal.SizeOf(typeof(IntPtr));
        IntPtr intPtr      = TessBaseAPIGetWords(_tessHandle, IntPtr.Zero);
        Boxa   boxa        = Marshal.PtrToStructure <Boxa>(intPtr);

        Box[] boxes = new Box[boxa.n];
        for (int index = 0; index < boxes.Length; index++)
        {
            IntPtr boxPtr = Marshal.ReadIntPtr(boxa.box,
                                               index * pointerSize);
            boxes[index] = Marshal.PtrToStructure <Box>(boxPtr);
            Box box = boxes[index];
            DrawLines(texture,
                      new Rect(box.x, texture.height - box.y - box.h, box.w, box.h),
                      Color.green);
        }

        IntPtr str_ptr = TessBaseAPIGetUTF8Text(_tessHandle);

        Marshal.FreeHGlobal(imagePtr);
        if (str_ptr.Equals(IntPtr.Zero))
        {
            return(null);
        }

        #if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN
        string recognizedText = Marshal.PtrToStringAnsi(str_ptr);
        #else
        string recognizedText = Marshal.PtrToStringAuto(str_ptr);
        #endif

        TessBaseAPIClear(_tessHandle);
        TessDeleteText(str_ptr);

        return(recognizedText);
    }
Example #27
0
 public void Display(Boxa boxa)
 {
     var n = new ShowPix(_All.pixDrawBoxa(this, boxa, 1, Convert.RGBAUInt(Color.Red)));
 }