main(int argc, char **argv) { char *infile; PIX *pixs, *pixg, *pixc, *pixd; static char mainName[] = "morphseq_reg"; if (argc != 1) return ERROR_INT(" Syntax: morphseq_reg", mainName, 1); pixs = pixRead("feyn.tif"); /* 1 bpp */ pixd = pixMorphSequence(pixs, SEQUENCE1, -1); pixDestroy(&pixd); pixd = pixMorphSequence(pixs, SEQUENCE1, DISPLAY_SEPARATION); pixWrite("/tmp/morphseq1.png", pixd, IFF_PNG); pixDestroy(&pixd); pixd = pixMorphCompSequence(pixs, SEQUENCE2, -2); pixDestroy(&pixd); pixd = pixMorphCompSequence(pixs, SEQUENCE2, DISPLAY_SEPARATION); pixWrite("/tmp/morphseq2.png", pixd, IFF_PNG); pixDestroy(&pixd); pixd = pixMorphSequenceDwa(pixs, SEQUENCE2, -3); pixDestroy(&pixd); pixd = pixMorphSequenceDwa(pixs, SEQUENCE2, DISPLAY_SEPARATION); pixWrite("/tmp/morphseq3.png", pixd, IFF_PNG); pixDestroy(&pixd); pixd = pixMorphCompSequenceDwa(pixs, SEQUENCE2, -4); pixDestroy(&pixd); pixd = pixMorphCompSequenceDwa(pixs, SEQUENCE2, DISPLAY_SEPARATION); pixWrite("/tmp/morphseq4.png", pixd, IFF_PNG); pixDestroy(&pixd); /* 8 bpp */ pixg = pixScaleToGray(pixs, 0.25); pixd = pixGrayMorphSequence(pixg, SEQUENCE3, -5, 150); pixDestroy(&pixd); pixd = pixGrayMorphSequence(pixg, SEQUENCE3, DISPLAY_SEPARATION, 150); pixWrite("/tmp/morphseq5.png", pixd, IFF_PNG); pixDestroy(&pixd); pixd = pixGrayMorphSequence(pixg, SEQUENCE4, -6, 300); pixWrite("/tmp/morphseq6.png", pixd, IFF_PNG); pixDestroy(&pixd); /* 32 bpp */ pixc = pixRead("wyom.jpg"); pixd = pixColorMorphSequence(pixc, SEQUENCE5, -7, 150); pixDestroy(&pixd); pixd = pixColorMorphSequence(pixc, SEQUENCE5, DISPLAY_SEPARATION, 450); pixWrite("/tmp/morphseq7.png", pixd, IFF_PNG); pixDestroy(&pixc); pixDestroy(&pixd); /* Syntax error handling */ fprintf(stderr, " ------------ Error messages follow ------------------\n"); pixd = pixMorphSequence(pixs, BAD_SEQUENCE, 50); /* fails; returns null */ pixd = pixGrayMorphSequence(pixg, BAD_SEQUENCE, 50, 0); /* this fails */ pixDestroy(&pixg); pixDestroy(&pixs); return 0; }
/*! * pixMirrorDetectDwa() * * Input: pixs (1 bpp, deskewed, English text) * &conf (<return> confidence that text is not LR mirror reversed) * mincount (min number of left + right; use 0 for default) * debug (1 for debug output; 0 otherwise) * Return: 0 if OK, 1 on error * * Notes: * (1) We assume the text is horizontally oriented, with * ascenders going up. * (2) See notes in pixMirrorDetect(). */ l_int32 pixMirrorDetectDwa(PIX *pixs, l_float32 *pconf, l_int32 mincount, l_int32 debug) { char flipsel1[] = "flipsel1"; char flipsel2[] = "flipsel2"; l_int32 count1, count2, nmax; l_float32 nleft, nright; PIX *pixt0, *pixt1, *pixt2, *pixt3; PROCNAME("pixMirrorDetectDwa"); if (!pconf) return ERROR_INT("&conf not defined", procName, 1); *pconf = 0.0; if (!pixs) return ERROR_INT("pixs not defined", procName, 1); if (mincount == 0) mincount = DEFAULT_MIN_MIRROR_FLIP_COUNT; /* Fill x-height characters but not space between them, sort of. */ pixt3 = pixMorphSequenceDwa(pixs, "d1.30", 0); pixXor(pixt3, pixt3, pixs); pixt0 = pixMorphSequenceDwa(pixs, "c15.1", 0); pixXor(pixt0, pixt0, pixs); pixAnd(pixt0, pixt0, pixt3); pixOr(pixt3, pixt0, pixs); pixDestroy(&pixt0); pixt0 = pixAddBorderGeneral(pixt3, ADDED_BORDER, ADDED_BORDER, ADDED_BORDER, ADDED_BORDER, 0); pixDestroy(&pixt3); /* Filter the right-facing characters. */ pixt1 = pixFlipFHMTGen(NULL, pixt0, flipsel1); pixt3 = pixReduceRankBinaryCascade(pixt1, 1, 1, 0, 0); pixCountPixels(pixt3, &count1, NULL); pixDestroy(&pixt1); pixDestroy(&pixt3); /* Filter the left-facing characters. */ pixt2 = pixFlipFHMTGen(NULL, pixt0, flipsel2); pixt3 = pixReduceRankBinaryCascade(pixt2, 1, 1, 0, 0); pixCountPixels(pixt3, &count2, NULL); pixDestroy(&pixt2); pixDestroy(&pixt3); pixDestroy(&pixt0); nright = (l_float32)count1; nleft = (l_float32)count2; nmax = L_MAX(count1, count2); if (nmax > mincount) *pconf = 2. * ((nright - nleft) / sqrt(nright + nleft)); if (debug) { fprintf(stderr, "nright = %f, nleft = %f\n", nright, nleft); if (*pconf > DEFAULT_MIN_MIRROR_FLIP_CONF) fprintf(stderr, "Text is not mirror reversed\n"); if (*pconf < -DEFAULT_MIN_MIRROR_FLIP_CONF) fprintf(stderr, "Text is mirror reversed\n"); } return 0; }
main(int argc, char **argv) { l_int32 i, ok, same; char sequence[512]; PIX *pixs, *pixref; PIX *pixt1, *pixt2, *pixt3, *pixt4, *pixt5, *pixt6; PIX *pixt7, *pixt8, *pixt9, *pixt10, *pixt11; PIX *pixt12, *pixt13, *pixt14; SEL *sel; static char mainName[] = "binmorph1_reg"; if (argc != 1) exit(ERROR_INT(" Syntax: binmorph1_reg", mainName, 1)); if ((pixs = pixRead("feyn.tif")) == NULL) exit(ERROR_INT("pix not made", mainName, 1)); #if TEST_SYMMETRIC /* This works properly if there is an added border */ resetMorphBoundaryCondition(SYMMETRIC_MORPH_BC); #if 1 pixt1 = pixAddBorder(pixs, 32, 0); pixTransferAllData(pixs, &pixt1, 0, 0); #endif #endif /* TEST_SYMMETRIC */ /* This is our test sel */ sel = selCreateBrick(HEIGHT, WIDTH, HEIGHT / 2, WIDTH / 2, SEL_HIT); /* Dilation */ fprintf(stderr, "Testing dilation\n"); ok = TRUE; pixref = pixDilate(NULL, pixs, sel); /* new one */ pixt1 = pixCreateTemplate(pixs); pixDilate(pixt1, pixs, sel); /* existing one */ pixEqual(pixref, pixt1, &same); if (!same) { fprintf(stderr, "pixref != pixt1 !\n"); ok = FALSE; } pixt2 = pixCopy(NULL, pixs); pixDilate(pixt2, pixt2, sel); /* in-place */ pixEqual(pixref, pixt2, &same); if (!same) { fprintf(stderr, "pixref != pixt2 !\n"); ok = FALSE; } sprintf(sequence, "d%d.%d", WIDTH, HEIGHT); pixt3 = pixMorphSequence(pixs, sequence, 0); /* sequence, atomic */ pixEqual(pixref, pixt3, &same); if (!same) { fprintf(stderr, "pixref != pixt3 !\n"); ok = FALSE; } sprintf(sequence, "d%d.1 + d1.%d", WIDTH, HEIGHT); pixt4 = pixMorphSequence(pixs, sequence, 0); /* sequence, separable */ pixEqual(pixref, pixt4, &same); if (!same) { fprintf(stderr, "pixref != pixt4 !\n"); ok = FALSE; } pixt5 = pixDilateBrick(NULL, pixs, WIDTH, HEIGHT); /* new one */ pixEqual(pixref, pixt5, &same); if (!same) { fprintf(stderr, "pixref != pixt5 !\n"); ok = FALSE; } pixt6 = pixCreateTemplate(pixs); pixDilateBrick(pixt6, pixs, WIDTH, HEIGHT); /* existing one */ pixEqual(pixref, pixt6, &same); if (!same) { fprintf(stderr, "pixref != pixt6 !\n"); ok = FALSE; } pixt7 = pixCopy(NULL, pixs); pixDilateBrick(pixt7, pixt7, WIDTH, HEIGHT); /* in-place */ pixEqual(pixref, pixt7, &same); if (!same) { fprintf(stderr, "pixref != pixt7 !\n"); ok = FALSE; } pixt8 = pixDilateBrickDwa(NULL, pixs, WIDTH, HEIGHT); /* new one */ pixEqual(pixref, pixt8, &same); if (!same) { fprintf(stderr, "pixref != pixt8 !\n"); ok = FALSE; } pixt9 = pixCreateTemplate(pixs); pixDilateBrickDwa(pixt9, pixs, WIDTH, HEIGHT); /* existing one */ pixEqual(pixref, pixt9, &same); if (!same) { fprintf(stderr, "pixref != pixt9 !\n"); ok = FALSE; } pixt10 = pixCopy(NULL, pixs); pixDilateBrickDwa(pixt10, pixt10, WIDTH, HEIGHT); /* in-place */ pixEqual(pixref, pixt10, &same); if (!same) { fprintf(stderr, "pixref != pixt10 !\n"); ok = FALSE; } pixt11 = pixCreateTemplate(pixs); pixDilateCompBrickDwa(pixt11, pixs, WIDTH, HEIGHT); /* existing one */ pixEqual(pixref, pixt11, &same); if (!same) { fprintf(stderr, "pixref != pixt11 !\n"); ok = FALSE; } sprintf(sequence, "d%d.%d", WIDTH, HEIGHT); pixt12 = pixMorphCompSequence(pixs, sequence, 0); /* comp sequence */ pixEqual(pixref, pixt12, &same); if (!same) { fprintf(stderr, "pixref != pixt12!\n"); ok = FALSE; } pixt13 = pixMorphSequenceDwa(pixs, sequence, 0); /* dwa sequence */ pixEqual(pixref, pixt13, &same); if (!same) { fprintf(stderr, "pixref != pixt13!\n"); ok = FALSE; } pixDestroy(&pixref); pixDestroy(&pixt1); pixDestroy(&pixt2); pixDestroy(&pixt3); pixDestroy(&pixt4); pixDestroy(&pixt5); pixDestroy(&pixt6); pixDestroy(&pixt7); pixDestroy(&pixt8); pixDestroy(&pixt9); pixDestroy(&pixt10); pixDestroy(&pixt11); pixDestroy(&pixt12); pixDestroy(&pixt13); /* Erosion */ fprintf(stderr, "Testing erosion\n"); pixref = pixErode(NULL, pixs, sel); /* new one */ pixt1 = pixCreateTemplate(pixs); pixErode(pixt1, pixs, sel); /* existing one */ pixEqual(pixref, pixt1, &same); if (!same) { fprintf(stderr, "pixref != pixt1 !\n"); ok = FALSE; } pixt2 = pixCopy(NULL, pixs); pixErode(pixt2, pixt2, sel); /* in-place */ pixEqual(pixref, pixt2, &same); if (!same) { fprintf(stderr, "pixref != pixt2 !\n"); ok = FALSE; } sprintf(sequence, "e%d.%d", WIDTH, HEIGHT); pixt3 = pixMorphSequence(pixs, sequence, 0); /* sequence, atomic */ pixEqual(pixref, pixt3, &same); if (!same) { fprintf(stderr, "pixref != pixt3 !\n"); ok = FALSE; } sprintf(sequence, "e%d.1 + e1.%d", WIDTH, HEIGHT); pixt4 = pixMorphSequence(pixs, sequence, 0); /* sequence, separable */ pixEqual(pixref, pixt4, &same); if (!same) { fprintf(stderr, "pixref != pixt4 !\n"); ok = FALSE; } pixt5 = pixErodeBrick(NULL, pixs, WIDTH, HEIGHT); /* new one */ pixEqual(pixref, pixt5, &same); if (!same) { fprintf(stderr, "pixref != pixt5 !\n"); ok = FALSE; } pixt6 = pixCreateTemplate(pixs); pixErodeBrick(pixt6, pixs, WIDTH, HEIGHT); /* existing one */ pixEqual(pixref, pixt6, &same); if (!same) { fprintf(stderr, "pixref != pixt6 !\n"); ok = FALSE; } pixt7 = pixCopy(NULL, pixs); pixErodeBrick(pixt7, pixt7, WIDTH, HEIGHT); /* in-place */ pixEqual(pixref, pixt7, &same); if (!same) { fprintf(stderr, "pixref != pixt7 !\n"); ok = FALSE; } pixt8 = pixErodeBrickDwa(NULL, pixs, WIDTH, HEIGHT); /* new one */ pixEqual(pixref, pixt8, &same); if (!same) { fprintf(stderr, "pixref != pixt8 !\n"); ok = FALSE; } pixt9 = pixCreateTemplate(pixs); pixErodeBrickDwa(pixt9, pixs, WIDTH, HEIGHT); /* existing one */ pixEqual(pixref, pixt9, &same); if (!same) { fprintf(stderr, "pixref != pixt9 !\n"); ok = FALSE; } pixt10 = pixCopy(NULL, pixs); pixErodeBrickDwa(pixt10, pixt10, WIDTH, HEIGHT); /* in-place */ pixEqual(pixref, pixt10, &same); if (!same) { fprintf(stderr, "pixref != pixt10 !\n"); ok = FALSE; } pixt11 = pixCreateTemplate(pixs); pixErodeCompBrickDwa(pixt11, pixs, WIDTH, HEIGHT); /* existing one */ pixEqual(pixref, pixt11, &same); if (!same) { fprintf(stderr, "pixref != pixt11 !\n"); ok = FALSE; } sprintf(sequence, "e%d.%d", WIDTH, HEIGHT); pixt12 = pixMorphCompSequence(pixs, sequence, 0); /* comp sequence */ pixEqual(pixref, pixt12, &same); if (!same) { fprintf(stderr, "pixref != pixt12!\n"); ok = FALSE; } pixt13 = pixMorphSequenceDwa(pixs, sequence, 0); /* dwa sequence */ pixEqual(pixref, pixt13, &same); if (!same) { fprintf(stderr, "pixref != pixt13!\n"); ok = FALSE; } pixDestroy(&pixref); pixDestroy(&pixt1); pixDestroy(&pixt2); pixDestroy(&pixt3); pixDestroy(&pixt4); pixDestroy(&pixt5); pixDestroy(&pixt6); pixDestroy(&pixt7); pixDestroy(&pixt8); pixDestroy(&pixt9); pixDestroy(&pixt10); pixDestroy(&pixt11); pixDestroy(&pixt12); pixDestroy(&pixt13); /* Opening */ fprintf(stderr, "Testing opening\n"); pixref = pixOpen(NULL, pixs, sel); /* new one */ pixt1 = pixCreateTemplate(pixs); pixOpen(pixt1, pixs, sel); /* existing one */ pixEqual(pixref, pixt1, &same); if (!same) { fprintf(stderr, "pixref != pixt1 !\n"); ok = FALSE; } pixt2 = pixCopy(NULL, pixs); pixOpen(pixt2, pixt2, sel); /* in-place */ pixEqual(pixref, pixt2, &same); if (!same) { fprintf(stderr, "pixref != pixt2 !\n"); ok = FALSE; } sprintf(sequence, "o%d.%d", WIDTH, HEIGHT); pixt3 = pixMorphSequence(pixs, sequence, 0); /* sequence, atomic */ pixEqual(pixref, pixt3, &same); if (!same) { fprintf(stderr, "pixref != pixt3 !\n"); ok = FALSE; } sprintf(sequence, "e%d.%d + d%d.%d", WIDTH, HEIGHT, WIDTH, HEIGHT); pixt4 = pixMorphSequence(pixs, sequence, 0); /* sequence, separable */ pixEqual(pixref, pixt4, &same); if (!same) { fprintf(stderr, "pixref != pixt4 !\n"); ok = FALSE; } sprintf(sequence, "e%d.1 + e1.%d + d%d.1 + d1.%d", WIDTH, HEIGHT, WIDTH, HEIGHT); pixt5 = pixMorphSequence(pixs, sequence, 0); /* sequence, separable^2 */ pixEqual(pixref, pixt5, &same); if (!same) { fprintf(stderr, "pixref != pixt5 !\n"); ok = FALSE; } pixt6 = pixOpenBrick(NULL, pixs, WIDTH, HEIGHT); /* new one */ pixEqual(pixref, pixt6, &same); if (!same) { fprintf(stderr, "pixref != pixt6 !\n"); ok = FALSE; } pixt7 = pixCreateTemplate(pixs); pixOpenBrick(pixt7, pixs, WIDTH, HEIGHT); /* existing one */ pixEqual(pixref, pixt7, &same); if (!same) { fprintf(stderr, "pixref != pixt7 !\n"); ok = FALSE; } pixt8 = pixCopy(NULL, pixs); /* in-place */ pixOpenBrick(pixt8, pixt8, WIDTH, HEIGHT); /* existing one */ pixEqual(pixref, pixt8, &same); if (!same) { fprintf(stderr, "pixref != pixt8 !\n"); ok = FALSE; } pixt9 = pixOpenBrickDwa(NULL, pixs, WIDTH, HEIGHT); /* new one */ pixEqual(pixref, pixt9, &same); if (!same) { fprintf(stderr, "pixref != pixt9 !\n"); ok = FALSE; } pixt10 = pixCreateTemplate(pixs); pixOpenBrickDwa(pixt10, pixs, WIDTH, HEIGHT); /* existing one */ pixEqual(pixref, pixt10, &same); if (!same) { fprintf(stderr, "pixref != pixt10 !\n"); ok = FALSE; } pixt11 = pixCopy(NULL, pixs); pixOpenBrickDwa(pixt11, pixt11, WIDTH, HEIGHT); /* in-place */ pixEqual(pixref, pixt11, &same); if (!same) { fprintf(stderr, "pixref != pixt11 !\n"); ok = FALSE; } sprintf(sequence, "o%d.%d", WIDTH, HEIGHT); pixt12 = pixMorphCompSequence(pixs, sequence, 0); /* comp sequence */ pixEqual(pixref, pixt12, &same); if (!same) { fprintf(stderr, "pixref != pixt12!\n"); ok = FALSE; } #if 0 pixWrite("/tmp/junkref.png", pixref, IFF_PNG); pixWrite("/tmp/junk12.png", pixt12, IFF_PNG); pixt13 = pixXor(NULL, pixref, pixt12); pixWrite("/tmp/junk12a.png", pixt13, IFF_PNG); pixDestroy(&pixt13); #endif pixt13 = pixMorphSequenceDwa(pixs, sequence, 0); /* dwa sequence */ pixEqual(pixref, pixt13, &same); if (!same) { fprintf(stderr, "pixref != pixt13!\n"); ok = FALSE; } pixt14 = pixCreateTemplate(pixs); pixOpenCompBrickDwa(pixt14, pixs, WIDTH, HEIGHT); /* existing one */ pixEqual(pixref, pixt14, &same); if (!same) { fprintf(stderr, "pixref != pixt14 !\n"); ok = FALSE; } pixDestroy(&pixref); pixDestroy(&pixt1); pixDestroy(&pixt2); pixDestroy(&pixt3); pixDestroy(&pixt4); pixDestroy(&pixt5); pixDestroy(&pixt6); pixDestroy(&pixt7); pixDestroy(&pixt8); pixDestroy(&pixt9); pixDestroy(&pixt10); pixDestroy(&pixt11); pixDestroy(&pixt12); pixDestroy(&pixt13); pixDestroy(&pixt14); /* Closing */ fprintf(stderr, "Testing closing\n"); pixref = pixClose(NULL, pixs, sel); /* new one */ pixt1 = pixCreateTemplate(pixs); pixClose(pixt1, pixs, sel); /* existing one */ pixEqual(pixref, pixt1, &same); if (!same) { fprintf(stderr, "pixref != pixt1 !\n"); ok = FALSE; } pixt2 = pixCopy(NULL, pixs); pixClose(pixt2, pixt2, sel); /* in-place */ pixEqual(pixref, pixt2, &same); if (!same) { fprintf(stderr, "pixref != pixt2 !\n"); ok = FALSE; } sprintf(sequence, "d%d.%d + e%d.%d", WIDTH, HEIGHT, WIDTH, HEIGHT); pixt3 = pixMorphSequence(pixs, sequence, 0); /* sequence, separable */ pixEqual(pixref, pixt3, &same); if (!same) { fprintf(stderr, "pixref != pixt3 !\n"); ok = FALSE; } sprintf(sequence, "d%d.1 + d1.%d + e%d.1 + e1.%d", WIDTH, HEIGHT, WIDTH, HEIGHT); pixt4 = pixMorphSequence(pixs, sequence, 0); /* sequence, separable^2 */ pixEqual(pixref, pixt4, &same); if (!same) { fprintf(stderr, "pixref != pixt4 !\n"); ok = FALSE; } pixt5 = pixCloseBrick(NULL, pixs, WIDTH, HEIGHT); /* new one */ pixEqual(pixref, pixt5, &same); if (!same) { fprintf(stderr, "pixref != pixt5 !\n"); ok = FALSE; } pixt6 = pixCreateTemplate(pixs); pixCloseBrick(pixt6, pixs, WIDTH, HEIGHT); /* existing one */ pixEqual(pixref, pixt6, &same); if (!same) { fprintf(stderr, "pixref != pixt6 !\n"); ok = FALSE; } pixt7 = pixCopy(NULL, pixs); /* in-place */ pixCloseBrick(pixt7, pixt7, WIDTH, HEIGHT); /* existing one */ pixEqual(pixref, pixt7, &same); if (!same) { fprintf(stderr, "pixref != pixt7 !\n"); ok = FALSE; } pixDestroy(&pixref); pixDestroy(&pixt1); pixDestroy(&pixt2); pixDestroy(&pixt3); pixDestroy(&pixt4); pixDestroy(&pixt5); pixDestroy(&pixt6); pixDestroy(&pixt7); /* Safe closing (using pix, not pixs) */ fprintf(stderr, "Testing safe closing\n"); pixref = pixCloseSafe(NULL, pixs, sel); /* new one */ pixt1 = pixCreateTemplate(pixs); pixCloseSafe(pixt1, pixs, sel); /* existing one */ pixEqual(pixref, pixt1, &same); if (!same) { fprintf(stderr, "pixref != pixt1 !\n"); ok = FALSE; } pixt2 = pixCopy(NULL, pixs); pixCloseSafe(pixt2, pixt2, sel); /* in-place */ pixEqual(pixref, pixt2, &same); if (!same) { fprintf(stderr, "pixref != pixt2 !\n"); ok = FALSE; } sprintf(sequence, "c%d.%d", WIDTH, HEIGHT); pixt3 = pixMorphSequence(pixs, sequence, 0); /* sequence, atomic */ pixEqual(pixref, pixt3, &same); if (!same) { fprintf(stderr, "pixref != pixt3 !\n"); ok = FALSE; } sprintf(sequence, "b32 + d%d.%d + e%d.%d", WIDTH, HEIGHT, WIDTH, HEIGHT); pixt4 = pixMorphSequence(pixs, sequence, 0); /* sequence, separable */ pixEqual(pixref, pixt4, &same); if (!same) { fprintf(stderr, "pixref != pixt4 !\n"); ok = FALSE; } sprintf(sequence, "b32 + d%d.1 + d1.%d + e%d.1 + e1.%d", WIDTH, HEIGHT, WIDTH, HEIGHT); pixt5 = pixMorphSequence(pixs, sequence, 0); /* sequence, separable^2 */ pixEqual(pixref, pixt5, &same); if (!same) { fprintf(stderr, "pixref != pixt5 !\n"); ok = FALSE; } pixt6 = pixCloseSafeBrick(NULL, pixs, WIDTH, HEIGHT); /* new one */ pixEqual(pixref, pixt6, &same); if (!same) { fprintf(stderr, "pixref != pixt6 !\n"); ok = FALSE; } pixt7 = pixCreateTemplate(pixs); pixCloseSafeBrick(pixt7, pixs, WIDTH, HEIGHT); /* existing one */ pixEqual(pixref, pixt7, &same); if (!same) { fprintf(stderr, "pixref != pixt7 !\n"); ok = FALSE; } pixt8 = pixCopy(NULL, pixs); /* in-place */ pixCloseSafeBrick(pixt8, pixt8, WIDTH, HEIGHT); /* existing one */ pixEqual(pixref, pixt8, &same); if (!same) { fprintf(stderr, "pixref != pixt8 !\n"); ok = FALSE; } pixt9 = pixCloseBrickDwa(NULL, pixs, WIDTH, HEIGHT); /* new one */ pixEqual(pixref, pixt9, &same); if (!same) { fprintf(stderr, "pixref != pixt9 !\n"); ok = FALSE; } pixt10 = pixCreateTemplate(pixs); pixCloseBrickDwa(pixt10, pixs, WIDTH, HEIGHT); /* existing one */ pixEqual(pixref, pixt10, &same); if (!same) { fprintf(stderr, "pixref != pixt10 !\n"); ok = FALSE; } pixt11 = pixCopy(NULL, pixs); pixCloseBrickDwa(pixt11, pixt11, WIDTH, HEIGHT); /* in-place */ pixEqual(pixref, pixt11, &same); if (!same) { fprintf(stderr, "pixref != pixt11 !\n"); ok = FALSE; } sprintf(sequence, "c%d.%d", WIDTH, HEIGHT); pixt12 = pixMorphCompSequence(pixs, sequence, 0); /* comp sequence */ pixEqual(pixref, pixt12, &same); if (!same) { fprintf(stderr, "pixref != pixt12!\n"); ok = FALSE; } pixt13 = pixMorphSequenceDwa(pixs, sequence, 0); /* dwa sequence */ pixEqual(pixref, pixt13, &same); if (!same) { fprintf(stderr, "pixref != pixt13!\n"); ok = FALSE; } pixt14 = pixCreateTemplate(pixs); pixCloseCompBrickDwa(pixt14, pixs, WIDTH, HEIGHT); /* existing one */ pixEqual(pixref, pixt14, &same); if (!same) { fprintf(stderr, "pixref != pixt14 !\n"); ok = FALSE; } #if 0 pixWrite("/tmp/junkref.png", pixref, IFF_PNG); pixWrite("/tmp/junk12.png", pixt12, IFF_PNG); pixt13 = pixXor(NULL, pixref, pixt12); pixWrite("/tmp/junk12a.png", pixt13, IFF_PNG); pixDestroy(&pixt13); #endif pixDestroy(&pixref); pixDestroy(&pixt1); pixDestroy(&pixt2); pixDestroy(&pixt3); pixDestroy(&pixt4); pixDestroy(&pixt5); pixDestroy(&pixt6); pixDestroy(&pixt7); pixDestroy(&pixt8); pixDestroy(&pixt9); pixDestroy(&pixt10); pixDestroy(&pixt11); pixDestroy(&pixt12); pixDestroy(&pixt13); pixDestroy(&pixt14); if (ok) fprintf(stderr, "All morph tests OK!\n"); pixDestroy(&pixs); selDestroy(&sel); exit(0); }
/*! * pixUpDownDetectGeneralDwa() * * Input: pixs (1 bpp, deskewed, English text) * &conf (<return> confidence that text is rightside-up) * mincount (min number of up + down; use 0 for default) * npixels (number of pixels removed from each side of word box) * debug (1 for debug output; 0 otherwise) * Return: 0 if OK, 1 on error * * Notes: * (1) See the notes in pixUpDownDetectGeneral() for usage. */ l_int32 pixUpDownDetectGeneralDwa(PIX *pixs, l_float32 *pconf, l_int32 mincount, l_int32 npixels, l_int32 debug) { char flipsel1[] = "flipsel1"; char flipsel2[] = "flipsel2"; char flipsel3[] = "flipsel3"; char flipsel4[] = "flipsel4"; l_int32 countup, countdown, nmax; l_float32 nup, ndown; PIX *pixt, *pixt0, *pixt1, *pixt2, *pixt3, *pixm; PROCNAME("pixUpDownDetectGeneralDwa"); if (!pconf) return ERROR_INT("&conf not defined", procName, 1); *pconf = 0.0; if (!pixs) return ERROR_INT("pixs not defined", procName, 1); if (mincount == 0) mincount = DEFAULT_MIN_UP_DOWN_COUNT; if (npixels < 0) npixels = 0; /* One of many reasonable pre-filtering sequences: (1, 8) and (30, 1). * This closes holes in x-height characters and joins them at * the x-height. There is more noise in the descender detection * from this, but it works fairly well. */ pixt = pixMorphSequenceDwa(pixs, "c1.8 + c30.1", 0); /* Be sure to add the border before the flip DWA operations! */ pixt0 = pixAddBorderGeneral(pixt, ADDED_BORDER, ADDED_BORDER, ADDED_BORDER, ADDED_BORDER, 0); pixDestroy(&pixt); /* Optionally, make a mask of the word bounding boxes, shortening * each of them by a fixed amount at each end. */ pixm = NULL; if (npixels > 0) { l_int32 i, nbox, x, y, w, h; BOX *box; BOXA *boxa; pixt1 = pixMorphSequenceDwa(pixt0, "o10.1", 0); boxa = pixConnComp(pixt1, NULL, 8); pixm = pixCreateTemplate(pixt1); pixDestroy(&pixt1); nbox = boxaGetCount(boxa); for (i = 0; i < nbox; i++) { box = boxaGetBox(boxa, i, L_CLONE); boxGetGeometry(box, &x, &y, &w, &h); if (w > 2 * npixels) pixRasterop(pixm, x + npixels, y - 6, w - 2 * npixels, h + 13, PIX_SET, NULL, 0, 0); boxDestroy(&box); } boxaDestroy(&boxa); } /* Find the ascenders and optionally filter with pixm. * For an explanation of the procedure used for counting the result * of the HMT, see comments in pixUpDownDetectGeneral(). */ pixt1 = pixFlipFHMTGen(NULL, pixt0, flipsel1); pixt2 = pixFlipFHMTGen(NULL, pixt0, flipsel2); pixOr(pixt1, pixt1, pixt2); if (pixm) pixAnd(pixt1, pixt1, pixm); pixt3 = pixReduceRankBinaryCascade(pixt1, 1, 1, 0, 0); pixCountPixels(pixt3, &countup, NULL); pixDestroy(&pixt1); pixDestroy(&pixt2); pixDestroy(&pixt3); /* Find the ascenders and optionally filter with pixm. */ pixt1 = pixFlipFHMTGen(NULL, pixt0, flipsel3); pixt2 = pixFlipFHMTGen(NULL, pixt0, flipsel4); pixOr(pixt1, pixt1, pixt2); if (pixm) pixAnd(pixt1, pixt1, pixm); pixt3 = pixReduceRankBinaryCascade(pixt1, 1, 1, 0, 0); pixCountPixels(pixt3, &countdown, NULL); pixDestroy(&pixt1); pixDestroy(&pixt2); pixDestroy(&pixt3); /* Evaluate statistically, generating a confidence that is * related to the probability with a gaussian distribution. */ nup = (l_float32)(countup); ndown = (l_float32)(countdown); nmax = L_MAX(countup, countdown); if (nmax > mincount) *pconf = 2. * ((nup - ndown) / sqrt(nup + ndown)); if (debug) { if (pixm) pixWrite("junkpixm2", pixm, IFF_PNG); fprintf(stderr, "nup = %7.3f, ndown = %7.3f, conf = %7.3f\n", nup, ndown, *pconf); if (*pconf > DEFAULT_MIN_UP_DOWN_CONF) fprintf(stderr, "Text is rightside-up\n"); if (*pconf < -DEFAULT_MIN_UP_DOWN_CONF) fprintf(stderr, "Text is upside-down\n"); } pixDestroy(&pixt0); pixDestroy(&pixm); return 0; }