Esempio n. 1
0
/*!
 *  pixGaussianSelectiveFilter()
 *
 *      Input:  pix (8 or 32 bpp; or 2, 4 or 8 bpp with colormap)
 *              radius (circle radius)
 *              bandwidth (width of the band)
 *              typeflag (L_BAND_REJECT or L_BAND_PASS)
 *              outflag (L_CLIP_TO_ZERO, L_TAKE_ABSVAL,
 *                       L_THRESH_NEG_TO_BLACK or L_THRESH_NEG_TO_WHITE)
 *              dpixf (<optional return> filter used)
 *      Return: filtered pix, or null on error
 *
 *  Notes:
 *      (1) Implements a Gaussian bandreject or bandpass filter,
 *          depending on the value of @typeflag.
 *      (2) The same concepts and arguments of pixGaussianFilter() apply,
 *          the difference being that the latter operates over the entire
 *          frequency rectangle while the selective filter processes only
 *          specific bands of frequencies of radius @radius and width
 *          @bandwidth.
 */
PIX *
pixGaussianSelectiveFilter(PIX        *pixs,
						   l_float32   radius,
						   l_float32   bandwidth,
						   l_int32     typeflag,
						   l_int32     outflag,
						   DPIX      **dpixf)
{
	DPIX    *dpix;
	PIX     *pixd;
	
	PROCNAME("pixGaussianSelectiveFilter");
	
	if (!pixs)
		return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
	
	dpix = filterCreateGaussianSelective(pixGetWidth(pixs), pixGetHeight(pixs), radius, bandwidth, typeflag);
	if (dpix == NULL)
		return (PIX *)ERROR_PTR("dpix not made", procName, NULL);
	
	pixd = pixApplyFilter(pixs, dpix, outflag);
	
	if (dpixf)
		*dpixf = dpix;
	else
		dpixDestroy(&dpix);
	
	return pixd;
}
Esempio n. 2
0
/*!
 *  pixDFT()
 *
 *      Input:  pix (1 bpp or 8 bpp)
 *              shiftflag (L_NO_SHIFTING or L_WITH_SHIFTING)
 *      Return: complex array, or null on error
 *
 *  Notes:
 *      (1) The complex array returned has size (pixs->h) * (pixs->w / 2 + 1).
 *          This is to save space, given the fact the other half of the
 *          transform can be calculated by the complex conjugate.
 *      (2) By default, the DC of the DFT is in the top left corner (0, 0).
 *          Set @shiftflag to L_WITH_SHIFTING to move the DC to the center.
 *      (3) It is the responsibility of the caller to release the allocated
 *          complex array by invoking fftw_free().
 */
fftw_complex *
pixDFT(PIX      *pixs,
	   l_int32   shiftflag)
{
	l_int32	       w, h, d;
	l_int32        i, j, k;
	DPIX          *dpix;
	fftw_complex  *output;
	fftw_plan      plan;
	
	PROCNAME("pixDFT");
	
    if (!pixs)
        return (fftw_complex *)ERROR_PTR("pixs not defined", procName, NULL);
	if (shiftflag != L_NO_SHIFTING && shiftflag != L_WITH_SHIFTING)
        return (fftw_complex *)ERROR_PTR("invalid shiftflag", procName, NULL);
	
	pixGetDimensions(pixs, &w, &h, &d);
	if (d != 1 && d != 8)
        return (fftw_complex *)ERROR_PTR("pixs not 1 bpp or 8 bpp", procName, NULL);
	
	/* Convert Pix to a DPix that can be fed to the FFTW library */
	if ((dpix = pixConvertToDPix(pixs, 1, shiftflag)) == NULL)
        return (fftw_complex *)ERROR_PTR("dpix not made", procName, NULL);
	
	/* Compute the DFT of the DPix */
	output = (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * h * (w / 2 + 1));
	plan = fftw_plan_dft_r2c_2d(h, w, (double *) dpixGetData(dpix), output, FFTW_ESTIMATE);
	fftw_execute(plan);
	
	dpixDestroy(&dpix);
	fftw_destroy_plan(plan);
	
	return output;
}
Esempio n. 3
0
/*!
 *  pixInverseDFT()
 *
 *      Input:  dft
 *              w, h (image size)
 *              shiftflag (L_NO_SHIFTING or L_WITH_SHIFTING)
 *              outflag (L_CLIP_TO_ZERO, L_TAKE_ABSVAL,
 *                       L_THRESH_NEG_TO_BLACK or L_THRESH_NEG_TO_WHITE)
 *      Return: pixd (8bpp), or null on error
 *
 *  Notes:
 *      (1) Set @shiftflag to L_WITH_SHIFTING if the DC was moved to the
 *          center of the image during the DFT computation. Reshifting it
 *          will move the DC back to the top left corner (0, 0).
 *      (2) It is the responsibility of the caller to release the allocated
 *          complex array by invoking fftw_free().
 */
PIX *
pixInverseDFT(fftw_complex *dft,
			  l_int32       w,
			  l_int32       h,
			  l_int32       shiftflag,
			  l_int32       outflag)
{
	PIX          *pixd;
	DPIX         *dpix;
	
	PROCNAME("pixInverseDFT");
	
	dpix = dpixInverseDFT(dft, w, h);
	
	/* Convert DPix to a Pix */
	pixd = dpixConvertToPix(dpix, 8, outflag, 0, shiftflag);
	dpixDestroy(&dpix);
	
	return pixd;
}
Esempio n. 4
0
/*!
 *  pixQuadtreeVariance()
 *
 *      Input:  pixs (8 bpp, no colormap)
 *              nlevels (in quadtree)
 *             *pix_ma (input mean accumulator; can be null)
 *             *dpix_msa (input mean square accumulator; can be null)
 *             *pfpixa_v (<optional return> variance values in quadtree)
 *             *pfpixa_rv (<optional return> root variance values in quadtree)
 *      Return: 0 if OK, 1 on error
 *
 *  Notes:
 *      (1) The returned fpixav and fpixarv have @nlevels of fpix,
 *          each containing at the respective levels the variance
 *          and root variance values.
 */
l_int32
pixQuadtreeVariance(PIX *pixs,
                    l_int32 nlevels,
                    PIX *pix_ma,
                    DPIX *dpix_msa,
                    FPIXA **pfpixa_v,
                    FPIXA **pfpixa_rv) {
    l_int32 i, j, w, h, size, n;
    l_float32 var, rvar;
    BOX *box;
    BOXA *boxa;
    BOXAA *baa;
    FPIX *fpixv, *fpixrv;
    PIX *pix_mac;  /* copy of mean accumulator */
    DPIX *dpix_msac;  /* msa clone */

    PROCNAME("pixQuadtreeVariance");

    if (!pfpixa_v && !pfpixa_rv)
        return ERROR_INT("neither &fpixav nor &fpixarv defined", procName, 1);
    if (pfpixa_v) *pfpixa_v = NULL;
    if (pfpixa_rv) *pfpixa_rv = NULL;
    if (!pixs || pixGetDepth(pixs) != 8)
        return ERROR_INT("pixs not defined or not 8 bpp", procName, 1);
    pixGetDimensions(pixs, &w, &h, NULL);
    if (nlevels > quadtreeMaxLevels(w, h))
        return ERROR_INT("nlevels too large for image", procName, 1);

    if (!pix_ma)
        pix_mac = pixBlockconvAccum(pixs);
    else
        pix_mac = pixClone(pix_ma);
    if (!pix_mac)
        return ERROR_INT("pix_mac not made", procName, 1);
    if (!dpix_msa)
        dpix_msac = pixMeanSquareAccum(pixs);
    else
        dpix_msac = dpixClone(dpix_msa);
    if (!dpix_msac)
        return ERROR_INT("dpix_msac not made", procName, 1);

    if ((baa = boxaaQuadtreeRegions(w, h, nlevels)) == NULL) {
        pixDestroy(&pix_mac);
        dpixDestroy(&dpix_msac);
        return ERROR_INT("baa not made", procName, 1);
    }

    if (pfpixa_v) *pfpixa_v = fpixaCreate(nlevels);
    if (pfpixa_rv) *pfpixa_rv = fpixaCreate(nlevels);
    for (i = 0; i < nlevels; i++) {
        boxa = boxaaGetBoxa(baa, i, L_CLONE);
        size = 1 << i;
        n = boxaGetCount(boxa);  /* n == size * size */
        if (pfpixa_v) fpixv = fpixCreate(size, size);
        if (pfpixa_rv) fpixrv = fpixCreate(size, size);
        for (j = 0; j < n; j++) {
            box = boxaGetBox(boxa, j, L_CLONE);
            pixVarianceInRectangle(pixs, box, pix_mac, dpix_msac, &var, &rvar);
            if (pfpixa_v) fpixSetPixel(fpixv, j % size, j / size, var);
            if (pfpixa_rv) fpixSetPixel(fpixrv, j % size, j / size, rvar);
            boxDestroy(&box);
        }
        if (pfpixa_v) fpixaAddFPix(*pfpixa_v, fpixv, L_INSERT);
        if (pfpixa_rv) fpixaAddFPix(*pfpixa_rv, fpixrv, L_INSERT);
        boxaDestroy(&boxa);
    }

    pixDestroy(&pix_mac);
    dpixDestroy(&dpix_msac);
    boxaaDestroy(&baa);
    return 0;
}
Esempio n. 5
0
main(int    argc,
char **argv)
{
l_float32     sum, sumx, sumy, diff;
L_DEWARP     *dew;
L_DEWARPA    *dewa;
FPIX         *fpixs, *fpixs2, *fpixs3, *fpixs4, *fpixg, *fpixd;
FPIX         *fpix1, *fpix2, *fpixt1, *fpixt2;
DPIX         *dpix, *dpix2;
L_KERNEL     *kel, *kelx, *kely;
PIX          *pixs, *pixs2, *pixs3, *pixt, *pixd, *pixg, *pixb, *pixn;
PIX          *pixt1, *pixt2, *pixt3, *pixt4, *pixt5, *pixt6;
PIXA         *pixa;
PTA          *ptas, *ptad;
L_REGPARAMS  *rp;

    if (regTestSetup(argc, argv, &rp))
        return 1;

    pixa = pixaCreate(0);

        /* Gaussian kernel */
    kel = makeGaussianKernel(5, 5, 3.0, 4.0);
    kernelGetSum(kel, &sum);
    if (rp->display) fprintf(stderr, "Sum for 2d gaussian kernel = %f\n", sum);
    pixt = kernelDisplayInPix(kel, 41, 2);
    regTestWritePixAndCheck(rp, pixt, IFF_PNG);  /* 0 */
    pixSaveTiled(pixt, pixa, 1, 1, 20, 8);
    pixDestroy(&pixt);

        /* Separable gaussian kernel */
    makeGaussianKernelSep(5, 5, 3.0, 4.0, &kelx, &kely);
    kernelGetSum(kelx, &sumx);
    if (rp->display) fprintf(stderr, "Sum for x gaussian kernel = %f\n", sumx);
    kernelGetSum(kely, &sumy);
    if (rp->display) fprintf(stderr, "Sum for y gaussian kernel = %f\n", sumy);
    if (rp->display) fprintf(stderr, "Sum for x * y gaussian kernel = %f\n",
                         sumx * sumy);
    pixt = kernelDisplayInPix(kelx, 41, 2);
    regTestWritePixAndCheck(rp, pixt, IFF_PNG);  /* 1 */
    pixSaveTiled(pixt, pixa, 1, 0, 20, 8);
    pixDestroy(&pixt);
    pixt = kernelDisplayInPix(kely, 41, 2);
    regTestWritePixAndCheck(rp, pixt, IFF_PNG);  /* 2 */
    pixSaveTiled(pixt, pixa, 1, 0, 20, 8);
    pixDestroy(&pixt);

        /* Use pixRasterop() to generate source image */
    pixs = pixRead("test8.jpg");
    pixs2 = pixRead("karen8.jpg");
    pixRasterop(pixs, 150, 125, 150, 100, PIX_SRC, pixs2, 75, 100);
    regTestWritePixAndCheck(rp, pixs, IFF_JFIF_JPEG);  /* 3 */

        /* Convolution directly with pix */
    pixt1 = pixConvolve(pixs, kel, 8, 1);
    regTestWritePixAndCheck(rp, pixt1, IFF_JFIF_JPEG);  /* 4 */
    pixSaveTiled(pixt1, pixa, 1, 1, 20, 8);
    pixt2 = pixConvolveSep(pixs, kelx, kely, 8, 1);
    regTestWritePixAndCheck(rp, pixt2, IFF_JFIF_JPEG);  /* 5 */
    pixSaveTiled(pixt2, pixa, 1, 0, 20, 8);

        /* Convolution indirectly with fpix, using fpixRasterop()
         * to generate the source image. */
    fpixs = pixConvertToFPix(pixs, 3);
    fpixs2 = pixConvertToFPix(pixs2, 3);
    fpixRasterop(fpixs, 150, 125, 150, 100, fpixs2, 75, 100);
    fpixt1 = fpixConvolve(fpixs, kel, 1);
    pixt3 = fpixConvertToPix(fpixt1, 8, L_CLIP_TO_ZERO, 1);
    regTestWritePixAndCheck(rp, pixt3, IFF_JFIF_JPEG);  /* 6 */
    pixSaveTiled(pixt3, pixa, 1, 1, 20, 8);
    fpixt2 = fpixConvolveSep(fpixs, kelx, kely, 1);
    pixt4 = fpixConvertToPix(fpixt2, 8, L_CLIP_TO_ZERO, 1);
    regTestWritePixAndCheck(rp, pixt4, IFF_JFIF_JPEG);  /* 7 */
    pixSaveTiled(pixt4, pixa, 1, 0, 20, 8);
    pixDestroy(&pixs2);
    fpixDestroy(&fpixs2);
    fpixDestroy(&fpixt1);
    fpixDestroy(&fpixt2);

        /* Comparison of results */
    pixCompareGray(pixt1, pixt2, L_COMPARE_ABS_DIFF, 0, NULL,
                   &diff, NULL, NULL);
    if (rp->display)
        fprintf(stderr, "Ave diff of pixConvolve and pixConvolveSep: %f\n",
                diff);
    pixCompareGray(pixt3, pixt4, L_COMPARE_ABS_DIFF, 0, NULL,
                   &diff, NULL, NULL);
    if (rp->display)
        fprintf(stderr, "Ave diff of fpixConvolve and fpixConvolveSep: %f\n",
                diff);
    pixCompareGray(pixt1, pixt3, L_COMPARE_ABS_DIFF, 0, NULL,
                   &diff, NULL, NULL);
    if (rp->display)
        fprintf(stderr, "Ave diff of pixConvolve and fpixConvolve: %f\n", diff);
    pixCompareGray(pixt2, pixt4, L_COMPARE_ABS_DIFF, GPLOT_PNG, NULL,
                   &diff, NULL, NULL);
    if (rp->display)
        fprintf(stderr, "Ave diff of pixConvolveSep and fpixConvolveSep: %f\n",
                diff);
    pixDestroy(&pixt1);
    pixDestroy(&pixt2);
    pixDestroy(&pixt3);
    pixDestroy(&pixt4);

        /* Test arithmetic operations; add in a fraction rotated by 180 */
    pixs3 = pixRotate180(NULL, pixs);
    regTestWritePixAndCheck(rp, pixs3, IFF_JFIF_JPEG);  /* 8 */
    pixSaveTiled(pixs3, pixa, 1, 1, 20, 8);
    fpixs3 = pixConvertToFPix(pixs3, 3);
    fpixd = fpixLinearCombination(NULL, fpixs, fpixs3, 20.0, 5.0);
    fpixAddMultConstant(fpixd, 0.0, 23.174);   /* multiply up in magnitude */
    pixd = fpixDisplayMaxDynamicRange(fpixd);  /* bring back to 8 bpp */
    regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG);  /* 9 */
    pixSaveTiled(pixd, pixa, 1, 0, 20, 8);
    pixDestroy(&pixs3);
    fpixDestroy(&fpixs3);
    fpixDestroy(&fpixd);
    pixDestroy(&pixd);
    pixDestroy(&pixs);
    fpixDestroy(&fpixs);

        /* Save the comparison graph; gnuplot should have made it by now! */
#ifndef _WIN32
    sleep(2);
#else
    Sleep(2000);
#endif  /* _WIN32 */
    pixt5 = pixRead("/tmp/grayroot.png");
    regTestWritePixAndCheck(rp, pixt5, IFF_PNG);  /* 10 */
    pixSaveTiled(pixt5, pixa, 1, 1, 20, 8);
    pixDestroy(&pixt5);

        /* Display results */
    pixd = pixaDisplay(pixa, 0, 0);
    regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG);  /* 11 */
    pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display);
    pixDestroy(&pixd);
    pixaDestroy(&pixa);

        /* Test some more convolutions, with sampled output. First on pix */
    pixa = pixaCreate(0);
    pixs = pixRead("1555-7.jpg");
    pixg = pixConvertTo8(pixs, 0);
    l_setConvolveSampling(5, 5);
    pixt1 = pixConvolve(pixg, kel, 8, 1);
    regTestWritePixAndCheck(rp, pixt1, IFF_JFIF_JPEG);  /* 12 */
    pixSaveTiled(pixt1, pixa, 1, 1, 20, 32);
    pixt2 = pixConvolveSep(pixg, kelx, kely, 8, 1);
    regTestWritePixAndCheck(rp, pixt2, IFF_JFIF_JPEG);  /* 13 */
    pixSaveTiled(pixt2, pixa, 1, 0, 20, 32);
    pixt3 = pixConvolveRGB(pixs, kel);
    regTestWritePixAndCheck(rp, pixt3, IFF_JFIF_JPEG);  /* 14 */
    pixSaveTiled(pixt3, pixa, 1, 0, 20, 32);
    pixt4 = pixConvolveRGBSep(pixs, kelx, kely);
    regTestWritePixAndCheck(rp, pixt4, IFF_JFIF_JPEG);  /* 15 */
    pixSaveTiled(pixt4, pixa, 1, 0, 20, 32);

        /* Then on fpix */
    fpixg = pixConvertToFPix(pixg, 1);
    fpixt1 = fpixConvolve(fpixg, kel, 1);
    pixt5 = fpixConvertToPix(fpixt1, 8, L_CLIP_TO_ZERO, 0);
    regTestWritePixAndCheck(rp, pixt5, IFF_JFIF_JPEG);  /* 16 */
    pixSaveTiled(pixt5, pixa, 1, 1, 20, 32);
    fpixt2 = fpixConvolveSep(fpixg, kelx, kely, 1);
    pixt6 = fpixConvertToPix(fpixt2, 8, L_CLIP_TO_ZERO, 0);
    regTestWritePixAndCheck(rp, pixt6, IFF_JFIF_JPEG);  /* 17 */
    pixSaveTiled(pixt2, pixa, 1, 0, 20, 32);
    regTestCompareSimilarPix(rp, pixt1, pixt5, 2, 0.00, 0);  /* 18 */
    regTestCompareSimilarPix(rp, pixt2, pixt6, 2, 0.00, 0);  /* 19 */
    pixDestroy(&pixt1);
    pixDestroy(&pixt2);
    pixDestroy(&pixt3);
    pixDestroy(&pixt4);
    pixDestroy(&pixt5);
    pixDestroy(&pixt6);
    fpixDestroy(&fpixg);
    fpixDestroy(&fpixt1);
    fpixDestroy(&fpixt2);

    pixd = pixaDisplay(pixa, 0, 0);
    regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG);  /* 20 */
    pixDisplayWithTitle(pixd, 600, 100, NULL, rp->display);
    pixDestroy(&pixs);
    pixDestroy(&pixg);
    pixDestroy(&pixd);
    pixaDestroy(&pixa);

        /* Test extension (continued and slope).
         * First, build a smooth vertical disparity array;
         * then extend and show the contours. */
    pixs = pixRead("cat-35.jpg");
    pixn = pixBackgroundNormSimple(pixs, NULL, NULL);
    pixg = pixConvertRGBToGray(pixn, 0.5, 0.3, 0.2);
    pixb = pixThresholdToBinary(pixg, 130);
    dewa = dewarpaCreate(1, 30, 1, 15, 0);
    dew = dewarpCreate(pixb, 35);
    dewarpaInsertDewarp(dewa, dew);
    dewarpBuildModel(dew, NULL);
    dewarpPopulateFullRes(dew, NULL);
    fpixs = dew->fullvdispar;
    fpixs2 = fpixAddContinuedBorder(fpixs, 200, 200, 100, 300);
    fpixs3 = fpixAddSlopeBorder(fpixs, 200, 200, 100, 300);
    dpix = fpixConvertToDPix(fpixs3);
    fpixs4 = dpixConvertToFPix(dpix);
    pixt1 = fpixRenderContours(fpixs, 2.0, 0.2);
    pixt2 = fpixRenderContours(fpixs2, 2.0, 0.2);
    pixt3 = fpixRenderContours(fpixs3, 2.0, 0.2);
    pixt4 = fpixRenderContours(fpixs4, 2.0, 0.2);
    pixt5 = pixRead("karen8.jpg");
    dpix2 = pixConvertToDPix(pixt5, 1);
    pixt6 = dpixConvertToPix(dpix2, 8, L_CLIP_TO_ZERO, 0);
    regTestWritePixAndCheck(rp, pixt1, IFF_PNG);  /* 21 */
    pixDisplayWithTitle(pixt1, 0, 100, NULL, rp->display);
    regTestWritePixAndCheck(rp, pixt2, IFF_PNG);  /* 22 */
    pixDisplayWithTitle(pixt2, 470, 100, NULL, rp->display);
    regTestWritePixAndCheck(rp, pixt3, IFF_PNG);  /* 23 */
    pixDisplayWithTitle(pixt3, 1035, 100, NULL, rp->display);
    regTestComparePix(rp, pixt3, pixt4);  /* 24 */
    regTestComparePix(rp, pixt5, pixt6);  /* 25 */
    pixDestroy(&pixs);
    pixDestroy(&pixn);
    pixDestroy(&pixg);
    pixDestroy(&pixb);
    pixDestroy(&pixt1);
    pixDestroy(&pixt2);
    pixDestroy(&pixt3);
    pixDestroy(&pixt4);
    pixDestroy(&pixt5);
    pixDestroy(&pixt6);
    fpixDestroy(&fpixs2);
    fpixDestroy(&fpixs3);
    fpixDestroy(&fpixs4);
    dpixDestroy(&dpix);
    dpixDestroy(&dpix2);

        /* Test affine and projective transforms on fpix */
    fpixWrite("/tmp/fpix1.fp", dew->fullvdispar);
    fpix1 = fpixRead("/tmp/fpix1.fp");
    pixt1 = fpixAutoRenderContours(fpix1, 40);
    regTestWritePixAndCheck(rp, pixt1, IFF_PNG);  /* 26 */
    pixDisplayWithTitle(pixt1, 0, 500, NULL, rp->display);
    pixDestroy(&pixt1);

    MakePtasAffine(1, &ptas, &ptad);
    fpix2 = fpixAffinePta(fpix1, ptad, ptas, 200, 0.0);
    pixt2 = fpixAutoRenderContours(fpix2, 40);
    regTestWritePixAndCheck(rp, pixt2, IFF_PNG);  /* 27 */
    pixDisplayWithTitle(pixt2, 400, 500, NULL, rp->display);
    fpixDestroy(&fpix2);
    pixDestroy(&pixt2);
    ptaDestroy(&ptas);
    ptaDestroy(&ptad);

    MakePtas(1, &ptas, &ptad);
    fpix2 = fpixProjectivePta(fpix1, ptad, ptas, 200, 0.0);
    pixt3 = fpixAutoRenderContours(fpix2, 40);
    regTestWritePixAndCheck(rp, pixt3, IFF_PNG);  /* 28 */
    pixDisplayWithTitle(pixt3, 400, 500, NULL, rp->display);
    fpixDestroy(&fpix2);
    pixDestroy(&pixt3);
    ptaDestroy(&ptas);
    ptaDestroy(&ptad);
    fpixDestroy(&fpix1);
    dewarpaDestroy(&dewa);

    kernelDestroy(&kel);
    kernelDestroy(&kelx);
    kernelDestroy(&kely);
    return regTestCleanup(rp);
}
Esempio n. 6
0
l_int32 main(int    argc,
             char **argv)
{
l_int32       i, n;
l_float32     a, b, c;
L_DEWARP     *dew, *dew2;
DPIX         *dpix1, *dpix2, *dpix3;
FPIX         *fpix1, *fpix2, *fpix3;
NUMA         *nax, *nafit;
PIX          *pixs, *pixn, *pixg, *pixb, *pixt1, *pixt2;
PIX          *pixs2, *pixn2, *pixg2, *pixb2;
PTA          *pta, *ptad;
PTAA         *ptaa1, *ptaa2;
L_REGPARAMS  *rp;

    if (regTestSetup(argc, argv, &rp))
              return 1;

    pixs = pixRead("1555-7.jpg");
    
        /* Normalize for varying background and binarize */
    pixn = pixBackgroundNormSimple(pixs, NULL, NULL);
    pixg = pixConvertRGBToGray(pixn, 0.5, 0.3, 0.2);
    pixb = pixThresholdToBinary(pixg, 130);
    pixDestroy(&pixn);
    pixDestroy(&pixg);
    regTestWritePixAndCheck(rp, pixb, IFF_PNG);  /* 0 */
    pixDisplayWithTitle(pixb, 0, 0, "binarized input", rp->display);

        /* Get the textline centers */
    ptaa1 = pixGetTextlineCenters(pixb, 0);
    pixt1 = pixCreateTemplate(pixs);
    pixt2 = pixDisplayPtaa(pixt1, ptaa1);
    regTestWritePixAndCheck(rp, pixt2, IFF_PNG);  /* 1 */
    pixDisplayWithTitle(pixt2, 0, 500, "textline centers", rp->display);
    pixDestroy(&pixt1);

        /* Remove short lines */
    ptaa2 = ptaaRemoveShortLines(pixb, ptaa1, 0.8, 0);

        /* Fit to quadratic */
    n = ptaaGetCount(ptaa2);
    for (i = 0; i < n; i++) {
        pta = ptaaGetPta(ptaa2, i, L_CLONE);
        ptaGetArrays(pta, &nax, NULL);
        ptaGetQuadraticLSF(pta, &a, &b, &c, &nafit);
        ptad = ptaCreateFromNuma(nax, nafit);
        pixDisplayPta(pixt2, pixt2, ptad);
        ptaDestroy(&pta);
        ptaDestroy(&ptad);
        numaDestroy(&nax);
        numaDestroy(&nafit);
    }
    regTestWritePixAndCheck(rp, pixt2, IFF_PNG);  /* 2 */
    pixDisplayWithTitle(pixt2, 300, 500, "fitted lines superimposed",
                        rp->display);
    ptaaDestroy(&ptaa1);
    ptaaDestroy(&ptaa2);
    pixDestroy(&pixt2);

        /* Run with only vertical disparity correction */
    if ((dew = dewarpCreate(pixb, 7, 30, 15, 0)) == NULL)
        return ERROR_INT("\n\n\n FAILURE !!! \n\n\n", rp->testname, 1);
    dewarpBuildModel(dew, 0);
    dewarpApplyDisparity(dew, pixb, 0);
    regTestWritePixAndCheck(rp, dew->pixd, IFF_PNG);  /* 3 */
    pixDisplayWithTitle(dew->pixd, 400, 0, "fixed for vert disparity",
                        rp->display);
    dewarpDestroy(&dew);

        /* Run with both vertical and horizontal disparity correction */
    if ((dew = dewarpCreate(pixb, 7, 30, 15, 1)) == NULL)
        return ERROR_INT("\n\n\n FAILURE !!! \n\n\n", rp->testname, 1);
    dewarpBuildModel(dew, 0);
    dewarpApplyDisparity(dew, pixb, 0);
    regTestWritePixAndCheck(rp, dew->pixd, IFF_PNG);  /* 4 */
    pixDisplayWithTitle(dew->pixd, 800, 0, "fixed for both disparities",
                        rp->display);

        /* Read another image, normalize background and binarize */
    pixs2 = pixRead("1555-3.jpg");
    pixn2 = pixBackgroundNormSimple(pixs2, NULL, NULL);
    pixg2 = pixConvertRGBToGray(pixn2, 0.5, 0.3, 0.2);
    pixb2 = pixThresholdToBinary(pixg2, 130);
    pixDestroy(&pixn2);
    pixDestroy(&pixg2);
    regTestWritePixAndCheck(rp, pixb, IFF_PNG);  /* 5 */
    pixDisplayWithTitle(pixb, 0, 400, "binarized input (2)", rp->display);

        /* Minimize and re-apply previous disparity to this image */
    dewarpMinimize(dew);
    dewarpApplyDisparity(dew, pixb2, 0);
    regTestWritePixAndCheck(rp, dew->pixd, IFF_PNG);  /* 6 */
    pixDisplayWithTitle(dew->pixd, 400, 400, "fixed (2) for both disparities",
                        rp->display);

        /* Write and read back minimized dewarp struct */
    dewarpWrite("/tmp/dewarp.7.dew", dew);
    regTestCheckFile(rp, "/tmp/dewarp.7.dew");  /* 7 */
    dew2 = dewarpRead("/tmp/dewarp.7.dew");
    dewarpWrite("/tmp/dewarp.8.dew", dew2);
    regTestCheckFile(rp, "/tmp/dewarp.8.dew");  /* 8 */
    regTestCompareFiles(rp, 7, 8);  /* 9 */

        /* Apply dew2 to pixb2 */
    dewarpApplyDisparity(dew2, pixb2, 0);
    regTestWritePixAndCheck(rp, dew2->pixd, IFF_PNG);  /* 10 */
    pixDisplayWithTitle(dew->pixd, 800, 400, "fixed (3) for both disparities",
                        rp->display);

        /* Minimize, repopulate disparity arrays, and apply again */
    dewarpMinimize(dew2);
    dewarpApplyDisparity(dew2, pixb2, 0);
    regTestWritePixAndCheck(rp, dew2->pixd, IFF_PNG);  /* 11 */
    regTestCompareFiles(rp, 10, 11);  /* 12 */
    pixDisplayWithTitle(dew->pixd, 900, 400, "fixed (4) for both disparities",
                        rp->display);

        /* Test a few of the fpix functions */
    fpix1 = fpixClone(dew->sampvdispar);
    fpixWrite("/tmp/sampv.13.fpix", fpix1);
    regTestCheckFile(rp, "/tmp/sampv.13.fpix");  /* 13 */
    fpix2 = fpixRead("/tmp/sampv.13.fpix");
    fpixWrite("/tmp/sampv.14.fpix", fpix2);
    regTestCheckFile(rp, "/tmp/sampv.14.fpix");  /* 14 */
    regTestCompareFiles(rp, 13, 14);  /* 15 */
    fpix3 = fpixScaleByInteger(fpix2, 30);
    pixt1 = fpixRenderContours(fpix3, -2., 2.0, 0.2);
    regTestWritePixAndCheck(rp, pixt1, IFF_PNG);  /* 16 */
    pixDisplayWithTitle(pixt1, 0, 800, "v. disparity contours", rp->display);
    fpixDestroy(&fpix1);
    fpixDestroy(&fpix2);
    fpixDestroy(&fpix3);
    pixDestroy(&pixt1);

        /* Test a few of the dpix functions */
    dpix1 = fpixConvertToDPix(dew->sampvdispar);
    dpixWrite("/tmp/sampv.17.dpix", dpix1);
    regTestCheckFile(rp, "/tmp/sampv.17.dpix");  /* 17 */
    dpix2 = dpixRead("/tmp/sampv.17.dpix");
    dpixWrite("/tmp/sampv.18.dpix", dpix2);
    regTestCheckFile(rp, "/tmp/sampv.18.dpix");  /* 18 */
    regTestCompareFiles(rp, 17, 18);  /* 19 */
    dpix3 = dpixScaleByInteger(dpix2, 30);
    fpix3 = dpixConvertToFPix(dpix3);
    pixt1 = fpixRenderContours(fpix3, -2., 2.0, 0.2);
    regTestWritePixAndCheck(rp, pixt1, IFF_PNG);  /* 20 */
    pixDisplayWithTitle(pixt1, 400, 800, "v. disparity contours", rp->display);
    regTestCompareFiles(rp, 16, 20);  /* 21 */
    dpixDestroy(&dpix1);
    dpixDestroy(&dpix2);
    dpixDestroy(&dpix3);
    fpixDestroy(&fpix3);
    pixDestroy(&pixt1);

    dewarpDestroy(&dew);
    dewarpDestroy(&dew2);
    pixDestroy(&pixs);
    pixDestroy(&pixb);
    pixDestroy(&pixs2);
    pixDestroy(&pixb2);
    regTestCleanup(rp);
    return 0;
}