85#include <config_auto.h>
89#include "allheaders.h"
93static const l_int32 MinWidth = 100;
94static const l_int32 MinHeight = 100;
122l_int32 w, h, htfound, tlfound;
123PIX *pixr, *pix1, *pix2;
134 if (ppixhm) *ppixhm = NULL;
135 if (ppixtm) *ppixtm = NULL;
136 if (ppixtb) *ppixtb = NULL;
137 if (!pixs || pixGetDepth(pixs) != 1)
138 return ERROR_INT(
"pixs undefined or not 1 bpp", __func__, 1);
139 pixGetDimensions(pixs, &w, &h, NULL);
140 if (w < MinWidth || h < MinHeight) {
141 L_ERROR(
"pix too small: w = %d, h = %d\n", __func__, w, h);
146 pixr = pixReduceRankBinaryCascade(pixs, 1, 0, 0, 0);
147 if (pixadb) pixaAddPix(pixadb, pixr,
L_COPY);
158 pixDestroy(&pixtext);
168 if (pixadb) pixaAddPix(pixadb, pixtbf2,
L_COPY);
173 pixhm = pixExpandReplicate(pixhm2, 2);
174 pix1 = pixSeedfillBinary(NULL, pixhm, pixs, 8);
175 pixOr(pixhm, pixhm, pix1);
178 if (pixadb) pixaAddPix(pixadb, pixhm,
L_COPY);
180 pix1 = pixExpandReplicate(pixtm2, 2);
181 pixtm = pixDilateBrick(NULL, pix1, 3, 3);
184 if (pixadb) pixaAddPix(pixadb, pixtm,
L_COPY);
187 pix1 = pixExpandReplicate(pixtbf2, 2);
188 pixtb = pixDilateBrick(NULL, pix1, 3, 3);
189 pixDestroy(&pixtbf2);
191 if (pixadb) pixaAddPix(pixadb, pixtb,
L_COPY);
193 pixtb = pixCreateTemplate(pixs);
198 pix1 = pixSubtract(NULL, pixs, pixtm);
199 pix2 = pixSubtract(NULL, pix1, pixhm);
209 boxa = pixConnComp(pixtm, &pixa, 8);
210 pixGetDimensions(pixtm, &w, &h, NULL);
211 pix1 = pixaDisplayRandomCmap(pixa, w, h);
212 pixcmapResetColor(pixGetColormap(pix1), 0, 255, 255, 255);
222 ptaa = pixGetOuterBordersPtaa(pixtb);
223 lept_mkdir(
"lept/pageseg");
224 ptaaWriteDebug(
"/tmp/lept/pageseg/tb_outlines.ptaa", ptaa, 1);
225 pix1 = pixRenderRandomCmapPtaa(pixtb, ptaa, 1, 16, 1);
226 cmap = pixGetColormap(pix1);
227 pixcmapResetColor(cmap, 0, 130, 130, 130);
234 BOXA *bahm, *batm, *batb;
235 bahm = pixConnComp(pixhm, NULL, 4);
236 batm = pixConnComp(pixtm, NULL, 4);
237 batb = pixConnComp(pixtb, NULL, 4);
238 boxaWriteDebug(
"/tmp/lept/pageseg/htmask.boxa", bahm);
239 boxaWriteDebug(
"/tmp/lept/pageseg/textmask.boxa", batm);
240 boxaWriteDebug(
"/tmp/lept/pageseg/textblock.boxa", batb);
246 pixaConvertToPdf(pixadb, 0, 1.0, 0, 0,
"Debug page segmentation",
247 "/tmp/lept/pageseg/debug.pdf");
248 L_INFO(
"Writing debug pdf to /tmp/lept/pageseg/debug.pdf\n", __func__);
313PIX *pix1, *pix2, *pixhs, *pixhm, *pixd;
315 if (ppixtext) *ppixtext = NULL;
316 if (phtfound) *phtfound = 0;
317 if (!pixs || pixGetDepth(pixs) != 1)
318 return (
PIX *)ERROR_PTR(
"pixs undefined or not 1 bpp", __func__, NULL);
319 pixGetDimensions(pixs, &w, &h, NULL);
320 if (w < MinWidth || h < MinHeight) {
321 L_ERROR(
"pix too small: w = %d, h = %d\n", __func__, w, h);
326 pix1 = pixReduceRankBinaryCascade(pixs, 4, 4, 0, 0);
327 pix2 = pixOpenBrick(NULL, pix1, 5, 5);
328 pixhs = pixExpandReplicate(pix2, 4);
331 if (pixadb) pixaAddPix(pixadb, pixhs,
L_COPY);
334 pixhm = pixCloseSafeBrick(NULL, pixs, 4, 4);
335 if (pixadb) pixaAddPix(pixadb, pixhm,
L_COPY);
338 pixd = pixSeedfillBinary(NULL, pixhs, pixhm, 4);
339 if (pixadb) pixaAddPix(pixadb, pixd,
L_COPY);
342 pixOpenBrick(pixd, pixd, 9, 9);
346 pixZero(pixd, &empty);
347 if (phtfound && !empty)
353 *ppixtext = pixCopy(NULL, pixs);
355 *ppixtext = pixSubtract(NULL, pixs, pixd);
356 if (pixadb) pixaAddPix(pixadb, *ppixtext,
L_COPY);
394PIX *pix1, *pix2, *pixvws, *pixd;
396 if (ptlfound) *ptlfound = 0;
398 return (
PIX *)ERROR_PTR(
"&pixvws not defined", __func__, NULL);
400 if (!pixs || pixGetDepth(pixs) != 1)
401 return (
PIX *)ERROR_PTR(
"pixs undefined or not 1 bpp", __func__, NULL);
402 pixGetDimensions(pixs, &w, &h, NULL);
403 if (w < MinWidth || h < MinHeight) {
404 L_ERROR(
"pix too small: w = %d, h = %d\n", __func__, w, h);
409 pix1 = pixInvert(NULL, pixs);
418 pix2 = pixMorphCompSequence(pix1,
"o80.60", 0);
419 pixSubtract(pix1, pix1, pix2);
420 if (pixadb) pixaAddPix(pixadb, pix1,
L_COPY);
426 pixvws = pixMorphCompSequence(pix1,
"o5.1 + o1.200", 0);
428 if (pixadb) pixaAddPix(pixadb, pixvws,
L_COPY);
435 pix1 = pixMorphSequence(pixs,
"c30.1", 0);
436 if (pixadb) pixaAddPix(pixadb, pix1,
L_COPY);
437 pixd = pixSubtract(NULL, pix1, pixvws);
438 pixOpenBrick(pixd, pixd, 3, 3);
439 if (pixadb) pixaAddPix(pixadb, pixd,
L_COPY);
444 pixZero(pixd, &empty);
483PIX *pix1, *pix2, *pix3, *pixd;
485 if (!pixs || pixGetDepth(pixs) != 1)
486 return (
PIX *)ERROR_PTR(
"pixs undefined or not 1 bpp", __func__, NULL);
487 pixGetDimensions(pixs, &w, &h, NULL);
488 if (w < MinWidth || h < MinHeight) {
489 L_ERROR(
"pix too small: w = %d, h = %d\n", __func__, w, h);
493 return (
PIX *)ERROR_PTR(
"pixvws not defined", __func__, NULL);
496 pix1 = pixMorphSequence(pixs,
"c1.10 + o4.1", 0);
497 pixZero(pix1, &empty);
500 L_INFO(
"no fg pixels in textblock mask\n", __func__);
503 if (pixadb) pixaAddPix(pixadb, pix1,
L_COPY);
511 pix2 = pixMorphSequenceByComponent(pix1,
"c30.30 + d3.3", 8, 0, 0, NULL);
512 pixCloseSafeBrick(pix2, pix2, 10, 1);
513 if (pixadb) pixaAddPix(pixadb, pix2,
L_COPY);
514 pix3 = pixSubtract(NULL, pix2, pixvws);
515 if (pixadb) pixaAddPix(pixadb, pix3,
L_COPY);
518 if (pixadb) pixaAddPix(pixadb, pixd,
L_COPY);
580 const char *debugfile,
585l_int32 left, right, top, bot, leftfinal, rightfinal, topfinal, botfinal;
586static l_int32 first_time = TRUE;
588PIX *pix1, *pix2, *pix3;
592 if (pcropbox) *pcropbox = NULL;
594 return (
PIX *)ERROR_PTR(
"pixs not defined", __func__, NULL);
595 if (edgeclean < 0) edgeclean = 0;
596 if (edgeclean > 15) {
597 L_WARNING(
"edgeclean > 15; setting to 15\n", __func__);
600 pixGetDimensions(pixs, &w, &h, &d);
601 if (w < MinWidth || h < MinHeight) {
602 L_ERROR(
"pix too small: w = %d, h = %d\n", __func__, w, h);
605 if (lr_clear < 0) lr_clear = 0;
606 if (tb_clear < 0) tb_clear = 0;
607 if (lr_add < 0) lr_add = 0;
608 if (tb_add < 0) tb_add = 0;
609 if (lr_clear > w / 6 || tb_clear > h / 6) {
610 L_ERROR(
"lr_clear or tb_clear too large; must be <= %d and %d\n",
611 __func__, w / 6, h / 6);
615 L_WARNING(
"maxwiden = %f > 1.2; suggest between 1.0 and 1.15\n",
617 pixa1 = (debugfile) ? pixaCreate(5) : NULL;
618 if (pixa1) pixaAddPix(pixa1, pixs,
L_COPY);
622 pix2 = pixReduceRankBinary2(pix1, 2, NULL);
625 pixSetOrClearBorder(pix2, lr_clear / 2, lr_clear / 2, tb_clear / 2,
627 if (pixa1) pixaAddPix(pixa1, pixScale(pix2, 2.0, 2.0),
L_INSERT);
631 if (edgeclean == 0) {
632 pixClipToForeground(pix2, NULL, &box1);
635 snprintf(cmd, 64,
"c%d.%d + o%d.%d", val, val, val, val);
636 pix3 = pixMorphSequence(pix2, cmd, 0);
637 pixClipToForeground(pix3, NULL, &box1);
643 box2 = boxTransform(box1, 0, 0, 2.0, 2.0);
645 pix2 = pixCopy(NULL, pix1);
646 pixRenderBoxArb(pix2, box2, 5, 255, 0, 0);
651 boxGetSideLocations(box2, &left, &right, &top, &bot);
652 leftfinal = L_MAX(left - lr_add, lr_clear);
653 rightfinal = L_MIN(right + lr_add, w - lr_clear);
654 topfinal = L_MAX(top - tb_add, tb_clear);
655 botfinal = L_MIN(bot + tb_add, h - tb_clear);
656 boxSetSideLocations(box2, leftfinal, rightfinal, topfinal, botfinal);
659 pix2 = pixCopy(NULL, pix1);
660 pixRenderBoxArb(pix2, box2, 5, 255, 0, 0);
665 pix2 = pixClipRectangle(pix1, box2, NULL);
669 pix3 = pixMorphSequence(pix2,
"o80.1 + d1.2", 0);
670 pixOr(pix2, pix2, pix3);
675 pixGetDimensions(pix2, &w, &h, NULL);
676 hscale = (l_float32)h / (1.2941f * (l_float32)w);
677 if (hscale > 1.0 && maxwiden > 1.0) {
678 hscale = L_MIN(hscale, maxwiden);
679 pix3 = pixScale(pix2, hscale, 1.0);
680 if (first_time == TRUE) {
681 lept_stderr(
"Widening page by factor %5.3f\n", hscale);
685 pix3 = pixClone(pix2);
695 pixaAddPix(pixa1, pix3,
L_COPY);
696 lept_stderr(
"Writing debug file: %s\n", debugfile);
745PIX *pix1, *pix2, *pix3, *pix4, *pix5;
748 return (
PIX *)ERROR_PTR(
"pixs not defined", __func__, NULL);
749 if (rotation < 0 || rotation > 3) {
750 L_ERROR(
"invalid rotation = %d; rotation must be in {0,1,2,3}\n",
754 if (contrast < 1 || contrast > 10) {
755 L_ERROR(
"invalid contrast = %d; contrast must be in [1...10]\n",
759 if (scale != 1 && scale != 2) {
760 L_ERROR(
"invalid scale = %d; scale must be 1 or 2\n",
765 L_ERROR(
"invalid opensize = %d; opensize must be <= 3\n",
770 if (pixGetDepth(pixs) == 1) {
772 pix1 = pixRotateOrth(pixs, rotation);
774 pix1 = pixClone(pixs);
775 pix2 = pixFindSkewAndDeskew(pix1, 2, NULL, NULL);
777 pix4 = pixExpandBinaryReplicate(pix2, 2, 2);
779 pix4 = pixClone(pix2);
783 pix2 = pixRotateOrth(pix1, rotation);
785 pix2 = pixClone(pix1);
786 pix3 = pixFindSkewAndDeskew(pix2, 2, NULL, NULL);
791 if (opensize == 2 || opensize == 3) {
792 snprintf(sequence,
sizeof(sequence),
"o%d.%d", opensize, opensize);
793 pix5 = pixMorphSequence(pix4, sequence, 0);
795 pix5 = pixClone(pix4);
848l_int32 flag, nbox, intersects;
849l_int32 w, h, bx, by, bw, bh, left, right, top, bottom;
850PIX *pixb, *pixb2, *pixseed, *pixsf, *pixm, *pix1, *pixg2;
851BOX *box, *boxfg, *boxin, *boxd;
855 return (
BOX *)ERROR_PTR(
"pixs not defined", __func__, NULL);
856 pixGetDimensions(pixs, &w, &h, NULL);
857 if (w < MinWidth || h < MinHeight) {
858 L_ERROR(
"pix too small: w = %d, h = %d\n", __func__, w, h);
866 flag = (showmorph) ? 100 : 0;
867 pixb = pixConvertTo1(pixs, threshold);
868 pixb2 = pixScale(pixb, 0.5, 0.5);
869 pixseed = pixMorphSequence(pixb2,
"o1.2 + c9.9 + o3.3", flag);
870 pix1 = pixMorphSequence(pixb2,
"o50.1", 0);
871 pixOr(pixseed, pixseed, pix1);
873 pix1 = pixMorphSequence(pixb2,
"o1.50", 0);
874 pixOr(pixseed, pixseed, pix1);
876 pixsf = pixSeedfillBinary(NULL, pixseed, pixb2, 8);
877 pixm = pixRemoveBorderConnComps(pixsf, 8);
885 pix1 = pixMorphSequence(pixm,
"c50.50", flag);
886 ba1 = pixConnComp(pix1, NULL, 8);
888 pixGetDimensions(pix1, &w, &h, NULL);
889 nbox = boxaGetCount(ba2);
891 box = boxaGetBox(ba2, 0,
L_CLONE);
892 boxGetGeometry(box, &bx, &by, &bw, &bh);
893 left = (bx > mindist) ? erasedist : 0;
894 right = (w - bx - bw > mindist) ? erasedist : 0;
895 top = (by > mindist) ? erasedist : 0;
896 bottom = (h - by - bh > mindist) ? erasedist : 0;
897 pixSetOrClearBorder(pixm, left, right, top, bottom,
PIX_CLR);
905 pixClipToForeground(pixm, NULL, &boxfg);
911 boxin = boxCreate(0.1 * w, 0, 0.8 * w, h);
912 boxIntersects(boxfg, boxin, &intersects);
914 if (!intersects) boxDestroy(&boxfg);
919 boxAdjustSides(boxfg, boxfg, -2, 2, -2, 2);
920 boxd = boxTransform(boxfg, 0, 0, 2.0, 2.0);
924 pixg2 = pixConvert1To4Cmap(pixb);
925 pixRenderBoxArb(pixg2, boxd, 3, 255, 0, 0);
926 pixacompAddPix(pixac, pixg2, IFF_DEFAULT);
933 pixDestroy(&pixseed);
974l_int32 ncomp, i, xoff, yoff;
975BOXA *boxa1, *boxa2, *boxat1, *boxat2, *boxad;
977PIX *pix, *pix1, *pix2, *pixdb;
980 if (pboxa) *pboxa = NULL;
981 if (ppixa) *ppixa = NULL;
982 if (ppixdebug) *ppixdebug = NULL;
983 if (!pixs || pixGetDepth(pixs) != 1)
984 return ERROR_INT(
"pixs not defined or not 1 bpp", __func__, 1);
991 pix2 = pixMorphSequence(pix1,
"c1.10", 0);
995 boxa1 = pixConnComp(pix2, &pixa1, 8);
1000 ncomp = pixaGetCount(pixa1);
1001 boxa2 = boxaCreate(ncomp);
1002 pixadb = (ppixdebug) ? pixaCreate(ncomp) : NULL;
1003 for (i = 0; i < ncomp; i++) {
1004 pix = pixaGetPix(pixa1, i,
L_CLONE);
1008 pixaAddPix(pixadb, pixdb,
L_INSERT);
1012 pixaGetBoxGeometry(pixa1, i, &xoff, &yoff, NULL, NULL);
1013 boxat2 = boxaTransform(boxat1, xoff, yoff, 1.0, 1.0);
1014 boxaJoin(boxa2, boxat2, 0, -1);
1016 boxaDestroy(&boxat1);
1017 boxaDestroy(&boxat2);
1019 pixaDestroy(&pixa1);
1023 if (pixaGetCount(pixadb) > 0) {
1024 *ppixdebug = pixaDisplayTiledInRows(pixadb, 32, 1500,
1027 pixaDestroy(&pixadb);
1031 baa = boxaSort2d(boxa2, NULL, 0, 0, 5);
1032 boxad = boxaaFlattenToBoxa(baa, NULL,
L_CLONE);
1034 boxaDestroy(&boxa2);
1038 *ppixa = pixClipRectangles(pixs, boxad);
1042 boxaDestroy(&boxad);
1071l_int32 w, h, n2, i, firstmin, xmin, xshift;
1072l_int32 nmin, nleft, nright, nsplit, isplit, ncomp;
1073l_int32 *array1, *array2;
1076NUMA *na1, *na2, *nasplit;
1079 if (ppixdebug) *ppixdebug = NULL;
1080 if (!pixs || pixGetDepth(pixs) != 1)
1081 return (
BOXA *)ERROR_PTR(
"pixa undefined or not 1 bpp", __func__, NULL);
1082 pixGetDimensions(pixs, &w, &h, NULL);
1085 pix1 = pixCloseSafeBrick(NULL, pixs, 1, 100);
1088 boxad = boxaCreate(2);
1089 na1 = pixCountPixelsByColumn(pix1);
1091 na2 = numaFindExtrema(na1, delta, NULL);
1092 n2 = numaGetCount(na2);
1094 box = boxCreate(0, 0, w, h);
1104 array1 = numaGetIArray(na1);
1105 array2 = numaGetIArray(na2);
1106 if (ppixdebug) numaWriteStderr(na2);
1107 firstmin = (array1[array2[0]] > array1[array2[1]]) ? 1 : 2;
1108 nasplit = numaCreate(n2);
1109 for (i = firstmin; i < n2 - 1; i+= 2) {
1111 nmin = array1[xmin];
1112 if (xmin + 2 >= w)
break;
1113 nleft = array1[xmin - 2];
1114 nright = array1[xmin + 2];
1117 "Splitting: xmin = %d, w = %d; nl = %d, nmin = %d, nr = %d\n",
1118 xmin, w, nleft, nmin, nright);
1120 if (nleft - nmin >= mindel && nright - nmin >= mindel)
1121 numaAddNumber(nasplit, xmin);
1123 nsplit = numaGetCount(nasplit);
1126 if (ppixdebug && nsplit > 0) {
1127 lept_mkdir(
"lept/split");
1128 gplotSimple1(na1, GPLOT_PNG,
"/tmp/lept/split/split", NULL);
1138 numaDestroy(&nasplit);
1139 box = boxCreate(0, 0, w, h);
1145 for (i = 0, xshift = 0; i < nsplit; i++) {
1146 numaGetIValue(nasplit, i, &isplit);
1147 box = boxCreate(xshift, 0, isplit - xshift, h);
1149 xshift = isplit + 1;
1151 box = boxCreate(xshift, 0, w - xshift, h);
1153 numaDestroy(&nasplit);
1156 pixdb = pixConvertTo32(pixs);
1157 ncomp = boxaGetCount(boxad);
1158 for (i = 0; i < ncomp; i++) {
1159 box = boxaGetBox(boxad, i,
L_CLONE);
1160 pixRenderBoxBlend(pixdb, box, 1, 255, 0, 0, 0.5);
1230l_int32 res, csize, empty;
1231BOXA *boxa1, *boxa2, *boxa3;
1232PIX *pix1, *pix2, *pix3;
1233PIXA *pixa1, *pixa2, *pixa3;
1236 return (
PIXA *)ERROR_PTR(
"pixs not defined", __func__, NULL);
1239 if (pixGetDepth(pixs) > 1) {
1240 pix2 = pixConvertTo8(pixs, FALSE);
1242 pix1 = pixThresholdToBinary(pix3, 150);
1246 pix1 = pixClone(pixs);
1248 pixZero(pix1, &empty);
1251 L_INFO(
"no fg pixels in input image\n", __func__);
1254 if (pixadb) pixaAddPix(pixadb, pix1,
L_COPY);
1259 if (pixadb) pixaAddPix(pixadb, pix2,
L_COPY);
1265 if ((res = pixGetXRes(pixs)) == 0) {
1266 L_INFO(
"Resolution is not set: setting to 300 ppi\n", __func__);
1269 csize = L_MIN(120., 60.0 * res / 300.0);
1270 snprintf(buf,
sizeof(buf),
"c%d.1 + o%d.1", csize, csize / 3);
1271 pix3 = pixMorphCompSequence(pix2, buf, 0);
1272 if (pixadb) pixaAddPix(pixadb, pix3,
L_COPY);
1275 boxa1 = pixConnComp(pix3, &pixa1, 4);
1277 pix1 = pixaDisplayRandomCmap(pixa1, 0, 0);
1278 pixcmapResetColor(pixGetColormap(pix1), 0, 255, 255, 255);
1279 pixaAddPix(pixadb, pix1,
L_INSERT);
1283 minw = (minw != 0) ? minw : (l_int32)(0.12 * res);
1284 minh = (minh != 0) ? minh : (l_int32)(0.07 * res);
1290 pix1 = pixaDisplayRandomCmap(pixa2, 0, 0);
1291 pixcmapResetColor(pixGetColormap(pix1), 0, 255, 255, 255);
1292 pixaAddPix(pixadb, pix1,
L_INSERT);
1293 pix1 = pixConvertTo32(pix2);
1294 pixRenderBoxaArb(pix1, pixa2->
boxa, 2, 255, 0, 0);
1295 pixaAddPix(pixadb, pix1,
L_INSERT);
1299 boxa2 = pixaGetBoxa(pixa2,
L_CLONE);
1300 boxa3 = boxaAdjustSides(boxa2, -adjw, adjw, -adjh, adjh);
1301 pixa3 = pixClipRectangles(pix2, boxa3);
1303 pix1 = pixaDisplayRandomCmap(pixa3, 0, 0);
1304 pixcmapResetColor(pixGetColormap(pix1), 0, 255, 255, 255);
1305 pixaAddPix(pixadb, pix1,
L_INSERT);
1310 pixaDestroy(&pixa1);
1311 pixaDestroy(&pixa2);
1312 boxaDestroy(&boxa1);
1313 boxaDestroy(&boxa2);
1314 boxaDestroy(&boxa3);
1366l_int32 res, csize, empty;
1367BOXA *boxa1, *boxa2, *boxa3;
1369PIX *pix1, *pix2, *pix3;
1373 return (
PIXA *)ERROR_PTR(
"pixs not defined", __func__, NULL);
1376 if ((res = pixGetXRes(pixs)) == 0) {
1377 L_INFO(
"Resolution is not set: setting to 300 ppi\n", __func__);
1380 maxw = (maxw != 0) ? maxw : (l_int32)(0.5 * res);
1381 maxh = (maxh != 0) ? maxh : (l_int32)(0.5 * res);
1384 if (pixGetDepth(pixs) > 1) {
1385 pix2 = pixConvertTo8(pixs, FALSE);
1387 pix1 = pixThresholdToBinary(pix3, 150);
1391 pix1 = pixClone(pixs);
1393 pixZero(pix1, &empty);
1396 L_INFO(
"no fg pixels in input image\n", __func__);
1399 if (pixadb) pixaAddPix(pixadb, pix1,
L_COPY);
1404 if (pixadb) pixaAddPix(pixadb, pix2,
L_COPY);
1409 csize = L_MIN(120., 60.0 * res / 300.0);
1410 snprintf(buf,
sizeof(buf),
"c%d.1", csize);
1411 pix3 = pixMorphCompSequence(pix2, buf, 0);
1412 if (pixadb) pixaAddPix(pixadb, pix3,
L_COPY);
1415 boxa1 = pixConnComp(pix3, &pixa1, 4);
1417 pix1 = pixaDisplayRandomCmap(pixa1, 0, 0);
1418 pixcmapResetColor(pixGetColormap(pix1), 0, 255, 255, 255);
1419 pixaAddPix(pixadb, pix1,
L_INSERT);
1425 baa1 = boxaSort2d(boxa1, NULL, -1, -1, 5);
1426 boxaaGetExtent(baa1, NULL, NULL, NULL, &boxa2);
1428 pix1 = pixConvertTo32(pix2);
1429 pixRenderBoxaArb(pix1, boxa2, 2, 255, 0, 0);
1430 pixaAddPix(pixadb, pix1,
L_INSERT);
1435 boxa3 = boxaAdjustSides(boxa2, -adjw, adjw, -adjh, adjh);
1436 pixa2 = pixClipRectangles(pix2, boxa3);
1438 pix1 = pixaDisplayRandomCmap(pixa2, 0, 0);
1439 pixcmapResetColor(pixGetColormap(pix1), 0, 255, 255, 255);
1440 pixaAddPix(pixadb, pix1,
L_INSERT);
1445 pixaDestroy(&pixa1);
1446 boxaDestroy(&boxa1);
1447 boxaDestroy(&boxa2);
1448 boxaDestroy(&boxa3);
1449 boxaaDestroy(&baa1);
1485 l_float32 deltafract,
1486 l_float32 peakfract,
1487 l_float32 clipfract,
1491l_int32 w, h, res, i, n, npeak;
1492l_float32 scalefact, redfact, minval, maxval, val4, val5, fract;
1494NUMA *na1, *na2, *na3, *na4, *na5;
1495PIX *pix1, *pix2, *pix3, *pix4, *pix5;
1498 return ERROR_INT(
"&ncols not defined", __func__, 1);
1500 if (!pixs || pixGetDepth(pixs) != 1)
1501 return ERROR_INT(
"pixs not defined or not 1 bpp", __func__, 1);
1502 if (deltafract < 0.15 || deltafract > 0.75)
1503 L_WARNING(
"deltafract not in [0.15 ... 0.75]\n", __func__);
1504 if (peakfract < 0.25 || peakfract > 0.9)
1505 L_WARNING(
"peakfract not in [0.25 ... 0.9]\n", __func__);
1506 if (clipfract < 0.0 || clipfract >= 0.5)
1507 return ERROR_INT(
"clipfract not in [0.0 ... 0.5)\n", __func__, 1);
1508 if (pixadb) pixaAddPix(pixadb, pixs,
L_COPY);
1511 if ((res = pixGetXRes(pixs)) == 0) {
1512 L_WARNING(
"resolution undefined; set to 300\n", __func__);
1513 pixSetResolution(pixs, 300, 300);
1517 L_WARNING(
"resolution %d very low\n", __func__, res);
1518 scalefact = 37.5 / res;
1519 pix1 = pixScale(pixs, scalefact, scalefact);
1521 redfact = (l_float32)res / 37.5;
1523 pix1 = pixClone(pixs);
1524 else if (redfact < 4.0)
1525 pix1 = pixReduceRankBinaryCascade(pixs, 1, 0, 0, 0);
1526 else if (redfact < 8.0)
1527 pix1 = pixReduceRankBinaryCascade(pixs, 1, 2, 0, 0);
1528 else if (redfact < 16.0)
1529 pix1 = pixReduceRankBinaryCascade(pixs, 1, 2, 2, 0);
1531 pix1 = pixReduceRankBinaryCascade(pixs, 1, 2, 2, 2);
1533 if (pixadb) pixaAddPix(pixadb, pix1,
L_COPY);
1536 pixGetDimensions(pix1, &w, &h, NULL);
1537 box = boxCreate(clipfract * w, clipfract * h,
1538 (1.0 - 2 * clipfract) * w, (1.0 - 2 * clipfract) * h);
1539 pix2 = pixClipRectangle(pix1, box, NULL);
1540 pixGetDimensions(pix2, &w, &h, NULL);
1542 if (pixadb) pixaAddPix(pixadb, pix2,
L_COPY);
1545 pix3 = pixDeskew(pix2, 0);
1546 if (pixadb) pixaAddPix(pixadb, pix3,
L_COPY);
1549 pix4 = pixCloseSafeBrick(NULL, pix3, 5, 21);
1550 if (pixadb) pixaAddPix(pixadb, pix4,
L_COPY);
1551 pixInvert(pix4, pix4);
1552 na1 = pixCountByColumn(pix4, NULL);
1555 gplotSimple1(na1, GPLOT_PNG,
"/tmp/lept/plot", NULL);
1556 pix5 = pixRead(
"/tmp/lept/plot.png");
1557 pixaAddPix(pixadb, pix5,
L_INSERT);
1565 numaGetMax(na1, &maxval, NULL);
1566 numaGetMin(na1, &minval, NULL);
1567 fract = (l_float32)(maxval - minval) / h;
1569 L_INFO(
"very little content on page; 0 text columns\n", __func__);
1572 na2 = numaFindExtrema(na1, deltafract * (maxval - minval), &na3);
1573 na4 = numaTransform(na2, 0, 1.0 / w);
1574 na5 = numaTransform(na3, -minval, 1.0 / (maxval - minval));
1575 n = numaGetCount(na4);
1576 for (i = 0, npeak = 0; i < n; i++) {
1577 numaGetFValue(na4, i, &val4);
1578 numaGetFValue(na5, i, &val5);
1579 if (val4 > 0.3 && val4 < 0.7 && val5 >= peakfract) {
1581 L_INFO(
"Peak(loc,val) = (%5.3f,%5.3f)\n", __func__, val4, val5);
1584 *pncols = npeak + 1;
1635l_int32 i, empty, maxw, w, h, n1, n2, n3, minlines, big_comp;
1636l_float32 ratio1, ratio2;
1638BOXA *boxa1, *boxa2, *boxa3, *boxa4, *boxa5;
1639PIX *pix1, *pix2, *pix3, *pix4, *pix5, *pix6, *pix7;
1644 return ERROR_INT(
"&istext not defined", __func__, 1);
1647 return ERROR_INT(
"pixs not defined", __func__, 1);
1651 return ERROR_INT(
"pix1 not made", __func__, 1);
1653 pixZero(pix1, &empty);
1656 L_INFO(
"pix is empty\n", __func__);
1659 w = pixGetWidth(pix1);
1668 pix2 = pixCreate(11, 81, 1);
1669 for (i = 0; i < 81; i++)
1670 pixSetPixel(pix2, 5, i, 1);
1671 sel1 = selCreateFromPix(pix2, 40, 5, NULL);
1672 selSetElement(sel1, 20, 0, SEL_MISS);
1673 selSetElement(sel1, 20, 10, SEL_MISS);
1674 selSetElement(sel1, 40, 0, SEL_MISS);
1675 selSetElement(sel1, 40, 10, SEL_MISS);
1676 selSetElement(sel1, 60, 0, SEL_MISS);
1677 selSetElement(sel1, 60, 10, SEL_MISS);
1678 pix3 = pixHMT(NULL, pix1, sel1);
1679 pix4 = pixSeedfillBinaryRestricted(NULL, pix3, pix1, 8, 5, 1000);
1680 pix5 = pixXor(NULL, pix1, pix4);
1685 pix6 = pixMorphCompSequence(pix5,
"c30.1 + o15.1 + c60.1 + o2.2", 0);
1689 pixGetDimensions(pix6, NULL, &h, NULL);
1695 bmf = bmfCreate(NULL, 6);
1696 pixaAddPixWithText(pixadb, pix1, 1, bmf,
"threshold/crop to binary",
1698 pixaAddPixWithText(pixadb, pix3, 2, bmf,
"hit-miss for vertical line",
1700 pixaAddPixWithText(pixadb, pix4, 2, bmf,
"restricted seed-fill",
1702 pixaAddPixWithText(pixadb, pix5, 2, bmf,
"remove using xor",
1704 pixaAddPixWithText(pixadb, pix6, 2, bmf,
"make long horiz components",
1710 boxa1 = pixConnComp(pix6, &pixa1, 8);
1711 pix7 = pixaDisplayRandomCmap(pixa1, 0, 0);
1712 pixcmapResetColor(pixGetColormap(pix7), 0, 255, 255, 255);
1713 pixaAddPixWithText(pixadb, pix7, 2, bmf,
"show connected components",
1716 pixaDestroy(&pixa1);
1719 boxa1 = pixConnComp(pix6, NULL, 8);
1738 boxaGetBoxGeometry(boxa2, 1, NULL, NULL, &maxw, NULL);
1745 big_comp = (boxaGetCount(boxa5) == 0) ? 0 : 1;
1746 n1 = boxaGetCount(boxa1);
1747 n2 = boxaGetCount(boxa3);
1748 n3 = boxaGetCount(boxa4);
1749 ratio1 = (l_float32)maxw / (l_float32)w;
1750 ratio2 = (l_float32)n3 / (l_float32)n2;
1751 minlines = L_MAX(2, h / 125);
1752 if (big_comp || ratio1 < 0.6 || ratio2 < 0.8 || n3 < minlines)
1757 if (*pistext == 1) {
1758 L_INFO(
"This is text: \n n1 = %d, n2 = %d, n3 = %d, "
1759 "minlines = %d\n maxw = %d, ratio1 = %4.2f, h = %d, "
1760 "big_comp = %d\n", __func__, n1, n2, n3, minlines,
1761 maxw, ratio1, h, big_comp);
1763 L_INFO(
"This is not text: \n n1 = %d, n2 = %d, n3 = %d, "
1764 "minlines = %d\n maxw = %d, ratio1 = %4.2f, h = %d, "
1765 "big_comp = %d\n", __func__, n1, n2, n3, minlines,
1766 maxw, ratio1, h, big_comp);
1770 boxaDestroy(&boxa1);
1771 boxaDestroy(&boxa2);
1772 boxaDestroy(&boxa3);
1773 boxaDestroy(&boxa4);
1774 boxaDestroy(&boxa5);
1803 if (ptop) *ptop = 0;
1804 if (pbot) *pbot = 0;
1806 return ERROR_INT(
"nothing to determine", __func__, 1);
1807 if (!pixs || pixGetDepth(pixs) != 1)
1808 return ERROR_INT(
"pixs not defined or not 1 bpp", __func__, 1);
1810 na = pixCountPixelsByRow(pixs, NULL);
1811 n = numaGetCount(na);
1812 array = numaGetIArray(na);
1814 for (i = 0; i < n; i++) {
1815 if (array[i] >= thresh) {
1822 for (i = n - 1; i >= 0; i--) {
1823 if (array[i] >= thresh) {
1888l_int32 empty, nhb, nvb, nvw, score, htfound;
1889PIX *pix1, *pix2, *pix3, *pix4, *pix5, *pix6, *pix7, *pix8, *pix9;
1892 return ERROR_INT(
"&score not defined", __func__, 1);
1895 return ERROR_INT(
"pixs not defined", __func__, 1);
1901 if (htfound && pixadb) pixaAddPix(pixadb, pix2,
L_COPY);
1906 L_INFO(
"pix has an image region\n", __func__);
1912 return ERROR_INT(
"pix1 not made", __func__, 1);
1914 pixZero(pix1, &empty);
1918 L_INFO(
"pix is empty\n", __func__);
1929 pix2 = pixDilateBrick(NULL, pix1, 2, 2);
1933 pix3 = pixDeskewBoth(pix2, 1);
1935 pixaAddPix(pixadb, pix2,
L_COPY);
1936 pixaAddPix(pixadb, pix3,
L_COPY);
1939 pix4 = pixRotate90(pix3, 1);
1941 pix4 = pixClone(pix3);
1945 pix1 = pixClone(pix4);
1949 pix2 = pixMorphSequence(pix1,
"o100.1 + c1.4", 0);
1950 pix3 = pixSeedfillBinary(NULL, pix2, pix1, 8);
1951 pix4 = pixMorphSequence(pix1,
"o1.100 + c4.1", 0);
1952 pix5 = pixSeedfillBinary(NULL, pix4, pix1, 8);
1953 pix6 = pixOr(NULL, pix3, pix5);
1955 pixaAddPix(pixadb, pix2,
L_COPY);
1956 pixaAddPix(pixadb, pix4,
L_COPY);
1957 pixaAddPix(pixadb, pix3,
L_COPY);
1958 pixaAddPix(pixadb, pix5,
L_COPY);
1959 pixaAddPix(pixadb, pix6,
L_COPY);
1961 pixCountConnComp(pix2, 8, &nhb);
1962 pixCountConnComp(pix4, 8, &nvb);
1965 pixSubtract(pix1, pix1, pix6);
1966 if (pixadb) pixaAddPix(pixadb, pix1,
L_COPY);
1969 pix7 = pixMorphSequence(pix1,
"c4.1 + o8.1", 0);
1970 if (pixadb) pixaAddPix(pixadb, pix7,
L_COPY);
1978 pixInvert(pix7, pix7);
1979 pix8 = pixMorphSequence(pix7,
"r1 + o1.100", 0);
1982 pixCountConnComp(pix9, 8, &nvw);
1984 pixaAddPix(pixadb, pixScale(pix8, 2.0, 2.0),
L_INSERT);
1985 pixaAddPix(pixadb, pixScale(pix9, 2.0, 2.0),
L_INSERT);
1992 if (nhb > 1) score++;
1993 if (nvb > 2) score++;
1994 if (nvw > 3) score++;
1995 if (nvw > 6) score++;
2032 l_float32 cropfract,
2038PIX *pix1, *pix2, *pix3, *pix4, *pix5;
2041 return (
PIX *)ERROR_PTR(
"pixs not defined", __func__, NULL);
2047 pix1 = pixClipRectangle(pixs, box, NULL);
2049 pixGetDimensions(pixs, &w, &h, NULL);
2050 box1 = boxCreate((l_int32)(cropfract * w), (l_int32)(cropfract * h),
2051 (l_int32)((1.0 - 2 * cropfract) * w),
2052 (l_int32)((1.0 - 2 * cropfract) * h));
2053 pix1 = pixClipRectangle(pixs, box1, NULL);
2058 if (pixGetDepth(pixs) > 1) {
2059 pix2 = pixConvertTo8(pix1, 0);
2064 L_INFO(
"pix cleaning failed\n", __func__);
2067 pix4 = pixThresholdToBinary(pix3, 200);
2070 pix4 = pixClone(pix1);
2078 if ((res = pixGetXRes(pixs)) == 0) {
2079 L_WARNING(
"Resolution is not set: using 300 ppi\n", __func__);
2082 if (res != outres) {
2083 factor = (l_float32)outres / (l_float32)res;
2084 pix5 = pixScale(pix4, factor, factor);
2086 pix5 = pixClone(pix4);
2118l_int32 w, h, sampling;
2121PIX *pix1, *pix2, *pixm;
2124 return ERROR_INT(
"&bg not defined", __func__, 1);
2126 if (!pixs || pixGetDepth(pixs) != 8)
2127 return ERROR_INT(
"pixs not defined or not 8 bpp", __func__, 1);
2128 if (darkthresh > 128)
2129 L_WARNING(
"darkthresh unusually large\n", __func__);
2130 if (edgecrop < 0.0 || edgecrop >= 1.0)
2131 return ERROR_INT(
"edgecrop not in [0.0 ... 1.0)", __func__, 1);
2134 pixGetDimensions(pix1, &w, &h, NULL);
2137 if (edgecrop > 0.0) {
2138 box = boxCreate(0.5 * edgecrop * w, 0.5 * edgecrop * h,
2139 (1.0 - edgecrop) * w, (1.0 - edgecrop) * h);
2140 pix2 = pixClipRectangle(pix1, box, NULL);
2143 pix2 = pixClone(pix1);
2147 sampling = L_MAX(1, (l_int32)sqrt((l_float64)(w * h) / 50000. + 0.5));
2151 if (darkthresh > 0) {
2152 pixm = pixThresholdToBinary(pix2, darkthresh);
2153 pixInvert(pixm, pixm);
2156 pixGetRankValueMasked(pix2, pixm, 0, 0, sampling, 0.5, &fbg, NULL);
2157 *pbg = (l_int32)(fbg + 0.5);
2201l_int32 i, op, bx, by, bw, bh;
2206 if (ppixdb) *ppixdb = NULL;
2208 return ERROR_INT(
"&boxa not defined", __func__, 1);
2210 if (!pixs || pixGetDepth(pixs) != 1)
2211 return ERROR_INT(
"pixs not defined or not 1 bpp", __func__, 1);
2212 if (polarity != 0 && polarity != 1)
2213 return ERROR_INT(
"invalid polarity", __func__, 1);
2215 L_WARNING(
"large num rectangles = %d requested; using 1000\n",
2220 pix = pixCopy(NULL, pixs);
2221 boxa = boxaCreate(nrect);
2225 for (i = 0; i < nrect; i++) {
2228 L_ERROR(
"failure in pixFindLargestRectangle\n", __func__);
2233 boxGetGeometry(box, &bx, &by, &bw, &bh);
2234 pixRasterop(pix, bx, by, bw, bh, op, NULL, 0, 0);
2238 *ppixdb = pixDrawBoxaRandom(pixs, boxa, 3);
2301l_int32 i, j, w, h, d, wpls, val;
2302l_int32 wp, hp, w1, w2, h1, h2, wmin, hmin, area1, area2;
2304l_int32 maxarea, wmax, hmax, vertdist, horizdist, prevfg;
2306l_uint32 *datas, *lines;
2307l_uint32 **linew, **lineh;
2312 if (ppixdb) *ppixdb = NULL;
2314 return ERROR_INT(
"&box not defined", __func__, 1);
2317 return ERROR_INT(
"pixs not defined", __func__, 1);
2318 pixGetDimensions(pixs, &w, &h, &d);
2320 return ERROR_INT(
"pixs not 1 bpp", __func__, 1);
2321 if (polarity != 0 && polarity != 1)
2322 return ERROR_INT(
"invalid polarity", __func__, 1);
2325 lowestfg = (l_int32 *)LEPT_CALLOC(w,
sizeof(l_int32));
2326 for (i = 0; i < w; i++)
2332 pixw = pixCreate(w, h, 32);
2333 pixh = pixCreate(w, h, 32);
2334 linew = (l_uint32 **)pixGetLinePtrs(pixw, NULL);
2335 lineh = (l_uint32 **)pixGetLinePtrs(pixh, NULL);
2336 datas = pixGetData(pixs);
2337 wpls = pixGetWpl(pixs);
2338 maxarea = xmax = ymax = wmax = hmax = 0;
2339 for (i = 0; i < h; i++) {
2340 lines = datas + i * wpls;
2342 for (j = 0; j < w; j++) {
2344 if ((val ^ polarity) == 0) {
2345 if (i == 0 && j == 0) {
2347 }
else if (i == 0) {
2348 wp = linew[i][j - 1] + 1;
2350 }
else if (j == 0) {
2352 hp = lineh[i - 1][j] + 1;
2355 w1 = linew[i - 1][j];
2356 h1 = lineh[i - 1][j];
2357 horizdist = j - prevfg;
2358 wmin = L_MIN(w1, horizdist);
2359 area1 = wmin * (h1 + 1);
2362 w2 = linew[i][j - 1];
2363 h2 = lineh[i][j - 1];
2364 vertdist = i - lowestfg[j];
2365 hmin = L_MIN(h2, vertdist);
2366 area2 = hmin * (w2 + 1);
2368 if (area1 > area2) {
2383 if (wp * hp > maxarea) {
2394 box = boxCreate(xmax - wmax + 1, ymax - hmax + 1, wmax, hmax);
2398 *ppixdb = pixConvertTo8(pixs, TRUE);
2404 LEPT_FREE(lowestfg);
2446pixFindRectangleInCC(
PIX *pixs,
2453l_int32 x, y, i, w, h, w1, h1, w2, h2, found, res;
2454l_int32 xfirst, xlast, xstart, yfirst, ylast, length;
2455BOX *box1, *box2, *box3, *box4, *box5;
2456PIX *pix1, *pix2, *pixdb1, *pixdb2;
2459 if (!pixs || pixGetDepth(pixs) != 1)
2460 return (
BOX *)ERROR_PTR(
"pixs undefined or not 1 bpp", __func__, NULL);
2461 if (fract <= 0.0 || fract > 1.0)
2462 return (
BOX *)ERROR_PTR(
"invalid fraction", __func__, NULL);
2464 return (
BOX *)ERROR_PTR(
"invalid scan direction", __func__, NULL);
2467 return (
BOX *)ERROR_PTR(
"invalid select", __func__, NULL);
2472 pix1 = pixClipRectangle(pixs, boxs, NULL);
2473 boxGetGeometry(boxs, &x, &y, NULL, NULL);
2475 pix1 = pixClone(pixs);
2480 pix2 = pixRotate90(pix1, 1);
2482 pix2 = pixClone(pix1);
2483 pixGetDimensions(pix2, &w, &h, NULL);
2485 pixadb = (debug) ? pixaCreate(0) : NULL;
2488 lept_mkdir(
"lept/rect");
2489 pixaAddPix(pixadb, pix1,
L_CLONE);
2490 pixdb1 = pixConvertTo32(pix2);
2497 for (i = 0; i < h; i++) {
2498 pixFindMaxHorizontalRunOnLine(pix2, i, &xstart, &length);
2499 if (length >= (l_int32)(fract * w + 0.5)) {
2502 xlast = xfirst + length - 1;
2508 L_WARNING(
"no run of sufficient size was found\n", __func__);
2510 pixDestroy(&pixdb1);
2511 pixaDestroy(&pixadb);
2516 w1 = xlast - xfirst + 1;
2519 for (i = yfirst + 1; i < h; i++) {
2520 pixFindMaxHorizontalRunOnLine(pix2, i, &xstart, &length);
2521 if (xstart > xfirst || (xstart + length - 1 < xlast) ||
2524 h1 = ylast - yfirst + 1;
2528 box1 = boxCreate(xfirst, yfirst, w1, h1);
2532 for (i = h - 1; i >= 0; i--) {
2533 pixFindMaxHorizontalRunOnLine(pix2, i, &xstart, &length);
2534 if (length >= (l_int32)(fract * w + 0.5)) {
2537 xlast = xfirst + length - 1;
2543 w2 = xlast - xfirst + 1;
2545 for (i = ylast - 1; i >= 0; i--) {
2546 pixFindMaxHorizontalRunOnLine(pix2, i, &xstart, &length);
2547 if (xstart > xfirst || (xstart + length - 1 < xlast) ||
2550 h2 = ylast - yfirst + 1;
2554 box2 = boxCreate(xfirst, yfirst, w2, h2);
2558 pixRenderBoxArb(pixdb1, box1, 2, 255, 0, 0);
2559 pixRenderBoxArb(pixdb1, box2, 2, 0, 255, 0);
2560 pixaAddPix(pixadb, pixdb1,
L_INSERT);
2565 box3 = boxBoundingRegion(box1, box2);
2567 box3 = boxOverlapRegion(box1, box2);
2569 box3 = (w1 * h1 >= w2 * h2) ? boxCopy(box1) : boxCopy(box2);
2571 box3 = (w1 * h1 <= w2 * h2) ? boxCopy(box1) : boxCopy(box2);
2579 box4 = boxRotateOrth(box3, w, h, 3);
2581 box4 = boxCopy(box3);
2585 box5 = (box4) ? boxTransform(box4, x, y, 1.0, 1.0) : NULL;
2591 pixdb1 = pixConvertTo8(pixs, 0);
2592 pixAddConstantGray(pixdb1, 190);
2593 pixdb2 = pixConvertTo32(pixdb1);
2594 if (box5) pixRenderBoxArb(pixdb2, box5, 4, 0, 0, 255);
2595 pixaAddPix(pixadb, pixdb2,
L_INSERT);
2596 res = pixGetXRes(pixs);
2597 L_INFO(
"Writing debug files to /tmp/lept/rect/\n", __func__);
2599 "/tmp/lept/rect/fitrect.pdf");
2600 pix1 = pixaDisplayTiledAndScaled(pixadb, 32, 800, 1, 0, 40, 2);
2601 pixWrite(
"/tmp/lept/rect/fitrect.png", pix1, IFF_PNG);
2603 pixDestroy(&pixdb1);
2604 pixaDestroy(&pixadb);
2638l_int32 i, n, empty, x, y, w, h;
2642PIX *pix1, *pix2, *pix3, *pix4, *pix5;
2644 if (ppixm) *ppixm = NULL;
2646 return (
PIX *)ERROR_PTR(
"pixs not defined", __func__, NULL);
2647 if (thresh == 0) thresh = 128;
2649 if ((pix1 = pixConvertTo1(pixs, thresh)) == NULL)
2650 return (
PIX *)ERROR_PTR(
"pix1 not made", __func__, NULL);
2651 if (pixadb) pixaAddPix(pixadb, pix1,
L_COPY);
2660 pix3 = pixMorphSequence(pix2,
"o15.15 + c25.25", 0);
2661 pix4 = pixFillHolesToBoundingRect(pix3, 1, 0.5, 1.0);
2663 pixaAddPix(pixadb, pix2,
L_CLONE);
2664 pixaAddPix(pixadb, pix3,
L_CLONE);
2665 pixaAddPix(pixadb, pix4,
L_COPY);
2669 pixZero(pix4, &empty);
2677 boxa1 = pixConnCompBB(pix4, 8);
2678 n = boxaGetCount(boxa1);
2679 for (i = 0; i < n; i++) {
2680 box1 = boxaGetBox(boxa1, i,
L_COPY);
2681 pix5 = pixClipRectangle(pix1, box1, NULL);
2682 pixForegroundFraction(pix5, &fgfract);
2683 if (pixadb) lept_stderr(
"fg fraction: %5.3f\n", fgfract);
2684 boxGetGeometry(box1, &x, &y, &w, &h);
2686 pixRasterop(pix4, x, y, w, h,
PIX_CLR, NULL, 0, 0);
2690 boxaDestroy(&boxa1);
2691 pixZero(pix4, &empty);
2698 pix5 = pixInvert(NULL, pix1);
2699 pixCombineMasked(pix1, pix5, pix4);
2702 pixaAddPix(pixadb, pix5,
L_CLONE);
2703 pixaAddPix(pixadb, pix1,
L_COPY);
PIX * pixConvertTo8MinMax(PIX *pixs)
pixConvertTo8MinMax()
PIX * pixBackgroundNormTo1MinMax(PIX *pixs, l_int32 contrast, l_int32 scalefactor)
pixBackgroundNormTo1MinMax()
PIX * pixCleanBackgroundToWhite(PIX *pixs, PIX *pixim, PIX *pixg, l_float32 gamma, l_int32 blackval, l_int32 whiteval)
pixCleanBackgroundToWhite()
#define GET_DATA_BIT(pdata, n)
l_ok pixFindThreshFgExtent(PIX *pixs, l_int32 thresh, l_int32 *ptop, l_int32 *pbot)
pixFindThreshFgExtent()
PIX * pixGenTextblockMask(PIX *pixs, PIX *pixvws, PIXA *pixadb)
pixGenTextblockMask()
l_ok pixGetRegionsBinary(PIX *pixs, PIX **ppixhm, PIX **ppixtm, PIX **ppixtb, PIXA *pixadb)
pixGetRegionsBinary()
PIX * pixGenTextlineMask(PIX *pixs, PIX **ppixvws, l_int32 *ptlfound, PIXA *pixadb)
pixGenTextlineMask()
l_ok pixEstimateBackground(PIX *pixs, l_int32 darkthresh, l_float32 edgecrop, l_int32 *pbg)
pixEstimateBackground()
BOX * pixFindPageForeground(PIX *pixs, l_int32 threshold, l_int32 mindist, l_int32 erasedist, l_int32 showmorph, PIXAC *pixac)
pixFindPageForeground()
PIXA * pixExtractRawTextlines(PIX *pixs, l_int32 maxw, l_int32 maxh, l_int32 adjw, l_int32 adjh, PIXA *pixadb)
pixExtractRawTextlines()
PIX * pixAutoPhotoinvert(PIX *pixs, l_int32 thresh, PIX **ppixm, PIXA *pixadb)
pixFindRectangleInCC()
PIX * pixPrepare1bpp(PIX *pixs, BOX *box, l_float32 cropfract, l_int32 outres)
pixPrepare1bpp()
PIXA * pixExtractTextlines(PIX *pixs, l_int32 maxw, l_int32 maxh, l_int32 minw, l_int32 minh, l_int32 adjw, l_int32 adjh, PIXA *pixadb)
pixExtractTextlines()
PIX * pixCropImage(PIX *pixs, l_int32 lr_clear, l_int32 tb_clear, l_int32 edgeclean, l_int32 lr_add, l_int32 tb_add, l_float32 maxwiden, const char *debugfile, BOX **pcropbox)
pixCropImage()
l_ok pixFindLargeRectangles(PIX *pixs, l_int32 polarity, l_int32 nrect, BOXA **pboxa, PIX **ppixdb)
pixFindLargeRectangles()
l_ok pixCountTextColumns(PIX *pixs, l_float32 deltafract, l_float32 peakfract, l_float32 clipfract, l_int32 *pncols, PIXA *pixadb)
pixCountTextColumns()
l_ok pixSplitIntoCharacters(PIX *pixs, l_int32 minw, l_int32 minh, BOXA **pboxa, PIXA **ppixa, PIX **ppixdebug)
pixSplitIntoCharacters()
PIX * pixGenHalftoneMask(PIX *pixs, PIX **ppixtext, l_int32 *phtfound, l_int32 debug)
pixGenHalftoneMask()
l_ok pixFindLargestRectangle(PIX *pixs, l_int32 polarity, BOX **pbox, PIX **ppixdb)
pixFindLargestRectangle()
PIX * pixGenerateHalftoneMask(PIX *pixs, PIX **ppixtext, l_int32 *phtfound, PIXA *pixadb)
pixGenerateHalftoneMask()
PIX * pixCleanImage(PIX *pixs, l_int32 contrast, l_int32 rotation, l_int32 scale, l_int32 opensize)
pixCleanImage()
l_ok pixDecideIfTable(PIX *pixs, BOX *box, l_int32 orient, l_int32 *pscore, PIXA *pixadb)
pixDecideIfTable()
BOXA * pixSplitComponentWithProfile(PIX *pixs, l_int32 delta, l_int32 mindel, PIX **ppixdebug)
pixSplitComponentWithProfile()
l_ok pixDecideIfText(PIX *pixs, BOX *box, l_int32 *pistext, PIXA *pixadb)
pixDecideIfText()
@ REMOVE_CMAP_TO_GRAYSCALE
@ L_GEOMETRIC_INTERSECTION