88#include <config_auto.h>
92#include "allheaders.h"
162 l_float32 scorefract,
166l_int32 w, h, nx, ny, i, j, thresh;
168PIX *pixt, *pixb, *pixthresh, *pixth, *pixd;
171 if (!ppixth && !ppixd)
172 return ERROR_INT(
"neither &pixth nor &pixd defined", __func__, 1);
173 if (ppixth) *ppixth = NULL;
174 if (ppixd) *ppixd = NULL;
175 if (!pixs || pixGetDepth(pixs) != 8)
176 return ERROR_INT(
"pixs not defined or not 8 bpp", __func__, 1);
177 if (sx < 16 || sy < 16)
178 return ERROR_INT(
"sx and sy must be >= 16", __func__, 1);
181 pixGetDimensions(pixs, &w, &h, NULL);
182 nx = L_MAX(1, w / sx);
183 ny = L_MAX(1, h / sy);
184 smoothx = L_MIN(smoothx, (nx - 1) / 2);
185 smoothy = L_MIN(smoothy, (ny - 1) / 2);
186 pt = pixTilingCreate(pixs, nx, ny, 0, 0, 0, 0);
187 pixthresh = pixCreate(nx, ny, 8);
188 for (i = 0; i < ny; i++) {
189 for (j = 0; j < nx; j++) {
190 pixt = pixTilingGetTile(pt, i, j);
191 pixSplitDistributionFgBg(pixt, scorefract, 1, &thresh,
193 pixSetPixel(pixthresh, j, i, thresh);
199 if (smoothx > 0 || smoothy > 0)
200 pixth = pixBlockconv(pixthresh, smoothx, smoothy);
202 pixth = pixClone(pixthresh);
203 pixDestroy(&pixthresh);
207 pixd = pixCreate(w, h, 1);
208 pixCopyResolution(pixd, pixs);
209 for (i = 0; i < ny; i++) {
210 for (j = 0; j < nx; j++) {
211 pixt = pixTilingGetTile(pt, i, j);
212 pixGetPixel(pixth, j, i, &val);
213 pixb = pixThresholdToBinary(pixt, val);
214 pixTilingPaintTile(pixd, i, j, pixb, pt);
227 pixTilingDestroy(&pt);
280 l_float32 scorefract,
285PIX *pixn, *pixt, *pixd;
287 if (pthresh) *pthresh = 0;
288 if (!pixs || pixGetDepth(pixs) != 8)
289 return (
PIX *)ERROR_PTR(
"pixs undefined or not 8 bpp", __func__, NULL);
290 if (pixGetColormap(pixs))
291 return (
PIX *)ERROR_PTR(
"pixs is colormapped", __func__, NULL);
292 if (sx < 4 || sy < 4)
293 return (
PIX *)ERROR_PTR(
"sx and sy must be >= 4", __func__, NULL);
294 if (mincount > sx * sy) {
295 L_WARNING(
"mincount too large for tile size\n", __func__);
296 mincount = (sx * sy) / 3;
300 mincount, bgval, smoothx, smoothy);
302 return (
PIX *)ERROR_PTR(
"pixn not made", __func__, NULL);
306 pixGetDimensions(pixn, &w, &h, NULL);
310 if (pixt && pthresh) {
311 pixGetPixel(pixt, 0, 0, &val);
317 return (
PIX *)ERROR_PTR(
"pixd not made", __func__, NULL);
375 l_float32 scorefract,
378l_int32 w, h, highthresh;
380PIX *pixn, *pixm, *pixd, *pix1, *pix2, *pix3, *pix4;
382 if (pthresh) *pthresh = 0;
383 if (!pixs || pixGetDepth(pixs) != 8)
384 return (
PIX *)ERROR_PTR(
"pixs undefined or not 8 bpp", __func__, NULL);
385 if (pixGetColormap(pixs))
386 return (
PIX *)ERROR_PTR(
"pixs is colormapped", __func__, NULL);
387 if (sx < 4 || sy < 4)
388 return (
PIX *)ERROR_PTR(
"sx and sy must be >= 4", __func__, NULL);
389 if (mincount > sx * sy) {
390 L_WARNING(
"mincount too large for tile size\n", __func__);
391 mincount = (sx * sy) / 3;
396 mincount, 255, smoothx, smoothy);
398 return (
PIX *)ERROR_PTR(
"pixn not made", __func__, NULL);
407 pix2 = pixThresholdToBinary(pix1, 240);
408 pixInvert(pix2, pix2);
409 pixm = pixMorphSequence(pix2,
"d21.21", 0);
415 pixGetDimensions(pixs, &w, &h, NULL);
417 pixGetPixel(pix3, 0, 0, &val);
418 if (pthresh) *pthresh = val;
430 highthresh = L_MIN(256, val + 30);
431 pixd = pixThresholdToBinary(pixn, highthresh);
432 pix4 = pixThresholdToBinary(pixn, 190);
433 pixCombineMasked(pixd, pix4, pixm);
439 return (
PIX *)ERROR_PTR(
"pixd not made", __func__, NULL);
486l_int32 i, j, w, h, xrat, yrat;
487PIX *pixth = NULL, *pixd = NULL, *tileth = NULL, *tiled = NULL, *pixt;
488PIX **ptileth, **ptiled;
491 if (!ppixth && !ppixd)
492 return ERROR_INT(
"no outputs", __func__, 1);
493 if (ppixth) *ppixth = NULL;
494 if (ppixd) *ppixd = NULL;
495 if (!pixs || pixGetDepth(pixs) != 8)
496 return ERROR_INT(
"pixs undefined or not 8 bpp", __func__, 1);
497 if (pixGetColormap(pixs))
498 return ERROR_INT(
"pixs is cmapped", __func__, 1);
499 pixGetDimensions(pixs, &w, &h, NULL);
501 return ERROR_INT(
"whsize must be >= 2", __func__, 1);
502 if (w < 2 * whsize + 3 || h < 2 * whsize + 3)
503 return ERROR_INT(
"whsize too large for image", __func__, 1);
505 return ERROR_INT(
"factor must be >= 0", __func__, 1);
507 if (nx <= 1 && ny <= 1)
516 if (xrat < whsize + 2) {
517 nx = w / (whsize + 2);
518 L_WARNING(
"tile width too small; nx reduced to %d\n", __func__, nx);
520 if (yrat < whsize + 2) {
521 ny = h / (whsize + 2);
522 L_WARNING(
"tile height too small; ny reduced to %d\n", __func__, ny);
524 if (nx <= 1 && ny <= 1)
530 pixth = pixCreate(w, h, 8);
534 pixd = pixCreate(w, h, 1);
537 pt = pixTilingCreate(pixs, nx, ny, 0, 0, whsize + 1, whsize + 1);
538 pixTilingNoStripOnPaint(pt);
540 for (i = 0; i < ny; i++) {
541 for (j = 0; j < nx; j++) {
542 pixt = pixTilingGetTile(pt, i, j);
543 ptileth = (ppixth) ? &tileth : NULL;
544 ptiled = (ppixd) ? &tiled : NULL;
548 pixTilingPaintTile(pixth, i, j, tileth, pt);
552 pixTilingPaintTile(pixd, i, j, tiled, pt);
559 pixTilingDestroy(&pt);
613PIX *pixg, *pixsc, *pixm = NULL, *pixms = NULL, *pixth = NULL, *pixd = NULL;
615 if (ppixm) *ppixm = NULL;
616 if (ppixsd) *ppixsd = NULL;
617 if (ppixth) *ppixth = NULL;
618 if (ppixd) *ppixd = NULL;
619 if (!ppixm && !ppixsd && !ppixth && !ppixd)
620 return ERROR_INT(
"no outputs", __func__, 1);
621 if (!pixs || pixGetDepth(pixs) != 8)
622 return ERROR_INT(
"pixs undefined or not 8 bpp", __func__, 1);
623 if (pixGetColormap(pixs))
624 return ERROR_INT(
"pixs is cmapped", __func__, 1);
625 pixGetDimensions(pixs, &w, &h, NULL);
627 return ERROR_INT(
"whsize must be >= 2", __func__, 1);
628 if (w < 2 * whsize + 3 || h < 2 * whsize + 3)
629 return ERROR_INT(
"whsize too large for image", __func__, 1);
631 return ERROR_INT(
"factor must be >= 0", __func__, 1);
634 pixg = pixAddMirroredBorder(pixs, whsize + 1, whsize + 1,
635 whsize + 1, whsize + 1);
636 pixsc = pixClone(pixs);
638 pixg = pixClone(pixs);
639 pixsc = pixRemoveBorder(pixs, whsize + 1);
642 return ERROR_INT(
"pixg and pixsc not made", __func__, 1);
645 if (ppixm || ppixth || ppixd)
646 pixm = pixWindowedMean(pixg, whsize, whsize, 1, 1);
647 if (ppixsd || ppixth || ppixd)
648 pixms = pixWindowedMeanSquare(pixg, whsize, whsize, 1);
653 pixCopyResolution(pixd, pixs);
716l_int32 i, j, w, h, tabsize, wplm, wplms, wplsd, wpld, usetab;
717l_int32 mv, ms, var, thresh;
718l_uint32 *datam, *datams, *datasd = NULL, *datad;
719l_uint32 *linem, *linems, *linesd = NULL, *lined;
721l_float32 *tab = NULL;
722PIX *pixsd = NULL, *pixd = NULL;
724 if (ppixsd) *ppixsd = NULL;
725 if (!pixm || pixGetDepth(pixm) != 8)
726 return (
PIX *)ERROR_PTR(
"pixm undefined or not 8 bpp", __func__, NULL);
727 if (pixGetColormap(pixm))
728 return (
PIX *)ERROR_PTR(
"pixm is colormapped", __func__, NULL);
729 if (!pixms || pixGetDepth(pixms) != 32)
730 return (
PIX *)ERROR_PTR(
"pixms undefined or not 32 bpp",
733 return (
PIX *)ERROR_PTR(
"factor must be >= 0", __func__, NULL);
737 pixGetDimensions(pixm, &w, &h, NULL);
738 usetab = (w * h > 100000) ? 1 : 0;
741 tab = (l_float32 *)LEPT_CALLOC(tabsize,
sizeof(l_float32));
742 for (i = 0; i < tabsize; i++)
743 tab[i] = sqrtf((l_float32)i);
746 pixd = pixCreate(w, h, 8);
748 pixsd = pixCreate(w, h, 8);
751 datam = pixGetData(pixm);
752 datams = pixGetData(pixms);
753 if (ppixsd) datasd = pixGetData(pixsd);
754 datad = pixGetData(pixd);
755 wplm = pixGetWpl(pixm);
756 wplms = pixGetWpl(pixms);
757 if (ppixsd) wplsd = pixGetWpl(pixsd);
758 wpld = pixGetWpl(pixd);
759 for (i = 0; i < h; i++) {
760 linem = datam + i * wplm;
761 linems = datams + i * wplms;
762 if (ppixsd) linesd = datasd + i * wplsd;
763 lined = datad + i * wpld;
764 for (j = 0; j < w; j++) {
771 sd = sqrtf((l_float32)var);
773 thresh = (l_int32)(mv * (1.0 - factor * (1.0 - sd / 128.)));
778 if (usetab) LEPT_FREE(tab);
794l_int32 i, j, w, h, wpls, wplt, wpld, vals, valt;
795l_uint32 *datas, *datat, *datad, *lines, *linet, *lined;
798 if (!pixs || pixGetDepth(pixs) != 8)
799 return (
PIX *)ERROR_PTR(
"pixs undefined or not 8 bpp", __func__, NULL);
800 if (pixGetColormap(pixs))
801 return (
PIX *)ERROR_PTR(
"pixs is colormapped", __func__, NULL);
802 if (!pixth || pixGetDepth(pixth) != 8)
803 return (
PIX *)ERROR_PTR(
"pixth undefined or not 8 bpp", __func__, NULL);
805 pixGetDimensions(pixs, &w, &h, NULL);
806 pixd = pixCreate(w, h, 1);
807 datas = pixGetData(pixs);
808 datat = pixGetData(pixth);
809 datad = pixGetData(pixd);
810 wpls = pixGetWpl(pixs);
811 wplt = pixGetWpl(pixth);
812 wpld = pixGetWpl(pixd);
813 for (i = 0; i < h; i++) {
814 lines = datas + i * wpls;
815 linet = datat + i * wplt;
816 lined = datad + i * wpld;
817 for (j = 0; j < w; j++) {
855l_int32 w, h, d, nx, ny;
856PIX *pixg, *pix1, *pixd;
858 if (ppixn) *ppixn = NULL;
859 if (ppixth) *ppixth = NULL;
860 if (!pixs || (d = pixGetDepth(pixs)) < 8)
861 return (
PIX *)ERROR_PTR(
"pixs undefined or d < 8 bpp", __func__, NULL);
863 pixg = pixConvertRGBToGray(pixs, 0.3f, 0.4f, 0.3f);
865 pixg = pixConvertTo8(pixs, 0);
870 pixGetDimensions(pix1, &w, &h, NULL);
871 nx = L_MAX(1, (w + 125) / 250);
872 ny = L_MAX(1, (h + 125) / 250);
909PIX *pixg, *pix1, *pixd;
911 if (!pixs || (d = pixGetDepth(pixs)) < 8)
912 return (
PIX *)ERROR_PTR(
"pixs undefined or d < 8 bpp", __func__, NULL);
914 pixg = pixConvertRGBToGray(pixs, 0.3f, 0.4f, 0.3f);
916 pixg = pixConvertTo8(pixs, 0);
920 pixGetPixel(pix1, 0, 0, &val);
922 ival = L_MIN(ival, 110);
931 pixd = pixThresholdToBinary(pix1, ival);
1001 l_float32 threshdiff,
1002 l_int32 *pglobthresh,
1006l_int32 i, thresh, n, n4, n8, mincounts, found, globthresh;
1007l_float32 count4, count8, firstcount4, prevcount4, diff48, diff4;
1010PIX *pix1, *pix2, *pix3;
1012 if (pglobthresh) *pglobthresh = 0;
1013 if (ppixd) *ppixd = NULL;
1014 if (!pixs || pixGetDepth(pixs) == 1)
1015 return ERROR_INT(
"pixs undefined or 1 bpp", __func__, 1);
1016 if (pixm && pixGetDepth(pixm) != 1)
1017 return ERROR_INT(
"pixm must be 1 bpp", __func__, 1);
1020 if (start <= 0) start = 80;
1021 if (end <= 0) end = 200;
1022 if (incr <= 0) incr = 10;
1023 if (thresh48 <= 0.0) thresh48 = 0.01f;
1024 if (threshdiff <= 0.0) threshdiff = 0.01f;
1026 return ERROR_INT(
"invalid start,end", __func__, 1);
1029 if (pixGetColormap(pixs))
1032 pix1 = pixClone(pixs);
1033 if (pixGetDepth(pix1) == 32)
1034 pix2 = pixConvertRGBToGrayMinMax(pix1, L_CHOOSE_MAX);
1036 pix2 = pixConvertTo8(pix1, 0);
1042 pixSetMasked(pix2, pixm, 255);
1045 pix3 = pixConvertTo1(pix2, start);
1046 pixCountConnComp(pix3, 4, &n4);
1049 if (n4 < mincounts) {
1050 L_INFO(
"Insufficient component count: %d\n", __func__, n4);
1056 na4 = numaCreate(0);
1057 na8 = numaCreate(0);
1058 numaSetParameters(na4, start, incr);
1059 numaSetParameters(na8, start, incr);
1060 for (thresh = start, i = 0; thresh <= end; thresh += incr, i++) {
1061 pix3 = pixConvertTo1(pix2, thresh);
1062 pixCountConnComp(pix3, 4, &n4);
1063 pixCountConnComp(pix3, 8, &n8);
1064 numaAddNumber(na4, n4);
1065 numaAddNumber(na8, n8);
1069 lept_mkdir(
"lept/binarize");
1070 gplot = gplotCreate(
"/tmp/lept/binarize", GPLOT_PNG,
1071 "number of cc vs. threshold",
1072 "threshold",
"number of cc");
1073 gplotAddPlot(gplot, NULL, na4, GPLOT_LINES,
"plot 4cc");
1074 gplotAddPlot(gplot, NULL, na8, GPLOT_LINES,
"plot 8cc");
1075 gplotMakeOutput(gplot);
1076 gplotDestroy(&gplot);
1079 n = numaGetCount(na4);
1081 for (i = 0; i < n; i++) {
1083 numaGetFValue(na4, i, &firstcount4);
1084 prevcount4 = firstcount4;
1086 numaGetFValue(na4, i, &count4);
1087 numaGetFValue(na8, i, &count8);
1088 diff48 = (count4 - count8) / firstcount4;
1089 diff4 = L_ABS(prevcount4 - count4) / firstcount4;
1091 lept_stderr(
"diff48 = %7.3f, diff4 = %7.3f\n",
1094 if (diff48 < thresh48 && diff4 < threshdiff) {
1098 prevcount4 = count4;
1105 globthresh = start + i * incr;
1106 if (pglobthresh) *pglobthresh = globthresh;
1108 *ppixd = pixConvertTo1(pix2, globthresh);
1109 pixCopyResolution(*ppixd, pixs);
1111 if (debugflag) lept_stderr(
"global threshold = %d\n", globthresh);
1116 if (debugflag) lept_stderr(
"no global threshold found\n");
1160l_float32 maxval, fract;
1161NUMA *na1, *na2, *na3;
1163 if (ppixd) *ppixd = NULL;
1164 if (pnahisto) *pnahisto = NULL;
1165 if (ppixhisto) *ppixhisto = NULL;
1167 return ERROR_INT(
"&thresh not defined", __func__, 1);
1169 if (!pixs || pixGetDepth(pixs) != 8)
1170 return ERROR_INT(
"pixs undefined or not 8 bpp", __func__, 1);
1171 if (pixGetColormap(pixs))
1172 return ERROR_INT(
"pixs has colormap", __func__, 1);
1174 return ERROR_INT(
"sampling must be >= 1", __func__, 1);
1175 if (halfw <= 0) halfw = 20;
1176 if (skip <= 0) skip = 20;
1180 na1 = pixGetGrayHistogram(pixs, factor);
1181 na2 = numaWindowedMean(na1, halfw);
1182 numaGetMax(na2, &maxval, NULL);
1183 na3 = numaTransform(na2, 0.0, 1.0 / maxval);
1187 if (numaFindLocForThreshold(na3, skip, pthresh, &fract) == 1) {
1189 return ERROR_INT(
"failure to find threshold", __func__, 1);
1191 L_INFO(
"fractional area under first peak: %5.3f\n", __func__, fract);
1194 lept_mkdir(
"lept/histo");
1195 gplotSimple1(na3, GPLOT_PNG,
"/tmp/lept/histo/histo", NULL);
1196 *ppixhisto = pixRead(
"/tmp/lept/histo/histo.png");
1202 if (*pthresh > 0 && ppixd)
1203 *ppixd = pixThresholdToBinary(pixs, *pthresh);
PIX * pixBackgroundNormFlex(PIX *pixs, l_int32 sx, l_int32 sy, l_int32 smoothx, l_int32 smoothy, l_int32 delta)
pixBackgroundNormFlex()
PIX * pixBackgroundNormSimple(PIX *pixs, PIX *pixim, PIX *pixg)
pixBackgroundNormSimple()
PIX * pixContrastNorm(PIX *pixd, PIX *pixs, l_int32 sx, l_int32 sy, l_int32 mindiff, l_int32 smoothx, l_int32 smoothy)
pixContrastNorm()
PIX * pixBackgroundNorm(PIX *pixs, PIX *pixim, PIX *pixg, l_int32 sx, l_int32 sy, l_int32 thresh, l_int32 mincount, l_int32 bgval, l_int32 smoothx, l_int32 smoothy)
pixBackgroundNorm()
#define SET_DATA_BIT(pdata, n)
#define GET_DATA_BYTE(pdata, n)
#define SET_DATA_BYTE(pdata, n, val)
static PIX * pixApplyLocalThreshold(PIX *pixs, PIX *pixth)
pixApplyLocalThreshold()
l_ok pixSauvolaBinarizeTiled(PIX *pixs, l_int32 whsize, l_float32 factor, l_int32 nx, l_int32 ny, PIX **ppixth, PIX **ppixd)
pixSauvolaBinarizeTiled()
l_ok pixThresholdByConnComp(PIX *pixs, PIX *pixm, l_int32 start, l_int32 end, l_int32 incr, l_float32 thresh48, l_float32 threshdiff, l_int32 *pglobthresh, PIX **ppixd, l_int32 debugflag)
pixThresholdByConnComp()
static PIX * pixSauvolaGetThreshold(PIX *pixm, PIX *pixms, l_float32 factor, PIX **ppixsd)
pixSauvolaGetThreshold()
PIX * pixOtsuThreshOnBackgroundNorm(PIX *pixs, PIX *pixim, l_int32 sx, l_int32 sy, l_int32 thresh, l_int32 mincount, l_int32 bgval, l_int32 smoothx, l_int32 smoothy, l_float32 scorefract, l_int32 *pthresh)
pixOtsuThreshOnBackgroundNorm()
PIX * pixSauvolaOnContrastNorm(PIX *pixs, l_int32 mindiff, PIX **ppixn, PIX **ppixth)
pixSauvolaOnContrastNorm()
l_ok pixSauvolaBinarize(PIX *pixs, l_int32 whsize, l_float32 factor, l_int32 addborder, PIX **ppixm, PIX **ppixsd, PIX **ppixth, PIX **ppixd)
pixSauvolaBinarize()
PIX * pixThreshOnDoubleNorm(PIX *pixs, l_int32 mindiff)
pixThreshOnDoubleNorm()
l_ok pixOtsuAdaptiveThreshold(PIX *pixs, l_int32 sx, l_int32 sy, l_int32 smoothx, l_int32 smoothy, l_float32 scorefract, PIX **ppixth, PIX **ppixd)
pixOtsuAdaptiveThreshold()
l_ok pixThresholdByHisto(PIX *pixs, l_int32 factor, l_int32 halfw, l_int32 skip, l_int32 *pthresh, PIX **ppixd, NUMA **pnahisto, PIX **ppixhisto)
pixThresholdByHisto()
PIX * pixMaskedThreshOnBackgroundNorm(PIX *pixs, PIX *pixim, l_int32 sx, l_int32 sy, l_int32 thresh, l_int32 mincount, l_int32 smoothx, l_int32 smoothy, l_float32 scorefract, l_int32 *pthresh)
pixMaskedThreshOnBackgroundNorm()
@ REMOVE_CMAP_BASED_ON_SRC