static l_int32 GenerateSplitPlot(l_int32 i) { char title[256]; l_int32 split; l_float32 ave1, ave2, num1, num2, maxnum, maxscore; GPLOT *gplot; NUMA *na1, *na2, *nascore, *nax, *nay; PIX *pixs, *pixd; /* Generate */ na1 = MakeGaussian(gaussmean1[i], gaussstdev1[i], gaussfract1[i]); na2 = MakeGaussian(gaussmean2[i], gaussstdev1[i], 1.0 - gaussfract1[i]); numaArithOp(na1, na1, na2, L_ARITH_ADD); /* Otsu splitting */ numaSplitDistribution(na1, 0.08, &split, &ave1, &ave2, &num1, &num2, &nascore); fprintf(stderr, "split = %d, ave1 = %6.1f, ave2 = %6.1f\n", split, ave1, ave2); fprintf(stderr, "num1 = %8.0f, num2 = %8.0f\n", num1, num2); /* Prepare for plotting a vertical line at the split point */ nax = numaMakeConstant(split, 2); numaGetMax(na1, &maxnum, NULL); nay = numaMakeConstant(0, 2); numaReplaceNumber(nay, 1, (l_int32)(0.5 * maxnum)); /* Plot the input histogram with the split location */ sprintf(buf, "/tmp/junkplot.%d", i); sprintf(title, "Plot %d", i); gplot = gplotCreate(buf, GPLOT_PNG, "Histogram: mixture of 2 gaussians", "Grayscale value", "Number of pixels"); gplotAddPlot(gplot, NULL, na1, GPLOT_LINES, title); gplotAddPlot(gplot, nax, nay, GPLOT_LINES, NULL); gplotMakeOutput(gplot); gplotDestroy(&gplot); numaDestroy(&na1); numaDestroy(&na2); /* Plot the score function */ sprintf(buf, "/tmp/junkplots.%d", i); sprintf(title, "Plot %d", i); gplot = gplotCreate(buf, GPLOT_PNG, "Otsu score function for splitting", "Grayscale value", "Score"); gplotAddPlot(gplot, NULL, nascore, GPLOT_LINES, title); numaGetMax(nascore, &maxscore, NULL); numaReplaceNumber(nay, 1, maxscore); gplotAddPlot(gplot, nax, nay, GPLOT_LINES, NULL); gplotMakeOutput(gplot); gplotDestroy(&gplot); numaDestroy(&nax); numaDestroy(&nay); numaDestroy(&nascore); return 0; }
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; }
/*! * gplotSimpleXY2() * * Input: nax (<optional; can be NULL) * nay1 * nay2 * outformat (GPLOT_PNG, GPLOT_PS, GPLOT_EPS, GPLOT_X11, * GPLOT_LATEX) * outroot (root of output files) * title (<optional>) * Return: 0 if OK, 1 on error * * Notes: * (1) This gives line plots of @nay1 and @nay2 against nax, generated * in the specified output format. The title is optional. * (2) @nax is optional. If NULL, @nay1 and @nay2 are plotted * against the array index. * (3) When calling these simple plot functions more than once, use * different @outroot to avoid overwriting the output files. */ l_int32 gplotSimpleXY2(NUMA *nax, NUMA *nay1, NUMA *nay2, l_int32 outformat, const char *outroot, const char *title) { GPLOT *gplot; PROCNAME("gplotSimpleXY2"); if (!nay1 || !nay2) return ERROR_INT("nay1 and nay2 not both defined", procName, 1); if (outformat != GPLOT_PNG && outformat != GPLOT_PS && outformat != GPLOT_EPS && outformat != GPLOT_X11 && outformat != GPLOT_LATEX) return ERROR_INT("invalid outformat", procName, 1); if (!outroot) return ERROR_INT("outroot not specified", procName, 1); if ((gplot = gplotCreate(outroot, outformat, title, NULL, NULL)) == 0) return ERROR_INT("gplot not made", procName, 1); gplotAddPlot(gplot, nax, nay1, GPLOT_LINES, NULL); gplotAddPlot(gplot, nax, nay2, GPLOT_LINES, NULL); gplotMakeOutput(gplot); gplotDestroy(&gplot); return 0; }
/*! * gplotSimpleXYN() * * Input: nax (<optional>; can be NULL) * naay (numaa of arrays to plot against @nax) * outformat (GPLOT_PNG, GPLOT_PS, GPLOT_EPS, GPLOT_X11, * GPLOT_LATEX) * outroot (root of output files) * title (<optional>) * Return: 0 if OK, 1 on error * * Notes: * (1) This gives line plots of each Numa in @naa against nax, * generated in the specified output format. The title is optional. * (2) @nax is optional. If NULL, each Numa array is plotted against * the array index. * (3) When calling these simple plot functions more than once, use * different @outroot to avoid overwriting the output files. */ l_int32 gplotSimpleXYN(NUMA *nax, NUMAA *naay, l_int32 outformat, const char *outroot, const char *title) { l_int32 i, n; GPLOT *gplot; NUMA *nay; PROCNAME("gplotSimpleXYN"); if (!naay) return ERROR_INT("naay not defined", procName, 1); if ((n = numaaGetCount(naay)) == 0) return ERROR_INT("no numa in array", procName, 1); if (outformat != GPLOT_PNG && outformat != GPLOT_PS && outformat != GPLOT_EPS && outformat != GPLOT_X11 && outformat != GPLOT_LATEX) return ERROR_INT("invalid outformat", procName, 1); if (!outroot) return ERROR_INT("outroot not specified", procName, 1); if ((gplot = gplotCreate(outroot, outformat, title, NULL, NULL)) == 0) return ERROR_INT("gplot not made", procName, 1); for (i = 0; i < n; i++) { nay = numaaGetNuma(naay, i, L_CLONE); gplotAddPlot(gplot, nax, nay, GPLOT_LINES, NULL); numaDestroy(&nay); } gplotMakeOutput(gplot); gplotDestroy(&gplot); return 0; }
/*! * \brief gplotSimpleXY1() * * \param[in] nax [optional] * \param[in] nay * \param[in] plotstyle GPLOT_LINES, GPLOT_POINTS, GPLOT_IMPULSES, * GPLOT_LINESPOINTS, GPLOT_DOTS * \param[in] outformat GPLOT_PNG, GPLOT_PS, GPLOT_EPS, GPLOT_LATEX * \param[in] outroot root of output files * \param[in] title [optional], can be NULL * \return 0 if OK, 1 on error * * <pre> * Notes: * (1) This gives a plot of a %nay vs %nax, generated in * the specified output format. The title is optional. * (2) Use 0 for default plotstyle (lines). * (3) %nax is optional. If NULL, %nay is plotted against * the array index. * (4) When calling these simple plot functions more than once, use * different %outroot to avoid overwriting the output files. * </pre> */ l_int32 gplotSimpleXY1(NUMA *nax, NUMA *nay, l_int32 plotstyle, l_int32 outformat, const char *outroot, const char *title) { GPLOT *gplot; PROCNAME("gplotSimpleXY1"); if (!nay) return ERROR_INT("nay not defined", procName, 1); if (plotstyle != GPLOT_LINES && plotstyle != GPLOT_POINTS && plotstyle != GPLOT_IMPULSES && plotstyle != GPLOT_LINESPOINTS && plotstyle != GPLOT_DOTS) return ERROR_INT("invalid plotstyle", procName, 1); if (outformat != GPLOT_PNG && outformat != GPLOT_PS && outformat != GPLOT_EPS && outformat != GPLOT_LATEX) return ERROR_INT("invalid outformat", procName, 1); if (!outroot) return ERROR_INT("outroot not specified", procName, 1); if ((gplot = gplotCreate(outroot, outformat, title, NULL, NULL)) == 0) return ERROR_INT("gplot not made", procName, 1); gplotAddPlot(gplot, nax, nay, plotstyle, NULL); gplotMakeOutput(gplot); gplotDestroy(&gplot); return 0; }
int main(int argc, char **argv) { char *filein, *fileout; char bigbuf[512]; l_int32 iplot, same; l_float32 gam; l_float64 gamma[] = {.5, 1.0, 1.5, 2.0, 2.5, -1.0}; GPLOT *gplot; NUMA *na, *nax; PIX *pixs, *pixd; static char mainName[] = "gammatest"; if (argc != 4) return ERROR_INT(" Syntax: gammatest filein gam fileout", mainName, 1); lept_mkdir("lept/gamma"); filein = argv[1]; gam = atof(argv[2]); fileout = argv[3]; if ((pixs = pixRead(filein)) == NULL) return ERROR_INT("pixs not made", mainName, 1); startTimer(); pixd = pixGammaTRC(NULL, pixs, gam, MINVAL, MAXVAL); fprintf(stderr, "Time for gamma: %7.3f sec\n", stopTimer()); pixGammaTRC(pixs, pixs, gam, MINVAL, MAXVAL); pixEqual(pixs, pixd, &same); if (!same) fprintf(stderr, "Error in pixGammaTRC!\n"); pixWrite(fileout, pixs, IFF_JFIF_JPEG); pixDestroy(&pixs); na = numaGammaTRC(gam, MINVAL, MAXVAL); gplotSimple1(na, GPLOT_PNG, "/tmp/lept/gamma/trc", "gamma trc"); l_fileDisplay("/tmp/lept/gamma/trc.png", 100, 100, 1.0); numaDestroy(&na); /* Plot gamma TRC maps */ gplot = gplotCreate("/tmp/lept/gamma/corr", GPLOT_PNG, "Mapping function for gamma correction", "value in", "value out"); nax = numaMakeSequence(0.0, 1.0, 256); for (iplot = 0; gamma[iplot] >= 0.0; iplot++) { na = numaGammaTRC(gamma[iplot], 30, 215); sprintf(bigbuf, "gamma = %3.1f", gamma[iplot]); gplotAddPlot(gplot, nax, na, GPLOT_LINES, bigbuf); numaDestroy(&na); } gplotMakeOutput(gplot); gplotDestroy(&gplot); l_fileDisplay("/tmp/lept/gamma/corr.png", 100, 100, 1.0); numaDestroy(&nax); return 0; }
int main(int argc, char **argv) { char *filein, *fileout; char bigbuf[512]; l_int32 iplot; l_float32 factor; /* scaled width of atan curve */ l_float32 fact[] = {.2, 0.4, 0.6, 0.8, 1.0, -1.0}; GPLOT *gplot; NUMA *na, *nax; PIX *pixs; static char mainName[] = "contrasttest"; if (argc != 4) return ERROR_INT(" Syntax: contrasttest filein factor fileout", mainName, 1); lept_mkdir("lept/contrast"); filein = argv[1]; factor = atof(argv[2]); fileout = argv[3]; if ((pixs = pixRead(filein)) == NULL) return ERROR_INT("pixs not made", mainName, 1); na = numaContrastTRC(factor); gplotSimple1(na, GPLOT_PNG, "/tmp/lept/contrast/trc1", "contrast trc"); l_fileDisplay("/tmp/lept/contrast/trc1.png", 0, 100, 1.0); numaDestroy(&na); /* Plot contrast TRC maps */ nax = numaMakeSequence(0.0, 1.0, 256); gplot = gplotCreate("/tmp/lept/contrast/trc2", GPLOT_PNG, "Atan mapping function for contrast enhancement", "value in", "value out"); for (iplot = 0; fact[iplot] >= 0.0; iplot++) { na = numaContrastTRC(fact[iplot]); sprintf(bigbuf, "factor = %3.1f", fact[iplot]); gplotAddPlot(gplot, nax, na, GPLOT_LINES, bigbuf); numaDestroy(&na); } gplotMakeOutput(gplot); gplotDestroy(&gplot); l_fileDisplay("/tmp/lept/contrast/trc2.png", 600, 100, 1.0); numaDestroy(&nax); /* Apply the input contrast enhancement */ pixContrastTRC(pixs, pixs, factor); pixWrite(fileout, pixs, IFF_PNG); pixDestroy(&pixs); return 0; }
main(int argc, char **argv) { l_int32 i, ival, n; l_float32 f, val; GPLOT *gplot; NUMA *na1, *na2, *na3; PIX *pixt; L_REGPARAMS *rp; if (regTestSetup(argc, argv, &rp)) return 1; /* Generate a 1D signal and plot it */ na1 = numaCreate(500); for (i = 0; i < 500; i++) { f = 48.3 * sin(0.13 * (l_float32)i); f += 63.4 * cos(0.21 * (l_float32)i); numaAddNumber(na1, f); } gplot = gplotCreate("/tmp/extrema", GPLOT_PNG, "Extrema test", "x", "y"); gplotAddPlot(gplot, NULL, na1, GPLOT_LINES, "plot 1"); /* Find the local min and max and plot them */ na2 = numaFindExtrema(na1, 38.3); n = numaGetCount(na2); na3 = numaCreate(n); for (i = 0; i < n; i++) { numaGetIValue(na2, i, &ival); numaGetFValue(na1, ival, &val); numaAddNumber(na3, val); } gplotAddPlot(gplot, na2, na3, GPLOT_POINTS, "plot 2"); gplotMakeOutput(gplot); #ifndef _WIN32 sleep(1); #else Sleep(1000); #endif /* _WIN32 */ regTestCheckFile(rp, "/tmp/extrema.png"); /* 0 */ pixt = pixRead("/tmp/extrema.png"); pixDisplayWithTitle(pixt, 100, 100, "Extrema test", rp->display); pixDestroy(&pixt); gplotDestroy(&gplot); numaDestroy(&na1); numaDestroy(&na2); numaDestroy(&na3); return regTestCleanup(rp); }
void numaPlot(Numa* numa, Numa* numaExtrema, Numa* numaExtrema2, l_int32 outformat, std::string plotName) { Numa* numaYValues = numaMakeYNuma(numaExtrema, numa); GPLOT *gplot; std::ostringstream name; std::ostringstream rootName; std::ostringstream title; rootName<<plotName<<outformat; gplot = gplotCreate(rootName.str().c_str(), outformat, name.str().c_str(), "x", "y"); gplotAddPlot(gplot, NULL, numa, GPLOT_LINES, "numa"); gplotAddPlot(gplot, numaExtrema, numaYValues, GPLOT_IMPULSES, "extrema"); if(numaExtrema2!=NULL) { Numa* numaYValues2 = numaMakeYNuma(numaExtrema2, numa); gplotAddPlot(gplot, numaExtrema2, numaYValues2, GPLOT_IMPULSES, "extrema2"); numaDestroy(&numaYValues2); } gplotMakeOutput(gplot); gplotDestroy(&gplot); numaDestroy(&numaYValues); }
int main(int argc, char **argv) { l_int32 size, i, n, n0; BOXA *boxa; GPLOT *gplot; NUMA *nax, *nay1, *nay2; PIX *pixs, *pixd; static char mainName[] = "pixa1_reg"; if (argc != 1) return ERROR_INT(" Syntax: pixa1_reg", mainName, 1); if ((pixs = pixRead("feyn.tif")) == NULL) return ERROR_INT("pixs not made", mainName, 1); /* ---------------- Remove small components --------------- */ boxa = pixConnComp(pixs, NULL, 8); n0 = boxaGetCount(boxa); nax = numaMakeSequence(0, 2, 51); nay1 = numaCreate(51); nay2 = numaCreate(51); boxaDestroy(&boxa); fprintf(stderr, "\n Select Large if Both\n"); fprintf(stderr, "Iter 0: n = %d\n", n0); numaAddNumber(nay1, n0); for (i = 1; i <= 50; i++) { size = 2 * i; pixd = pixSelectBySize(pixs, size, size, CONNECTIVITY, L_SELECT_IF_BOTH, L_SELECT_IF_GTE, NULL); boxa = pixConnComp(pixd, NULL, 8); n = boxaGetCount(boxa); numaAddNumber(nay1, n); fprintf(stderr, "Iter %d: n = %d\n", i, n); boxaDestroy(&boxa); pixDestroy(&pixd); } fprintf(stderr, "\n Select Large if Either\n"); fprintf(stderr, "Iter 0: n = %d\n", n0); numaAddNumber(nay2, n0); for (i = 1; i <= 50; i++) { size = 2 * i; pixd = pixSelectBySize(pixs, size, size, CONNECTIVITY, L_SELECT_IF_EITHER, L_SELECT_IF_GTE, NULL); boxa = pixConnComp(pixd, NULL, 8); n = boxaGetCount(boxa); numaAddNumber(nay2, n); fprintf(stderr, "Iter %d: n = %d\n", i, n); boxaDestroy(&boxa); pixDestroy(&pixd); } gplot = gplotCreate("/tmp/junkroot1", GPLOT_X11, "Select large: number of cc vs size removed", "min size", "number of c.c."); gplotAddPlot(gplot, nax, nay1, GPLOT_LINES, "select if both"); gplotAddPlot(gplot, nax, nay2, GPLOT_LINES, "select if either"); gplotMakeOutput(gplot); gplotDestroy(&gplot); /* ---------------- Remove large components --------------- */ numaEmpty(nay1); numaEmpty(nay2); fprintf(stderr, "\n Select Small if Both\n"); fprintf(stderr, "Iter 0: n = %d\n", 0); numaAddNumber(nay1, 0); for (i = 1; i <= 50; i++) { size = 2 * i; pixd = pixSelectBySize(pixs, size, size, CONNECTIVITY, L_SELECT_IF_BOTH, L_SELECT_IF_LTE, NULL); boxa = pixConnComp(pixd, NULL, 8); n = boxaGetCount(boxa); numaAddNumber(nay1, n); fprintf(stderr, "Iter %d: n = %d\n", i, n); boxaDestroy(&boxa); pixDestroy(&pixd); } fprintf(stderr, "\n Select Small if Either\n"); fprintf(stderr, "Iter 0: n = %d\n", 0); numaAddNumber(nay2, 0); for (i = 1; i <= 50; i++) { size = 2 * i; pixd = pixSelectBySize(pixs, size, size, CONNECTIVITY, L_SELECT_IF_EITHER, L_SELECT_IF_LTE, NULL); boxa = pixConnComp(pixd, NULL, 8); n = boxaGetCount(boxa); numaAddNumber(nay2, n); fprintf(stderr, "Iter %d: n = %d\n", i, n); boxaDestroy(&boxa); pixDestroy(&pixd); } gplot = gplotCreate("/tmp/junkroot2", GPLOT_X11, "Remove large: number of cc vs size removed", "min size", "number of c.c."); gplotAddPlot(gplot, nax, nay1, GPLOT_LINES, "select if both"); gplotAddPlot(gplot, nax, nay2, GPLOT_LINES, "select if either"); gplotMakeOutput(gplot); gplotDestroy(&gplot); numaDestroy(&nax); numaDestroy(&nay1); numaDestroy(&nay2); pixDestroy(&pixs); return 0; }
/*! * pixFindSkewSweep() * * Input: pixs (1 bpp) * &angle (<return> angle required to deskew, in degrees) * reduction (factor = 1, 2, 4 or 8) * sweeprange (half the full range; assumed about 0; in degrees) * sweepdelta (angle increment of sweep; in degrees) * Return: 0 if OK, 1 on error or if angle measurment not valid * * Notes: * (1) This examines the 'score' for skew angles with equal intervals. * (2) Caller must check the return value for validity of the result. */ l_int32 pixFindSkewSweep(PIX *pixs, l_float32 *pangle, l_int32 reduction, l_float32 sweeprange, l_float32 sweepdelta) { l_int32 ret, bzero, i, nangles; l_float32 deg2rad, theta; l_float32 sum, maxscore, maxangle; NUMA *natheta, *nascore; PIX *pix, *pixt; PROCNAME("pixFindSkewSweep"); if (!pixs) return ERROR_INT("pixs not defined", procName, 1); if (pixGetDepth(pixs) != 1) return ERROR_INT("pixs not 1 bpp", procName, 1); if (!pangle) return ERROR_INT("&angle not defined", procName, 1); if (reduction != 1 && reduction != 2 && reduction != 4 && reduction != 8) return ERROR_INT("reduction must be in {1,2,4,8}", procName, 1); *pangle = 0.0; /* init */ deg2rad = 3.1415926535 / 180.; ret = 0; /* Generate reduced image, if requested */ if (reduction == 1) pix = pixClone(pixs); else if (reduction == 2) pix = pixReduceRankBinaryCascade(pixs, 1, 0, 0, 0); else if (reduction == 4) pix = pixReduceRankBinaryCascade(pixs, 1, 1, 0, 0); else /* reduction == 8 */ pix = pixReduceRankBinaryCascade(pixs, 1, 1, 2, 0); pixZero(pix, &bzero); if (bzero) { pixDestroy(&pix); return 1; } nangles = (l_int32)((2. * sweeprange) / sweepdelta + 1); natheta = numaCreate(nangles); nascore = numaCreate(nangles); pixt = pixCreateTemplate(pix); if (!pix || !pixt) { ret = ERROR_INT("pix and pixt not both made", procName, 1); goto cleanup; } if (!natheta || !nascore) { ret = ERROR_INT("natheta and nascore not both made", procName, 1); goto cleanup; } for (i = 0; i < nangles; i++) { theta = -sweeprange + i * sweepdelta; /* degrees */ /* Shear pix about the UL corner and put the result in pixt */ pixVShearCorner(pixt, pix, deg2rad * theta, L_BRING_IN_WHITE); /* Get score */ pixFindDifferentialSquareSum(pixt, &sum); #if DEBUG_PRINT_SCORES L_INFO("sum(%7.2f) = %7.0f\n", procName, theta, sum); #endif /* DEBUG_PRINT_SCORES */ /* Save the result in the output arrays */ numaAddNumber(nascore, sum); numaAddNumber(natheta, theta); } /* Find the location of the maximum (i.e., the skew angle) * by fitting the largest data point and its two neighbors * to a quadratic, using lagrangian interpolation. */ numaFitMax(nascore, &maxscore, natheta, &maxangle); *pangle = maxangle; #if DEBUG_PRINT_SWEEP L_INFO(" From sweep: angle = %7.3f, score = %7.3f\n", procName, maxangle, maxscore); #endif /* DEBUG_PRINT_SWEEP */ #if DEBUG_PLOT_SCORES /* Plot the result -- the scores versus rotation angle -- * using gnuplot with GPLOT_LINES (lines connecting data points). * The GPLOT data structure is first created, with the * appropriate data incorporated from the two input NUMAs, * and then the function gplotMakeOutput() uses gnuplot to * generate the output plot. This can be either a .png file * or a .ps file, depending on whether you use GPLOT_PNG * or GPLOT_PS. */ {GPLOT *gplot; gplot = gplotCreate("sweep_output", GPLOT_PNG, "Sweep. Variance of difference of ON pixels vs. angle", "angle (deg)", "score"); gplotAddPlot(gplot, natheta, nascore, GPLOT_LINES, "plot1"); gplotAddPlot(gplot, natheta, nascore, GPLOT_POINTS, "plot2"); gplotMakeOutput(gplot); gplotDestroy(&gplot); } #endif /* DEBUG_PLOT_SCORES */ cleanup: pixDestroy(&pix); pixDestroy(&pixt); numaDestroy(&nascore); numaDestroy(&natheta); return ret; }
int main(int argc, char **argv) { l_int32 i, j, w, h, same; l_float32 t, t1, t2; GPLOT *gplot; NUMA *nax, *nay1, *nay2; PIX *pixs, *pixd, *pixt1, *pixt2, *pixt3, *pixt4; PIXA *pixa; static char mainName[] = "rank_reg"; if (argc != 1) return ERROR_INT(" Syntax: rank_reg", mainName, 1); if ((pixs = pixRead("lucasta.150.jpg")) == NULL) return ERROR_INT("pixs not made", mainName, 1); pixGetDimensions(pixs, &w, &h, NULL); startTimer(); pixd = pixRankFilterGray(pixs, 15, 15, 0.4); t = stopTimer(); fprintf(stderr, "Time = %7.3f sec\n", t); fprintf(stderr, "MPix/sec: %7.3f\n", 0.000001 * w * h / t); pixDisplay(pixs, 0, 200); pixDisplay(pixd, 600, 200); pixWrite("/tmp/filter.png", pixd, IFF_PNG); pixDestroy(&pixd); /* Get results for dilation */ startTimer(); pixt1 = pixDilateGray(pixs, 15, 15); t = stopTimer(); fprintf(stderr, "Dilation time = %7.3f sec\n", t); /* Get results for erosion */ pixt2 = pixErodeGray(pixs, 15, 15); /* Get results using the rank filter for rank = 0.0 and 1.0. * Don't use 0.0 or 1.0, because those are dispatched * automatically to erosion and dilation! */ pixt3 = pixRankFilterGray(pixs, 15, 15, 0.0001); pixt4 = pixRankFilterGray(pixs, 15, 15, 0.9999); /* Compare */ pixEqual(pixt1, pixt4, &same); if (same) fprintf(stderr, "Correct: dilation results same as rank 1.0\n"); else fprintf(stderr, "Error: dilation results differ from rank 1.0\n"); pixEqual(pixt2, pixt3, &same); if (same) fprintf(stderr, "Correct: erosion results same as rank 0.0\n"); else fprintf(stderr, "Error: erosion results differ from rank 0.0\n"); pixDestroy(&pixt1); pixDestroy(&pixt2); pixDestroy(&pixt3); pixDestroy(&pixt4); fprintf(stderr, "\n----------------------------------------\n"); fprintf(stderr, "The next part takes about 30 seconds\n"); fprintf(stderr, "----------------------------------------\n\n"); nax = numaMakeSequence(1, 1, SIZE); nay1 = numaCreate(SIZE); nay2 = numaCreate(SIZE); gplot = gplotCreate("/tmp/rankroot", GPLOT_X11, "sec/MPix vs filter size", "size", "time"); for (i = 1; i <= SIZE; i++) { t1 = t2 = 0.0; for (j = 0; j < 5; j++) { startTimer(); pixt1 = pixRankFilterGray(pixs, i, SIZE + 1, 0.5); t1 += stopTimer(); pixDestroy(&pixt1); startTimer(); pixt1 = pixRankFilterGray(pixs, SIZE + 1, i, 0.5); t2 += stopTimer(); if (j == 0) pixDisplayWrite(pixt1, 1); pixDestroy(&pixt1); } numaAddNumber(nay1, 1000000. * t1 / (5. * w * h)); numaAddNumber(nay2, 1000000. * t2 / (5. * w * h)); } gplotAddPlot(gplot, nax, nay1, GPLOT_LINES, "vertical"); gplotAddPlot(gplot, nax, nay2, GPLOT_LINES, "horizontal"); gplotMakeOutput(gplot); gplotDestroy(&gplot); /* Display tiled */ pixa = pixaReadFiles("/tmp/display", "file"); pixd = pixaDisplayTiledAndScaled(pixa, 8, 250, 5, 0, 25, 2); pixWrite("/tmp/tiles.jpg", pixd, IFF_JFIF_JPEG); pixDestroy(&pixd); pixaDestroy(&pixa); pixDestroy(&pixs); pixDisplayWrite(NULL, -1); /* clear out */ pixs = pixRead("test8.jpg"); for (i = 1; i <= 4; i++) { pixt1 = pixScaleGrayRank2(pixs, i); pixDisplay(pixt1, 300 * (i - 1), 100); pixDestroy(&pixt1); } pixDestroy(&pixs); pixs = pixRead("test24.jpg"); pixt1 = pixConvertRGBToLuminance(pixs); pixt2 = pixScale(pixt1, 1.5, 1.5); for (i = 1; i <= 4; i++) { for (j = 1; j <= 4; j++) { pixt3 = pixScaleGrayRankCascade(pixt2, i, j, 0, 0); pixDisplayWrite(pixt3, 1); pixDestroy(&pixt3); } } pixDestroy(&pixt1); pixDestroy(&pixt2); pixDestroy(&pixs); pixDisplayMultiple("/tmp/display/file*"); return 0; }
int main(int argc, char **argv) { char label[512]; l_int32 rval, gval, bval, w, h, i, j, rwhite, gwhite, bwhite, count; l_uint32 pixel; GPLOT *gplot1, *gplot2; NUMA *naseq, *na; NUMAA *naa1, *naa2; PIX *pixs, *pixt, *pixt0, *pixt1, *pixt2; PIX *pixr, *pixg, *pixb; PIXA *pixa; PIXCMAP *cmap; static char mainName[] = "colorspacetest"; if (argc != 2) return ERROR_INT(" Syntax: colorspacetest filein", mainName, 1); if ((pixs = pixRead(argv[1])) == NULL) return ERROR_INT("pixs not made", mainName, 1); /* Generate colors by sampling hue with max sat and value. * This was used to make the color strip 19-colors.png. */ pixa = pixaCreate(19); for (i = 0; i < 19; i++) { convertHSVToRGB((240 * i / 18), 255, 255, &rval, &gval, &bval); composeRGBPixel(rval, gval, bval, &pixel); pixt1 = pixCreate(50, 100, 32); pixSetAllArbitrary(pixt1, pixel); pixaAddPix(pixa, pixt1, L_INSERT); } pixt2 = pixaDisplayTiledInRows(pixa, 32, 1100, 1.0, 0, 0, 0); pixDisplayWrite(pixt2, 1); pixDestroy(&pixt2); pixaDestroy(&pixa); /* Colorspace conversion in rgb */ pixDisplayWrite(pixs, 1); pixt = pixConvertRGBToHSV(NULL, pixs); pixDisplayWrite(pixt, 1); pixConvertHSVToRGB(pixt, pixt); pixDisplayWrite(pixt, 1); pixDestroy(&pixt); /* Colorspace conversion on a colormap */ pixt = pixOctreeQuantNumColors(pixs, 25, 0); pixDisplayWrite(pixt, 1); cmap = pixGetColormap(pixt); pixcmapWriteStream(stderr, cmap); pixcmapConvertRGBToHSV(cmap); pixcmapWriteStream(stderr, cmap); pixDisplayWrite(pixt, 1); pixcmapConvertHSVToRGB(cmap); pixcmapWriteStream(stderr, cmap); pixDisplayWrite(pixt, 1); pixDestroy(&pixt); /* Color content extraction */ pixColorContent(pixs, 0, 0, 0, 0, &pixr, &pixg, &pixb); pixDisplayWrite(pixr, 1); pixDisplayWrite(pixg, 1); pixDisplayWrite(pixb, 1); pixDestroy(&pixr); pixDestroy(&pixg); pixDestroy(&pixb); /* Color content measurement */ pixa = pixaCreate(20); naseq = numaMakeSequence(100, 5, 20); naa1 = numaaCreate(6); naa2 = numaaCreate(6); for (i = 0; i < 6; i++) { na = numaCreate(20); numaaAddNuma(naa1, na, L_COPY); numaaAddNuma(naa2, na, L_INSERT); } pixGetDimensions(pixs, &w, &h, NULL); for (i = 0; i < 20; i++) { rwhite = 100 + 5 * i; gwhite = 200 - 5 * i; bwhite = 150; pixt0 = pixGlobalNormRGB(NULL, pixs, rwhite, gwhite, bwhite, 255); pixaAddPix(pixa, pixt0, L_INSERT); pixt1 = pixColorMagnitude(pixs, rwhite, gwhite, bwhite, L_MAX_DIFF_FROM_AVERAGE_2); for (j = 0; j < 6; j++) { pixt2 = pixThresholdToBinary(pixt1, 30 + 10 * j); pixInvert(pixt2, pixt2); pixCountPixels(pixt2, &count, NULL); na = numaaGetNuma(naa1, j, L_CLONE); numaAddNumber(na, (l_float32)count / (l_float32)(w * h)); numaDestroy(&na); pixDestroy(&pixt2); } pixDestroy(&pixt1); pixt1 = pixColorMagnitude(pixs, rwhite, gwhite, bwhite, L_MAX_MIN_DIFF_FROM_2); for (j = 0; j < 6; j++) { pixt2 = pixThresholdToBinary(pixt1, 30 + 10 * j); pixInvert(pixt2, pixt2); pixCountPixels(pixt2, &count, NULL); na = numaaGetNuma(naa2, j, L_CLONE); numaAddNumber(na, (l_float32)count / (l_float32)(w * h)); numaDestroy(&na); pixDestroy(&pixt2); } pixDestroy(&pixt1); } gplot1 = gplotCreate("/tmp/junkplot1", GPLOT_X11, "Fraction with given color (diff from average)", "white point space for red", "amount of color"); gplot2 = gplotCreate("/tmp/junkplot2", GPLOT_X11, "Fraction with given color (min diff)", "white point space for red", "amount of color"); for (j = 0; j < 6; j++) { na = numaaGetNuma(naa1, j, L_CLONE); sprintf(label, "thresh %d", 30 + 10 * j); gplotAddPlot(gplot1, naseq, na, GPLOT_LINES, label); numaDestroy(&na); na = numaaGetNuma(naa2, j, L_CLONE); gplotAddPlot(gplot2, naseq, na, GPLOT_LINES, label); numaDestroy(&na); } gplotMakeOutput(gplot1); gplotMakeOutput(gplot2); gplotDestroy(&gplot1); gplotDestroy(&gplot2); pixt1 = pixaDisplayTiledAndScaled(pixa, 32, 250, 4, 0, 10, 2); pixWrite("/tmp/junkcolormag", pixt1, IFF_PNG); pixDisplayWithTitle(pixt1, 0, 100, "Color magnitude", 1); pixDestroy(&pixt1); pixaDestroy(&pixa); numaDestroy(&naseq); numaaDestroy(&naa1); numaaDestroy(&naa2); pixDisplayMultiple("/tmp/display/file*"); pixDestroy(&pixs); return 0; }
int main(int argc, char **argv) { char *str1, *str2; l_int32 i; size_t size1, size2; l_float32 x, y1, y2, pi; GPLOT *gplot1, *gplot2, *gplot3, *gplot4, *gplot5; NUMA *nax, *nay1, *nay2; static char mainName[] = "plottest"; if (argc != 1) return ERROR_INT(" Syntax: plottest", mainName, 1); /* Generate plot data */ nax = numaCreate(0); nay1 = numaCreate(0); nay2 = numaCreate(0); pi = 3.1415926535; for (i = 0; i < 180; i++) { x = (pi / 180.) * i; y1 = (l_float32)sin(2.4 * x); y2 = (l_float32)cos(2.4 * x); numaAddNumber(nax, x); numaAddNumber(nay1, y1); numaAddNumber(nay2, y2); } /* Show the plot */ gplot1 = gplotCreate("/tmp/plotroot1", GPLOT_OUTPUT, "Example plots", "theta", "f(theta)"); gplotAddPlot(gplot1, nax, nay1, GPLOT_STYLE, "sin (2.4 * theta)"); gplotAddPlot(gplot1, nax, nay2, GPLOT_STYLE, "cos (2.4 * theta)"); gplotMakeOutput(gplot1); /* Also save the plot to png */ gplot1->outformat = GPLOT_PNG; stringReplace(&gplot1->outname, "/tmp/plotroot1.png"); gplotMakeOutput(gplot1); /* Test gplot serialization */ gplotWrite("/tmp/gplot1", gplot1); if ((gplot2 = gplotRead("/tmp/gplot1")) == NULL) return ERROR_INT("gplotRead failure!", mainName, 1); gplotWrite("/tmp/gplot2", gplot2); /* Are the two written gplot files the same? */ str1 = (char *)l_binaryRead("/tmp/gplot1", &size1); str2 = (char *)l_binaryRead("/tmp/gplot2", &size2); if (size1 != size2) fprintf(stderr, "Error: size1 = %lu, size2 = %lu\n", (unsigned long)size1, (unsigned long)size2); else fprintf(stderr, "Correct: size1 = size2 = %lu\n", (unsigned long)size1); if (strcmp(str1, str2)) fprintf(stderr, "Error: str1 != str2\n"); else fprintf(stderr, "Correct: str1 == str2\n"); lept_free(str1); lept_free(str2); /* Read from file and regenerate the plot */ gplot3 = gplotRead("/tmp/gplot2"); stringReplace(&gplot3->title , "Example plots regen"); gplot3->outformat = GPLOT_X11; gplotMakeOutput(gplot3); /* Build gplot but do not make the output formatted stuff */ gplot4 = gplotCreate("/tmp/plotroot2", GPLOT_OUTPUT, "Example plots 2", "theta", "f(theta)"); gplotAddPlot(gplot4, nax, nay1, GPLOT_STYLE, "sin (2.4 * theta)"); gplotAddPlot(gplot4, nax, nay2, GPLOT_STYLE, "cos (2.4 * theta)"); /* Write, read back, and generate the plot */ gplotWrite("/tmp/gplot4", gplot4); if ((gplot5 = gplotRead("/tmp/gplot4")) == NULL) return ERROR_INT("gplotRead failure!", mainName, 1); gplotMakeOutput(gplot5); gplotDestroy(&gplot1); gplotDestroy(&gplot2); gplotDestroy(&gplot3); gplotDestroy(&gplot4); gplotDestroy(&gplot5); numaDestroy(&nax); numaDestroy(&nay1); numaDestroy(&nay2); return 0; }
/*! * \brief pixThresholdByConnComp() * * \param[in] pixs depth > 1, colormap OK * \param[in] pixm [optional] 1 bpp mask giving region to ignore by setting * pixels to white; use NULL if no mask * \param[in] start, end, incr binarization threshold levels to test * \param[in] thresh48 threshold on normalized difference between the * numbers of 4 and 8 connected components * \param[in] threshdiff threshold on normalized difference between the * number of 4 cc at successive iterations * \param[out] pglobthresh [optional] best global threshold; 0 * if no threshold is found * \param[out] ppixd [optional] image thresholded to binary, or * null if no threshold is found * \param[in] debugflag 1 for plotted results * \return 0 if OK, 1 on error or if no threshold is found * * <pre> * Notes: * (1) This finds a global threshold based on connected components. * Although slow, it is reasonable to use it in a situation where * (a) the background in the image is relatively uniform, and * (b) the result will be fed to an OCR program that accepts 1 bpp * images and works best with easily segmented characters. * The reason for (b) is that this selects a threshold with a * minimum number of both broken characters and merged characters. * (2) If the pix has color, it is converted to gray using the * max component. * (3) Input 0 to use default values for any of these inputs: * %start, %end, %incr, %thresh48, %threshdiff. * (4) This approach can be understood as follows. When the * binarization threshold is varied, the numbers of c.c. identify * four regimes: * (a) For low thresholds, text is broken into small pieces, and * the number of c.c. is large, with the 4 c.c. significantly * exceeding the 8 c.c. * (b) As the threshold rises toward the optimum value, the text * characters coalesce and there is very little difference * between the numbers of 4 and 8 c.c, which both go * through a minimum. * (c) Above this, the image background gets noisy because some * pixels are(thresholded to foreground, and the numbers * of c.c. quickly increase, with the 4 c.c. significantly * larger than the 8 c.c. * (d) At even higher thresholds, the image background noise * coalesces as it becomes mostly foreground, and the * number of c.c. drops quickly. * (5) If there is no global threshold that distinguishes foreground * text from background (e.g., weak text over a background that * has significant variation and/or bleedthrough), this returns 1, * which the caller should check. * </pre> */ l_int32 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) { l_int32 i, thresh, n, n4, n8, mincounts, found, globthresh; l_float32 count4, count8, firstcount4, prevcount4, diff48, diff4; GPLOT *gplot; NUMA *na4, *na8; PIX *pix1, *pix2, *pix3; PROCNAME("pixThresholdByConnComp"); if (pglobthresh) *pglobthresh = 0; if (ppixd) *ppixd = NULL; if (!pixs || pixGetDepth(pixs) == 1) return ERROR_INT("pixs undefined or 1 bpp", procName, 1); if (pixm && pixGetDepth(pixm) != 1) return ERROR_INT("pixm must be 1 bpp", procName, 1); /* Assign default values if requested */ if (start <= 0) start = 80; if (end <= 0) end = 200; if (incr <= 0) incr = 10; if (thresh48 <= 0.0) thresh48 = 0.01; if (threshdiff <= 0.0) threshdiff = 0.01; if (start > end) return ERROR_INT("invalid start,end", procName, 1); /* Make 8 bpp, using the max component if color. */ if (pixGetColormap(pixs)) pix1 = pixRemoveColormap(pixs, REMOVE_CMAP_BASED_ON_SRC); else pix1 = pixClone(pixs); if (pixGetDepth(pix1) == 32) pix2 = pixConvertRGBToGrayMinMax(pix1, L_CHOOSE_MAX); else pix2 = pixConvertTo8(pix1, 0); pixDestroy(&pix1); /* Mask out any non-text regions. Do this in-place, because pix2 * can never be the same pix as pixs. */ if (pixm) pixSetMasked(pix2, pixm, 255); /* Make sure there are enough components to get a valid signal */ pix3 = pixConvertTo1(pix2, start); pixCountConnComp(pix3, 4, &n4); pixDestroy(&pix3); mincounts = 500; if (n4 < mincounts) { L_INFO("Insufficient component count: %d\n", procName, n4); pixDestroy(&pix2); return 1; } /* Compute the c.c. data */ na4 = numaCreate(0); na8 = numaCreate(0); numaSetParameters(na4, start, incr); numaSetParameters(na8, start, incr); for (thresh = start, i = 0; thresh <= end; thresh += incr, i++) { pix3 = pixConvertTo1(pix2, thresh); pixCountConnComp(pix3, 4, &n4); pixCountConnComp(pix3, 8, &n8); numaAddNumber(na4, n4); numaAddNumber(na8, n8); pixDestroy(&pix3); } if (debugflag) { gplot = gplotCreate("/tmp/threshroot", GPLOT_PNG, "number of cc vs. threshold", "threshold", "number of cc"); gplotAddPlot(gplot, NULL, na4, GPLOT_LINES, "plot 4cc"); gplotAddPlot(gplot, NULL, na8, GPLOT_LINES, "plot 8cc"); gplotMakeOutput(gplot); gplotDestroy(&gplot); } n = numaGetCount(na4); found = FALSE; for (i = 0; i < n; i++) { if (i == 0) { numaGetFValue(na4, i, &firstcount4); prevcount4 = firstcount4; } else { numaGetFValue(na4, i, &count4); numaGetFValue(na8, i, &count8); diff48 = (count4 - count8) / firstcount4; diff4 = L_ABS(prevcount4 - count4) / firstcount4; if (debugflag) { fprintf(stderr, "diff48 = %7.3f, diff4 = %7.3f\n", diff48, diff4); } if (diff48 < thresh48 && diff4 < threshdiff) { found = TRUE; break; } prevcount4 = count4; } } numaDestroy(&na4); numaDestroy(&na8); if (found) { globthresh = start + i * incr; if (pglobthresh) *pglobthresh = globthresh; if (ppixd) { *ppixd = pixConvertTo1(pix2, globthresh); pixCopyResolution(*ppixd, pixs); } if (debugflag) fprintf(stderr, "global threshold = %d\n", globthresh); pixDestroy(&pix2); return 0; } if (debugflag) fprintf(stderr, "no global threshold found\n"); pixDestroy(&pix2); return 1; }
main(int argc, char **argv) { char *filein, *fileout; char bigbuf[512]; l_int32 iplot; l_float32 factor; /* scaled width of atan curve */ l_float32 fact[NPLOTS] = {.2, 0.4, 0.6, 0.8, 1.0}; GPLOT *gplot; NUMA *na, *nax; PIX *pixs, *pixd; static char mainName[] = "contrasttest"; if (argc != 4) return ERROR_INT(" Syntax: contrasttest filein factor fileout", mainName, 1); filein = argv[1]; factor = atof(argv[2]); fileout = argv[3]; if ((pixs = pixRead(filein)) == NULL) return ERROR_INT("pixs not made", mainName, 1); #if 0 startTimer(); pixContrastTRC(pixs, pixs, factor); fprintf(stderr, "Time for contrast: %7.3f sec\n", stopTimer()); pixWrite(fileout, pixs, IFF_JFIF_JPEG); pixDestroy(&pixs); #endif #if 0 startTimer(); pixd = pixContrastTRC(NULL, pixs, factor); fprintf(stderr, "Time for contrast: %7.3f sec\n", stopTimer()); pixWrite(fileout, pixd, IFF_JFIF_JPEG); pixDestroy(&pixs); pixDestroy(&pixd); #endif na = numaContrastTRC(factor); gplotSimple1(na, GPLOT_X11, "junkroot", "contrast trc"); numaDestroy(&na); #if 1 /* plot contrast TRC maps */ nax = numaMakeSequence(0.0, 1.0, 256); gplot = gplotCreate("junkmap", GPLOT_X11, "Atan mapping function for contrast enhancement", "value in", "value out"); for (iplot = 0; iplot < NPLOTS; iplot++) { na = numaContrastTRC(fact[iplot]); sprintf(bigbuf, "factor = %3.1f", fact[iplot]); gplotAddPlot(gplot, nax, na, GPLOT_LINES, bigbuf); numaDestroy(&na); } gplotMakeOutput(gplot); gplotDestroy(&gplot); numaDestroy(&nax); #endif return 0; }
/*! * pixFindSkewSweepAndSearchScorePivot() * * Input: pixs (1 bpp) * &angle (<return> angle required to deskew; in degrees) * &conf (<return> confidence given by ratio of max/min score) * &endscore (<optional return> max score; use NULL to ignore) * redsweep (sweep reduction factor = 1, 2, 4 or 8) * redsearch (binary search reduction factor = 1, 2, 4 or 8; * and must not exceed redsweep) * sweepcenter (angle about which sweep is performed; in degrees) * sweeprange (half the full range, taken about sweepcenter; * in degrees) * sweepdelta (angle increment of sweep; in degrees) * minbsdelta (min binary search increment angle; in degrees) * pivot (L_SHEAR_ABOUT_CORNER, L_SHEAR_ABOUT_CENTER) * Return: 0 if OK, 1 on error or if angle measurment not valid * * Notes: * (1) See notes in pixFindSkewSweepAndSearchScore(). * (2) This allows choice of shear pivoting from either the UL corner * or the center. For small angles, the ability to discriminate * angles is better with shearing from the UL corner. However, * for large angles (say, greater than 20 degrees), it is better * to shear about the center because a shear from the UL corner * loses too much of the image. */ l_int32 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) { l_int32 ret, bzero, i, nangles, n, ratio, maxindex, minloc; l_int32 width, height; l_float32 deg2rad, theta, delta; l_float32 sum, maxscore, maxangle; l_float32 centerangle, leftcenterangle, rightcenterangle; l_float32 lefttemp, righttemp; l_float32 bsearchscore[5]; l_float32 minscore, minthresh; l_float32 rangeleft; NUMA *natheta, *nascore; PIX *pixsw, *pixsch, *pixt1, *pixt2; PROCNAME("pixFindSkewSweepAndSearchScorePivot"); if (!pixs) return ERROR_INT("pixs not defined", procName, 1); if (pixGetDepth(pixs) != 1) return ERROR_INT("pixs not 1 bpp", procName, 1); if (!pangle) return ERROR_INT("&angle not defined", procName, 1); if (!pconf) return ERROR_INT("&conf not defined", procName, 1); if (redsweep != 1 && redsweep != 2 && redsweep != 4 && redsweep != 8) return ERROR_INT("redsweep must be in {1,2,4,8}", procName, 1); if (redsearch != 1 && redsearch != 2 && redsearch != 4 && redsearch != 8) return ERROR_INT("redsearch must be in {1,2,4,8}", procName, 1); if (redsearch > redsweep) return ERROR_INT("redsearch must not exceed redsweep", procName, 1); if (pivot != L_SHEAR_ABOUT_CORNER && pivot != L_SHEAR_ABOUT_CENTER) return ERROR_INT("invalid pivot", procName, 1); *pangle = 0.0; *pconf = 0.0; deg2rad = 3.1415926535 / 180.; ret = 0; /* Generate reduced image for binary search, if requested */ if (redsearch == 1) pixsch = pixClone(pixs); else if (redsearch == 2) pixsch = pixReduceRankBinaryCascade(pixs, 1, 0, 0, 0); else if (redsearch == 4) pixsch = pixReduceRankBinaryCascade(pixs, 1, 1, 0, 0); else /* redsearch == 8 */ pixsch = pixReduceRankBinaryCascade(pixs, 1, 1, 2, 0); pixZero(pixsch, &bzero); if (bzero) { pixDestroy(&pixsch); return 1; } /* Generate reduced image for sweep, if requested */ ratio = redsweep / redsearch; if (ratio == 1) { pixsw = pixClone(pixsch); } else { /* ratio > 1 */ if (ratio == 2) pixsw = pixReduceRankBinaryCascade(pixsch, 1, 0, 0, 0); else if (ratio == 4) pixsw = pixReduceRankBinaryCascade(pixsch, 1, 2, 0, 0); else /* ratio == 8 */ pixsw = pixReduceRankBinaryCascade(pixsch, 1, 2, 2, 0); } pixt1 = pixCreateTemplate(pixsw); if (ratio == 1) pixt2 = pixClone(pixt1); else pixt2 = pixCreateTemplate(pixsch); nangles = (l_int32)((2. * sweeprange) / sweepdelta + 1); natheta = numaCreate(nangles); nascore = numaCreate(nangles); if (!pixsch || !pixsw) { ret = ERROR_INT("pixsch and pixsw not both made", procName, 1); goto cleanup; } if (!pixt1 || !pixt2) { ret = ERROR_INT("pixt1 and pixt2 not both made", procName, 1); goto cleanup; } if (!natheta || !nascore) { ret = ERROR_INT("natheta and nascore not both made", procName, 1); goto cleanup; } /* Do sweep */ rangeleft = sweepcenter - sweeprange; for (i = 0; i < nangles; i++) { theta = rangeleft + i * sweepdelta; /* degrees */ /* Shear pix and put the result in pixt1 */ if (pivot == L_SHEAR_ABOUT_CORNER) pixVShearCorner(pixt1, pixsw, deg2rad * theta, L_BRING_IN_WHITE); else pixVShearCenter(pixt1, pixsw, deg2rad * theta, L_BRING_IN_WHITE); /* Get score */ pixFindDifferentialSquareSum(pixt1, &sum); #if DEBUG_PRINT_SCORES L_INFO("sum(%7.2f) = %7.0f\n", procName, theta, sum); #endif /* DEBUG_PRINT_SCORES */ /* Save the result in the output arrays */ numaAddNumber(nascore, sum); numaAddNumber(natheta, theta); } /* Find the largest of the set (maxscore at maxangle) */ numaGetMax(nascore, &maxscore, &maxindex); numaGetFValue(natheta, maxindex, &maxangle); #if DEBUG_PRINT_SWEEP L_INFO(" From sweep: angle = %7.3f, score = %7.3f\n", procName, maxangle, maxscore); #endif /* DEBUG_PRINT_SWEEP */ #if DEBUG_PLOT_SCORES /* Plot the sweep result -- the scores versus rotation angle -- * using gnuplot with GPLOT_LINES (lines connecting data points). */ {GPLOT *gplot; gplot = gplotCreate("sweep_output", GPLOT_PNG, "Sweep. Variance of difference of ON pixels vs. angle", "angle (deg)", "score"); gplotAddPlot(gplot, natheta, nascore, GPLOT_LINES, "plot1"); gplotAddPlot(gplot, natheta, nascore, GPLOT_POINTS, "plot2"); gplotMakeOutput(gplot); gplotDestroy(&gplot); } #endif /* DEBUG_PLOT_SCORES */ /* Check if the max is at the end of the sweep. */ n = numaGetCount(natheta); if (maxindex == 0 || maxindex == n - 1) { L_WARNING("max found at sweep edge\n", procName); goto cleanup; } /* Empty the numas for re-use */ numaEmpty(nascore); numaEmpty(natheta); /* Do binary search to find skew angle. * First, set up initial three points. */ centerangle = maxangle; if (pivot == L_SHEAR_ABOUT_CORNER) { pixVShearCorner(pixt2, pixsch, deg2rad * centerangle, L_BRING_IN_WHITE); pixFindDifferentialSquareSum(pixt2, &bsearchscore[2]); pixVShearCorner(pixt2, pixsch, deg2rad * (centerangle - sweepdelta), L_BRING_IN_WHITE); pixFindDifferentialSquareSum(pixt2, &bsearchscore[0]); pixVShearCorner(pixt2, pixsch, deg2rad * (centerangle + sweepdelta), L_BRING_IN_WHITE); pixFindDifferentialSquareSum(pixt2, &bsearchscore[4]); } else { pixVShearCenter(pixt2, pixsch, deg2rad * centerangle, L_BRING_IN_WHITE); pixFindDifferentialSquareSum(pixt2, &bsearchscore[2]); pixVShearCenter(pixt2, pixsch, deg2rad * (centerangle - sweepdelta), L_BRING_IN_WHITE); pixFindDifferentialSquareSum(pixt2, &bsearchscore[0]); pixVShearCenter(pixt2, pixsch, deg2rad * (centerangle + sweepdelta), L_BRING_IN_WHITE); pixFindDifferentialSquareSum(pixt2, &bsearchscore[4]); } numaAddNumber(nascore, bsearchscore[2]); numaAddNumber(natheta, centerangle); numaAddNumber(nascore, bsearchscore[0]); numaAddNumber(natheta, centerangle - sweepdelta); numaAddNumber(nascore, bsearchscore[4]); numaAddNumber(natheta, centerangle + sweepdelta); /* Start the search */ delta = 0.5 * sweepdelta; while (delta >= minbsdelta) { /* Get the left intermediate score */ leftcenterangle = centerangle - delta; if (pivot == L_SHEAR_ABOUT_CORNER) pixVShearCorner(pixt2, pixsch, deg2rad * leftcenterangle, L_BRING_IN_WHITE); else pixVShearCenter(pixt2, pixsch, deg2rad * leftcenterangle, L_BRING_IN_WHITE); pixFindDifferentialSquareSum(pixt2, &bsearchscore[1]); numaAddNumber(nascore, bsearchscore[1]); numaAddNumber(natheta, leftcenterangle); /* Get the right intermediate score */ rightcenterangle = centerangle + delta; if (pivot == L_SHEAR_ABOUT_CORNER) pixVShearCorner(pixt2, pixsch, deg2rad * rightcenterangle, L_BRING_IN_WHITE); else pixVShearCenter(pixt2, pixsch, deg2rad * rightcenterangle, L_BRING_IN_WHITE); pixFindDifferentialSquareSum(pixt2, &bsearchscore[3]); numaAddNumber(nascore, bsearchscore[3]); numaAddNumber(natheta, rightcenterangle); /* Find the maximum of the five scores and its location. * Note that the maximum must be in the center * three values, not in the end two. */ maxscore = bsearchscore[1]; maxindex = 1; for (i = 2; i < 4; i++) { if (bsearchscore[i] > maxscore) { maxscore = bsearchscore[i]; maxindex = i; } } /* Set up score array to interpolate for the next iteration */ lefttemp = bsearchscore[maxindex - 1]; righttemp = bsearchscore[maxindex + 1]; bsearchscore[2] = maxscore; bsearchscore[0] = lefttemp; bsearchscore[4] = righttemp; /* Get new center angle and delta for next iteration */ centerangle = centerangle + delta * (maxindex - 2); delta = 0.5 * delta; } *pangle = centerangle; #if DEBUG_PRINT_SCORES L_INFO(" Binary search score = %7.3f\n", procName, bsearchscore[2]); #endif /* DEBUG_PRINT_SCORES */ if (pendscore) /* save if requested */ *pendscore = bsearchscore[2]; /* Return the ratio of Max score over Min score * as a confidence value. Don't trust if the Min score * is too small, which can happen if the image is all black * with only a few white pixels interspersed. In that case, * we get a contribution from the top and bottom edges when * vertically sheared, but this contribution becomes zero when * the shear angle is zero. For zero shear angle, the only * contribution will be from the white pixels. We expect that * the signal goes as the product of the (height * width^2), * so we compute a (hopefully) normalized minimum threshold as * a function of these dimensions. */ numaGetMin(nascore, &minscore, &minloc); width = pixGetWidth(pixsch); height = pixGetHeight(pixsch); minthresh = MINSCORE_THRESHOLD_CONSTANT * width * width * height; #if DEBUG_THRESHOLD L_INFO(" minthresh = %10.2f, minscore = %10.2f\n", procName, minthresh, minscore); L_INFO(" maxscore = %10.2f\n", procName, maxscore); #endif /* DEBUG_THRESHOLD */ if (minscore > minthresh) *pconf = maxscore / minscore; else *pconf = 0.0; /* Don't trust it if too close to the edge of the sweep * range or if maxscore is small */ if ((centerangle > rangeleft + 2 * sweeprange - sweepdelta) || (centerangle < rangeleft + sweepdelta) || (maxscore < MIN_VALID_MAXSCORE)) *pconf = 0.0; #if DEBUG_PRINT_BINARY fprintf(stderr, "Binary search: angle = %7.3f, score ratio = %6.2f\n", *pangle, *pconf); fprintf(stderr, " max score = %8.0f\n", maxscore); #endif /* DEBUG_PRINT_BINARY */ #if DEBUG_PLOT_SCORES /* Plot the result -- the scores versus rotation angle -- * using gnuplot with GPLOT_POINTS. Because the data * points are not ordered by theta (increasing or decreasing), * using GPLOT_LINES would be confusing! */ {GPLOT *gplot; gplot = gplotCreate("search_output", GPLOT_PNG, "Binary search. Variance of difference of ON pixels vs. angle", "angle (deg)", "score"); gplotAddPlot(gplot, natheta, nascore, GPLOT_POINTS, "plot1"); gplotMakeOutput(gplot); gplotDestroy(&gplot); } #endif /* DEBUG_PLOT_SCORES */ cleanup: pixDestroy(&pixsw); pixDestroy(&pixsch); pixDestroy(&pixt1); pixDestroy(&pixt2); numaDestroy(&nascore); numaDestroy(&natheta); return ret; }
int main(int argc, char **argv) { char label[512]; l_int32 rval, gval, bval, w, h, i, j, rwhite, gwhite, bwhite, count; l_uint32 pixel; GPLOT *gplot1, *gplot2; NUMA *naseq, *na; NUMAA *naa1, *naa2; PIX *pixs, *pixt, *pixt0, *pixt1, *pixt2; PIX *pixr, *pixg, *pixb; /* for color content extraction */ PIXA *pixa, *pixat; PIXCMAP *cmap; L_REGPARAMS *rp; if (regTestSetup(argc, argv, &rp)) return 1; /* Generate a pdf of results when called with display */ pixa = pixaCreate(0); /* Generate colors by sampling hue with max sat and value. * This image has been saved as 19-colors.png. */ pixat = pixaCreate(19); for (i = 0; i < 19; i++) { convertHSVToRGB((240 * i / 18), 255, 255, &rval, &gval, &bval); composeRGBPixel(rval, gval, bval, &pixel); pixt1 = pixCreate(50, 100, 32); pixSetAllArbitrary(pixt1, pixel); pixaAddPix(pixat, pixt1, L_INSERT); } pixt2 = pixaDisplayTiledInRows(pixat, 32, 1100, 1.0, 0, 0, 0); regTestWritePixAndCheck(rp, pixt2, IFF_PNG); /* 0 */ pixaAddPix(pixa, pixt2, L_INSERT); pixaDestroy(&pixat); /* Colorspace conversion in rgb */ pixs = pixRead("wyom.jpg"); pixaAddPix(pixa, pixs, L_INSERT); pixt = pixConvertRGBToHSV(NULL, pixs); regTestWritePixAndCheck(rp, pixt, IFF_JFIF_JPEG); /* 1 */ pixaAddPix(pixa, pixt, L_COPY); pixConvertHSVToRGB(pixt, pixt); regTestWritePixAndCheck(rp, pixt, IFF_JFIF_JPEG); /* 2 */ pixaAddPix(pixa, pixt, L_INSERT); /* Colorspace conversion on a colormap */ pixt = pixOctreeQuantNumColors(pixs, 25, 0); regTestWritePixAndCheck(rp, pixt, IFF_JFIF_JPEG); /* 3 */ pixaAddPix(pixa, pixt, L_COPY); cmap = pixGetColormap(pixt); if (rp->display) pixcmapWriteStream(stderr, cmap); pixcmapConvertRGBToHSV(cmap); if (rp->display) pixcmapWriteStream(stderr, cmap); regTestWritePixAndCheck(rp, pixt, IFF_JFIF_JPEG); /* 4 */ pixaAddPix(pixa, pixt, L_COPY); pixcmapConvertHSVToRGB(cmap); if (rp->display) pixcmapWriteStream(stderr, cmap); regTestWritePixAndCheck(rp, pixt, IFF_JFIF_JPEG); /* 5 */ pixaAddPix(pixa, pixt, L_INSERT); /* Color content extraction */ pixColorContent(pixs, 0, 0, 0, 0, &pixr, &pixg, &pixb); regTestWritePixAndCheck(rp, pixr, IFF_JFIF_JPEG); /* 6 */ pixaAddPix(pixa, pixr, L_INSERT); regTestWritePixAndCheck(rp, pixg, IFF_JFIF_JPEG); /* 7 */ pixaAddPix(pixa, pixg, L_INSERT); regTestWritePixAndCheck(rp, pixb, IFF_JFIF_JPEG); /* 8 */ pixaAddPix(pixa, pixb, L_INSERT); /* Color content measurement. This tests the global * mapping of (r,g,b) --> (white), for 20 different * values of (r,g,b). For each mappings, we compute * the color magnitude and threshold it at six values. * For each of those six thresholds, we plot the * fraction of pixels that exceeds the threshold * color magnitude, where the red value (mapped to * white) goes between 100 and 195. */ pixat = pixaCreate(20); naseq = numaMakeSequence(100, 5, 20); naa1 = numaaCreate(6); naa2 = numaaCreate(6); for (i = 0; i < 6; i++) { na = numaCreate(20); numaaAddNuma(naa1, na, L_COPY); numaaAddNuma(naa2, na, L_INSERT); } pixGetDimensions(pixs, &w, &h, NULL); for (i = 0; i < 20; i++) { rwhite = 100 + 5 * i; gwhite = 200 - 5 * i; bwhite = 150; pixt0 = pixGlobalNormRGB(NULL, pixs, rwhite, gwhite, bwhite, 255); pixaAddPix(pixat, pixt0, L_INSERT); pixt1 = pixColorMagnitude(pixs, rwhite, gwhite, bwhite, L_MAX_DIFF_FROM_AVERAGE_2); for (j = 0; j < 6; j++) { pixt2 = pixThresholdToBinary(pixt1, 30 + 10 * j); pixInvert(pixt2, pixt2); pixCountPixels(pixt2, &count, NULL); na = numaaGetNuma(naa1, j, L_CLONE); numaAddNumber(na, (l_float32)count / (l_float32)(w * h)); numaDestroy(&na); pixDestroy(&pixt2); } pixDestroy(&pixt1); pixt1 = pixColorMagnitude(pixs, rwhite, gwhite, bwhite, L_MAX_MIN_DIFF_FROM_2); for (j = 0; j < 6; j++) { pixt2 = pixThresholdToBinary(pixt1, 30 + 10 * j); pixInvert(pixt2, pixt2); pixCountPixels(pixt2, &count, NULL); na = numaaGetNuma(naa2, j, L_CLONE); numaAddNumber(na, (l_float32)count / (l_float32)(w * h)); numaDestroy(&na); pixDestroy(&pixt2); } pixDestroy(&pixt1); } gplot1 = gplotCreate("/tmp/regout/colorspace.10", GPLOT_PNG, "Fraction with given color (diff from average)", "white point space for red", "amount of color"); gplot2 = gplotCreate("/tmp/regout/colorspace.11", GPLOT_PNG, "Fraction with given color (min diff)", "white point space for red", "amount of color"); for (j = 0; j < 6; j++) { na = numaaGetNuma(naa1, j, L_CLONE); sprintf(label, "thresh %d", 30 + 10 * j); gplotAddPlot(gplot1, naseq, na, GPLOT_LINES, label); numaDestroy(&na); na = numaaGetNuma(naa2, j, L_CLONE); gplotAddPlot(gplot2, naseq, na, GPLOT_LINES, label); numaDestroy(&na); } gplotMakeOutput(gplot1); gplotMakeOutput(gplot2); gplotDestroy(&gplot1); gplotDestroy(&gplot2); pixt1 = pixaDisplayTiledAndScaled(pixat, 32, 250, 4, 0, 10, 2); regTestWritePixAndCheck(rp, pixt1, IFF_JFIF_JPEG); /* 9 */ pixaAddPix(pixa, pixt1, L_INSERT); pixDisplayWithTitle(pixt1, 0, 100, "Color magnitude", rp->display); pixaDestroy(&pixat); numaDestroy(&naseq); numaaDestroy(&naa1); numaaDestroy(&naa2); /* Give gnuplot time to write out the files */ #ifndef _WIN32 sleep(1); #else Sleep(1000); #endif /* _WIN32 */ /* Save as golden files, or check against them */ regTestCheckFile(rp, "/tmp/regout/colorspace.10.png"); /* 10 */ regTestCheckFile(rp, "/tmp/regout/colorspace.11.png"); /* 11 */ if (rp->display) { pixt = pixRead("/tmp/regout/colorspace.10.png"); pixaAddPix(pixa, pixt, L_INSERT); pixt = pixRead("/tmp/regout/colorspace.11.png"); pixaAddPix(pixa, pixt, L_INSERT); pixaConvertToPdf(pixa, 0, 1.0, 0, 0, "colorspace tests", "/tmp/regout/colorspace.pdf"); L_INFO("Output pdf: /tmp/regout/colorspace.pdf\n", rp->testname); } pixaDestroy(&pixa); return regTestCleanup(rp); }
int main(int argc, char **argv) { l_int32 i, n, binsize, binstart, nbins; l_float32 pi, val, angle, xval, yval, x0, y0, rank, startval, fbinsize; l_float32 minval, maxval, meanval, median, variance, rankval; GPLOT *gplot; NUMA *na, *nahisto, *nax, *nay, *nap, *nasx, *nasy; NUMA *nadx, *nady, *nafx, *nafy, *na1, *na2, *na3, *na4; PIX *pixs, *pix1, *pix2, *pix3, *pix4, *pix5, *pixd; PIXA *pixa; static char mainName[] = "numa1_reg"; if (argc != 1) return ERROR_INT(" Syntax: numa1_reg", mainName, 1); lept_mkdir("lept"); /* -------------------------------------------------------------------* * Histograms * * -------------------------------------------------------------------*/ #if DO_ALL pi = 3.1415926535; na = numaCreate(5000); for (i = 0; i < 500000; i++) { angle = 0.02293 * i * pi; val = (l_float32)(999. * sin(angle)); numaAddNumber(na, val); } nahisto = numaMakeHistogramClipped(na, 6, 2000); nbins = numaGetCount(nahisto); nax = numaMakeSequence(0, 1, nbins); gplot = gplotCreate("/tmp/lept/numa_histo1", GPLOT_X11, "example histo 1", "i", "histo[i]"); gplotAddPlot(gplot, nax, nahisto, GPLOT_LINES, "sine"); gplotMakeOutput(gplot); gplotDestroy(&gplot); numaDestroy(&nax); numaDestroy(&nahisto); nahisto = numaMakeHistogram(na, 1000, &binsize, &binstart); nbins = numaGetCount(nahisto); nax = numaMakeSequence(binstart, binsize, nbins); fprintf(stderr, " binsize = %d, binstart = %d\n", binsize, binstart); gplot = gplotCreate("/tmp/lept/numa_histo2", GPLOT_X11, "example histo 2", "i", "histo[i]"); gplotAddPlot(gplot, nax, nahisto, GPLOT_LINES, "sine"); gplotMakeOutput(gplot); gplotDestroy(&gplot); numaDestroy(&nax); numaDestroy(&nahisto); nahisto = numaMakeHistogram(na, 1000, &binsize, NULL); nbins = numaGetCount(nahisto); nax = numaMakeSequence(0, binsize, nbins); fprintf(stderr, " binsize = %d, binstart = %d\n", binsize, 0); gplot = gplotCreate("/tmp/lept/numa_histo3", GPLOT_X11, "example histo 3", "i", "histo[i]"); gplotAddPlot(gplot, nax, nahisto, GPLOT_LINES, "sine"); gplotMakeOutput(gplot); gplotDestroy(&gplot); numaDestroy(&nax); numaDestroy(&nahisto); nahisto = numaMakeHistogramAuto(na, 1000); nbins = numaGetCount(nahisto); numaGetParameters(nahisto, &startval, &fbinsize); nax = numaMakeSequence(startval, fbinsize, nbins); fprintf(stderr, " binsize = %7.4f, binstart = %8.3f\n", fbinsize, startval); gplot = gplotCreate("/tmp/lept/numa_histo4", GPLOT_X11, "example histo 4", "i", "histo[i]"); gplotAddPlot(gplot, nax, nahisto, GPLOT_LINES, "sine"); gplotMakeOutput(gplot); gplotDestroy(&gplot); numaDestroy(&nax); numaDestroy(&nahisto); numaGetStatsUsingHistogram(na, 2000, &minval, &maxval, &meanval, &variance, &median, 0.80, &rankval, &nahisto); fprintf(stderr, "Sin histogram: \n" " min val = %7.2f -- should be -999.00\n" " max val = %7.2f -- should be 999.00\n" " mean val = %7.2f -- should be 0.06\n" " median = %7.2f -- should be 0.30\n" " rmsdev = %7.2f -- should be 706.41\n" " rank val = %7.2f -- should be 808.15\n", minval, maxval, meanval, median, sqrt((l_float64) variance), rankval); numaHistogramGetRankFromVal(nahisto, 808.15, &rank); fprintf(stderr, " rank = %7.3f -- should be 0.800\n", rank); numaDestroy(&nahisto); numaDestroy(&na); #endif /* -------------------------------------------------------------------* * Interpolation * * -------------------------------------------------------------------*/ #if DO_ALL /* Test numaInterpolateEqxInterval() */ pixs = pixRead("test8.jpg"); na = pixGetGrayHistogramMasked(pixs, NULL, 0, 0, 1); /* numaWriteStream(stderr, na); */ nasy = numaGetPartialSums(na); gplotSimple1(nasy, GPLOT_X11, "/tmp/lept/numa_int1", "partial sums"); gplotSimple1(na, GPLOT_X11, "/tmp/lept/numa_int2", "simple test"); numaInterpolateEqxInterval(0.0, 1.0, na, L_LINEAR_INTERP, 0.0, 255.0, 15, &nax, &nay); gplot = gplotCreate("/tmp/lept/numa_int3", GPLOT_X11, "test interpolation", "pix val", "num pix"); gplotAddPlot(gplot, nax, nay, GPLOT_LINES, "plot 1"); gplotMakeOutput(gplot); gplotDestroy(&gplot); numaDestroy(&na); numaDestroy(&nasy); numaDestroy(&nax); numaDestroy(&nay); pixDestroy(&pixs); #endif #if DO_ALL /* Test numaInterpolateArbxInterval() */ pixs = pixRead("test8.jpg"); na = pixGetGrayHistogramMasked(pixs, NULL, 0, 0, 1); nasy = numaGetPartialSums(na); numaInsertNumber(nasy, 0, 0.0); nasx = numaMakeSequence(0.0, 1.0, 257); /* gplotSimple1(nasy, GPLOT_X11, "/tmp/numa/nasy", "partial sums"); */ numaInterpolateArbxInterval(nasx, nasy, L_LINEAR_INTERP, 10.0, 250.0, 23, &nax, &nay); gplot = gplotCreate("/tmp/lept/numa_int4", GPLOT_X11, "arbx interpolation", "pix val", "cum num pix"); gplotAddPlot(gplot, nax, nay, GPLOT_LINES, "plot 1"); gplotMakeOutput(gplot); gplotDestroy(&gplot); numaDestroy(&na); numaDestroy(&nasx); numaDestroy(&nasy); numaDestroy(&nax); numaDestroy(&nay); pixDestroy(&pixs); #endif #if DO_ALL /* Test numaInterpolateArbxVal() */ pixs = pixRead("test8.jpg"); na = pixGetGrayHistogramMasked(pixs, NULL, 0, 0, 1); nasy = numaGetPartialSums(na); numaInsertNumber(nasy, 0, 0.0); nasx = numaMakeSequence(0.0, 1.0, 257); /* gplotSimple1(nasy, GPLOT_X11, "/tmp/numa/nasy", "partial sums"); */ nax = numaMakeSequence(15.0, (250.0 - 15.0) / 23.0, 24); n = numaGetCount(nax); nay = numaCreate(n); for (i = 0; i < n; i++) { numaGetFValue(nax, i, &xval); numaInterpolateArbxVal(nasx, nasy, L_QUADRATIC_INTERP, xval, &yval); numaAddNumber(nay, yval); } gplot = gplotCreate("/tmp/lept/numa_int5", GPLOT_X11, "arbx interpolation", "pix val", "cum num pix"); gplotAddPlot(gplot, nax, nay, GPLOT_LINES, "plot 1"); gplotMakeOutput(gplot); gplotDestroy(&gplot); numaDestroy(&na); numaDestroy(&nasx); numaDestroy(&nasy); numaDestroy(&nax); numaDestroy(&nay); pixDestroy(&pixs); #endif #if DO_ALL /* Test interpolation */ nasx = numaRead("testangle.na"); nasy = numaRead("testscore.na"); gplot = gplotCreate("/tmp/lept/numa_int6", GPLOT_X11, "arbx interpolation", "angle", "score"); numaInterpolateArbxInterval(nasx, nasy, L_LINEAR_INTERP, -2.00, 0.0, 50, &nax, &nay); gplotAddPlot(gplot, nax, nay, GPLOT_LINES, "linear"); numaDestroy(&nax); numaDestroy(&nay); numaInterpolateArbxInterval(nasx, nasy, L_QUADRATIC_INTERP, -2.00, 0.0, 50, &nax, &nay); gplotAddPlot(gplot, nax, nay, GPLOT_LINES, "quadratic"); numaDestroy(&nax); numaDestroy(&nay); gplotMakeOutput(gplot); gplotDestroy(&gplot); gplot = gplotCreate("/tmp/lept/numa_int7", GPLOT_X11, "arbx interpolation", "angle", "score"); numaInterpolateArbxInterval(nasx, nasy, L_LINEAR_INTERP, -1.2, -0.8, 50, &nax, &nay); gplotAddPlot(gplot, nax, nay, GPLOT_LINES, "quadratic"); gplotMakeOutput(gplot); gplotDestroy(&gplot); numaFitMax(nay, &yval, nax, &xval); fprintf(stderr, "max = %f at loc = %f\n", yval, xval); numaDestroy(&nasx); numaDestroy(&nasy); numaDestroy(&nax); numaDestroy(&nay); #endif /* -------------------------------------------------------------------* * Integration and differentiation * * -------------------------------------------------------------------*/ #if DO_ALL /* Test integration and differentiation */ nasx = numaRead("testangle.na"); nasy = numaRead("testscore.na"); /* ---------- Plot the derivative ---------- */ numaDifferentiateInterval(nasx, nasy, -2.0, 0.0, 50, &nadx, &nady); gplot = gplotCreate("/tmp/lept/numa_diff1", GPLOT_X11, "derivative", "angle", "slope"); gplotAddPlot(gplot, nadx, nady, GPLOT_LINES, "derivative"); gplotMakeOutput(gplot); gplotDestroy(&gplot); /* ---------- Plot the original function ----------- */ /* and the integral of the derivative; the two */ /* should be approximately the same. */ gplot = gplotCreate("/tmp/lept/numa_diff2", GPLOT_X11, "integ-diff", "angle", "val"); numaInterpolateArbxInterval(nasx, nasy, L_LINEAR_INTERP, -2.00, 0.0, 50, &nafx, &nafy); gplotAddPlot(gplot, nafx, nafy, GPLOT_LINES, "function"); n = numaGetCount(nadx); numaGetFValue(nafx, 0, &x0); numaGetFValue(nafy, 0, &y0); nay = numaCreate(n); /* (Note: this tests robustness of the integrator: we go from * i = 0, and choose to have only 1 point in the interpolation * there, which is too small and causes the function to bomb out.) */ fprintf(stderr, "We must get a 'npts < 2' error here:\n"); for (i = 0; i < n; i++) { numaGetFValue(nadx, i, &xval); numaIntegrateInterval(nadx, nady, x0, xval, 2 * i + 1, &yval); numaAddNumber(nay, y0 + yval); } gplotAddPlot(gplot, nafx, nay, GPLOT_LINES, "anti-derivative"); gplotMakeOutput(gplot); gplotDestroy(&gplot); numaDestroy(&nasx); numaDestroy(&nasy); numaDestroy(&nafx); numaDestroy(&nafy); numaDestroy(&nadx); numaDestroy(&nady); numaDestroy(&nay); #endif /* -------------------------------------------------------------------* * Rank extraction * * -------------------------------------------------------------------*/ #if DO_ALL /* Rank extraction with interpolation */ pixs = pixRead("test8.jpg"); nasy = pixGetGrayHistogramMasked(pixs, NULL, 0, 0, 1); numaMakeRankFromHistogram(0.0, 1.0, nasy, 350, &nax, &nay); gplot = gplotCreate("/tmp/lept/numa_rank1", GPLOT_X11, "test rank extractor", "pix val", "rank val"); gplotAddPlot(gplot, nax, nay, GPLOT_LINES, "plot 1"); gplotMakeOutput(gplot); gplotDestroy(&gplot); numaDestroy(&nasy); numaDestroy(&nax); numaDestroy(&nay); pixDestroy(&pixs); #endif #if DO_ALL /* Rank extraction, point by point */ pixs = pixRead("test8.jpg"); nap = numaCreate(200); pixGetRankValueMasked(pixs, NULL, 0, 0, 2, 0.0, &val, &na); for (i = 0; i < 101; i++) { rank = 0.01 * i; numaHistogramGetValFromRank(na, rank, &val); numaAddNumber(nap, val); } gplotSimple1(nap, GPLOT_X11, "/tmp/lept/numa_rank2", "rank value"); numaDestroy(&na); numaDestroy(&nap); pixDestroy(&pixs); #endif /* -------------------------------------------------------------------* * Numa-morphology * * -------------------------------------------------------------------*/ #if DO_ALL na = numaRead("lyra.5.na"); gplotSimple1(na, GPLOT_PNG, "/tmp/lept/numa_lyra1", "Original"); na1 = numaErode(na, 21); gplotSimple1(na1, GPLOT_PNG, "/tmp/lept/numa_lyra2", "Erosion"); na2 = numaDilate(na, 21); gplotSimple1(na2, GPLOT_PNG, "/tmp/lept/numa_lyra3", "Dilation"); na3 = numaOpen(na, 21); gplotSimple1(na3, GPLOT_PNG, "/tmp/lept/numa_lyra4", "Opening"); na4 = numaClose(na, 21); gplotSimple1(na4, GPLOT_PNG, "/tmp/lept/numa_lyra5", "Closing"); #ifndef _WIN32 sleep(1); #else Sleep(1000); #endif /* _WIN32 */ pixa = pixaCreate(5); pix1 = pixRead("/tmp/lept/numa_lyra1.png"); pix2 = pixRead("/tmp/lept/numa_lyra2.png"); pix3 = pixRead("/tmp/lept/numa_lyra3.png"); pix4 = pixRead("/tmp/lept/numa_lyra4.png"); pix5 = pixRead("/tmp/lept/numa_lyra5.png"); pixSaveTiled(pix1, pixa, 1.0, 1, 25, 32); pixSaveTiled(pix2, pixa, 1.0, 1, 25, 32); pixSaveTiled(pix3, pixa, 1.0, 0, 25, 32); pixSaveTiled(pix4, pixa, 1.0, 1, 25, 32); pixSaveTiled(pix5, pixa, 1.0, 0, 25, 32); pixd = pixaDisplay(pixa, 0, 0); pixDisplay(pixd, 100, 100); pixWrite("/tmp/lept/numa_morph.png", pixd, IFF_PNG); numaDestroy(&na); numaDestroy(&na1); numaDestroy(&na2); numaDestroy(&na3); numaDestroy(&na4); pixaDestroy(&pixa); pixDestroy(&pix1); pixDestroy(&pix2); pixDestroy(&pix3); pixDestroy(&pix4); pixDestroy(&pix5); pixDestroy(&pixd); #endif return 0; }
int main(int argc, char **argv) { char *selname; l_int32 i, j, nsels, sx, sy; l_float32 fact, time; GPLOT *gplot; NUMA *na1, *na2, *na3, *na4, *nac1, *nac2, *nac3, *nac4, *nax; PIX *pixs, *pixt; PIXA *pixa; SEL *sel; SELA *selalinear; static char mainName[] = "dwamorph2_reg"; if (argc != 1) return ERROR_INT(" Syntax: dwamorph2_reg", mainName, 1); pixs = pixRead("feyn-fract.tif"); pixt = pixCreateTemplate(pixs); selalinear = selaAddDwaLinear(NULL); nsels = selaGetCount(selalinear); fact = 1000. / (l_float32)NTIMES; /* converts to time in msec */ na1 = numaCreate(64); na2 = numaCreate(64); na3 = numaCreate(64); na4 = numaCreate(64); lept_mkdir("lept/morph"); /* --------- dilation ----------*/ for (i = 0; i < nsels / 2; i++) { sel = selaGetSel(selalinear, i); selGetParameters(sel, &sy, &sx, NULL, NULL); selname = selGetName(sel); fprintf(stderr, " %d .", i); startTimer(); for (j = 0; j < NTIMES; j++) pixDilate(pixt, pixs, sel); time = fact * stopTimer(); numaAddNumber(na1, time); startTimer(); for (j = 0; j < NTIMES; j++) pixDilateCompBrick(pixt, pixs, sx, sy); time = fact * stopTimer(); numaAddNumber(na2, time); startTimer(); for (j = 0; j < NTIMES; j++) pixMorphDwa_3(pixt, pixs, L_MORPH_DILATE, selname); time = fact * stopTimer(); numaAddNumber(na3, time); startTimer(); for (j = 0; j < NTIMES; j++) pixDilateCompBrickDwa(pixt, pixs, sx, sy); time = fact * stopTimer(); numaAddNumber(na4, time); } nax = numaMakeSequence(2, 1, nsels / 2); nac1 = numaWindowedMean(na1, HALFWIDTH); nac2 = numaWindowedMean(na2, HALFWIDTH); nac3 = numaWindowedMean(na3, HALFWIDTH); nac4 = numaWindowedMean(na4, HALFWIDTH); gplot = gplotCreate("/tmp/lept/morph/dilate", GPLOT_PNG, "Dilation time vs sel size", "size", "time (ms)"); gplotAddPlot(gplot, nax, nac1, GPLOT_LINES, "linear rasterop"); gplotAddPlot(gplot, nax, nac2, GPLOT_LINES, "composite rasterop"); gplotAddPlot(gplot, nax, nac3, GPLOT_LINES, "linear dwa"); gplotAddPlot(gplot, nax, nac4, GPLOT_LINES, "composite dwa"); gplotMakeOutput(gplot); gplotDestroy(&gplot); numaDestroy(&nac1); numaDestroy(&nac2); numaDestroy(&nac3); numaDestroy(&nac4); /* --------- erosion ----------*/ numaEmpty(na1); numaEmpty(na2); numaEmpty(na3); numaEmpty(na4); for (i = 0; i < nsels / 2; i++) { sel = selaGetSel(selalinear, i); selGetParameters(sel, &sy, &sx, NULL, NULL); selname = selGetName(sel); fprintf(stderr, " %d .", i); startTimer(); for (j = 0; j < NTIMES; j++) pixErode(pixt, pixs, sel); time = fact * stopTimer(); numaAddNumber(na1, time); startTimer(); for (j = 0; j < NTIMES; j++) pixErodeCompBrick(pixt, pixs, sx, sy); time = fact * stopTimer(); numaAddNumber(na2, time); startTimer(); for (j = 0; j < NTIMES; j++) pixMorphDwa_3(pixt, pixs, L_MORPH_ERODE, selname); time = fact * stopTimer(); numaAddNumber(na3, time); startTimer(); for (j = 0; j < NTIMES; j++) pixErodeCompBrickDwa(pixt, pixs, sx, sy); time = fact * stopTimer(); numaAddNumber(na4, time); } nac1 = numaWindowedMean(na1, HALFWIDTH); nac2 = numaWindowedMean(na2, HALFWIDTH); nac3 = numaWindowedMean(na3, HALFWIDTH); nac4 = numaWindowedMean(na4, HALFWIDTH); gplot = gplotCreate("/tmp/lept/morph/erode", GPLOT_PNG, "Erosion time vs sel size", "size", "time (ms)"); gplotAddPlot(gplot, nax, nac1, GPLOT_LINES, "linear rasterop"); gplotAddPlot(gplot, nax, nac2, GPLOT_LINES, "composite rasterop"); gplotAddPlot(gplot, nax, nac3, GPLOT_LINES, "linear dwa"); gplotAddPlot(gplot, nax, nac4, GPLOT_LINES, "composite dwa"); gplotMakeOutput(gplot); gplotDestroy(&gplot); numaDestroy(&nac1); numaDestroy(&nac2); numaDestroy(&nac3); numaDestroy(&nac4); /* --------- opening ----------*/ numaEmpty(na1); numaEmpty(na2); numaEmpty(na3); numaEmpty(na4); for (i = 0; i < nsels / 2; i++) { sel = selaGetSel(selalinear, i); selGetParameters(sel, &sy, &sx, NULL, NULL); selname = selGetName(sel); fprintf(stderr, " %d .", i); startTimer(); for (j = 0; j < NTIMES; j++) pixOpen(pixt, pixs, sel); time = fact * stopTimer(); numaAddNumber(na1, time); startTimer(); for (j = 0; j < NTIMES; j++) pixOpenCompBrick(pixt, pixs, sx, sy); time = fact * stopTimer(); numaAddNumber(na2, time); startTimer(); for (j = 0; j < NTIMES; j++) pixMorphDwa_3(pixt, pixs, L_MORPH_OPEN, selname); time = fact * stopTimer(); numaAddNumber(na3, time); startTimer(); for (j = 0; j < NTIMES; j++) pixOpenCompBrickDwa(pixt, pixs, sx, sy); time = fact * stopTimer(); numaAddNumber(na4, time); } nac1 = numaWindowedMean(na1, HALFWIDTH); nac2 = numaWindowedMean(na2, HALFWIDTH); nac3 = numaWindowedMean(na3, HALFWIDTH); nac4 = numaWindowedMean(na4, HALFWIDTH); gplot = gplotCreate("/tmp/lept/morph/open", GPLOT_PNG, "Opening time vs sel size", "size", "time (ms)"); gplotAddPlot(gplot, nax, nac1, GPLOT_LINES, "linear rasterop"); gplotAddPlot(gplot, nax, nac2, GPLOT_LINES, "composite rasterop"); gplotAddPlot(gplot, nax, nac3, GPLOT_LINES, "linear dwa"); gplotAddPlot(gplot, nax, nac4, GPLOT_LINES, "composite dwa"); gplotMakeOutput(gplot); gplotDestroy(&gplot); numaDestroy(&nac1); numaDestroy(&nac2); numaDestroy(&nac3); numaDestroy(&nac4); /* --------- closing ----------*/ numaEmpty(na1); numaEmpty(na2); numaEmpty(na3); numaEmpty(na4); for (i = 0; i < nsels / 2; i++) { sel = selaGetSel(selalinear, i); selGetParameters(sel, &sy, &sx, NULL, NULL); selname = selGetName(sel); fprintf(stderr, " %d .", i); startTimer(); for (j = 0; j < NTIMES; j++) pixClose(pixt, pixs, sel); time = fact * stopTimer(); numaAddNumber(na1, time); startTimer(); for (j = 0; j < NTIMES; j++) pixCloseCompBrick(pixt, pixs, sx, sy); time = fact * stopTimer(); numaAddNumber(na2, time); startTimer(); for (j = 0; j < NTIMES; j++) pixMorphDwa_3(pixt, pixs, L_MORPH_CLOSE, selname); time = fact * stopTimer(); numaAddNumber(na3, time); startTimer(); for (j = 0; j < NTIMES; j++) pixCloseCompBrickDwa(pixt, pixs, sx, sy); time = fact * stopTimer(); numaAddNumber(na4, time); } nac1 = numaWindowedMean(na1, HALFWIDTH); nac2 = numaWindowedMean(na2, HALFWIDTH); nac3 = numaWindowedMean(na3, HALFWIDTH); nac4 = numaWindowedMean(na4, HALFWIDTH); gplot = gplotCreate("/tmp/lept/morph/close", GPLOT_PNG, "Closing time vs sel size", "size", "time (ms)"); gplotAddPlot(gplot, nax, nac1, GPLOT_LINES, "linear rasterop"); gplotAddPlot(gplot, nax, nac2, GPLOT_LINES, "composite rasterop"); gplotAddPlot(gplot, nax, nac3, GPLOT_LINES, "linear dwa"); gplotAddPlot(gplot, nax, nac4, GPLOT_LINES, "composite dwa"); gplotMakeOutput(gplot); #ifndef _WIN32 sleep(1); #else Sleep(1000); #endif /* _WIN32 */ gplotDestroy(&gplot); numaDestroy(&nac1); numaDestroy(&nac2); numaDestroy(&nac3); numaDestroy(&nac4); numaDestroy(&na1); numaDestroy(&na2); numaDestroy(&na3); numaDestroy(&na4); numaDestroy(&nax); selaDestroy(&selalinear); pixDestroy(&pixt); pixDestroy(&pixs); /* Display the results together */ pixa = pixaCreate(0); pixs = pixRead("/tmp/lept/morph/dilate.png"); pixaAddPix(pixa, pixs, L_INSERT); pixs = pixRead("/tmp/lept/morph/erode.png"); pixaAddPix(pixa, pixs, L_INSERT); pixs = pixRead("/tmp/lept/morph/open.png"); pixaAddPix(pixa, pixs, L_INSERT); pixs = pixRead("/tmp/lept/morph/close.png"); pixaAddPix(pixa, pixs, L_INSERT); pixt = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 40, 3); pixWrite("/tmp/lept/morph/timings.png", pixt, IFF_PNG); pixDisplay(pixt, 100, 100); pixDestroy(&pixt); pixaDestroy(&pixa); return 0; }
/*! * \brief pixItalicWords() * * \param[in] pixs 1 bpp * \param[in] boxaw [optional] word bounding boxes; can be NULL * \param[in] pixw [optional] word box mask; can be NULL * \param[out] pboxa boxa of italic words * \param[in] debugflag 1 for debug output; 0 otherwise * \return 0 if OK, 1 on error * * <pre> * Notes: * (1) You can input the bounding boxes for the words in one of * two forms: as bounding boxes (%boxaw) or as a word mask with * the word bounding boxes filled (%pixw). For example, * to compute %pixw, you can use pixWordMaskByDilation(). * (2) Alternatively, you can set both of these inputs to NULL, * in which case the word mask is generated here. This is * done by dilating and closing the input image to connect * letters within a word, while leaving the words separated. * The parameters are chosen under the assumption that the * input is 10 to 12 pt text, scanned at about 300 ppi. * (3) sel_ital1 and sel_ital2 detect the right edges that are * nearly vertical, at approximately the angle of italic * strokes. We use the right edge to avoid getting seeds * from lower-case 'y'. The typical italic slant has a smaller * angle with the vertical than the 'W', so in most cases we * will not trigger on the slanted lines in the 'W'. * (4) Note that sel_ital2 is shorter than sel_ital1. It is * more appropriate for a typical font scanned at 200 ppi. * </pre> */ l_int32 pixItalicWords(PIX *pixs, BOXA *boxaw, PIX *pixw, BOXA **pboxa, l_int32 debugflag) { char opstring[32]; l_int32 size; BOXA *boxa; PIX *pixsd, *pixm, *pixd; SEL *sel_ital1, *sel_ital2, *sel_ital3; PROCNAME("pixItalicWords"); if (!pixs) return ERROR_INT("pixs not defined", procName, 1); if (!pboxa) return ERROR_INT("&boxa not defined", procName, 1); if (boxaw && pixw) return ERROR_INT("both boxaw and pixw are defined", procName, 1); sel_ital1 = selCreateFromString(str_ital1, 13, 6, NULL); sel_ital2 = selCreateFromString(str_ital2, 10, 6, NULL); sel_ital3 = selCreateFromString(str_ital3, 4, 2, NULL); /* Make the italic seed: extract with HMT; remove noise. * The noise removal close/open is important to exclude * situations where a small slanted line accidentally * matches sel_ital1. */ pixsd = pixHMT(NULL, pixs, sel_ital1); pixClose(pixsd, pixsd, sel_ital3); pixOpen(pixsd, pixsd, sel_ital3); /* Make the word mask. Use input boxes or mask if given. */ size = 0; /* init */ if (boxaw) { pixm = pixCreateTemplate(pixs); pixMaskBoxa(pixm, pixm, boxaw, L_SET_PIXELS); } else if (pixw) { pixm = pixClone(pixw); } else { pixWordMaskByDilation(pixs, NULL, &size, NULL); L_INFO("dilation size = %d\n", procName, size); snprintf(opstring, sizeof(opstring), "d1.5 + c%d.1", size); pixm = pixMorphSequence(pixs, opstring, 0); } /* Binary reconstruction to fill in those word mask * components for which there is at least one seed pixel. */ pixd = pixSeedfillBinary(NULL, pixsd, pixm, 8); boxa = pixConnComp(pixd, NULL, 8); *pboxa = boxa; if (debugflag) { /* Save results at at 2x reduction */ lept_mkdir("lept/ital"); l_int32 res, upper; BOXA *boxat; GPLOT *gplot; NUMA *na; PIXA *pad; PIX *pix1, *pix2, *pix3; pad = pixaCreate(0); boxat = pixConnComp(pixm, NULL, 8); boxaWrite("/tmp/lept/ital/ital.ba", boxat); pixSaveTiledOutline(pixs, pad, 0.5, 1, 20, 2, 32); /* orig */ pixSaveTiledOutline(pixsd, pad, 0.5, 1, 20, 2, 0); /* seed */ pix1 = pixConvertTo32(pixm); pixRenderBoxaArb(pix1, boxat, 3, 255, 0, 0); pixSaveTiledOutline(pix1, pad, 0.5, 1, 20, 2, 0); /* mask + outline */ pixDestroy(&pix1); pixSaveTiledOutline(pixd, pad, 0.5, 1, 20, 2, 0); /* ital mask */ pix1 = pixConvertTo32(pixs); pixRenderBoxaArb(pix1, boxa, 3, 255, 0, 0); pixSaveTiledOutline(pix1, pad, 0.5, 1, 20, 2, 0); /* orig + outline */ pixDestroy(&pix1); pix1 = pixCreateTemplate(pixs); pix2 = pixSetBlackOrWhiteBoxa(pix1, boxa, L_SET_BLACK); pixCopy(pix1, pixs); pix3 = pixDilateBrick(NULL, pixs, 3, 3); pixCombineMasked(pix1, pix3, pix2); pixSaveTiledOutline(pix1, pad, 0.5, 1, 20, 2, 0); /* ital bolded */ pixDestroy(&pix1); pixDestroy(&pix2); pixDestroy(&pix3); pix2 = pixaDisplay(pad, 0, 0); pixWrite("/tmp/lept/ital/ital.png", pix2, IFF_PNG); pixDestroy(&pix2); /* Assuming the image represents 6 inches of actual page width, * the pixs resolution is approximately * (width of pixs in pixels) / 6 * and the images have been saved at half this resolution. */ res = pixGetWidth(pixs) / 12; L_INFO("resolution = %d\n", procName, res); l_pdfSetDateAndVersion(0); pixaConvertToPdf(pad, res, 1.0, L_FLATE_ENCODE, 75, "Italic Finder", "/tmp/lept/ital/ital.pdf"); l_pdfSetDateAndVersion(1); pixaDestroy(&pad); boxaDestroy(&boxat); /* Plot histogram of horizontal white run sizes. A small * initial vertical dilation removes most runs that are neither * inter-character nor inter-word. The larger first peak is * from inter-character runs, and the smaller second peak is * from inter-word runs. */ pix1 = pixDilateBrick(NULL, pixs, 1, 15); upper = L_MAX(30, 3 * size); na = pixRunHistogramMorph(pix1, L_RUN_OFF, L_HORIZ, upper); pixDestroy(&pix1); gplot = gplotCreate("/tmp/lept/ital/runhisto", GPLOT_PNG, "Histogram of horizontal runs of white pixels, vs length", "run length", "number of runs"); gplotAddPlot(gplot, NULL, na, GPLOT_LINES, "plot1"); gplotMakeOutput(gplot); gplotDestroy(&gplot); numaDestroy(&na); } selDestroy(&sel_ital1); selDestroy(&sel_ital2); selDestroy(&sel_ital3); pixDestroy(&pixsd); pixDestroy(&pixm); pixDestroy(&pixd); return 0; }
/*! * \brief pixFindBaselines() * * \param[in] pixs 1 bpp, 300 ppi * \param[out] ppta [optional] pairs of pts corresponding to * approx. ends of each text line * \param[in] pixadb for debug output; use NULL to skip * \return na of baseline y values, or NULL on error * * <pre> * Notes: * (1) Input binary image must have text lines already aligned * horizontally. This can be done by either rotating the * image with pixDeskew(), or, if a projective transform * is required, by doing pixDeskewLocal() first. * (2) Input null for &pta if you don't want this returned. * The pta will come in pairs of points (left and right end * of each baseline). * (3) Caution: this will not work properly on text with multiple * columns, where the lines are not aligned between columns. * If there are multiple columns, they should be extracted * separately before finding the baselines. * (4) This function constructs different types of output * for baselines; namely, a set of raster line values and * a set of end points of each baseline. * (5) This function was designed to handle short and long text lines * without using dangerous thresholds on the peak heights. It does * this by combining the differential signal with a morphological * analysis of the locations of the text lines. One can also * combine this data to normalize the peak heights, by weighting * the differential signal in the region of each baseline * by the inverse of the width of the text line found there. * </pre> */ NUMA * pixFindBaselines(PIX *pixs, PTA **ppta, PIXA *pixadb) { l_int32 h, i, j, nbox, val1, val2, ndiff, bx, by, bw, bh; l_int32 imaxloc, peakthresh, zerothresh, inpeak; l_int32 mintosearch, max, maxloc, nloc, locval; l_int32 *array; l_float32 maxval; BOXA *boxa1, *boxa2, *boxa3; GPLOT *gplot; NUMA *nasum, *nadiff, *naloc, *naval; PIX *pix1, *pix2; PTA *pta; PROCNAME("pixFindBaselines"); if (ppta) *ppta = NULL; if (!pixs || pixGetDepth(pixs) != 1) return (NUMA *)ERROR_PTR("pixs undefined or not 1 bpp", procName, NULL); /* Close up the text characters, removing noise */ pix1 = pixMorphSequence(pixs, "c25.1 + e15.1", 0); /* Estimate the resolution */ if (pixadb) pixaAddPix(pixadb, pixScale(pix1, 0.25, 0.25), L_INSERT); /* Save the difference of adjacent row sums. * The high positive-going peaks are the baselines */ if ((nasum = pixCountPixelsByRow(pix1, NULL)) == NULL) { pixDestroy(&pix1); return (NUMA *)ERROR_PTR("nasum not made", procName, NULL); } h = pixGetHeight(pixs); nadiff = numaCreate(h); numaGetIValue(nasum, 0, &val2); for (i = 0; i < h - 1; i++) { val1 = val2; numaGetIValue(nasum, i + 1, &val2); numaAddNumber(nadiff, val1 - val2); } numaDestroy(&nasum); if (pixadb) { /* show the difference signal */ lept_mkdir("lept/baseline"); gplotSimple1(nadiff, GPLOT_PNG, "/tmp/lept/baseline/diff", "Diff Sig"); pix2 = pixRead("/tmp/lept/baseline/diff.png"); pixaAddPix(pixadb, pix2, L_INSERT); } /* Use the zeroes of the profile to locate each baseline. */ array = numaGetIArray(nadiff); ndiff = numaGetCount(nadiff); numaGetMax(nadiff, &maxval, &imaxloc); numaDestroy(&nadiff); /* Use this to begin locating a new peak: */ peakthresh = (l_int32)maxval / PEAK_THRESHOLD_RATIO; /* Use this to begin a region between peaks: */ zerothresh = (l_int32)maxval / ZERO_THRESHOLD_RATIO; naloc = numaCreate(0); naval = numaCreate(0); inpeak = FALSE; for (i = 0; i < ndiff; i++) { if (inpeak == FALSE) { if (array[i] > peakthresh) { /* transition to in-peak */ inpeak = TRUE; mintosearch = i + MIN_DIST_IN_PEAK; /* accept no zeros * between i and mintosearch */ max = array[i]; maxloc = i; } } else { /* inpeak == TRUE; look for max */ if (array[i] > max) { max = array[i]; maxloc = i; mintosearch = i + MIN_DIST_IN_PEAK; } else if (i > mintosearch && array[i] <= zerothresh) { /* leave */ inpeak = FALSE; numaAddNumber(naval, max); numaAddNumber(naloc, maxloc); } } } LEPT_FREE(array); /* If array[ndiff-1] is max, eg. no descenders, baseline at bottom */ if (inpeak) { numaAddNumber(naval, max); numaAddNumber(naloc, maxloc); } if (pixadb) { /* show the raster locations for the peaks */ gplot = gplotCreate("/tmp/lept/baseline/loc", GPLOT_PNG, "Peak locs", "rasterline", "height"); gplotAddPlot(gplot, naloc, naval, GPLOT_POINTS, "locs"); gplotMakeOutput(gplot); gplotDestroy(&gplot); pix2 = pixRead("/tmp/lept/baseline/loc.png"); pixaAddPix(pixadb, pix2, L_INSERT); } numaDestroy(&naval); /* Generate an approximate profile of text line width. * First, filter the boxes of text, where there may be * more than one box for a given textline. */ pix2 = pixMorphSequence(pix1, "r11 + c20.1 + o30.1 +c1.3", 0); if (pixadb) pixaAddPix(pixadb, pix2, L_COPY); boxa1 = pixConnComp(pix2, NULL, 4); pixDestroy(&pix1); pixDestroy(&pix2); if (boxaGetCount(boxa1) == 0) { numaDestroy(&naloc); boxaDestroy(&boxa1); L_INFO("no compnents after filtering\n", procName); return NULL; } boxa2 = boxaTransform(boxa1, 0, 0, 4., 4.); boxa3 = boxaSort(boxa2, L_SORT_BY_Y, L_SORT_INCREASING, NULL); boxaDestroy(&boxa1); boxaDestroy(&boxa2); /* Optionally, find the baseline segments */ pta = NULL; if (ppta) { pta = ptaCreate(0); *ppta = pta; } if (pta) { nloc = numaGetCount(naloc); nbox = boxaGetCount(boxa3); for (i = 0; i < nbox; i++) { boxaGetBoxGeometry(boxa3, i, &bx, &by, &bw, &bh); for (j = 0; j < nloc; j++) { numaGetIValue(naloc, j, &locval); if (L_ABS(locval - (by + bh)) > 25) continue; ptaAddPt(pta, bx, locval); ptaAddPt(pta, bx + bw, locval); break; } } } boxaDestroy(&boxa3); if (pixadb && pta) { /* display baselines */ l_int32 npts, x1, y1, x2, y2; pix1 = pixConvertTo32(pixs); npts = ptaGetCount(pta); for (i = 0; i < npts; i += 2) { ptaGetIPt(pta, i, &x1, &y1); ptaGetIPt(pta, i + 1, &x2, &y2); pixRenderLineArb(pix1, x1, y1, x2, y2, 2, 255, 0, 0); } pixWrite("/tmp/lept/baseline/baselines.png", pix1, IFF_PNG); pixaAddPix(pixadb, pixScale(pix1, 0.25, 0.25), L_INSERT); pixDestroy(&pix1); } return naloc; }
main(int argc, char **argv) { l_int32 i, nbins, ival; l_float64 pi, angle, val, sum; L_DNA *da1, *da2, *da3, *da4, *da5; L_DNAA *daa1, *daa2; GPLOT *gplot; NUMA *na, *nahisto, *nax; L_REGPARAMS *rp; if (regTestSetup(argc, argv, &rp)) return 1; pi = 3.1415926535; da1 = l_dnaCreate(50); for (i = 0; i < 5000; i++) { angle = 0.02293 * i * pi; val = 999. * sin(angle); l_dnaAddNumber(da1, val); } /* Conversion to Numa; I/O for Dna */ na = l_dnaConvertToNuma(da1); da2 = numaConvertToDna(na); l_dnaWrite("/tmp/dna1.da", da1); l_dnaWrite("/tmp/dna2.da", da2); da3 = l_dnaRead("/tmp/dna2.da"); l_dnaWrite("/tmp/dna3.da", da3); regTestCheckFile(rp, "/tmp/dna1.da"); /* 0 */ regTestCheckFile(rp, "/tmp/dna2.da"); /* 1 */ regTestCheckFile(rp, "/tmp/dna3.da"); /* 2 */ regTestCompareFiles(rp, 1, 2); /* 3 */ /* I/O for Dnaa */ daa1 = l_dnaaCreate(3); l_dnaaAddDna(daa1, da1, L_INSERT); l_dnaaAddDna(daa1, da2, L_INSERT); l_dnaaAddDna(daa1, da3, L_INSERT); l_dnaaWrite("/tmp/dnaa1.daa", daa1); daa2 = l_dnaaRead("/tmp/dnaa1.daa"); l_dnaaWrite("/tmp/dnaa2.daa", daa2); regTestCheckFile(rp, "/tmp/dnaa1.daa"); /* 4 */ regTestCheckFile(rp, "/tmp/dnaa2.daa"); /* 5 */ regTestCompareFiles(rp, 4, 5); /* 6 */ l_dnaaDestroy(&daa1); l_dnaaDestroy(&daa2); /* Just for fun -- is the numa ok? */ nahisto = numaMakeHistogramClipped(na, 12, 2000); nbins = numaGetCount(nahisto); nax = numaMakeSequence(0, 1, nbins); gplot = gplotCreate("/tmp/historoot", GPLOT_PNG, "Histo example", "i", "histo[i]"); gplotAddPlot(gplot, nax, nahisto, GPLOT_LINES, "sine"); gplotMakeOutput(gplot); #ifndef _WIN32 sleep(1); #else Sleep(1000); #endif /* _WIN32 */ regTestCheckFile(rp, "/tmp/historoot.png"); /* 7 */ gplotDestroy(&gplot); numaDestroy(&na); numaDestroy(&nax); numaDestroy(&nahisto); /* Handling precision of int32 in double */ da4 = l_dnaCreate(25); for (i = 0; i < 1000; i++) l_dnaAddNumber(da4, 1928374 * i); l_dnaWrite("/tmp/dna4.da", da4); da5 = l_dnaRead("/tmp/dna4.da"); sum = 0; for (i = 0; i < 1000; i++) { l_dnaGetIValue(da5, i, &ival); sum += L_ABS(ival - i * 1928374); /* we better be adding 0 each time */ } regTestCompareValues(rp, sum, 0.0, 0.0); /* 8 */ l_dnaDestroy(&da4); l_dnaDestroy(&da5); return regTestCleanup(rp); }
/*! * \brief pixGetLocalSkewAngles() * * \param[in] pixs 1 bpp * \param[in] nslices the number of horizontal overlapping slices; must * be larger than 1 and not exceed 20; 0 for default * \param[in] redsweep sweep reduction factor: 1, 2, 4 or 8; * use 0 for default value * \param[in] redsearch search reduction factor: 1, 2, 4 or 8, and not * larger than redsweep; use 0 for default value * \param[in] sweeprange half the full range, assumed about 0; in degrees; * use 0.0 for default value * \param[in] sweepdelta angle increment of sweep; in degrees; * use 0.0 for default value * \param[in] minbsdelta min binary search increment angle; in degrees; * use 0.0 for default value * \param[out] pa [optional] slope of skew as fctn of y * \param[out] pb [optional] intercept at y=0 of skew as fctn of y * \param[in] debug 1 for generating plot of skew angle vs. y; 0 otherwise * \return naskew, or NULL on error * * <pre> * Notes: * (1) The local skew is measured in a set of overlapping strips. * We then do a least square linear fit parameters to get * the slope and intercept parameters a and b in * skew-angle = a * y + b (degrees) * for the local skew as a function of raster line y. * This is then used to make naskew, which can be interpreted * as the computed skew angle (in degrees) at the left edge * of each raster line. * (2) naskew can then be used to find the baselines of text, because * each text line has a baseline that should intersect * the left edge of the image with the angle given by this * array, evaluated at the raster line of intersection. * </pre> */ NUMA * pixGetLocalSkewAngles(PIX *pixs, l_int32 nslices, l_int32 redsweep, l_int32 redsearch, l_float32 sweeprange, l_float32 sweepdelta, l_float32 minbsdelta, l_float32 *pa, l_float32 *pb, l_int32 debug) { l_int32 w, h, hs, i, ystart, yend, ovlap, npts; l_float32 angle, conf, ycenter, a, b; BOX *box; GPLOT *gplot; NUMA *naskew, *nax, *nay; PIX *pix; PTA *pta; PROCNAME("pixGetLocalSkewAngles"); if (!pixs || pixGetDepth(pixs) != 1) return (NUMA *)ERROR_PTR("pixs undefined or not 1 bpp", procName, NULL); if (nslices < 2 || nslices > 20) nslices = DEFAULT_SLICES; if (redsweep < 1 || redsweep > 8) redsweep = DEFAULT_SWEEP_REDUCTION; if (redsearch < 1 || redsearch > redsweep) redsearch = DEFAULT_BS_REDUCTION; if (sweeprange == 0.0) sweeprange = DEFAULT_SWEEP_RANGE; if (sweepdelta == 0.0) sweepdelta = DEFAULT_SWEEP_DELTA; if (minbsdelta == 0.0) minbsdelta = DEFAULT_MINBS_DELTA; pixGetDimensions(pixs, &w, &h, NULL); hs = h / nslices; ovlap = (l_int32)(OVERLAP_FRACTION * hs); pta = ptaCreate(nslices); for (i = 0; i < nslices; i++) { ystart = L_MAX(0, hs * i - ovlap); yend = L_MIN(h - 1, hs * (i + 1) + ovlap); ycenter = (ystart + yend) / 2; box = boxCreate(0, ystart, w, yend - ystart + 1); pix = pixClipRectangle(pixs, box, NULL); pixFindSkewSweepAndSearch(pix, &angle, &conf, redsweep, redsearch, sweeprange, sweepdelta, minbsdelta); if (conf > MIN_ALLOWED_CONFIDENCE) ptaAddPt(pta, ycenter, angle); pixDestroy(&pix); boxDestroy(&box); } /* Do linear least squares fit */ if ((npts = ptaGetCount(pta)) < 2) { ptaDestroy(&pta); return (NUMA *)ERROR_PTR("can't fit skew", procName, NULL); } ptaGetLinearLSF(pta, &a, &b, NULL); if (pa) *pa = a; if (pb) *pb = b; /* Make skew angle array as function of raster line */ naskew = numaCreate(h); for (i = 0; i < h; i++) { angle = a * i + b; numaAddNumber(naskew, angle); } if (debug) { lept_mkdir("lept/baseline"); ptaGetArrays(pta, &nax, &nay); gplot = gplotCreate("/tmp/lept/baseline/skew", GPLOT_PNG, "skew as fctn of y", "y (in raster lines from top)", "angle (in degrees)"); gplotAddPlot(gplot, NULL, naskew, GPLOT_POINTS, "linear lsf"); gplotAddPlot(gplot, nax, nay, GPLOT_POINTS, "actual data pts"); gplotMakeOutput(gplot); gplotDestroy(&gplot); numaDestroy(&nax); numaDestroy(&nay); } ptaDestroy(&pta); return naskew; }
int main(int argc, char **argv) { l_int32 i, w, h, d, rotflag; PIX *pixs, *pixt, *pixd; l_float32 angle, deg2rad, pops, ang; char *filein, *fileout; static char mainName[] = "rotatetest1"; if (argc != 4) return ERROR_INT(" Syntax: rotatetest1 filein angle fileout", mainName, 1); filein = argv[1]; angle = atof(argv[2]); fileout = argv[3]; deg2rad = 3.1415926535 / 180.; if ((pixs = pixRead(filein)) == NULL) return ERROR_INT("pix not made", mainName, 1); if (pixGetDepth(pixs) == 1) { pixt = pixScaleToGray3(pixs); pixDestroy(&pixs); pixs = pixAddBorderGeneral(pixt, 1, 0, 1, 0, 255); pixDestroy(&pixt); } pixGetDimensions(pixs, &w, &h, &d); fprintf(stderr, "w = %d, h = %d\n", w, h); #if 0 /* repertory of rotation operations to choose from */ pixd = pixRotateAM(pixs, deg2rad * angle, L_BRING_IN_WHITE); pixd = pixRotateAMColor(pixs, deg2rad * angle, 0xffffff00); pixd = pixRotateAMColorFast(pixs, deg2rad * angle, 255); pixd = pixRotateAMCorner(pixs, deg2rad * angle, L_BRING_IN_WHITE); pixd = pixRotateShear(pixs, w /2, h / 2, deg2rad * angle, L_BRING_IN_WHITE); pixd = pixRotate3Shear(pixs, w /2, h / 2, deg2rad * angle, L_BRING_IN_WHITE); pixRotateShearIP(pixs, w / 2, h / 2, deg2rad * angle); pixd = pixs; #endif #if 0 /* timing of shear rotation */ for (i = 0; i < NITERS; i++) { pixd = pixRotateShear(pixs, (i * w) / NITERS, (i * h) / NITERS, deg2rad * angle, L_BRING_IN_WHITE); pixDisplay(pixd, 100 + 20 * i, 100 + 20 * i); pixDestroy(&pixd); } #endif #if 0 /* timing of in-place shear rotation */ for (i = 0; i < NITERS; i++) { pixRotateShearIP(pixs, w/2, h/2, deg2rad * angle, L_BRING_IN_WHITE); /* pixRotateShearCenterIP(pixs, deg2rad * angle, L_BRING_IN_WHITE); */ pixDisplay(pixs, 100 + 20 * i, 100 + 20 * i); } pixd = pixs; if (pixGetDepth(pixd) == 1) pixWrite(fileout, pixd, IFF_PNG); else pixWrite(fileout, pixd, IFF_JFIF_JPEG); pixDestroy(&pixs); #endif #if 0 /* timing of various rotation operations (choose) */ startTimer(); w = pixGetWidth(pixs); h = pixGetHeight(pixs); for (i = 0; i < NTIMES; i++) { pixd = pixRotateShearCenter(pixs, deg2rad * angle, L_BRING_IN_WHITE); pixDestroy(&pixd); } pops = (l_float32)(w * h * NTIMES / 1000000.) / stopTimer(); fprintf(stderr, "vers. 1, mpops: %f\n", pops); startTimer(); w = pixGetWidth(pixs); h = pixGetHeight(pixs); for (i = 0; i < NTIMES; i++) { pixRotateShearIP(pixs, w/2, h/2, deg2rad * angle, L_BRING_IN_WHITE); } pops = (l_float32)(w * h * NTIMES / 1000000.) / stopTimer(); fprintf(stderr, "shear, mpops: %f\n", pops); pixWrite(fileout, pixs, IFF_PNG); for (i = 0; i < NTIMES; i++) { pixRotateShearIP(pixs, w/2, h/2, -deg2rad * angle, L_BRING_IN_WHITE); } pixWrite("/usr/tmp/junkout", pixs, IFF_PNG); #endif #if 0 /* area-mapping rotation operations */ pixd = pixRotateAM(pixs, deg2rad * angle, L_BRING_IN_WHITE); /* pixd = pixRotateAMColorFast(pixs, deg2rad * angle, 255); */ if (pixGetDepth(pixd) == 1) pixWrite(fileout, pixd, IFF_PNG); else pixWrite(fileout, pixd, IFF_JFIF_JPEG); #endif #if 0 /* compare the standard area-map color rotation with * the fast area-map color rotation, on a pixel basis */ { PIX *pix1, *pix2; NUMA *nar, *nag, *nab, *naseq; GPLOT *gplot; startTimer(); pix1 = pixRotateAMColor(pixs, 0.12, 0xffffff00); fprintf(stderr, " standard color rotate: %7.2f sec\n", stopTimer()); pixWrite("junkcolor1", pix1, IFF_JFIF_JPEG); startTimer(); pix2 = pixRotateAMColorFast(pixs, 0.12, 0xffffff00); fprintf(stderr, " fast color rotate: %7.2f sec\n", stopTimer()); pixWrite("junkcolor2", pix2, IFF_JFIF_JPEG); pixd = pixAbsDifference(pix1, pix2); pixGetColorHistogram(pixd, 1, &nar, &nag, &nab); naseq = numaMakeSequence(0., 1., 256); gplot = gplotCreate("junk_absdiff", GPLOT_X11, "Number vs diff", "diff", "number"); 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(&nar); numaDestroy(&nag); numaDestroy(&nab); numaDestroy(&naseq); gplotDestroy(&gplot); } #endif /* Do a succession of 180 7-degree rotations in a cw * direction, and unwind the result with another set in * a ccw direction. Although there is a considerable amount * of distortion after successive rotations, after all * 360 rotations, the resulting image is restored to * its original pristine condition! */ #if 1 rotflag = L_ROTATE_AREA_MAP; /* rotflag = L_ROTATE_SHEAR; */ /* rotflag = L_ROTATE_SAMPLING; */ ang = 7.0 * deg2rad; pixGetDimensions(pixs, &w, &h, NULL); pixd = pixRotate(pixs, ang, rotflag, L_BRING_IN_WHITE, w, h); pixWrite("junkrot7", pixd, IFF_PNG); for (i = 1; i < 180; i++) { pixs = pixd; pixd = pixRotate(pixs, ang, rotflag, L_BRING_IN_WHITE, w, h); if ((i % 30) == 0) pixDisplay(pixd, 600, 0); pixDestroy(&pixs); } pixWrite("junkspin", pixd, IFF_PNG); pixDisplay(pixd, 0, 0); for (i = 0; i < 180; i++) { pixs = pixd; pixd = pixRotate(pixs, -ang, rotflag, L_BRING_IN_WHITE, w, h); if (i && (i % 30) == 0) pixDisplay(pixd, 600, 500); pixDestroy(&pixs); } pixWrite("junkunspin", pixd, IFF_PNG); pixDisplay(pixd, 0, 500); pixDestroy(&pixd); #endif return 0; }
main(int argc, char **argv) { char *filein, *fileout; char bigbuf[512]; l_int32 iplot; l_float32 gam; l_float64 gamma[NPLOTS] = {.5, 1.0, 1.5, 2.0, 2.5}; GPLOT *gplot; NUMA *na, *nax; PIX *pixs, *pixd; static char mainName[] = "gammatest"; if (argc != 4) exit(ERROR_INT(" Syntax: gammatest filein gam fileout", mainName, 1)); filein = argv[1]; gam = atof(argv[2]); fileout = argv[3]; if ((pixs = pixRead(filein)) == NULL) exit(ERROR_INT("pixs not made", mainName, 1)); #if 1 startTimer(); pixGammaTRC(pixs, pixs, gam, MINVAL, MAXVAL); fprintf(stderr, "Time for gamma: %7.3f sec\n", stopTimer()); pixWrite(fileout, pixs, IFF_JFIF_JPEG); pixDestroy(&pixs); #endif #if 0 startTimer(); pixd = pixGammaTRC(NULL, pixs, gam, MINVAL, MAXVAL); fprintf(stderr, "Time for gamma: %7.3f sec\n", stopTimer()); pixWrite(fileout, pixd, IFF_JFIF_JPEG); pixDestroy(&pixs); pixDestroy(&pixd); #endif na = numaGammaTRC(gam, MINVAL, MAXVAL); gplotSimple1(na, GPLOT_X11, "/tmp/junkroot", "gamma trc"); numaDestroy(&na); #if 1 /* plot gamma TRC maps */ gplot = gplotCreate("/tmp/junkmap", GPLOT_X11, "Mapping function for gamma correction", "value in", "value out"); nax = numaMakeSequence(0.0, 1.0, 256); for (iplot = 0; iplot < NPLOTS; iplot++) { na = numaGammaTRC(gamma[iplot], 30, 215); sprintf(bigbuf, "gamma = %3.1f", gamma[iplot]); gplotAddPlot(gplot, nax, na, GPLOT_LINES, bigbuf); numaDestroy(&na); } gplotMakeOutput(gplot); gplotDestroy(&gplot); numaDestroy(&nax); #endif return 0; }
int main(int argc, char **argv) { l_int32 type, comptype, d1, d2, same, first, last; l_float32 fract, diff, rmsdiff; char *filein1, *filein2, *fileout; GPLOT *gplot; NUMA *na1, *na2; PIX *pixs1, *pixs2, *pixd; static char mainName[] = "comparetest"; if (argc != 5) return ERROR_INT(" Syntax: comparetest filein1 filein2 type fileout", mainName, 1); filein1 = argv[1]; filein2 = argv[2]; type = atoi(argv[3]); pixd = NULL; fileout = argv[4]; l_pngSetReadStrip16To8(0); if ((pixs1 = pixRead(filein1)) == NULL) return ERROR_INT("pixs1 not made", mainName, 1); if ((pixs2 = pixRead(filein2)) == NULL) return ERROR_INT("pixs2 not made", mainName, 1); d1 = pixGetDepth(pixs1); d2 = pixGetDepth(pixs2); if (d1 == 1 && d2 == 1) { pixEqual(pixs1, pixs2, &same); if (same) { fprintf(stderr, "Images are identical\n"); pixd = pixCreateTemplate(pixs1); /* write empty pix for diff */ } else { if (type == 0) comptype = L_COMPARE_XOR; else comptype = L_COMPARE_SUBTRACT; pixCompareBinary(pixs1, pixs2, comptype, &fract, &pixd); fprintf(stderr, "Fraction of different pixels: %10.6f\n", fract); } pixWrite(fileout, pixd, IFF_PNG); } else { if (type == 0) comptype = L_COMPARE_ABS_DIFF; else comptype = L_COMPARE_SUBTRACT; pixCompareGrayOrRGB(pixs1, pixs2, comptype, GPLOT_X11, &same, &diff, &rmsdiff, &pixd); if (type == 0) { if (same) fprintf(stderr, "Images are identical\n"); else { fprintf(stderr, "Images differ: <diff> = %10.6f\n", diff); fprintf(stderr, " <rmsdiff> = %10.6f\n", rmsdiff); } } else { /* subtraction */ if (same) fprintf(stderr, "pixs2 strictly greater than pixs1\n"); else { fprintf(stderr, "Images differ: <diff> = %10.6f\n", diff); fprintf(stderr, " <rmsdiff> = %10.6f\n", rmsdiff); } } if (d1 != 16) pixWrite(fileout, pixd, IFF_JFIF_JPEG); else pixWrite(fileout, pixd, IFF_PNG); if (d1 != 16 && !same) { na1 = pixCompareRankDifference(pixs1, pixs2, 1); if (na1) { fprintf(stderr, "na1[150] = %20.10f\n", na1->array[150]); fprintf(stderr, "na1[200] = %20.10f\n", na1->array[200]); fprintf(stderr, "na1[250] = %20.10f\n", na1->array[250]); numaGetNonzeroRange(na1, 0.00005, &first, &last); fprintf(stderr, "Nonzero diff range: first = %d, last = %d\n", first, last); na2 = numaClipToInterval(na1, first, last); gplot = gplotCreate("/tmp/junkrank", GPLOT_X11, "Pixel Rank Difference", "pixel val", "rank"); gplotAddPlot(gplot, NULL, na2, GPLOT_LINES, "rank"); gplotMakeOutput(gplot); gplotDestroy(&gplot); numaDestroy(&na1); numaDestroy(&na2); } } } pixDestroy(&pixs1); pixDestroy(&pixs2); pixDestroy(&pixd); return 0; }
int main(int argc, char **argv) { l_int32 i, n, binsize, binstart, nbins; l_float32 pi, val, angle, xval, yval, x0, y0, startval, fbinsize; l_float32 minval, maxval, meanval, median, variance, rankval, rank, rmsdev; GPLOT *gplot; NUMA *na, *nahisto, *nax, *nay, *nap, *nasx, *nasy; NUMA *nadx, *nady, *nafx, *nafy, *na1, *na2, *na3, *na4; PIX *pixs, *pix1, *pix2, *pix3, *pix4, *pix5, *pix6, *pix7, *pixd; PIXA *pixa; L_REGPARAMS *rp; if (regTestSetup(argc, argv, &rp)) return 1; lept_mkdir("lept/numa1"); /* -------------------------------------------------------------------* * Histograms * * -------------------------------------------------------------------*/ pi = 3.1415926535; na = numaCreate(5000); for (i = 0; i < 500000; i++) { angle = 0.02293 * i * pi; val = (l_float32)(999. * sin(angle)); numaAddNumber(na, val); } nahisto = numaMakeHistogramClipped(na, 6, 2000); nbins = numaGetCount(nahisto); nax = numaMakeSequence(0, 1, nbins); gplot = gplotCreate("/tmp/lept/numa1/histo1", GPLOT_PNG, "example histo 1", "i", "histo[i]"); gplotAddPlot(gplot, nax, nahisto, GPLOT_LINES, "sine"); gplotMakeOutput(gplot); gplotDestroy(&gplot); numaDestroy(&nax); numaDestroy(&nahisto); nahisto = numaMakeHistogram(na, 1000, &binsize, &binstart); nbins = numaGetCount(nahisto); nax = numaMakeSequence(binstart, binsize, nbins); fprintf(stderr, " binsize = %d, binstart = %d\n", binsize, binstart); gplot = gplotCreate("/tmp/lept/numa1/histo2", GPLOT_PNG, "example histo 2", "i", "histo[i]"); gplotAddPlot(gplot, nax, nahisto, GPLOT_LINES, "sine"); gplotMakeOutput(gplot); gplotDestroy(&gplot); numaDestroy(&nax); numaDestroy(&nahisto); nahisto = numaMakeHistogram(na, 1000, &binsize, NULL); nbins = numaGetCount(nahisto); nax = numaMakeSequence(0, binsize, nbins); fprintf(stderr, " binsize = %d, binstart = %d\n", binsize, 0); gplot = gplotCreate("/tmp/lept/numa1/histo3", GPLOT_PNG, "example histo 3", "i", "histo[i]"); gplotAddPlot(gplot, nax, nahisto, GPLOT_LINES, "sine"); gplotMakeOutput(gplot); gplotDestroy(&gplot); numaDestroy(&nax); numaDestroy(&nahisto); nahisto = numaMakeHistogramAuto(na, 1000); nbins = numaGetCount(nahisto); numaGetParameters(nahisto, &startval, &fbinsize); nax = numaMakeSequence(startval, fbinsize, nbins); fprintf(stderr, " binsize = %7.4f, binstart = %8.3f\n", fbinsize, startval); gplot = gplotCreate("/tmp/lept/numa1/histo4", GPLOT_PNG, "example histo 4", "i", "histo[i]"); gplotAddPlot(gplot, nax, nahisto, GPLOT_LINES, "sine"); gplotMakeOutput(gplot); gplotDestroy(&gplot); pix1 = pixRead("/tmp/lept/numa1/histo1.png"); pix2 = pixRead("/tmp/lept/numa1/histo2.png"); pix3 = pixRead("/tmp/lept/numa1/histo3.png"); pix4 = pixRead("/tmp/lept/numa1/histo4.png"); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 0 */ regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 1 */ regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 2 */ regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 3 */ pixa = pixaCreate(4); pixaAddPix(pixa, pix1, L_INSERT); pixaAddPix(pixa, pix2, L_INSERT); pixaAddPix(pixa, pix3, L_INSERT); pixaAddPix(pixa, pix4, L_INSERT); if (rp->display) { pixd = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 20, 2); pixDisplayWithTitle(pixd, 0, 0, NULL, 1); pixDestroy(&pixd); } pixaDestroy(&pixa); numaDestroy(&nax); numaDestroy(&nahisto); numaGetStatsUsingHistogram(na, 2000, &minval, &maxval, &meanval, &variance, &median, 0.80, &rankval, &nahisto); rmsdev = sqrt((l_float64)variance); numaHistogramGetRankFromVal(nahisto, rankval, &rank); regTestCompareValues(rp, -999.00, minval, 0.1); /* 4 */ regTestCompareValues(rp, 999.00, maxval, 0.1); /* 5 */ regTestCompareValues(rp, 0.055, meanval, 0.001); /* 6 */ regTestCompareValues(rp, 0.30, median, 0.005); /* 7 */ regTestCompareValues(rp, 706.41, rmsdev, 0.1); /* 8 */ regTestCompareValues(rp, 808.15, rankval, 0.1); /* 9 */ regTestCompareValues(rp, 0.800, rank, 0.01); /* 10 */ if (rp->display) { fprintf(stderr, "Sin histogram: \n" " min val = %7.3f -- should be -999.00\n" " max val = %7.3f -- should be 999.00\n" " mean val = %7.3f -- should be 0.055\n" " median = %7.3f -- should be 0.30\n" " rmsdev = %7.3f -- should be 706.41\n" " rank val = %7.3f -- should be 808.152\n" " rank = %7.3f -- should be 0.800\n", minval, maxval, meanval, median, rmsdev, rankval, rank); } numaDestroy(&nahisto); numaDestroy(&na); /* -------------------------------------------------------------------* * Interpolation * * -------------------------------------------------------------------*/ /* Test numaInterpolateEqxInterval() */ pixs = pixRead("test8.jpg"); na = pixGetGrayHistogramMasked(pixs, NULL, 0, 0, 1); nasy = numaGetPartialSums(na); gplotSimple1(nasy, GPLOT_PNG, "/tmp/lept/numa1/int1", "partial sums"); gplotSimple1(na, GPLOT_PNG, "/tmp/lept/numa1/int2", "simple test"); numaInterpolateEqxInterval(0.0, 1.0, na, L_LINEAR_INTERP, 0.0, 255.0, 15, &nax, &nay); gplot = gplotCreate("/tmp/lept/numa1/int3", GPLOT_PNG, "test interpolation", "pix val", "num pix"); gplotAddPlot(gplot, nax, nay, GPLOT_LINES, "plot 1"); gplotMakeOutput(gplot); gplotDestroy(&gplot); numaDestroy(&na); numaDestroy(&nasy); numaDestroy(&nax); numaDestroy(&nay); pixDestroy(&pixs); /* Test numaInterpolateArbxInterval() */ pixs = pixRead("test8.jpg"); na = pixGetGrayHistogramMasked(pixs, NULL, 0, 0, 1); nasy = numaGetPartialSums(na); numaInsertNumber(nasy, 0, 0.0); nasx = numaMakeSequence(0.0, 1.0, 257); numaInterpolateArbxInterval(nasx, nasy, L_LINEAR_INTERP, 10.0, 250.0, 23, &nax, &nay); gplot = gplotCreate("/tmp/lept/numa1/int4", GPLOT_PNG, "arbx interpolation", "pix val", "cum num pix"); gplotAddPlot(gplot, nax, nay, GPLOT_LINES, "plot 1"); gplotMakeOutput(gplot); gplotDestroy(&gplot); numaDestroy(&na); numaDestroy(&nasx); numaDestroy(&nasy); numaDestroy(&nax); numaDestroy(&nay); pixDestroy(&pixs); /* Test numaInterpolateArbxVal() */ pixs = pixRead("test8.jpg"); na = pixGetGrayHistogramMasked(pixs, NULL, 0, 0, 1); nasy = numaGetPartialSums(na); numaInsertNumber(nasy, 0, 0.0); nasx = numaMakeSequence(0.0, 1.0, 257); nax = numaMakeSequence(15.0, (250.0 - 15.0) / 23.0, 24); n = numaGetCount(nax); nay = numaCreate(n); for (i = 0; i < n; i++) { numaGetFValue(nax, i, &xval); numaInterpolateArbxVal(nasx, nasy, L_QUADRATIC_INTERP, xval, &yval); numaAddNumber(nay, yval); } gplot = gplotCreate("/tmp/lept/numa1/int5", GPLOT_PNG, "arbx interpolation", "pix val", "cum num pix"); gplotAddPlot(gplot, nax, nay, GPLOT_LINES, "plot 1"); gplotMakeOutput(gplot); gplotDestroy(&gplot); numaDestroy(&na); numaDestroy(&nasx); numaDestroy(&nasy); numaDestroy(&nax); numaDestroy(&nay); pixDestroy(&pixs); /* Test interpolation */ nasx = numaRead("testangle.na"); nasy = numaRead("testscore.na"); gplot = gplotCreate("/tmp/lept/numa1/int6", GPLOT_PNG, "arbx interpolation", "angle", "score"); numaInterpolateArbxInterval(nasx, nasy, L_LINEAR_INTERP, -2.00, 0.0, 50, &nax, &nay); gplotAddPlot(gplot, nax, nay, GPLOT_LINES, "linear"); numaDestroy(&nax); numaDestroy(&nay); numaInterpolateArbxInterval(nasx, nasy, L_QUADRATIC_INTERP, -2.00, 0.0, 50, &nax, &nay); gplotAddPlot(gplot, nax, nay, GPLOT_LINES, "quadratic"); numaDestroy(&nax); numaDestroy(&nay); gplotMakeOutput(gplot); gplotDestroy(&gplot); gplot = gplotCreate("/tmp/lept/numa1/int7", GPLOT_PNG, "arbx interpolation", "angle", "score"); numaInterpolateArbxInterval(nasx, nasy, L_LINEAR_INTERP, -1.2, -0.8, 50, &nax, &nay); gplotAddPlot(gplot, nax, nay, GPLOT_LINES, "quadratic"); gplotMakeOutput(gplot); gplotDestroy(&gplot); numaFitMax(nay, &yval, nax, &xval); if (rp->display) fprintf(stderr, "max = %f at loc = %f\n", yval, xval); pixa = pixaCreate(7); pix1 = pixRead("/tmp/lept/numa1/int1.png"); pix2 = pixRead("/tmp/lept/numa1/int2.png"); pix3 = pixRead("/tmp/lept/numa1/int3.png"); pix4 = pixRead("/tmp/lept/numa1/int4.png"); pix5 = pixRead("/tmp/lept/numa1/int5.png"); pix6 = pixRead("/tmp/lept/numa1/int6.png"); pix7 = pixRead("/tmp/lept/numa1/int7.png"); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 11 */ regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 12 */ regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 13 */ regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 14 */ regTestWritePixAndCheck(rp, pix5, IFF_PNG); /* 15 */ regTestWritePixAndCheck(rp, pix6, IFF_PNG); /* 16 */ regTestWritePixAndCheck(rp, pix7, IFF_PNG); /* 17 */ pixaAddPix(pixa, pix1, L_INSERT); pixaAddPix(pixa, pix2, L_INSERT); pixaAddPix(pixa, pix3, L_INSERT); pixaAddPix(pixa, pix4, L_INSERT); pixaAddPix(pixa, pix5, L_INSERT); pixaAddPix(pixa, pix6, L_INSERT); pixaAddPix(pixa, pix7, L_INSERT); if (rp->display) { pixd = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 20, 2); pixDisplayWithTitle(pixd, 300, 0, NULL, 1); pixDestroy(&pixd); } pixaDestroy(&pixa); numaDestroy(&nasx); numaDestroy(&nasy); numaDestroy(&nax); numaDestroy(&nay); /* -------------------------------------------------------------------* * Integration and differentiation * * -------------------------------------------------------------------*/ /* Test integration and differentiation */ nasx = numaRead("testangle.na"); nasy = numaRead("testscore.na"); /* ---------- Plot the derivative ---------- */ numaDifferentiateInterval(nasx, nasy, -2.0, 0.0, 50, &nadx, &nady); gplot = gplotCreate("/tmp/lept/numa1/diff1", GPLOT_PNG, "derivative", "angle", "slope"); gplotAddPlot(gplot, nadx, nady, GPLOT_LINES, "derivative"); gplotMakeOutput(gplot); gplotDestroy(&gplot); /* ---------- Plot the original function ----------- */ /* and the integral of the derivative; the two */ /* should be approximately the same. */ gplot = gplotCreate("/tmp/lept/numa1/diff2", GPLOT_PNG, "integ-diff", "angle", "val"); numaInterpolateArbxInterval(nasx, nasy, L_LINEAR_INTERP, -2.00, 0.0, 50, &nafx, &nafy); gplotAddPlot(gplot, nafx, nafy, GPLOT_LINES, "function"); n = numaGetCount(nadx); numaGetFValue(nafx, 0, &x0); numaGetFValue(nafy, 0, &y0); nay = numaCreate(n); /* (Note: this tests robustness of the integrator: we go from * i = 0, and choose to have only 1 point in the interpolation * there, which is too small and causes the function to bomb out.) */ fprintf(stderr, "We must get a 'npts < 2' error here:\n"); for (i = 0; i < n; i++) { numaGetFValue(nadx, i, &xval); numaIntegrateInterval(nadx, nady, x0, xval, 2 * i + 1, &yval); numaAddNumber(nay, y0 + yval); } gplotAddPlot(gplot, nafx, nay, GPLOT_LINES, "anti-derivative"); gplotMakeOutput(gplot); gplotDestroy(&gplot); pixa = pixaCreate(2); pix1 = pixRead("/tmp/lept/numa1/diff1.png"); pix2 = pixRead("/tmp/lept/numa1/diff2.png"); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 18 */ regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 19 */ pixaAddPix(pixa, pix1, L_INSERT); pixaAddPix(pixa, pix2, L_INSERT); if (rp->display) { pixd = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 20, 2); pixDisplayWithTitle(pixd, 600, 0, NULL, 1); pixDestroy(&pixd); } pixaDestroy(&pixa); numaDestroy(&nasx); numaDestroy(&nasy); numaDestroy(&nafx); numaDestroy(&nafy); numaDestroy(&nadx); numaDestroy(&nady); numaDestroy(&nay); /* -------------------------------------------------------------------* * Rank extraction * * -------------------------------------------------------------------*/ /* Rank extraction with interpolation */ pixs = pixRead("test8.jpg"); nasy= pixGetGrayHistogramMasked(pixs, NULL, 0, 0, 1); numaMakeRankFromHistogram(0.0, 1.0, nasy, 350, &nax, &nay); gplot = gplotCreate("/tmp/lept/numa1/rank1", GPLOT_PNG, "test rank extractor", "pix val", "rank val"); gplotAddPlot(gplot, nax, nay, GPLOT_LINES, "plot 1"); gplotMakeOutput(gplot); gplotDestroy(&gplot); numaDestroy(&nasy); numaDestroy(&nax); numaDestroy(&nay); pixDestroy(&pixs); /* Rank extraction, point by point */ pixs = pixRead("test8.jpg"); nap = numaCreate(200); pixGetRankValueMasked(pixs, NULL, 0, 0, 2, 0.0, &val, &na); for (i = 0; i < 101; i++) { rank = 0.01 * i; numaHistogramGetValFromRank(na, rank, &val); numaAddNumber(nap, val); } gplotSimple1(nap, GPLOT_PNG, "/tmp/lept/numa1/rank2", "rank value"); pixa = pixaCreate(2); pix1 = pixRead("/tmp/lept/numa1/rank1.png"); pix2 = pixRead("/tmp/lept/numa1/rank2.png"); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 20 */ regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 21 */ pixaAddPix(pixa, pix1, L_INSERT); pixaAddPix(pixa, pix2, L_INSERT); if (rp->display) { pixd = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 20, 2); pixDisplayWithTitle(pixd, 900, 0, NULL, 1); pixDestroy(&pixd); } pixaDestroy(&pixa); numaDestroy(&na); numaDestroy(&nap); pixDestroy(&pixs); /* -------------------------------------------------------------------* * Numa-morphology * * -------------------------------------------------------------------*/ na = numaRead("lyra.5.na"); gplotSimple1(na, GPLOT_PNG, "/tmp/lept/numa1/lyra1", "Original"); na1 = numaErode(na, 21); gplotSimple1(na1, GPLOT_PNG, "/tmp/lept/numa1/lyra2", "Erosion"); na2 = numaDilate(na, 21); gplotSimple1(na2, GPLOT_PNG, "/tmp/lept/numa1/lyra3", "Dilation"); na3 = numaOpen(na, 21); gplotSimple1(na3, GPLOT_PNG, "/tmp/lept/numa1/lyra4", "Opening"); na4 = numaClose(na, 21); gplotSimple1(na4, GPLOT_PNG, "/tmp/lept/numa1/lyra5", "Closing"); pixa = pixaCreate(2); pix1 = pixRead("/tmp/lept/numa1/lyra1.png"); pix2 = pixRead("/tmp/lept/numa1/lyra2.png"); pix3 = pixRead("/tmp/lept/numa1/lyra3.png"); pix4 = pixRead("/tmp/lept/numa1/lyra4.png"); pix5 = pixRead("/tmp/lept/numa1/lyra5.png"); pixaAddPix(pixa, pix1, L_INSERT); pixaAddPix(pixa, pix2, L_INSERT); pixaAddPix(pixa, pix3, L_INSERT); pixaAddPix(pixa, pix4, L_INSERT); pixaAddPix(pixa, pix5, L_INSERT); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 22 */ regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 23 */ regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 24 */ regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 25 */ regTestWritePixAndCheck(rp, pix5, IFF_PNG); /* 26 */ if (rp->display) { pixd = pixaDisplayTiledInRows(pixa, 32, 1500, 1.0, 0, 20, 2); pixDisplayWithTitle(pixd, 1200, 0, NULL, 1); pixDestroy(&pixd); } pixaDestroy(&pixa); numaDestroy(&na); numaDestroy(&na1); numaDestroy(&na2); numaDestroy(&na3); numaDestroy(&na4); pixaDestroy(&pixa); return regTestCleanup(rp); }
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; }