Leptonica 1.68
C Image Processing Library

textlinemask.c

Go to the documentation of this file.
00001 /*====================================================================*
00002  -  Copyright (C) 2001 Leptonica.  All rights reserved.
00003  -  This software is distributed in the hope that it will be
00004  -  useful, but with NO WARRANTY OF ANY KIND.
00005  -  No author or distributor accepts responsibility to anyone for the
00006  -  consequences of using this software, or for whether it serves any
00007  -  particular purpose or works at all, unless he or she says so in
00008  -  writing.  Everyone is granted permission to copy, modify and
00009  -  redistribute this source code, for commercial or non-commercial
00010  -  purposes, with the following restrictions: (1) the origin of this
00011  -  source code must not be misrepresented; (2) modified versions must
00012  -  be plainly marked as such; and (3) this notice may not be removed
00013  -  or altered from any source or modified source distribution.
00014  *====================================================================*/
00015 
00016 /*
00017  * textlinemask.c
00018  *
00019  *   This shows examples of finding textline masks for very
00020  *   simple geometries.  To do this task for more general layout,
00021  *   use pagesegtest* programs.
00022  *
00023  *      filein: e.g., use arabic.png
00024  *      fileout: debug output showing results
00025  */
00026 
00027 #include "allheaders.h"
00028 
00029 static const l_int32  DEBUG_OUTPUT = 1;
00030 
00031 static const char *seltext = "xxxxxxx"
00032                              "   x   " 
00033                              "   x   " 
00034                              "   x   " 
00035                              "   x   " 
00036                              "   x   " 
00037                              "   x   " 
00038                              "   x   " 
00039                              "o  X  o" 
00040                              "   x   " 
00041                              "   x   " 
00042                              "   x   " 
00043                              "   x   " 
00044                              "   x   " 
00045                              "   x   " 
00046                              "   x   " 
00047                              "xxxxxxx";
00048 
00049 
00050 main(int    argc,
00051      char **argv)
00052 {
00053 char        *filein, *fileout;
00054 l_int32      w, h, d, w2, h2, i, ncols;
00055 l_float32    angle, conf;
00056 BOX         *box;
00057 BOXA        *boxa, *boxas, *boxad, *boxa2;
00058 NUMA        *numa;
00059 PIX         *pixs, *pixt, *pixb, *pixb2, *pixd;
00060 PIX         *pixtlm, *pixvws;
00061 PIX         *pixt1, *pixt2, *pixt3, *pixt4, *pixt5, *pixt6;
00062 PIXA        *pixam, *pixac, *pixad, *pixat;
00063 PIXAA       *pixaa, *pixaa2;
00064 PTA         *pta;
00065 SEL         *selsplit;
00066 static char  mainName[] = "textlinemask";
00067 
00068     if (argc != 3)
00069         exit(ERROR_INT(" Syntax:  textlinemask filein fileout", mainName, 1));
00070 
00071     filein = argv[1];
00072     fileout = argv[2];
00073 
00074     pixDisplayWrite(NULL, -1);  /* init debug output */
00075 
00076     if ((pixs = pixRead(filein)) == NULL)
00077         return ERROR_INT("pixs not made", mainName, 1);
00078     pixGetDimensions(pixs, &w, &h, &d);
00079 
00080         /* Binarize input */
00081     if (d == 8)
00082         pixt = pixThresholdToBinary(pixs, 128);
00083     else if (d == 1)
00084         pixt = pixClone(pixs);
00085     else {
00086         fprintf(stderr, "depth is %d\n", d);
00087         exit(1);
00088     }
00089 
00090         /* Deskew */
00091     pixb = pixFindSkewAndDeskew(pixt, 1, &angle, &conf);
00092     pixDestroy(&pixt);
00093     fprintf(stderr, "Skew angle: %7.2f degrees; %6.2f conf\n", angle, conf);
00094     pixDisplayWrite(pixb, DEBUG_OUTPUT);
00095 
00096 #if 1
00097         /* Use full image morphology to find columns, at 2x reduction.
00098          * This only works for very simple layouts where each column
00099          * of text extends the full height of the input image. 
00100          * pixam has a pix component over each column.  */
00101     pixb2 = pixReduceRankBinary2(pixb, 2, NULL);
00102     pixt1 = pixMorphCompSequence(pixb2, "c5.500", 0);
00103     boxa = pixConnComp(pixt1, &pixam, 8);
00104     ncols = boxaGetCount(boxa);
00105     fprintf(stderr, "Num columns: %d\n", ncols);
00106     pixDisplayWrite(pixt1, DEBUG_OUTPUT);
00107 
00108         /* Use selective region-based morphology to get the textline mask. */
00109     pixad = pixaMorphSequenceByRegion(pixb2, pixam, "c100.3", 0, 0);
00110     pixGetDimensions(pixb2, &w2, &h2, NULL);
00111     if (DEBUG_OUTPUT) {
00112         pixt2 = pixaDisplay(pixad, w2, h2);
00113         pixDisplayWrite(pixt2, DEBUG_OUTPUT);
00114         pixDestroy(&pixt2);
00115     }
00116 
00117         /* Some of the lines may be touching, so use a HMT to split the
00118          * lines in each column, and use a pixaa to save the results. */
00119     selsplit = selCreateFromString(seltext, 17, 7, "selsplit");
00120     pixaa = pixaaCreate(ncols);
00121     for (i = 0; i < ncols; i++) {
00122         pixt3 = pixaGetPix(pixad, i, L_CLONE);
00123         box = pixaGetBox(pixad, i, L_COPY);
00124         pixt4 = pixHMT(NULL, pixt3, selsplit);
00125         pixXor(pixt4, pixt4, pixt3);
00126         boxa2 = pixConnComp(pixt4, &pixac, 8);
00127         pixaaAddPixa(pixaa, pixac, L_INSERT);
00128         pixaaAddBox(pixaa, box, L_INSERT);
00129         if (DEBUG_OUTPUT) {
00130             pixt5 = pixaDisplayRandomCmap(pixac, 0, 0);
00131             pixDisplayWrite(pixt5, DEBUG_OUTPUT);
00132             fprintf(stderr, "Num textlines in col %d: %d\n", i,
00133                     boxaGetCount(boxa2));
00134             pixDestroy(&pixt5);
00135         }
00136         pixDestroy(&pixt3);
00137         pixDestroy(&pixt4);
00138         boxaDestroy(&boxa2);
00139     }
00140 
00141         /* Visual output */
00142     if (DEBUG_OUTPUT) {
00143         pixDisplayMultiple("/tmp/junk_write_display*");
00144         pixat = pixaReadFiles("/tmp", "junk_write_display");
00145         pixt5 = selDisplayInPix(selsplit, 31, 2);
00146         pixaAddPix(pixat, pixt5, L_INSERT);
00147         pixt6 = pixaDisplayTiledAndScaled(pixat, 32, 400, 3, 0, 35, 3);
00148         pixWrite(fileout, pixt6, IFF_PNG);
00149         pixaDestroy(&pixat);
00150         pixDestroy(&pixt6);
00151     }
00152 
00153         /* Test pixaa I/O */
00154     pixaaWrite("/tmp/junkpixaa", pixaa);
00155     pixaa2 = pixaaRead("/tmp/junkpixaa");
00156     pixaaWrite("/tmp/junkpixaa2", pixaa2);
00157 
00158         /* Test pixaa display */
00159     pixd = pixaaDisplay(pixaa, w2, h2);
00160     pixWrite("/tmp/junkdisplay", pixd, IFF_PNG);
00161     pixDestroy(&pixd);
00162 
00163         /* Cleanup */
00164     pixDestroy(&pixb2);
00165     pixDestroy(&pixt1);
00166     pixaDestroy(&pixam);
00167     pixaDestroy(&pixad);
00168     pixaaDestroy(&pixaa);
00169     pixaaDestroy(&pixaa2);
00170     boxaDestroy(&boxa);
00171     selDestroy(&selsplit);
00172 #endif
00173 
00174 #if 0
00175         /*  Use the baseline finder; not really what is needed */
00176     numa = pixFindBaselines(pixb, &pta, 1);
00177 #endif
00178 
00179 #if 0
00180         /* Use the textline mask function; parameters are not quite right */
00181     pixb2 = pixReduceRankBinary2(pixb, 2, NULL);
00182     pixtlm = pixGenTextlineMask(pixb2, &pixvws, NULL, 1);
00183     pixDisplay(pixtlm, 0, 100);
00184     pixDisplay(pixvws, 500, 100);
00185     pixDestroy(&pixb2);
00186     pixDestroy(&pixtlm);
00187     pixDestroy(&pixvws);
00188 #endif
00189 
00190 #if 0
00191         /* Use the Breuel whitespace partition method; slow and we would
00192          * still need to work to extract the fg regions. */
00193     pixb2 = pixReduceRankBinary2(pixb, 2, NULL);
00194     boxas = pixConnComp(pixb2, NULL, 8);
00195     boxad = boxaGetWhiteblocks(boxas, NULL, L_SORT_BY_HEIGHT,
00196                               3, 0.1, 200, 0.2, 0);
00197     pixd = pixDrawBoxa(pixb2, boxad, 7, 0xe0708000);
00198     pixDisplay(pixd, 100, 500);
00199     pixDestroy(&pixb2);
00200     pixDestroy(&pixd);
00201     boxaDestroy(&boxas);
00202     boxaDestroy(&boxad);
00203 #endif
00204 
00205 
00206 #if 0
00207         /* Use morphology to find columns and then selective
00208          * region-based morphology to get the textline mask.
00209          * This is for display; we really want to get a pixa of the
00210          * specific textline masks.   */
00211     startTimer();
00212     pixb2 = pixReduceRankBinary2(pixb, 2, NULL);
00213     pixt1 = pixMorphCompSequence(pixb2, "c5.500", 0);  /* column mask */
00214     pixt2 = pixMorphSequenceByRegion(pixb2, pixt1, "c100.3", 8, 0, 0, &boxa);
00215     fprintf(stderr, "time = %7.3f sec\n", stopTimer());
00216     pixDisplay(pixt1, 100, 500);
00217     pixDisplay(pixt2, 800, 500);
00218     pixDestroy(&pixb2);
00219     pixDestroy(&pixt1);
00220     pixDestroy(&pixt2);
00221     boxaDestroy(&boxa);
00222 #endif
00223 
00224     pixDestroy(&pixs);
00225     pixDestroy(&pixb);
00226 
00227     exit(0);
00228 }
00229 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines