293 l_float32 *pleftconf,
298l_float32 upconf, leftconf;
301 if (!pixs || pixGetDepth(pixs) != 1)
302 return (
PIX *)ERROR_PTR(
"pixs undefined or not 1 bpp", __func__, NULL);
306 pix1 = pixRotate90(pixs, 1);
309 if (pupconf) *pupconf = upconf;
310 if (pleftconf) *pleftconf = leftconf;
319 L_INFO(
"text orientation not determined; no rotation\n", __func__);
320 if (protation) *protation = 0;
321 return pixCopy(NULL, pixs);
324 L_INFO(
"text is oriented up; no rotation\n", __func__);
325 if (protation) *protation = 0;
326 return pixCopy(NULL, pixs);
329 L_INFO(
"landscape; text oriented left; 90 cw rotation\n", __func__);
330 if (protation) *protation = 90;
331 return pixRotateOrth(pixs, 1);
334 L_INFO(
"text oriented down; 180 cw rotation\n", __func__);
335 if (protation) *protation = 180;
336 return pixRotateOrth(pixs, 2);
339 L_INFO(
"landscape; text oriented right; 270 cw rotation\n", __func__);
340 if (protation) *protation = 270;
341 return pixRotateOrth(pixs, 3);
344 L_ERROR(
"invalid orient flag!\n", __func__);
345 return pixCopy(NULL, pixs);
483l_float32 absupconf, absleftconf;
486 return ERROR_INT(
"&orient not defined", __func__, 1);
488 if (upconf == 0.0 || leftconf == 0.0) {
489 L_INFO(
"not enough confidence to get orientation\n", __func__);
493 if (minupconf == 0.0)
494 minupconf = DefaultMinUpDownConf;
496 minratio = DefaultMinUpDownRatio;
497 absupconf = L_ABS(upconf);
498 absleftconf = L_ABS(leftconf);
502 if (upconf > minupconf && absupconf > minratio * absleftconf)
504 else if (leftconf > minupconf && absleftconf > minratio * absupconf)
506 else if (upconf < -minupconf && absupconf > minratio * absleftconf)
508 else if (leftconf < -minupconf && absleftconf > minratio * absupconf)
512 lept_stderr(
"upconf = %7.3f, leftconf = %7.3f\n", upconf, leftconf);
514 lept_stderr(
"Confidence is low; no determination is made\n");
516 lept_stderr(
"Text is rightside-up\n");
518 lept_stderr(
"Text is rotated 90 deg ccw\n");
520 lept_stderr(
"Text is upside-down\n");
522 lept_stderr(
"Text is rotated 90 deg cw\n");
575l_int32 countup, countdown, nmax;
577PIX *pix0, *pix1, *pix2, *pix3, *pixm;
578SEL *sel1, *sel2, *sel3, *sel4;
581 return ERROR_INT(
"&conf not defined", __func__, 1);
583 if (!pixs || pixGetDepth(pixs) != 1)
584 return ERROR_INT(
"pixs not defined or not 1 bpp", __func__, 1);
586 mincount = DefaultMinUpDownCount;
591 lept_mkdir(
"lept/orient");
594 sel1 = selCreateFromString(textsel1, 5, 6, NULL);
595 sel2 = selCreateFromString(textsel2, 5, 6, NULL);
596 sel3 = selCreateFromString(textsel3, 5, 6, NULL);
597 sel4 = selCreateFromString(textsel4, 5, 6, NULL);
603 pix0 = pixMorphCompSequence(pixs,
"c1.8 + c30.1", 0);
609 l_int32 i, nbox, x, y, w, h;
612 pix1 = pixMorphSequence(pix0,
"o10.1", 0);
613 boxa = pixConnComp(pix1, NULL, 8);
614 pixm = pixCreateTemplate(pix1);
616 nbox = boxaGetCount(boxa);
617 for (i = 0; i < nbox; i++) {
618 box = boxaGetBox(boxa, i,
L_CLONE);
619 boxGetGeometry(box, &x, &y, &w, &h);
621 pixRasterop(pixm, x + npixels, y - 6, w - 2 * npixels, h + 13,
631 pix1 = pixHMT(NULL, pix0, sel1);
632 pix2 = pixHMT(NULL, pix0, sel2);
633 pixOr(pix1, pix1, pix2);
635 pixAnd(pix1, pix1, pixm);
636 pix3 = pixReduceRankBinaryCascade(pix1, 1, 1, 0, 0);
637 pixCountPixels(pix3, &countup, NULL);
638 pixDebugFlipDetect(
"/tmp/lept/orient/up.png", pixs, pix1, debug);
644 pix1 = pixHMT(NULL, pix0, sel3);
645 pix2 = pixHMT(NULL, pix0, sel4);
646 pixOr(pix1, pix1, pix2);
648 pixAnd(pix1, pix1, pixm);
649 pix3 = pixReduceRankBinaryCascade(pix1, 1, 1, 0, 0);
650 pixCountPixels(pix3, &countdown, NULL);
651 pixDebugFlipDetect(
"/tmp/lept/orient/down.png", pixs, pix1, debug);
658 nup = (l_float32)(countup);
659 ndown = (l_float32)(countdown);
660 nmax = L_MAX(countup, countdown);
662 *pconf = 2. * ((nup - ndown) / sqrt(nup + ndown));
665 if (pixm) pixWriteDebug(
"/tmp/lept/orient/pixm1.png", pixm, IFF_PNG);
666 lept_stderr(
"nup = %7.3f, ndown = %7.3f, conf = %7.3f\n",
668 if (*pconf > DefaultMinUpDownConf)
669 lept_stderr(
"Text is rightside-up\n");
670 if (*pconf < -DefaultMinUpDownConf)
671 lept_stderr(
"Text is upside-down\n");
733l_int32 count1, count2, nmax;
734l_float32 nleft, nright;
735PIX *pix0, *pix1, *pix2, *pix3;
739 return ERROR_INT(
"&conf not defined", __func__, 1);
741 if (!pixs || pixGetDepth(pixs) != 1)
742 return ERROR_INT(
"pixs not defined or not 1 bpp", __func__, 1);
744 mincount = DefaultMinMirrorFlipCount;
747 lept_mkdir(
"lept/orient");
750 sel1 = selCreateFromString(textsel1, 5, 6, NULL);
751 sel2 = selCreateFromString(textsel2, 5, 6, NULL);
754 pix3 = pixMorphCompSequence(pixs,
"d1.30", 0);
755 pixXor(pix3, pix3, pixs);
756 pix0 = pixMorphCompSequence(pixs,
"c15.1", 0);
757 pixXor(pix0, pix0, pixs);
758 pixAnd(pix0, pix0, pix3);
759 pixOr(pix0, pix0, pixs);
763 pix1 = pixHMT(NULL, pix0, sel1);
764 pix3 = pixReduceRankBinaryCascade(pix1, 1, 1, 0, 0);
765 pixCountPixels(pix3, &count1, NULL);
766 pixDebugFlipDetect(
"/tmp/lept/orient/right.png", pixs, pix1, debug);
771 pix2 = pixHMT(NULL, pix0, sel2);
772 pix3 = pixReduceRankBinaryCascade(pix2, 1, 1, 0, 0);
773 pixCountPixels(pix3, &count2, NULL);
774 pixDebugFlipDetect(
"/tmp/lept/orient/left.png", pixs, pix2, debug);
778 nright = (l_float32)count1;
779 nleft = (l_float32)count2;
780 nmax = L_MAX(count1, count2);
786 *pconf = 2. * ((nright - nleft) / sqrt(nright + nleft));
789 lept_stderr(
"nright = %f, nleft = %f\n", nright, nleft);
790 if (*pconf > DefaultMinMirrorFlipConf)
791 lept_stderr(
"Text is not mirror reversed\n");
792 if (*pconf < -DefaultMinMirrorFlipConf)
793 lept_stderr(
"Text is mirror reversed\n");