99 #include <config_auto.h> 103 #include "allheaders.h" 106 static const l_float32 DefaultSweepRange = 7.0;
107 static const l_float32 DefaultSweepDelta = 1.0;
113 static const l_float32 DefaultMinbsDelta = 0.01;
116 static const l_int32 DefaultSweepReduction = 4;
117 static const l_int32 DefaultBsReduction = 2;
120 static const l_float32 MinDeskewAngle = 0.1;
123 static const l_float32 MinAllowedConfidence = 3.0;
126 static const l_int32 MinValidMaxscore = 10000;
131 static const l_float32 MinscoreThreshFactor = 0.000002;
134 static const l_int32 DefaultBinaryThreshold = 130;
136 #ifndef NO_CONSOLE_IO 137 #define DEBUG_PRINT_SCORES 0 138 #define DEBUG_PRINT_SWEEP 0 139 #define DEBUG_PRINT_BINARY 0 140 #define DEBUG_PRINT_ORTH 0 141 #define DEBUG_THRESHOLD 0 142 #define DEBUG_PLOT_SCORES 0 170 PIX *pix1, *pix2, *pix3, *pix4;
172 PROCNAME(
"pixDeskewBoth");
175 return (
PIX *)ERROR_PTR(
"pixs not defined", procName, NULL);
177 redsearch = DefaultBsReduction;
178 else if (redsearch != 1 && redsearch != 2 && redsearch != 4)
179 return (
PIX *)ERROR_PTR(
"redsearch not in {1,2,4}", procName, NULL);
213 PROCNAME(
"pixDeskew");
216 return (
PIX *)ERROR_PTR(
"pixs not defined", procName, NULL);
218 redsearch = DefaultBsReduction;
219 else if (redsearch != 1 && redsearch != 2 && redsearch != 4)
220 return (
PIX *)ERROR_PTR(
"redsearch not in {1,2,4}", procName, NULL);
251 PROCNAME(
"pixFindSkewAndDeskew");
254 return (
PIX *)ERROR_PTR(
"pixs not defined", procName, NULL);
256 redsearch = DefaultBsReduction;
257 else if (redsearch != 1 && redsearch != 2 && redsearch != 4)
258 return (
PIX *)ERROR_PTR(
"redsearch not in {1,2,4}", procName, NULL);
292 l_float32 sweeprange,
293 l_float32 sweepdelta,
300 l_float32 angle, conf, deg2rad;
303 PROCNAME(
"pixDeskewGeneral");
305 if (pangle) *pangle = 0.0;
306 if (pconf) *pconf = 0.0;
308 return (
PIX *)ERROR_PTR(
"pixs not defined", procName, NULL);
310 redsweep = DefaultSweepReduction;
311 else if (redsweep != 1 && redsweep != 2 && redsweep != 4)
312 return (
PIX *)ERROR_PTR(
"redsweep not in {1,2,4}", procName, NULL);
313 if (sweeprange == 0.0)
314 sweeprange = DefaultSweepRange;
315 if (sweepdelta == 0.0)
316 sweepdelta = DefaultSweepDelta;
318 redsearch = DefaultBsReduction;
319 else if (redsearch != 1 && redsearch != 2 && redsearch != 4)
320 return (
PIX *)ERROR_PTR(
"redsearch not in {1,2,4}", procName, NULL);
322 thresh = DefaultBinaryThreshold;
324 deg2rad = 3.1415926535 / 180.;
327 depth = pixGetDepth(pixs);
335 sweeprange, sweepdelta,
338 if (pangle) *pangle = angle;
339 if (pconf) *pconf = conf;
343 if (L_ABS(angle) < MinDeskewAngle || conf < MinAllowedConfidence)
379 PROCNAME(
"pixFindSkew");
381 if (pangle) *pangle = 0.0;
382 if (pconf) *pconf = 0.0;
383 if (!pangle || !pconf)
384 return ERROR_INT(
"&angle and/or &conf not defined", procName, 1);
386 return ERROR_INT(
"pixs not defined", procName, 1);
387 if (pixGetDepth(pixs) != 1)
388 return ERROR_INT(
"pixs not 1 bpp", procName, 1);
391 DefaultSweepReduction,
422 l_float32 sweeprange,
423 l_float32 sweepdelta)
425 l_int32 ret, bzero, i, nangles;
426 l_float32 deg2rad, theta;
427 l_float32 sum, maxscore, maxangle;
428 NUMA *natheta, *nascore;
431 PROCNAME(
"pixFindSkewSweep");
434 return ERROR_INT(
"&angle not defined", procName, 1);
437 return ERROR_INT(
"pixs not defined", procName, 1);
438 if (pixGetDepth(pixs) != 1)
439 return ERROR_INT(
"pixs not 1 bpp", procName, 1);
440 if (reduction != 1 && reduction != 2 && reduction != 4 && reduction != 8)
441 return ERROR_INT(
"reduction must be in {1,2,4,8}", procName, 1);
443 deg2rad = 3.1415926535 / 180.;
449 else if (reduction == 2)
451 else if (reduction == 4)
462 nangles = (l_int32)((2. * sweeprange) / sweepdelta + 1);
468 ret = ERROR_INT(
"pix and pixt not both made", procName, 1);
471 if (!natheta || !nascore) {
472 ret = ERROR_INT(
"natheta and nascore not both made", procName, 1);
476 for (i = 0; i < nangles; i++) {
477 theta = -sweeprange + i * sweepdelta;
485 #if DEBUG_PRINT_SCORES 486 L_INFO(
"sum(%7.2f) = %7.0f\n", procName, theta, sum);
497 numaFitMax(nascore, &maxscore, natheta, &maxangle);
500 #if DEBUG_PRINT_SWEEP 501 L_INFO(
" From sweep: angle = %7.3f, score = %7.3f\n", procName,
505 #if DEBUG_PLOT_SCORES 516 "Sweep. Variance of difference of ON pixels vs. angle",
517 "angle (deg)",
"score");
518 gplotAddPlot(gplot, natheta, nascore, GPLOT_LINES,
"plot1");
519 gplotAddPlot(gplot, natheta, nascore, GPLOT_POINTS,
"plot2");
568 l_float32 sweeprange,
569 l_float32 sweepdelta,
570 l_float32 minbsdelta)
573 redsweep, redsearch, 0.0, sweeprange,
574 sweepdelta, minbsdelta);
620 l_float32 *pendscore,
623 l_float32 sweepcenter,
624 l_float32 sweeprange,
625 l_float32 sweepdelta,
626 l_float32 minbsdelta)
629 redsweep, redsearch, 0.0,
630 sweeprange, sweepdelta,
669 l_float32 *pendscore,
672 l_float32 sweepcenter,
673 l_float32 sweeprange,
674 l_float32 sweepdelta,
675 l_float32 minbsdelta,
678 l_int32 ret, bzero, i, nangles, n, ratio, maxindex, minloc;
679 l_int32 width, height;
680 l_float32 deg2rad, theta, delta;
681 l_float32 sum, maxscore, maxangle;
682 l_float32 centerangle, leftcenterangle, rightcenterangle;
683 l_float32 lefttemp, righttemp;
684 l_float32 bsearchscore[5];
685 l_float32 minscore, minthresh;
687 NUMA *natheta, *nascore;
688 PIX *pixsw, *pixsch, *pixt1, *pixt2;
690 PROCNAME(
"pixFindSkewSweepAndSearchScorePivot");
692 if (pendscore) *pendscore = 0.0;
693 if (pangle) *pangle = 0.0;
694 if (pconf) *pconf = 0.0;
695 if (!pangle || !pconf)
696 return ERROR_INT(
"&angle and/or &conf not defined", procName, 1);
697 if (!pixs || pixGetDepth(pixs) != 1)
698 return ERROR_INT(
"pixs not defined or not 1 bpp", procName, 1);
699 if (redsweep != 1 && redsweep != 2 && redsweep != 4 && redsweep != 8)
700 return ERROR_INT(
"redsweep must be in {1,2,4,8}", procName, 1);
701 if (redsearch != 1 && redsearch != 2 && redsearch != 4 && redsearch != 8)
702 return ERROR_INT(
"redsearch must be in {1,2,4,8}", procName, 1);
703 if (redsearch > redsweep)
704 return ERROR_INT(
"redsearch must not exceed redsweep", procName, 1);
706 return ERROR_INT(
"invalid pivot", procName, 1);
708 deg2rad = 3.1415926535 / 180.;
714 else if (redsearch == 2)
716 else if (redsearch == 4)
728 ratio = redsweep / redsearch;
746 nangles = (l_int32)((2. * sweeprange) / sweepdelta + 1);
750 if (!pixsch || !pixsw) {
751 ret = ERROR_INT(
"pixsch and pixsw not both made", procName, 1);
754 if (!pixt1 || !pixt2) {
755 ret = ERROR_INT(
"pixt1 and pixt2 not both made", procName, 1);
758 if (!natheta || !nascore) {
759 ret = ERROR_INT(
"natheta and nascore not both made", procName, 1);
764 rangeleft = sweepcenter - sweeprange;
765 for (i = 0; i < nangles; i++) {
766 theta = rangeleft + i * sweepdelta;
777 #if DEBUG_PRINT_SCORES 778 L_INFO(
"sum(%7.2f) = %7.0f\n", procName, theta, sum);
790 #if DEBUG_PRINT_SWEEP 791 L_INFO(
" From sweep: angle = %7.3f, score = %7.3f\n", procName,
795 #if DEBUG_PLOT_SCORES 800 "Sweep. Variance of difference of ON pixels vs. angle",
801 "angle (deg)",
"score");
802 gplotAddPlot(gplot, natheta, nascore, GPLOT_LINES,
"plot1");
803 gplotAddPlot(gplot, natheta, nascore, GPLOT_POINTS,
"plot2");
811 if (maxindex == 0 || maxindex == n - 1) {
812 L_WARNING(
"max found at sweep edge\n", procName);
822 centerangle = maxangle;
851 delta = 0.5 * sweepdelta;
852 while (delta >= minbsdelta)
855 leftcenterangle = centerangle - delta;
867 rightcenterangle = centerangle + delta;
881 maxscore = bsearchscore[1];
883 for (i = 2; i < 4; i++) {
884 if (bsearchscore[i] > maxscore) {
885 maxscore = bsearchscore[i];
891 lefttemp = bsearchscore[maxindex - 1];
892 righttemp = bsearchscore[maxindex + 1];
893 bsearchscore[2] = maxscore;
894 bsearchscore[0] = lefttemp;
895 bsearchscore[4] = righttemp;
898 centerangle = centerangle + delta * (maxindex - 2);
901 *pangle = centerangle;
903 #if DEBUG_PRINT_SCORES 904 L_INFO(
" Binary search score = %7.3f\n", procName, bsearchscore[2]);
908 *pendscore = bsearchscore[2];
922 width = pixGetWidth(pixsch);
923 height = pixGetHeight(pixsch);
924 minthresh = MinscoreThreshFactor * width * width * height;
927 L_INFO(
" minthresh = %10.2f, minscore = %10.2f\n", procName,
928 minthresh, minscore);
929 L_INFO(
" maxscore = %10.2f\n", procName, maxscore);
932 if (minscore > minthresh)
933 *pconf = maxscore / minscore;
939 if ((centerangle > rangeleft + 2 * sweeprange - sweepdelta) ||
940 (centerangle < rangeleft + sweepdelta) ||
941 (maxscore < MinValidMaxscore))
944 #if DEBUG_PRINT_BINARY 945 lept_stderr(
"Binary search: angle = %7.3f, score ratio = %6.2f\n",
950 #if DEBUG_PLOT_SCORES 957 "Binary search. Variance of difference of ON pixels vs. angle",
958 "angle (deg)",
"score");
959 gplotAddPlot(gplot, natheta, nascore, GPLOT_POINTS,
"plot1");
1039 pixFindSkewOrthogonalRange(
PIX *pixs,
1044 l_float32 sweeprange,
1045 l_float32 sweepdelta,
1046 l_float32 minbsdelta,
1047 l_float32 confprior)
1049 l_float32 angle1, conf1, score1, angle2, conf2, score2;
1052 PROCNAME(
"pixFindSkewOrthogonalRange");
1054 if (pangle) *pangle = 0.0;
1055 if (pconf) *pconf = 0.0;
1056 if (!pangle || !pconf)
1057 return ERROR_INT(
"&angle and/or &conf not defined", procName, 1);
1058 if (!pixs || pixGetDepth(pixs) != 1)
1059 return ERROR_INT(
"pixs not defined or not 1 bpp", procName, 1);
1062 redsweep, redsearch, 0.0,
1063 sweeprange, sweepdelta, minbsdelta,
1067 redsweep, redsearch, 0.0,
1068 sweeprange, sweepdelta, minbsdelta,
1072 if (conf1 > conf2 - confprior) {
1076 *pangle = -90.0 + angle2;
1080 #if DEBUG_PRINT_ORTH 1081 lept_stderr(
" About 0: angle1 = %7.3f, conf1 = %7.3f, score1 = %f\n",
1082 angle1, conf1, score1);
1083 lept_stderr(
" About 90: angle2 = %7.3f, conf2 = %7.3f, score2 = %f\n",
1084 angle2, conf2, score2);
1085 lept_stderr(
" Final: angle = %7.3f, conf = %7.3f\n", *pangle, *pconf);
1116 l_int32 w, h, skiph, skip, nskip;
1117 l_float32 val1, val2, diff, sum;
1120 PROCNAME(
"pixFindDifferentialSquareSum");
1123 return ERROR_INT(
"&sum not defined", procName, 1);
1126 return ERROR_INT(
"pixs not defined", procName, 1);
1131 return ERROR_INT(
"na not made", procName, 1);
1136 w = pixGetWidth(pixs);
1137 h = pixGetHeight(pixs);
1138 skiph = (l_int32)(0.05 * w);
1139 skip = L_MIN(h / 10, skiph);
1140 nskip = L_MAX(skip / 2, 1);
1146 for (i = nskip; i < n - nskip; i++) {
1190 l_int32 i, w, h, empty;
1191 l_float32 sum, sumsq, uniform, val;
1195 PROCNAME(
"pixFindNormalizedSquareSum");
1197 if (phratio) *phratio = 0.0;
1198 if (pvratio) *pvratio = 0.0;
1199 if (pfract) *pfract = 0.0;
1200 if (!phratio && !pvratio)
1201 return ERROR_INT(
"nothing to do", procName, 1);
1202 if (!pixs || pixGetDepth(pixs) != 1)
1203 return ERROR_INT(
"pixs not defined or not 1 bpp", procName, 1);
1210 if (pfract) *pfract = sum / (l_float32)(w * h);
1212 uniform = sum * sum / h;
1214 for (i = 0; i < h; i++) {
1218 *phratio = sumsq / uniform;
1226 if (empty == 1)
return 1;
1230 if (pfract) *pfract = sum / (l_float32)(w * h);
1232 uniform = sum * sum / w;
1234 for (i = 0; i < w; i++) {
1238 *pvratio = sumsq / uniform;
l_ok numaGetSum(NUMA *na, l_float32 *psum)
numaGetSum()
void gplotDestroy(GPLOT **pgplot)
gplotDestroy()
NUMA * pixCountPixelsByRow(PIX *pix, l_int32 *tab8)
pixCountPixelsByRow()
PIX * pixConvertTo1(PIX *pixs, l_int32 threshold)
pixConvertTo1()
l_ok numaGetFValue(NUMA *na, l_int32 index, l_float32 *pval)
numaGetFValue()
l_ok numaFitMax(NUMA *na, l_float32 *pmaxval, NUMA *naloc, l_float32 *pmaxloc)
numaFitMax()
PIX * pixDeskew(PIX *pixs, l_int32 redsearch)
pixDeskew()
l_ok pixFindDifferentialSquareSum(PIX *pixs, l_float32 *psum)
pixFindDifferentialSquareSum()
PIX * pixCreateTemplate(const PIX *pixs)
pixCreateTemplate()
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
l_ok gplotMakeOutput(GPLOT *gplot)
gplotMakeOutput()
GPLOT * gplotCreate(const char *rootname, l_int32 outformat, const char *title, const char *xlabel, const char *ylabel)
gplotCreate()
PIX * pixDeskewBoth(PIX *pixs, l_int32 redsearch)
pixDeskewBoth()
void lept_stderr(const char *fmt,...)
lept_stderr()
l_ok pixFindSkewSweep(PIX *pixs, l_float32 *pangle, l_int32 reduction, l_float32 sweeprange, l_float32 sweepdelta)
pixFindSkewSweep()
l_ok pixFindSkewSweepAndSearchScore(PIX *pixs, l_float32 *pangle, l_float32 *pconf, l_float32 *pendscore, l_int32 redsweep, l_int32 redsearch, l_float32 sweepcenter, l_float32 sweeprange, l_float32 sweepdelta, l_float32 minbsdelta)
pixFindSkewSweepAndSearchScore()
PIX * pixFindSkewAndDeskew(PIX *pixs, l_int32 redsearch, l_float32 *pangle, l_float32 *pconf)
pixFindSkewAndDeskew()
l_ok pixFindSkew(PIX *pixs, l_float32 *pangle, l_float32 *pconf)
pixFindSkew()
NUMA * numaCreate(l_int32 n)
numaCreate()
PIX * pixVShearCenter(PIX *pixd, PIX *pixs, l_float32 radang, l_int32 incolor)
pixVShearCenter()
PIX * pixVShearCorner(PIX *pixd, PIX *pixs, l_float32 radang, l_int32 incolor)
pixVShearCorner()
l_ok pixFindSkewSweepAndSearchScorePivot(PIX *pixs, l_float32 *pangle, l_float32 *pconf, l_float32 *pendscore, l_int32 redsweep, l_int32 redsearch, l_float32 sweepcenter, l_float32 sweeprange, l_float32 sweepdelta, l_float32 minbsdelta, l_int32 pivot)
pixFindSkewSweepAndSearchScorePivot()
l_int32 numaGetCount(NUMA *na)
numaGetCount()
l_ok pixFindNormalizedSquareSum(PIX *pixs, l_float32 *phratio, l_float32 *pvratio, l_float32 *pfract)
pixFindNormalizedSquareSum()
PIX * pixDeskewGeneral(PIX *pixs, l_int32 redsweep, l_float32 sweeprange, l_float32 sweepdelta, l_int32 redsearch, l_int32 thresh, l_float32 *pangle, l_float32 *pconf)
pixDeskewGeneral()
l_ok gplotAddPlot(GPLOT *gplot, NUMA *nax, NUMA *nay, l_int32 plotstyle, const char *plotlabel)
gplotAddPlot()
PIX * pixClone(PIX *pixs)
pixClone()
l_ok numaEmpty(NUMA *na)
numaEmpty()
void pixDestroy(PIX **ppix)
pixDestroy()
PIX * pixRotateOrth(PIX *pixs, l_int32 quads)
pixRotateOrth()
void numaDestroy(NUMA **pna)
numaDestroy()
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
l_ok numaGetMin(NUMA *na, l_float32 *pminval, l_int32 *piminloc)
numaGetMin()
l_ok pixZero(PIX *pix, l_int32 *pempty)
pixZero()
l_ok pixFindSkewSweepAndSearch(PIX *pixs, l_float32 *pangle, l_float32 *pconf, l_int32 redsweep, l_int32 redsearch, l_float32 sweeprange, l_float32 sweepdelta, l_float32 minbsdelta)
pixFindSkewSweepAndSearch()
PIX * pixRotate90(PIX *pixs, l_int32 direction)
pixRotate90()
l_ok numaGetMax(NUMA *na, l_float32 *pmaxval, l_int32 *pimaxloc)
numaGetMax()
PIX * pixReduceRankBinaryCascade(PIX *pixs, l_int32 level1, l_int32 level2, l_int32 level3, l_int32 level4)
pixReduceRankBinaryCascade()
PIX * pixRotate(PIX *pixs, l_float32 angle, l_int32 type, l_int32 incolor, l_int32 width, l_int32 height)
pixRotate()