278 l_float32 *pleftconf,
283l_float32 upconf, leftconf;
286 if (!pixs || pixGetDepth(pixs) != 1)
287 return (
PIX *)ERROR_PTR(
"pixs undefined or not 1 bpp", __func__, NULL);
291 pix1 = pixRotate90(pixs, 1);
294 if (pupconf) *pupconf = upconf;
295 if (pleftconf) *pleftconf = leftconf;
304 L_INFO(
"text orientation not determined; no rotation\n", __func__);
305 if (protation) *protation = 0;
306 return pixCopy(NULL, pixs);
309 L_INFO(
"text is oriented up; no rotation\n", __func__);
310 if (protation) *protation = 0;
311 return pixCopy(NULL, pixs);
314 L_INFO(
"landscape; text oriented left; 90 cw rotation\n", __func__);
315 if (protation) *protation = 90;
316 return pixRotateOrth(pixs, 1);
319 L_INFO(
"text oriented down; 180 cw rotation\n", __func__);
320 if (protation) *protation = 180;
321 return pixRotateOrth(pixs, 2);
324 L_INFO(
"landscape; text oriented right; 270 cw rotation\n", __func__);
325 if (protation) *protation = 270;
326 return pixRotateOrth(pixs, 3);
329 L_ERROR(
"invalid orient flag!\n", __func__);
330 return pixCopy(NULL, pixs);
467l_float32 absupconf, absleftconf;
470 return ERROR_INT(
"&orient not defined", __func__, 1);
472 if (upconf == 0.0 || leftconf == 0.0) {
473 L_INFO(
"not enough confidence to get orientation\n", __func__);
477 if (minupconf == 0.0)
478 minupconf = DefaultMinUpDownConf;
480 minratio = DefaultMinUpDownRatio;
481 absupconf = L_ABS(upconf);
482 absleftconf = L_ABS(leftconf);
486 if (upconf > minupconf && absupconf > minratio * absleftconf)
488 else if (leftconf > minupconf && absleftconf > minratio * absupconf)
490 else if (upconf < -minupconf && absupconf > minratio * absleftconf)
492 else if (leftconf < -minupconf && absleftconf > minratio * absupconf)
496 lept_stderr(
"upconf = %7.3f, leftconf = %7.3f\n", upconf, leftconf);
498 lept_stderr(
"Confidence is low; no determination is made\n");
500 lept_stderr(
"Text is rightside-up\n");
502 lept_stderr(
"Text is rotated 90 deg ccw\n");
504 lept_stderr(
"Text is upside-down\n");
506 lept_stderr(
"Text is rotated 90 deg cw\n");
558l_int32 countup, countdown, nmax;
560PIX *pix0, *pix1, *pix2, *pix3, *pixm;
561SEL *sel1, *sel2, *sel3, *sel4;
564 return ERROR_INT(
"&conf not defined", __func__, 1);
566 if (!pixs || pixGetDepth(pixs) != 1)
567 return ERROR_INT(
"pixs not defined or not 1 bpp", __func__, 1);
569 mincount = DefaultMinUpDownCount;
574 lept_mkdir(
"lept/orient");
577 sel1 = selCreateFromString(textsel1, 5, 6, NULL);
578 sel2 = selCreateFromString(textsel2, 5, 6, NULL);
579 sel3 = selCreateFromString(textsel3, 5, 6, NULL);
580 sel4 = selCreateFromString(textsel4, 5, 6, NULL);
586 pix0 = pixMorphCompSequence(pixs,
"c1.8 + c30.1", 0);
592 l_int32 i, nbox, x, y, w, h;
595 pix1 = pixMorphSequence(pix0,
"o10.1", 0);
596 boxa = pixConnComp(pix1, NULL, 8);
597 pixm = pixCreateTemplate(pix1);
599 nbox = boxaGetCount(boxa);
600 for (i = 0; i < nbox; i++) {
601 box = boxaGetBox(boxa, i,
L_CLONE);
602 boxGetGeometry(box, &x, &y, &w, &h);
604 pixRasterop(pixm, x + npixels, y - 6, w - 2 * npixels, h + 13,
614 pix1 = pixHMT(NULL, pix0, sel1);
615 pix2 = pixHMT(NULL, pix0, sel2);
616 pixOr(pix1, pix1, pix2);
618 pixAnd(pix1, pix1, pixm);
619 pix3 = pixReduceRankBinaryCascade(pix1, 1, 1, 0, 0);
620 pixCountPixels(pix3, &countup, NULL);
621 pixDebugFlipDetect(
"/tmp/lept/orient/up.png", pixs, pix1, debug);
627 pix1 = pixHMT(NULL, pix0, sel3);
628 pix2 = pixHMT(NULL, pix0, sel4);
629 pixOr(pix1, pix1, pix2);
631 pixAnd(pix1, pix1, pixm);
632 pix3 = pixReduceRankBinaryCascade(pix1, 1, 1, 0, 0);
633 pixCountPixels(pix3, &countdown, NULL);
634 pixDebugFlipDetect(
"/tmp/lept/orient/down.png", pixs, pix1, debug);
641 nup = (l_float32)(countup);
642 ndown = (l_float32)(countdown);
643 nmax = L_MAX(countup, countdown);
645 *pconf = 2. * ((nup - ndown) / sqrt(nup + ndown));
648 if (pixm) pixWriteDebug(
"/tmp/lept/orient/pixm1.png", pixm, IFF_PNG);
649 lept_stderr(
"nup = %7.3f, ndown = %7.3f, conf = %7.3f\n",
651 if (*pconf > DefaultMinUpDownConf)
652 lept_stderr(
"Text is rightside-up\n");
653 if (*pconf < -DefaultMinUpDownConf)
654 lept_stderr(
"Text is upside-down\n");
715l_int32 count1, count2, nmax;
716l_float32 nleft, nright;
717PIX *pix0, *pix1, *pix2, *pix3;
721 return ERROR_INT(
"&conf not defined", __func__, 1);
723 if (!pixs || pixGetDepth(pixs) != 1)
724 return ERROR_INT(
"pixs not defined or not 1 bpp", __func__, 1);
726 mincount = DefaultMinMirrorFlipCount;
729 lept_mkdir(
"lept/orient");
732 sel1 = selCreateFromString(textsel1, 5, 6, NULL);
733 sel2 = selCreateFromString(textsel2, 5, 6, NULL);
736 pix3 = pixMorphCompSequence(pixs,
"d1.30", 0);
737 pixXor(pix3, pix3, pixs);
738 pix0 = pixMorphCompSequence(pixs,
"c15.1", 0);
739 pixXor(pix0, pix0, pixs);
740 pixAnd(pix0, pix0, pix3);
741 pixOr(pix0, pix0, pixs);
745 pix1 = pixHMT(NULL, pix0, sel1);
746 pix3 = pixReduceRankBinaryCascade(pix1, 1, 1, 0, 0);
747 pixCountPixels(pix3, &count1, NULL);
748 pixDebugFlipDetect(
"/tmp/lept/orient/right.png", pixs, pix1, debug);
753 pix2 = pixHMT(NULL, pix0, sel2);
754 pix3 = pixReduceRankBinaryCascade(pix2, 1, 1, 0, 0);
755 pixCountPixels(pix3, &count2, NULL);
756 pixDebugFlipDetect(
"/tmp/lept/orient/left.png", pixs, pix2, debug);
760 nright = (l_float32)count1;
761 nleft = (l_float32)count2;
762 nmax = L_MAX(count1, count2);
768 *pconf = 2. * ((nright - nleft) / sqrt(nright + nleft));
771 lept_stderr(
"nright = %f, nleft = %f\n", nright, nleft);
772 if (*pconf > DefaultMinMirrorFlipConf)
773 lept_stderr(
"Text is not mirror reversed\n");
774 if (*pconf < -DefaultMinMirrorFlipConf)
775 lept_stderr(
"Text is mirror reversed\n");