Pix* stats(Pix* pix){ Numa* histo = pixGetGrayHistogram(pix, 4); Numa* norm = numaNormalizeHistogram(histo, 1); l_float32 mean, median, variance, stdd; numaGetHistogramStats(histo, 0, 1, &mean, &median, NULL, &variance); stdd = sqrt(variance); printf("stats: mean = %.2f, stdd = %.2f\n", mean, stdd); numaDestroy(&histo); numaDestroy(&norm); return pixClone(pix); }
int main(int argc, char **argv) { char *filein; l_int32 d, sigbits; GPLOT *gplot; NUMA *na; PIX *pixs; static char mainName[] = "histotest"; if (argc != 3) return ERROR_INT(" Syntax: histotest filein sigbits", mainName, 1); filein = argv[1]; sigbits = atoi(argv[2]); if ((pixs = pixRead(filein)) == NULL) return ERROR_INT("pixs not made", mainName, 1); d = pixGetDepth(pixs); if (d != 8 && d != 32) return ERROR_INT("depth not 8 or 32 bpp", mainName, 1); if (d == 32) { startTimer(); if ((na = pixOctcubeHistogram(pixs, sigbits, NULL)) == NULL) return ERROR_INT("na not made", mainName, 1); fprintf(stderr, "histo time = %7.3f sec\n", stopTimer()); gplot = gplotCreate("/tmp/junkrootc", GPLOT_X11, "color histogram with octcube indexing", "octcube index", "number of pixels in cube"); gplotAddPlot(gplot, NULL, na, GPLOT_LINES, "input pix"); gplotMakeOutput(gplot); gplotDestroy(&gplot); } else { if ((na = pixGetGrayHistogram(pixs, 1)) == NULL) return ERROR_INT("na not made", mainName, 1); numaWrite("/tmp/junkna", na); gplot = gplotCreate("/tmp/junkrootg", GPLOT_X11, "grayscale histogram", "gray value", "number of pixels"); gplotSetScaling(gplot, GPLOT_LOG_SCALE_Y); gplotAddPlot(gplot, NULL, na, GPLOT_LINES, "input pix"); gplotMakeOutput(gplot); gplotDestroy(&gplot); } pixDestroy(&pixs); numaDestroy(&na); return 0; }
/*! * \brief pixFindStrokeWidth() * * \param[in] pixs 1 bpp * \param[in] thresh fractional count threshold relative to distance 1 * \param[in] tab8 [optional] table for counting fg pixels; can be NULL * \param[out] *pwidth estimated width of the strokes * \param[out] *pnahisto [optional] histo of pixel distances from bg * \return 0 if OK, 1 on error * * <pre> * Notes: * (1) This uses two methods to estimate the stroke width: * (a) half the fg boundary length * (b) a value derived from the histogram of the fg distance transform * (2) Distance is measured in 8-connected * (3) %thresh is the minimum fraction N(dist=d)/N(dist=1) of pixels * required to determine if the pixels at distance d are above * the noise. It is typically about 0.15. * </pre> */ l_int32 pixFindStrokeWidth(PIX *pixs, l_float32 thresh, l_int32 *tab8, l_float32 *pwidth, NUMA **pnahisto) { l_int32 i, n, count, length, first, last; l_int32 *tab; l_float32 width1, width2, ratio, extra; l_float32 *fa; NUMA *na1, *na2; PIX *pix1; PROCNAME("pixFindStrokeWidth"); if (!pwidth) return ERROR_INT("&width not defined", procName, 1); *pwidth = 0; if (!pixs) return ERROR_INT("pixs not defined", procName, 1); tab = (tab8) ? tab8 : makePixelSumTab8(); /* ------- Method 1: via boundary length ------- */ /* The computed stroke length is a bit larger than that actual * length, because of the addition of the 'caps' at the * stroke ends. Therefore the computed width is a bit * smaller than the average width. */ pixFindStrokeLength(pixs, tab8, &length); pixCountPixels(pixs, &count, tab8); width1 = (l_float32)count / (l_float32)length; /* ------- Method 2: via distance transform ------- */ /* First get the histogram of distances */ pix1 = pixDistanceFunction(pixs, 8, 8, L_BOUNDARY_BG); na1 = pixGetGrayHistogram(pix1, 1); pixDestroy(&pix1); numaGetNonzeroRange(na1, 0.1, &first, &last); na2 = numaClipToInterval(na1, 0, last); numaWriteStream(stderr, na2); /* Find the bucket with the largest distance whose contents * exceed the threshold. */ fa = numaGetFArray(na2, L_NOCOPY); n = numaGetCount(na2); for (i = n - 1; i > 0; i--) { ratio = fa[i] / fa[1]; if (ratio > thresh) break; } /* Let the last skipped bucket contribute to the stop bucket. * This is the 'extra' term below. The result may be a slight * over-correction, so the computed width may be a bit larger * than the average width. */ extra = (i < n - 1) ? fa[i + 1] / fa[1] : 0; width2 = 2.0 * (i - 1.0 + ratio + extra); fprintf(stderr, "width1 = %5.2f, width2 = %5.2f\n", width1, width2); /* Average the two results */ *pwidth = (width1 + width2) / 2.0; if (!tab8) LEPT_FREE(tab); numaDestroy(&na1); if (pnahisto) *pnahisto = na2; else numaDestroy(&na2); return 0; }
main(int argc, char **argv) { PIX *pixs; l_int32 d; static char mainName[] = "scaletest2"; if (argc != 2) return ERROR_INT(" Syntax: scaletest2 filein", mainName, 1); if ((pixs = pixRead(argv[1])) == NULL) return ERROR_INT("pixs not made", mainName, 1); d = pixGetDepth(pixs); #if 1 /* Integer scale-to-gray functions */ if (d == 1) { PIX *pixd; pixd = pixScaleToGray2(pixs); pixWrite("/tmp/s2g_2x", pixd, IFF_PNG); pixDestroy(&pixd); pixd = pixScaleToGray3(pixs); pixWrite("/tmp/s2g_3x", pixd, IFF_PNG); pixDestroy(&pixd); pixd = pixScaleToGray4(pixs); pixWrite("/tmp/s2g_4x", pixd, IFF_PNG); pixDestroy(&pixd); pixd = pixScaleToGray6(pixs); pixWrite("/tmp/s2g_6x", pixd, IFF_PNG); pixDestroy(&pixd); pixd = pixScaleToGray8(pixs); pixWrite("/tmp/s2g_8x", pixd, IFF_PNG); pixDestroy(&pixd); pixd = pixScaleToGray16(pixs); pixWrite("/tmp/s2g_16x", pixd, IFF_PNG); pixDestroy(&pixd); } #endif #if 1 /* Various non-integer scale-to-gray, compared with * with different ways of getting similar results */ if (d == 1) { PIX *pixt, *pixd; pixd = pixScaleToGray8(pixs); pixWrite("/tmp/s2g_8.png", pixd, IFF_PNG); pixDestroy(&pixd); pixd = pixScaleToGray(pixs, 0.124); pixWrite("/tmp/s2g_124.png", pixd, IFF_PNG); pixDestroy(&pixd); pixd = pixScaleToGray(pixs, 0.284); pixWrite("/tmp/s2g_284.png", pixd, IFF_PNG); pixDestroy(&pixd); pixt = pixScaleToGray4(pixs); pixd = pixScaleBySampling(pixt, 284./250., 284./250.); pixWrite("/tmp/s2g_284.2.png", pixd, IFF_PNG); pixDestroy(&pixt); pixDestroy(&pixd); pixt = pixScaleToGray4(pixs); pixd = pixScaleGrayLI(pixt, 284./250., 284./250.); pixWrite("/tmp/s2g_284.3.png", pixd, IFF_PNG); pixDestroy(&pixt); pixDestroy(&pixd); pixt = pixScaleBinary(pixs, 284./250., 284./250.); pixd = pixScaleToGray4(pixt); pixWrite("/tmp/s2g_284.4.png", pixd, IFF_PNG); pixDestroy(&pixt); pixDestroy(&pixd); pixt = pixScaleToGray4(pixs); pixd = pixScaleGrayLI(pixt, 0.49, 0.49); pixWrite("/tmp/s2g_42.png", pixd, IFF_PNG); pixDestroy(&pixt); pixDestroy(&pixd); pixt = pixScaleToGray4(pixs); pixd = pixScaleSmooth(pixt, 0.49, 0.49); pixWrite("/tmp/s2g_4sm.png", pixd, IFF_PNG); pixDestroy(&pixt); pixDestroy(&pixd); pixt = pixScaleBinary(pixs, .16/.125, .16/.125); pixd = pixScaleToGray8(pixt); pixWrite("/tmp/s2g_16.png", pixd, IFF_PNG); pixDestroy(&pixt); pixDestroy(&pixd); pixd = pixScaleToGray(pixs, .16); pixWrite("/tmp/s2g_16.2.png", pixd, IFF_PNG); pixDestroy(&pixd); } #endif #if 1 /* Antialiased (smoothed) reduction, along with sharpening */ if (d != 1) { PIX *pixt1, *pixt2; startTimer(); pixt1 = pixScaleSmooth(pixs, 0.154, 0.154); fprintf(stderr, "fast scale: %5.3f sec\n", stopTimer()); pixDisplayWithTitle(pixt1, 0, 0, "smooth scaling", DISPLAY); pixWrite("/tmp/smooth1.png", pixt1, IFF_PNG); pixt2 = pixUnsharpMasking(pixt1, 1, 0.3); pixWrite("/tmp/smooth2.png", pixt2, IFF_PNG); pixDisplayWithTitle(pixt2, 200, 0, "sharp scaling", DISPLAY); pixDestroy(&pixt1); pixDestroy(&pixt2); } #endif #if 1 /* Test a large range of scale-to-gray reductions */ if (d == 1) { l_int32 i; l_float32 scale; PIX *pixd; for (i = 2; i < 15; i++) { scale = 1. / (l_float32)i; startTimer(); pixd = pixScaleToGray(pixs, scale); fprintf(stderr, "Time for scale %7.3f: %7.3f sec\n", scale, stopTimer()); pixDisplayWithTitle(pixd, 75 * i, 100, "scaletogray", DISPLAY); pixDestroy(&pixd); } for (i = 8; i < 14; i++) { scale = 1. / (l_float32)(2 * i); startTimer(); pixd = pixScaleToGray(pixs, scale); fprintf(stderr, "Time for scale %7.3f: %7.3f sec\n", scale, stopTimer()); pixDisplayWithTitle(pixd, 100 * i, 600, "scaletogray", DISPLAY); pixDestroy(&pixd); } } #endif #if 1 /* Test the same range of scale-to-gray mipmap reductions */ if (d == 1) { l_int32 i; l_float32 scale; PIX *pixd; for (i = 2; i < 15; i++) { scale = 1. / (l_float32)i; startTimer(); pixd = pixScaleToGrayMipmap(pixs, scale); fprintf(stderr, "Time for scale %7.3f: %7.3f sec\n", scale, stopTimer()); pixDisplayWithTitle(pixd, 75 * i, 100, "scale mipmap", DISPLAY); pixDestroy(&pixd); } for (i = 8; i < 12; i++) { scale = 1. / (l_float32)(2 * i); startTimer(); pixd = pixScaleToGrayMipmap(pixs, scale); fprintf(stderr, "Time for scale %7.3f: %7.3f sec\n", scale, stopTimer()); pixDisplayWithTitle(pixd, 100 * i, 600, "scale mipmap", DISPLAY); pixDestroy(&pixd); } } #endif #if 1 /* Test several methods for antialiased reduction, * along with sharpening */ if (d != 1) { PIX *pixt1, *pixt2, *pixt3, *pixt4, *pixt5, *pixt6, *pixt7; l_float32 SCALING = 0.27; l_int32 SIZE = 7; l_int32 smooth; l_float32 FRACT = 1.0; smooth = SIZE / 2; startTimer(); pixt1 = pixScaleSmooth(pixs, SCALING, SCALING); fprintf(stderr, "fast scale: %5.3f sec\n", stopTimer()); pixDisplayWithTitle(pixt1, 0, 0, "smooth scaling", DISPLAY); pixWrite("/tmp/sm_1.png", pixt1, IFF_PNG); pixt2 = pixUnsharpMasking(pixt1, 1, 0.3); pixDisplayWithTitle(pixt2, 150, 0, "sharpened scaling", DISPLAY); startTimer(); pixt3 = pixBlockconv(pixs, smooth, smooth); pixt4 = pixScaleBySampling(pixt3, SCALING, SCALING); fprintf(stderr, "slow scale: %5.3f sec\n", stopTimer()); pixDisplayWithTitle(pixt4, 200, 200, "sampled scaling", DISPLAY); pixWrite("/tmp/sm_2.png", pixt4, IFF_PNG); startTimer(); pixt5 = pixUnsharpMasking(pixs, smooth, FRACT); pixt6 = pixBlockconv(pixt5, smooth, smooth); pixt7 = pixScaleBySampling(pixt6, SCALING, SCALING); fprintf(stderr, "very slow scale + sharp: %5.3f sec\n", stopTimer()); pixDisplayWithTitle(pixt7, 500, 200, "sampled scaling", DISPLAY); pixWrite("/tmp/sm_3.jpg", pixt7, IFF_JFIF_JPEG); pixDestroy(&pixt1); pixDestroy(&pixt2); pixDestroy(&pixt3); pixDestroy(&pixt4); pixDestroy(&pixt5); pixDestroy(&pixt6); pixDestroy(&pixt7); } #endif #if 1 /* Test the color scaling function, comparing the * special case of scaling factor 2.0 with the * general case. */ if (d == 32) { PIX *pix1, *pix2, *pixd; NUMA *nar, *nag, *nab, *naseq; GPLOT *gplot; startTimer(); pix1 = pixScaleColorLI(pixs, 2.00001, 2.0); fprintf(stderr, " Time with regular LI: %7.3f\n", stopTimer()); pixWrite("/tmp/color1.jpg", pix1, IFF_JFIF_JPEG); startTimer(); pix2 = pixScaleColorLI(pixs, 2.0, 2.0); fprintf(stderr, " Time with 2x LI: %7.3f\n", stopTimer()); pixWrite("/tmp/color2.jpg", pix2, IFF_JFIF_JPEG); pixd = pixAbsDifference(pix1, pix2); pixGetColorHistogram(pixd, 1, &nar, &nag, &nab); naseq = numaMakeSequence(0., 1., 256); gplot = gplotCreate("/tmp/plot_absdiff", GPLOT_X11, "Number vs diff", "diff", "number"); gplotSetScaling(gplot, GPLOT_LOG_SCALE_Y); gplotAddPlot(gplot, naseq, nar, GPLOT_POINTS, "red"); gplotAddPlot(gplot, naseq, nag, GPLOT_POINTS, "green"); gplotAddPlot(gplot, naseq, nab, GPLOT_POINTS, "blue"); gplotMakeOutput(gplot); pixDestroy(&pix1); pixDestroy(&pix2); pixDestroy(&pixd); numaDestroy(&naseq); numaDestroy(&nar); numaDestroy(&nag); numaDestroy(&nab); gplotDestroy(&gplot); } #endif #if 1 /* Test the gray LI scaling function, comparing the * special cases of scaling factor 2.0 and 4.0 with the * general case */ if (d == 8 || d == 32) { PIX *pixt, *pix0, *pix1, *pix2, *pixd; NUMA *nagray, *naseq; GPLOT *gplot; if (d == 8) pixt = pixClone(pixs); else pixt = pixConvertRGBToGray(pixs, 0.33, 0.34, 0.33); pix0 = pixScaleGrayLI(pixt, 0.5, 0.5); #if 1 startTimer(); pix1 = pixScaleGrayLI(pix0, 2.00001, 2.0); fprintf(stderr, " Time with regular LI 2x: %7.3f\n", stopTimer()); startTimer(); pix2 = pixScaleGrayLI(pix0, 2.0, 2.0); fprintf(stderr, " Time with 2x LI: %7.3f\n", stopTimer()); #else startTimer(); pix1 = pixScaleGrayLI(pix0, 4.00001, 4.0); fprintf(stderr, " Time with regular LI 4x: %7.3f\n", stopTimer()); startTimer(); pix2 = pixScaleGrayLI(pix0, 4.0, 4.0); fprintf(stderr, " Time with 2x LI: %7.3f\n", stopTimer()); #endif pixWrite("/tmp/gray1", pix1, IFF_JFIF_JPEG); pixWrite("/tmp/gray2", pix2, IFF_JFIF_JPEG); pixd = pixAbsDifference(pix1, pix2); nagray = pixGetGrayHistogram(pixd, 1); naseq = numaMakeSequence(0., 1., 256); gplot = gplotCreate("/tmp/g_absdiff", GPLOT_X11, "Number vs diff", "diff", "number"); gplotSetScaling(gplot, GPLOT_LOG_SCALE_Y); gplotAddPlot(gplot, naseq, nagray, GPLOT_POINTS, "gray"); gplotMakeOutput(gplot); pixDestroy(&pixt); pixDestroy(&pix0); pixDestroy(&pix1); pixDestroy(&pix2); pixDestroy(&pixd); numaDestroy(&naseq); numaDestroy(&nagray); gplotDestroy(&gplot); } #endif pixDestroy(&pixs); return 0; }