93#include <config_auto.h>
97#include "allheaders.h"
102#define SPLIT_WITH_DID 1
105static const l_int32 LeftRightPadding = 32;
108static const l_float32 MinFillFactor = 0.10f;
109static const l_int32 DefaultMinHeight = 15;
110static const l_int32 MinOverlap1 = 6;
111static const l_int32 MinOverlap2 = 6;
112static const l_int32 MinHeightPass1 = 5;
116 NUMA *namoment1, l_int32 area2,
117 l_int32 ycent2, l_int32 maxyshift,
118 l_int32 *tab8, l_int32 *pdelx,
119 l_int32 *pdely, l_float32 *pscore,
121static L_RCH *
rchCreate(l_int32 index, l_float32 score,
char *text,
122 l_int32 sample, l_int32 xloc, l_int32 yloc,
127 l_float32 minaf, l_int32 debug);
129 l_float32 minaf, l_int32 *premove,
177 if (pboxa) *pboxa = NULL;
178 if (ppixa) *ppixa = NULL;
179 if (ppixdb) *ppixdb = NULL;
181 return ERROR_INT(
"recog not defined", __func__, 2);
183 return ERROR_INT(
"training not finished", __func__, 2);
185 return ERROR_INT(
"pixs not defined", __func__, 2);
188 if (pixGetDepth(pixs) > 1)
189 pixb = pixConvertTo1(pixs, recog->
threshold);
191 pixb = pixClone(pixs);
197 if (!pixa || (n = pixaGetCount(pixa)) == 0) {
200 L_WARNING(
"nothing found\n", __func__);
257static l_int32 ind = 0;
259l_int32 i, xoff, yoff, empty, maxw, bw, ncomp, scaling;
261BOXA *boxa1, *boxa2, *boxa3, *boxa4, *boxad;
263PIX *pix, *pix1, *pix2, *pix3;
266 lept_mkdir(
"lept/recog");
268 if (pboxa) *pboxa = NULL;
269 if (ppixa) *ppixa = NULL;
270 if (!pboxa || !ppixa)
271 return ERROR_INT(
"&boxa and &pixa not defined", __func__, 1);
273 return ERROR_INT(
"recog not defined", __func__, 1);
275 return ERROR_INT(
"training not finished", __func__, 1);
276 if (!pixs || pixGetDepth(pixs) != 1)
277 return ERROR_INT(
"pixs not defined or not 1 bpp", __func__, 1);
278 if (minh <= 0) minh = DefaultMinHeight;
279 pixZero(pixs, &empty);
284 pix1 = pixMorphSequence(pixs,
"c1.3", 0);
291 boxa1 = pixConnComp(pix2, NULL, 8);
293 ncomp = boxaGetCount(boxa1);
296 L_WARNING(
"all components removed\n", __func__);
301 boxa2 = boxaCreate(ncomp);
303 scaling = (recog->
scalew > 0 || recog->
scaleh > 0) ? TRUE : FALSE;
304 pixa = (debug) ? pixaCreate(ncomp) : NULL;
305 for (i = 0; i < ncomp; i++) {
306 box = boxaGetBox(boxa1, i,
L_CLONE);
307 boxGetGeometry(box, &xoff, &yoff, &bw, NULL);
310 if (bw <= maxw || scaling || skipsplit) {
313 pix = pixClipRectangle(pixs, box, NULL);
316 boxa3 = recogDecode(recog, pix, 2, NULL);
318 boxa3 = recogDecode(recog, pix, 2, &pix2);
325 pix2 = pixConvertTo32(pix);
326 pixRenderBoxaArb(pix2, boxa3, 2, 255, 0, 0);
333 L_ERROR(
"boxa3 not found for component %d\n", __func__, i);
335 boxa4 = boxaTransform(boxa3, xoff, yoff, 1.0, 1.0);
336 boxaJoin(boxa2, boxa4, 0, -1);
344 pix3 = pixaDisplayTiledInColumns(pixa, 1, 1.0, 20, 2);
345 snprintf(buf,
sizeof(buf),
"/tmp/lept/recog/decode-%d.png", ind++);
346 pixWrite(buf, pix3, IFF_PNG);
356 baa = boxaSort2d(boxa2, NULL, MinOverlap1, MinOverlap2, MinHeightPass1);
357 boxa3 = boxaaFlattenToBoxa(baa, NULL,
L_CLONE);
368 boxad = boxaHandleOverlaps(boxa3,
L_COMBINE, 10, 0.5f, 0.3f, NULL);
372 *ppixa = pixClipRectangles(pixs, boxad);
411l_int32 index, remove, w, h, bx, bw, bxc, bwc, w1, w2, w3;
413BOX *box, *boxc, *boxtrans, *boxl, *boxr, *boxlt, *boxrt;
415NUMA *nascoret, *naindext, *nasort;
416PIX *pixb, *pixc, *pixl, *pixr, *pixdb, *pixd;
422 if (pnascore) *pnascore = NULL;
423 if (pnaindex) *pnaindex = NULL;
424 if (psachar) *psachar = NULL;
426 return ERROR_INT(
"&boxa not defined", __func__, 1);
429 return ERROR_INT(
"recog not defined", __func__, 1);
430 if (!pixs || pixGetDepth(pixs) != 1)
431 return ERROR_INT(
"pixs not defined or not 1 bpp", __func__, 1);
432 if (pixGetWidth(pixs) < recog->
minwidth_u - 4)
433 return ERROR_INT(
"pixs too narrow", __func__, 1);
435 return ERROR_INT(
"training not finished", __func__, 1);
441 boxat = boxaCreate(4);
442 nascoret = numaCreate(4);
443 naindext = numaCreate(4);
444 sachart = sarrayCreate(4);
445 pixadb = (debug) ? pixaCreate(4) : NULL;
451 pixar = pixaCreate(1);
452 pixGetDimensions(pixb, &w, &h, NULL);
453 box = boxCreate(0, 0, w, h);
459 for (iter = 0; iter < 11; iter++) {
460 if (pixaGetCount(pixar) == 0)
463 L_WARNING(
"more than 10 chars; ending search\n", __func__);
468 pixaRemovePixAndSave(pixar, 0, &pixc, &boxc);
469 boxGetGeometry(boxc, &bxc, NULL, &bwc, NULL);
474 lept_stderr(
"iter = %d, removed = %d\n", iter, remove);
484 &index, &charstr, &pixdb);
485 pixaAddPix(pixadb, pixdb,
L_INSERT);
488 &index, &charstr, NULL);
493 boxtrans = boxTransform(box, bxc, 0, 1.0, 1.0);
494 boxaAddBox(boxat, boxtrans,
L_INSERT);
495 numaAddNumber(nascoret, score);
496 numaAddNumber(naindext, index);
497 sarrayAddString(sachart, charstr,
L_INSERT);
501 boxGetGeometry(box, &bx, NULL, &bw, NULL);
506 lept_stderr(
" w1 = %d, w2 = %d, w3 = %d\n", w1, w2, w3);
507 if (w1 < recog->minwidth_u - 4) {
508 if (debug) L_INFO(
"discarding width %d on left\n", __func__, w1);
510 boxl = boxCreate(0, 0, bx + 1, h);
511 pixl = pixClipRectangle(pixc, boxl, NULL);
512 boxlt = boxTransform(boxl, bxc, 0, 1.0, 1.0);
517 if (w3 < recog->minwidth_u - 4) {
518 if (debug) L_INFO(
"discarding width %d on right\n", __func__, w3);
520 boxr = boxCreate(bx + bw - 1, 0, w3 + 1, h);
521 pixr = pixClipRectangle(pixc, boxr, NULL);
522 boxrt = boxTransform(boxr, bxc, 0, 1.0, 1.0);
537 *pnascore = numaSortByIndex(nascoret, nasort);
539 *pnaindex = numaSortByIndex(naindext, nasort);
541 *psachar = sarraySortByIndex(sachart, nasort);
542 numaDestroy(&nasort);
544 numaDestroy(&nascoret);
545 numaDestroy(&naindext);
546 sarrayDestroy(&sachart);
550 pixd = pixaDisplayTiledInRows(pixadb, 32, 2000, 1.0, 0, 15, 2);
551 pixDisplay(pixd, 400, 400);
553 pixaDestroy(&pixadb);
590l_int32 i, n, w1, h1, w2, area2, ycent2, delx, dely;
591l_int32 bestdelx, bestdely, bestindex;
592l_float32 score, bestscore;
595NUMA *nasum, *namoment;
598 if (pindex) *pindex = 0;
599 if (pcharstr) *pcharstr = NULL;
600 if (ppixdb) *ppixdb = NULL;
601 if (pbox) *pbox = NULL;
602 if (pscore) *pscore = 0.0;
603 if (!pbox || !pscore)
604 return ERROR_INT(
"&box and &score not both defined", __func__, 1);
606 return ERROR_INT(
"recog not defined", __func__, 1);
607 if (!pixs || pixGetDepth(pixs) != 1)
608 return ERROR_INT(
"pixs not defined or not 1 bpp", __func__, 1);
610 return ERROR_INT(
"training not finished", __func__, 1);
616 pixGetDimensions(pix1, &w1, &h1, NULL);
619 nasum = pixCountPixelsByColumn(pix1);
620 namoment = pixGetMomentByColumn(pix1, 1);
624 boxa = boxaCreate(n);
626 bestindex = bestdelx = bestdely = 0;
627 for (i = 0; i < n; i++) {
629 w2 = pixGetWidth(pix2);
633 numaGetIValue(recog->
nasum_u, i, &area2);
634 ptaGetIPt(recog->
pta_u, i, NULL, &ycent2);
640 "Best match template %d: (x,y) = (%d,%d), score = %5.3f\n",
641 i, delx, dely, score);
644 box = boxCreate(delx - LeftRightPadding, 0, w2, h1);
645 if (score > bestscore) {
647 bestdelx = delx - LeftRightPadding;
652 box = boxCreate(0, 0, 1, 1);
654 lept_stderr(
"Component too thin: w1 = %d, w2 = %d\n", w1, w2);
661 *pbox = boxaGetBox(boxa, bestindex,
L_COPY);
662 if (pindex) *pindex = bestindex;
664 recogGetClassString(recog, bestindex, pcharstr);
667 L_INFO(
"Best match: class %d; shifts (%d, %d)\n",
668 __func__, bestindex, bestdelx, bestdely);
670 *ppixdb = recogShowMatch(recog, pix1, pix2, NULL, -1, 0.0);
677 numaDestroy(&namoment);
735l_int32 w1, w2, h1, h2, i, j, nx, shifty, delx, dely;
736l_int32 sum, moment, count;
737l_int32 *tab, *area1, *arraysum, *arraymoment;
738l_float32 maxscore, score;
741PIX *pixt, *pixt1, *pixt2;
743 if (pdelx) *pdelx = 0;
744 if (pdely) *pdely = 0;
745 if (pscore) *pscore = 0.0;
746 if (!pix1 || pixGetDepth(pix1) != 1)
747 return ERROR_INT(
"pix1 not defined or not 1 bpp", __func__, 1);
748 if (!pix2 || pixGetDepth(pix2) != 1)
749 return ERROR_INT(
"pix2 not defined or not 1 bpp", __func__, 1);
750 if (!nasum1 || !namoment1)
751 return ERROR_INT(
"nasum1 and namoment1 not both defined", __func__, 1);
752 if (area2 <= 0 || ycent2 <= 0)
753 return ERROR_INT(
"area2 and ycent2 must be > 0", __func__, 1);
758 pixGetDimensions(pix1, &w1, &h1, NULL);
759 pixGetDimensions(pix2, &w2, &h2, NULL);
762 L_INFO(
"skipping match with w1 = %d and w2 = %d\n",
770 fpix = fpixCreate(nx, 2 * maxyshift + 1);
772 tab = makePixelSumTab8();
778 area1 = (l_int32 *)LEPT_CALLOC(nx,
sizeof(l_int32));
779 ycent1 = (l_float32 *)LEPT_CALLOC(nx,
sizeof(l_int32));
780 arraysum = numaGetIArray(nasum1);
781 arraymoment = numaGetIArray(namoment1);
782 for (i = 0, sum = 0, moment = 0; i < w2; i++) {
784 moment += arraymoment[i];
786 for (i = 0; i < nx - 1; i++) {
788 ycent1[i] = (sum == 0) ? ycent2 : (l_float32)moment / (l_float32)sum;
789 sum += arraysum[w2 + i] - arraysum[i];
790 moment += arraymoment[w2 + i] - arraymoment[i];
793 ycent1[nx - 1] = (sum == 0) ? ycent2 : (l_float32)moment / (l_float32)sum;
802 pixt = pixCreate(w2, h1, 1);
806 for (i = 0; i < nx; i++) {
807 shifty = (l_int32)(ycent1[i] - ycent2 + 0.5);
808 for (j = -maxyshift; j <= maxyshift; j++) {
810 pixRasterop(pixt, 0, shifty + j, w2, h2,
PIX_SRC, pix2, 0, 0);
812 pixCountPixels(pixt, &count, tab);
813 score = (l_float32)count * (l_float32)count /
814 ((l_float32)area1[i] * (l_float32)area2);
815 if (score > maxscore) {
822 fpixSetPixel(fpix, i, maxyshift + j, 1000.0 * score);
828 lept_mkdir(
"lept/recog");
829 pixt1 = fpixDisplayMaxDynamicRange(fpix);
830 pixt2 = pixExpandReplicate(pixt1, 5);
831 snprintf(buf,
sizeof(buf),
"/tmp/lept/recog/junkbs_%d.png", debugflag);
832 pixWrite(buf, pixt2, IFF_PNG);
838 if (pdelx) *pdelx = delx;
839 if (pdely) *pdely = dely;
840 if (pscore) *pscore = maxscore;
841 if (!tab8) LEPT_FREE(tab);
845 LEPT_FREE(arraymoment);
878l_int32 i, n, fail, index, depth;
880PIX *pix1, *pix2, *pix3;
884 if (ppixdb) *ppixdb = NULL;
886 return ERROR_INT(
"recog not defined", __func__, 1);
888 return ERROR_INT(
"pixa not defined", __func__, 1);
892 n = pixaGetCount(pixa);
895 pixa1 = (ppixdb) ? pixaCreate(n) : NULL;
897 for (i = 0; i < n; i++) {
898 pix1 = pixaGetPix(pixa, i,
L_CLONE);
907 if ((rch = recog->
rch) == NULL) {
908 L_ERROR(
"rch not found for char %d\n", __func__, i);
913 rchExtract(rch, NULL, NULL, &text, NULL, NULL, NULL, NULL);
914 pixSetText(pix1, text);
917 rchExtract(rch, &index, &score, NULL, NULL, NULL, NULL, NULL);
918 pix3 = recogShowMatch(recog, pix2, NULL, NULL, index, score);
919 if (i == 0) depth = pixGetDepth(pix3);
929 *ppixdb = pixaDisplayTiledInRows(pixa1, depth, 2500, 1.0, 0, 20, 1);
969l_int32 i, j, n, bestindex, bestsample, area1, area2, ret;
970l_int32 shiftx, shifty, bestdelx, bestdely, bestwidth, maxyshift;
971l_float32 x1, y1, x2, y2, delx, dely, score, maxscore;
973PIX *pix0, *pix1, *pix2;
977 if (ppixdb) *ppixdb = NULL;
979 return ERROR_INT(
"recog not defined", __func__, 1);
980 if (!pixs || pixGetDepth(pixs) != 1)
981 return ERROR_INT(
"pixs not defined or not 1 bpp", __func__, 1);
985 ret = recogAverageSamples(recog, 0);
987 return ERROR_INT(
"averaging failed", __func__, 1);
992 return ERROR_INT(
"no fg pixels in pix0", __func__, 1);
995 pix1 = recogModifyTemplate(recog, pix0);
998 return ERROR_INT(
"no fg pixels in pix1", __func__, 1);
1002 pixCountPixels(pix1, &area1, recog->
sumtab);
1004 bestindex = bestsample = bestdelx = bestdely = bestwidth = 0;
1008 for (i = 0; i < recog->
setsize; i++) {
1009 numaGetIValue(recog->
nasum, i, &area2);
1010 if (area2 == 0)
continue;
1012 ptaGetPt(recog->
pta, i, &x2, &y2);
1015 for (shifty = -maxyshift; shifty <= maxyshift; shifty++) {
1016 for (shiftx = -maxyshift; shiftx <= maxyshift; shiftx++) {
1017 pixCorrelationScoreSimple(pix1, pix2, area1, area2,
1018 delx + shiftx, dely + shifty,
1019 5, 5, recog->
sumtab, &score);
1020 if (score > maxscore) {
1022 bestdelx = delx + shiftx;
1023 bestdely = dely + shifty;
1031 for (i = 0; i < recog->
setsize; i++) {
1033 n = pixaGetCount(pixa);
1040 for (j = 0; j < n; j++) {
1041 pix2 = pixaGetPix(pixa, j,
L_CLONE);
1042 numaGetIValue(numa, j, &area2);
1043 ptaGetPt(pta, j, &x2, &y2);
1046 for (shifty = -maxyshift; shifty <= maxyshift; shifty++) {
1047 for (shiftx = -maxyshift; shiftx <= maxyshift; shiftx++) {
1048 pixCorrelationScoreSimple(pix1, pix2, area1, area2,
1049 delx + shiftx, dely + shifty,
1050 5, 5, recog->
sumtab, &score);
1051 if (score > maxscore) {
1054 bestdelx = delx + shiftx;
1055 bestdely = dely + shifty;
1057 bestwidth = pixGetWidth(pix2);
1070 recogGetClassString(recog, bestindex, &text);
1072 recog->
rch =
rchCreate(bestindex, maxscore, text, bestsample,
1073 bestdelx, bestdely, bestwidth);
1077 L_INFO(
"Best match: str %s; class %d; sh (%d, %d); score %5.3f\n",
1078 __func__, text, bestindex, bestdelx, bestdely, maxscore);
1079 pix2 = pixaGetPix(recog->
pixa, bestindex,
L_CLONE);
1081 L_INFO(
"Best match: str %s; sample %d in class %d; score %5.3f\n",
1082 __func__, text, bestsample, bestindex, maxscore);
1083 if (maxyshift > 0 && (L_ABS(bestdelx) > 0 || L_ABS(bestdely) > 0)) {
1084 L_INFO(
" Best shift: (%d, %d)\n",
1085 __func__, bestdelx, bestdely);
1087 pix2 = pixaaGetPix(recog->
pixaa, bestindex, bestsample,
L_CLONE);
1089 *ppixdb = recogShowMatch(recog, pix1, pix2, NULL, -1, 0.0);
1114 return ERROR_INT(
"recog not defined", __func__, 1);
1118 recog->
rch =
rchCreate(0, 0.0, stringNew(
""), 0, 0, 0, 0);
1140 rcha->
naindex = numaCreate(0);
1141 rcha->
nascore = numaCreate(0);
1142 rcha->
satext = sarrayCreate(0);
1144 rcha->
naxloc = numaCreate(0);
1145 rcha->
nayloc = numaCreate(0);
1146 rcha->
nawidth = numaCreate(0);
1161 if (prcha == NULL) {
1162 L_WARNING(
"&rcha is null!\n", __func__);
1165 if ((rcha = *prcha) == NULL)
1170 sarrayDestroy(&rcha->
satext);
1172 numaDestroy(&rcha->
naxloc);
1173 numaDestroy(&rcha->
nayloc);
1210 rch = (
L_RCH *)LEPT_CALLOC(1,
sizeof(
L_RCH));
1233 L_WARNING(
"&rch is null!\n", __func__);
1236 if ((rch = *prch) == NULL)
1238 LEPT_FREE(rch->
text);
1273 if (pnaindex) *pnaindex = NULL;
1274 if (pnascore) *pnascore = NULL;
1275 if (psatext) *psatext = NULL;
1276 if (pnasample) *pnasample = NULL;
1277 if (pnaxloc) *pnaxloc = NULL;
1278 if (pnayloc) *pnayloc = NULL;
1279 if (pnawidth) *pnawidth = NULL;
1281 return ERROR_INT(
"rcha not defined", __func__, 1);
1283 if (pnaindex) *pnaindex = numaClone(rcha->
naindex);
1284 if (pnascore) *pnascore = numaClone(rcha->
nascore);
1285 if (psatext) *psatext = sarrayClone(rcha->
satext);
1286 if (pnasample) *pnasample = numaClone(rcha->
nasample);
1287 if (pnaxloc) *pnaxloc = numaClone(rcha->
naxloc);
1288 if (pnayloc) *pnayloc = numaClone(rcha->
nayloc);
1289 if (pnawidth) *pnawidth = numaClone(rcha->
nawidth);
1317 if (pindex) *pindex = 0;
1318 if (pscore) *pscore = 0.0;
1319 if (ptext) *ptext = NULL;
1320 if (psample) *psample = 0;
1321 if (pxloc) *pxloc = 0;
1322 if (pyloc) *pyloc = 0;
1323 if (pwidth) *pwidth = 0;
1325 return ERROR_INT(
"rch not defined", __func__, 1);
1327 if (pindex) *pindex = rch->
index;
1328 if (pscore) *pscore = rch->
score;
1329 if (ptext) *ptext = stringNew(rch->
text);
1330 if (psample) *psample = rch->
sample;
1331 if (pxloc) *pxloc = rch->
xloc;
1332 if (pyloc) *pyloc = rch->
yloc;
1333 if (pwidth) *pwidth = rch->
width;
1357 return ERROR_INT(
"rch not defined", __func__, 1);
1359 return ERROR_INT(
"rcha not defined", __func__, 1);
1397PIX *pix1, *pix2, *pixd;
1400 return (
PIX *)ERROR_PTR(
"recog not defined", __func__, NULL);
1402 return (
PIX *)ERROR_PTR(
"pixs not defined", __func__, NULL);
1404 if (pixGetDepth(pixs) != 1)
1405 pix1 = pixThresholdToBinary(pixs, recog->
threshold);
1407 pix1 = pixClone(pixs);
1408 pixTestClipToForeground(pix1, &canclip);
1410 pixClipToForeground(pix1, &pix2, NULL);
1412 pix2 = pixClone(pix1);
1415 return (
PIX *)ERROR_PTR(
"no foreground pixels", __func__, NULL);
1417 pixd = pixAddBorderGeneral(pix2, pad, pad, 0, 0, 0);
1440l_int32 scaling, minsplitw, maxsplith, maxasp;
1442NUMA *naw, *nah, *na1, *na1c, *na2, *na3, *na4, *na5, *na6, *na7;
1447 return (
PIX *)ERROR_PTR(
"recog not defined", __func__, NULL);
1449 return (
PIX *)ERROR_PTR(
"pixs not defined", __func__, NULL);
1453 scaling = (recog->
scalew > 0 || recog->
scaleh > 0) ? TRUE : FALSE;
1454 minsplitw = (scaling) ? 1 : recog->
min_splitw - 3;
1455 maxsplith = (scaling) ? 150 : recog->
max_splith;
1463 boxas = pixConnComp(pixs, &pixas, 8);
1464 pixaFindDimensions(pixas, &naw, &nah);
1465 na1 = numaMakeThresholdIndicator(naw, minsplitw,
L_SELECT_IF_LT);
1466 na1c = numaCopy(na1);
1468 na3 = numaMakeThresholdIndicator(nah, maxsplith,
L_SELECT_IF_GT);
1469 na4 = pixaFindWidthHeightRatio(pixas);
1471 na6 = pixaFindAreaFraction(pixas);
1473 numaLogicalOp(na1, na1, na2, L_UNION);
1474 numaLogicalOp(na1, na1, na3, L_UNION);
1475 numaLogicalOp(na1, na1, na5, L_UNION);
1476 numaLogicalOp(na1, na1, na7, L_UNION);
1477 pixd = pixCopy(NULL, pixs);
1478 pixRemoveWithIndicator(pixd, pixas, na1);
1491 boxaDestroy(&boxas);
1492 pixaDestroy(&pixas);
1517l_float32 aspratio, fract;
1520 return ERROR_INT(
"&remove not defined", __func__, 1);
1523 return ERROR_INT(
"recog not defined", __func__, 1);
1525 return ERROR_INT(
"pixs not defined", __func__, 1);
1526 if (minh <= 0) minh = DefaultMinHeight;
1532 pixGetDimensions(pixs, &w, &h, NULL);
1533 if (w < recog->min_splitw) {
1534 if (debug) L_INFO(
"w = %d < %d\n", __func__, w, recog->
min_splitw);
1539 if (debug) L_INFO(
"h = %d < %d\n", __func__, h, minh);
1543 aspratio = (l_float32)w / (l_float32)h;
1545 if (debug) L_INFO(
"w/h = %5.3f too large\n", __func__, aspratio);
1549 pixFindAreaFraction(pixs, recog->
sumtab, &fract);
1550 if (fract < minaf) {
1551 if (debug) L_INFO(
"area fill fract %5.3f < %5.3f\n",
1552 __func__, fract, minaf);
1601 l_float32 scorethresh,
1602 l_int32 spacethresh,
1607l_int32 i, n, x1, x2, h_ovl, v_ovl, h_sep, v_sep;
1612NUMA *nascore, *na = NULL;
1614SARRAY *satext, *sa = NULL, *saout;
1616 if (pbaa) *pbaa = NULL;
1617 if (pnaa) *pnaa = NULL;
1618 if (!recog || !recog->
rcha)
1619 return (
SARRAY *)ERROR_PTR(
"recog and rcha not both defined",
1622 return (
SARRAY *)ERROR_PTR(
"boxas not defined", __func__, NULL);
1624 if (spacethresh < 0)
1626 rchaExtract(recog->
rcha, NULL, &nascore, &satext, NULL, NULL, NULL, NULL);
1627 if (!nascore || !satext) {
1628 numaDestroy(&nascore);
1629 sarrayDestroy(&satext);
1630 return (
SARRAY *)ERROR_PTR(
"nascore and satext not both returned",
1634 saout = sarrayCreate(0);
1635 naa = numaaCreate(0);
1636 baa = boxaaCreate(0);
1638 n = numaGetCount(nascore);
1639 for (i = 0; i < n; i++) {
1640 numaGetFValue(nascore, i, &score);
1641 text = sarrayGetString(satext, i,
L_NOCOPY);
1642 if (prebox == NULL) {
1643 if (score < scorethresh) {
1646 sa = sarrayCreate(0);
1649 sarrayAddString(sa, text,
L_COPY);
1650 prebox = boxaGetBox(boxas, i,
L_CLONE);
1651 boxaAddBox(ba, prebox,
L_COPY);
1652 numaAddNumber(na, score);
1655 box = boxaGetBox(boxas, i,
L_CLONE);
1656 boxGetGeometry(prebox, &x1, NULL, NULL, NULL);
1657 boxGetGeometry(box, &x2, NULL, NULL, NULL);
1658 boxOverlapDistance(box, prebox, &h_ovl, &v_ovl);
1661 boxDestroy(&prebox);
1662 if (x1 < x2 && h_sep <= spacethresh &&
1663 v_sep < 0 && score >= scorethresh) {
1664 sarrayAddString(sa, text,
L_COPY);
1665 boxaAddBox(ba, box,
L_COPY);
1666 numaAddNumber(na, score);
1669 str = sarrayToString(sa, 0);
1670 sarrayAddString(saout, str,
L_INSERT);
1675 if (score >= scorethresh) {
1684 str = sarrayToString(sa, 0);
1685 sarrayAddString(saout, str,
L_INSERT);
1689 boxDestroy(&prebox);
1692 numaDestroy(&nascore);
1693 sarrayDestroy(&satext);
1694 if (sarrayGetCount(saout) == 0) {
1695 sarrayDestroy(&saout);
1698 L_INFO(
"saout has no identified text\n", __func__);
1739char *textstr, *scorestr;
1740l_int32 i, j, n, nchar, len;
1746PIX *pix1, *pix2, *pix3, *pix4;
1749 if (ppixdb) *ppixdb = NULL;
1751 return (
PIXA *)ERROR_PTR(
"pixs not defined", __func__, NULL);
1753 return (
PIXA *)ERROR_PTR(
"sa not defined", __func__, NULL);
1755 return (
PIXA *)ERROR_PTR(
"baa not defined", __func__, NULL);
1757 return (
PIXA *)ERROR_PTR(
"naa not defined", __func__, NULL);
1759 n = sarrayGetCount(sa);
1760 pixa = pixaCreate(n);
1761 bmf = bmfCreate(NULL, 6);
1762 if (ppixdb) *ppixdb = pixConvertTo8(pixs, 1);
1763 for (i = 0; i < n; i++) {
1764 textstr = sarrayGetString(sa, i,
L_NOCOPY);
1765 ba = boxaaGetBoxa(baa, i,
L_CLONE);
1766 na = numaaGetNuma(naa, i,
L_CLONE);
1767 boxaGetExtent(ba, NULL, NULL, &box1);
1768 box2 = boxAdjustSides(NULL, box1, -5, 5, -5, 5);
1769 if (ppixdb) pixRenderBoxArb(*ppixdb, box2, 3, 255, 0, 0);
1770 pix1 = pixClipRectangle(pixs, box1, NULL);
1771 len = strlen(textstr) + 1;
1772 pix2 = pixAddBlackOrWhiteBorder(pix1, 14 * len, 14 * len,
1774 pix3 = pixConvertTo8(pix2, 1);
1775 nchar = numaGetCount(na);
1777 for (j = 0; j < nchar; j++) {
1778 numaGetFValue(na, j, &score);
1779 snprintf(buf,
sizeof(buf),
"%d", (l_int32)(100 * score));
1780 stringJoinIP(&scorestr, buf);
1781 if (j < nchar - 1) stringJoinIP(&scorestr,
",");
1783 snprintf(buf,
sizeof(buf),
"%s: %s\n", textstr, scorestr);
1784 pix4 = pixAddTextlines(pix3, bmf, buf, 0xff000000,
L_ADD_BELOW);
1793 LEPT_FREE(scorestr);
1826 n = numaGetCount(na1);
1827 lept_stderr(
"================================================\n");
1828 lept_stderr(
"lt minw: ");
1829 for (i = 0; i < n; i++)
1830 lept_stderr(
"%4d ", (l_int32)na1->
array[i]);
1831 lept_stderr(
"\nlt minh: ");
1832 for (i = 0; i < n; i++)
1833 lept_stderr(
"%4d ", (l_int32)na2->
array[i]);
1834 lept_stderr(
"\ngt maxh: ");
1835 for (i = 0; i < n; i++)
1836 lept_stderr(
"%4d ", (l_int32)na3->
array[i]);
1837 lept_stderr(
"\ngt maxasp: ");
1838 for (i = 0; i < n; i++)
1839 lept_stderr(
"%4d ", (l_int32)na4->
array[i]);
1840 lept_stderr(
"\nlt minaf: ");
1841 for (i = 0; i < n; i++)
1842 lept_stderr(
"%4d ", (l_int32)na5->
array[i]);
1843 lept_stderr(
"\n------------------------------------------------");
1844 lept_stderr(
"\nresult: ");
1845 for (i = 0; i < n; i++)
1846 lept_stderr(
"%4d ", (l_int32)na6->
array[i]);
1847 lept_stderr(
"\n================================================\n");
@ L_USE_AVERAGE_TEMPLATES
PIX * recogProcessToIdentify(L_RECOG *recog, PIX *pixs, l_int32 pad)
recogProcessToIdentify()
l_ok recogCorrelationBestChar(L_RECOG *recog, PIX *pixs, BOX **pbox, l_float32 *pscore, l_int32 *pindex, char **pcharstr, PIX **ppixdb)
recogCorrelationBestChar()
void rchaDestroy(L_RCHA **prcha)
rchaDestroy()
l_ok rchExtract(L_RCH *rch, l_int32 *pindex, l_float32 *pscore, char **ptext, l_int32 *psample, l_int32 *pxloc, l_int32 *pyloc, l_int32 *pwidth)
rchExtract()
static l_int32 recogSplittingFilter(L_RECOG *recog, PIX *pixs, l_int32 min, l_float32 minaf, l_int32 *premove, l_int32 debug)
recogSplittingFilter()
static void l_showIndicatorSplitValues(NUMA *na1, NUMA *na2, NUMA *na3, NUMA *na4, NUMA *na5, NUMA *na6)
l_showIndicatorSplitValues()
static l_int32 transferRchToRcha(L_RCH *rch, L_RCHA *rcha)
transferRchToRcha()
static l_int32 pixCorrelationBestShift(PIX *pix1, PIX *pix2, NUMA *nasum1, NUMA *namoment1, l_int32 area2, l_int32 ycent2, l_int32 maxyshift, l_int32 *tab8, l_int32 *pdelx, l_int32 *pdely, l_float32 *pscore, l_int32 debugflag)
pixCorrelationBestShift()
void rchDestroy(L_RCH **prch)
rchDestroy()
l_ok recogIdentifyPixa(L_RECOG *recog, PIXA *pixa, PIX **ppixdb)
recogIdentifyPixa()
l_ok recogIdentifyPix(L_RECOG *recog, PIX *pixs, PIX **ppixdb)
recogIdentifyPix()
SARRAY * recogExtractNumbers(L_RECOG *recog, BOXA *boxas, l_float32 scorethresh, l_int32 spacethresh, BOXAA **pbaa, NUMAA **pnaa)
recogExtractNumbers()
static L_RCHA * rchaCreate()
rchaCreate()
l_ok recogCorrelationBestRow(L_RECOG *recog, PIX *pixs, BOXA **pboxa, NUMA **pnascore, NUMA **pnaindex, SARRAY **psachar, l_int32 debug)
recogCorrelationBestRow()
l_ok recogSkipIdentify(L_RECOG *recog)
recogSkipIdentify()
l_ok recogIdentifyMultiple(L_RECOG *recog, PIX *pixs, l_int32 minh, l_int32 skipsplit, BOXA **pboxa, PIXA **ppixa, PIX **ppixdb, l_int32 debugsplit)
recogIdentifyMultiple()
static PIX * recogPreSplittingFilter(L_RECOG *recog, PIX *pixs, l_int32 minh, l_float32 minaf, l_int32 debug)
recogPreSplittingFilter()
l_ok recogSplitIntoCharacters(L_RECOG *recog, PIX *pixs, l_int32 minh, l_int32 skipsplit, BOXA **pboxa, PIXA **ppixa, l_int32 debug)
recogSplitIntoCharacters()
l_ok rchaExtract(L_RCHA *rcha, NUMA **pnaindex, NUMA **pnascore, SARRAY **psatext, NUMA **pnasample, NUMA **pnaxloc, NUMA **pnayloc, NUMA **pnawidth)
rchaExtract()
PIXA * showExtractNumbers(PIX *pixs, SARRAY *sa, BOXAA *baa, NUMAA *naa, PIX **ppixdb)
showExtractNumbers()
static L_RCH * rchCreate(l_int32 index, l_float32 score, char *text, l_int32 sample, l_int32 xloc, l_int32 yloc, l_int32 width)
rchCreate()
struct Pixa * pixadb_split