Leptonica 1.68
C Image Processing Library
|
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