Beispiel #1
0
/*!
 *  pixBilateralGrayExact()
 *
 *      Input:  pixs (8 bpp gray)
 *              spatial_kel  (gaussian kernel)
 *              range_kel (<optional> 256 x 1, monotonically decreasing)
 *      Return: pixd (8 bpp bilateral filtered image)
 *
 *  Notes:
 *      (1) See pixBilateralExact().
 */
PIX *
pixBilateralGrayExact(PIX *pixs,
                      L_KERNEL *spatial_kel,
                      L_KERNEL *range_kel) {
    l_int32 i, j, id, jd, k, m, w, h, d, sx, sy, cx, cy, wplt, wpld;
    l_int32 val, center_val;
    l_uint32 *datat, *datad, *linet, *lined;
    l_float32 sum, weight_sum, weight;
    L_KERNEL *keli;
    PIX *pixt, *pixd;

    PROCNAME("pixBilateralGrayExact");

    if (!pixs)
        return (PIX *) ERROR_PTR("pixs not defined", procName, NULL);
    if (pixGetDepth(pixs) != 8)
        return (PIX *) ERROR_PTR("pixs must be gray", procName, NULL);
    pixGetDimensions(pixs, &w, &h, &d);
    if (!spatial_kel)
        return (PIX *) ERROR_PTR("spatial kel not defined", procName, NULL);

    if (!range_kel)
        return pixConvolve(pixs, spatial_kel, 8, 1);
    if (range_kel->sx != 256 || range_kel->sy != 1)
        return (PIX *) ERROR_PTR("range kel not {256 x 1", procName, NULL);

    keli = kernelInvert(spatial_kel);
    kernelGetParameters(keli, &sy, &sx, &cy, &cx);
    if ((pixt = pixAddMirroredBorder(pixs, cx, sx - cx, cy, sy - cy)) == NULL)
        return (PIX *) ERROR_PTR("pixt not made", procName, NULL);

    pixd = pixCreate(w, h, 8);
    datat = pixGetData(pixt);
    datad = pixGetData(pixd);
    wplt = pixGetWpl(pixt);
    wpld = pixGetWpl(pixd);
    for (i = 0, id = 0; id < h; i++, id++) {
        lined = datad + id * wpld;
        for (j = 0, jd = 0; jd < w; j++, jd++) {
            center_val = GET_DATA_BYTE(datat + (i + cy) * wplt, j + cx);
            weight_sum = 0.0;
            sum = 0.0;
            for (k = 0; k < sy; k++) {
                linet = datat + (i + k) * wplt;
                for (m = 0; m < sx; m++) {
                    val = GET_DATA_BYTE(linet, j + m);
                    weight = keli->data[k][m] *
                             range_kel->data[0][L_ABS(center_val - val)];
                    weight_sum += weight;
                    sum += val * weight;
                }
            }
            SET_DATA_BYTE(lined, jd, (l_int32)(sum / weight_sum + 0.5));
        }
    }

    kernelDestroy(&keli);
    pixDestroy(&pixt);
    return pixd;
}
Beispiel #2
0
/*!
 *  pixAdaptiveMeanFilter()
 *
 *      Input:  pixs   (8 bpp grayscale)
 *              wc, hc (half width/height of convolution kernel)
 *              varn   (value of overall noise variance)
 *      Return: pixd (8 bpp, filtered image)
 *
 *  Notes:
 *      (1) The filter reduces gaussian noise, achieving results similar
 *          to the arithmetic and geometric mean filters but avoiding the
 *          considerable image blurring effect introduced by those filters.
 *      (2) The filter can be expressed mathematically by:
 *            f'(x, y) = g(x, y) - varN / varL * [ g(x, y) - meanL ]
 *          where:
 *            -- g(x, y) is the pixel at the center of local region S of
 *               width (2 * wc + 1) and height (2 * wh + 1)
 *            -- varN and varL are the overall noise variance (given in input)
 *               and local variance of S, respectively
 *            -- meanL is the local mean of S
 *      (3) Typically @varn is estimated by studying the PDFs produced by
 *          the camera or equipment sensors.
 */
PIX *
pixAdaptiveMeanFilter(PIX       *pixs,
					  l_int32    wc,
					  l_int32    hc,
					  l_float32  varn)
{
	l_int32    i, j, w, h, d, wplt, wpld, wincr, hincr;
	l_uint32   val;
	l_uint32  *datat, *datad, *linet, *lined;
	l_float32  norm, meanl, varl, ratio;
	PIX       *pixt, *pixd;
	
    PROCNAME("pixAdaptiveMeanFilter");
    
    if (!pixs)
        return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
    pixGetDimensions(pixs, &w, &h, &d);
    if (d != 8)
        return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
    if (wc < 1 || hc < 1)
        return (PIX *)ERROR_PTR("wc and hc not >= 1", procName, NULL);
	
	/* Add wc to each side, and hc to top and bottom of the image,
	 * mirroring for accuracy and to avoid special-casing the boundary. */
    if ((pixt = pixAddMirroredBorder(pixs, wc, wc, hc, hc)) == NULL)
        return (PIX *)ERROR_PTR("pixt not made", procName, NULL);
	
	/* Place the filter center at (0, 0).  This is just a
	 * convenient location, because it allows us to perform
	 * the filtering over x:(0 ... w - 1) and y:(0 ... h - 1). */
	pixd = pixCreateTemplate(pixs);
	wplt = pixGetWpl(pixt);
    wpld = pixGetWpl(pixd);
	datat = pixGetData(pixt);
    datad = pixGetData(pixd);
	
    wincr = 2 * wc + 1;
    hincr = 2 * hc + 1;
	norm = 1.0 / (wincr * hincr);
	for (i = 0; i < h; i++) {
        linet = datat + (i + hc) * wplt;
		lined = datad + i * wpld;
        for (j = 0; j < w; j++) {
            /* Calculate mean intensity value */
			meanl = calculateLocalMeanLow(datat, wplt, wincr, hincr, i, j);
			/* Calculate local variance */
			varl = calculateLocalVarianceLow(datat, wplt, wincr, hincr, i, j, meanl);
			/* Account for special case in which varN is more than varL */
			ratio = (varn > varl) ? 1 : varn / varl;
			val = GET_DATA_BYTE(linet, j + wc);
			SET_DATA_BYTE(lined, j, (l_uint8) (val - ratio * (val - meanl)));
        } 
    }
	
	pixDestroy(&pixt);	
    return pixd;
}
Beispiel #3
0
main(int    argc,
char **argv)
{
l_int32      i, j, equal;
PIX         *pixs, *pixt, *pixd;
static char  mainName[] = "rasteropip_reg";


    pixs = pixRead("test8.jpg");
    pixt = pixCopy(NULL, pixs);

        /* Copy, in-place and one COLUMN at a time, from the right
           side to the left side. */
    for (j = 0; j < 200; j++)
        pixRasterop(pixs, 20 + j, 20, 1, 250, PIX_SRC, pixs, 250 + j, 20);
    pixDisplay(pixs, 50, 50);

        /* Copy, in-place and one ROW at a time, from the right
           side to the left side. */
    for (i = 0; i < 250; i++)
        pixRasterop(pixt, 20, 20 + i, 200, 1, PIX_SRC, pixt, 250, 20 + i);
    pixDisplay(pixt, 620, 50);

        /* Test */
    pixEqual(pixs, pixt, &equal);
    if (equal)
         fprintf(stderr, "OK: images are the same\n");
    else
         fprintf(stderr, "Error: images are different\n");
    pixWrite("/tmp/junkpix.png", pixs, IFF_PNG);
    pixDestroy(&pixs);
    pixDestroy(&pixt);


        /* Show the mirrored border, which uses the general
           pixRasterop() on an image in-place.  */
    pixs = pixRead("test8.jpg");
    pixt = pixRemoveBorder(pixs, 40);
    pixd = pixAddMirroredBorder(pixt, 25, 25, 25, 25);
    pixDisplay(pixd, 50, 550);
    pixDestroy(&pixs);
    pixDestroy(&pixt);
    pixDestroy(&pixd);

    return 0;
}
Beispiel #4
0
main(int    argc,
char **argv)
{
l_int32       i, j;
PIX          *pixs, *pixt, *pixd;
L_REGPARAMS  *rp;

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

    pixs = pixRead("test8.jpg");
    pixt = pixCopy(NULL, pixs);

        /* Copy, in-place and one COLUMN at a time, from the right
           side to the left side. */
    for (j = 0; j < 200; j++)
        pixRasterop(pixs, 20 + j, 20, 1, 250, PIX_SRC, pixs, 250 + j, 20);
    pixDisplayWithTitle(pixs, 50, 50, "in-place copy", rp->display);

        /* Copy, in-place and one ROW at a time, from the right
           side to the left side. */
    for (i = 0; i < 250; i++)
        pixRasterop(pixt, 20, 20 + i, 200, 1, PIX_SRC, pixt, 250, 20 + i);

        /* Test */
    regTestComparePix(rp, pixs, pixt);   /* 0 */
    pixDestroy(&pixs);
    pixDestroy(&pixt);

        /* Show the mirrored border, which uses the general
           pixRasterop() on an image in-place.  */
    pixs = pixRead("test8.jpg");
    pixt = pixRemoveBorder(pixs, 40);
    pixd = pixAddMirroredBorder(pixt, 40, 40, 40, 40);
    regTestWritePixAndCheck(rp, pixd, IFF_PNG);  /* 1 */
    pixDisplayWithTitle(pixd, 650, 50, "mirrored border", rp->display);
    pixDestroy(&pixs);
    pixDestroy(&pixt);
    pixDestroy(&pixd);
    return regTestCleanup(rp);
}
Beispiel #5
0
/*!
 *  pixSauvolaBinarize()
 *
 *      Input:  pixs (8 bpp grayscale; not colormapped)
 *              whsize (window half-width for measuring local statistics)
 *              factor (factor for reducing threshold due to variance; >= 0)
 *              addborder (1 to add border of width (@whsize + 1) on all sides)
 *              &pixm (<optional return> local mean values)
 *              &pixsd (<optional return> local standard deviation values)
 *              &pixth (<optional return> threshold values)
 *              &pixd (<optional return> thresholded image)
 *      Return: 0 if OK, 1 on error
 *
 *  Notes:
 *      (1) The window width and height are 2 * @whsize + 1.  The minimum
 *          value for @whsize is 2; typically it is >= 7..
 *      (2) The local statistics, measured over the window, are the
 *          average and standard deviation.
 *      (3) The measurements of the mean and standard deviation are
 *          performed inside a border of (@whsize + 1) pixels.  If pixs does
 *          not have these added border pixels, use @addborder = 1 to add
 *          it here; otherwise use @addborder = 0.
 *      (4) The Sauvola threshold is determined from the formula:
 *            t = m * (1 - k * (1 - s / 128))
 *          where:
 *            t = local threshold
 *            m = local mean
 *            k = @factor (>= 0)   [ typ. 0.35 ]
 *            s = local standard deviation, which is maximized at
 *                127.5 when half the samples are 0 and half are 255.
 *      (5) The basic idea of Niblack and Sauvola binarization is that
 *          the local threshold should be less than the median value,
 *          and the larger the variance, the closer to the median
 *          it should be chosen.  Typical values for k are between
 *          0.2 and 0.5.
 */
l_int32
pixSauvolaBinarize(PIX       *pixs,
                   l_int32    whsize,
                   l_float32  factor,
                   l_int32    addborder,
                   PIX      **ppixm,
                   PIX      **ppixsd,
                   PIX      **ppixth,
                   PIX      **ppixd)
{
l_int32  w, h;
PIX     *pixg, *pixsc, *pixm, *pixms, *pixth, *pixd;

    PROCNAME("pixSauvolaBinarize");


    if (!ppixm && !ppixsd && !ppixth && !ppixd)
        return ERROR_INT("no outputs", procName, 1);
    if (ppixm) *ppixm = NULL;
    if (ppixsd) *ppixsd = NULL;
    if (ppixth) *ppixth = NULL;
    if (ppixd) *ppixd = NULL;
    if (!pixs || pixGetDepth(pixs) != 8)
        return ERROR_INT("pixs undefined or not 8 bpp", procName, 1);
    if (pixGetColormap(pixs))
        return ERROR_INT("pixs is cmapped", procName, 1);
    pixGetDimensions(pixs, &w, &h, NULL);
    if (whsize < 2)
        return ERROR_INT("whsize must be >= 2", procName, 1);
    if (w < 2 * whsize + 3 || h < 2 * whsize + 3)
        return ERROR_INT("whsize too large for image", procName, 1);
    if (factor < 0.0)
        return ERROR_INT("factor must be >= 0", procName, 1);

    if (addborder) {
        pixg = pixAddMirroredBorder(pixs, whsize + 1, whsize + 1,
                                    whsize + 1, whsize + 1);
        pixsc = pixClone(pixs);
    } else {
        pixg = pixClone(pixs);
        pixsc = pixRemoveBorder(pixs, whsize + 1);
    }
    if (!pixg || !pixsc)
        return ERROR_INT("pixg and pixsc not made", procName, 1);

        /* All these functions strip off the border pixels. */
    if (ppixm || ppixth || ppixd)
        pixm = pixWindowedMean(pixg, whsize, whsize, 1, 1);
    if (ppixsd || ppixth || ppixd)
        pixms = pixWindowedMeanSquare(pixg, whsize, whsize, 1);
    if (ppixth || ppixd)
        pixth = pixSauvolaGetThreshold(pixm, pixms, factor, ppixsd);
    if (ppixd)
        pixd = pixApplyLocalThreshold(pixsc, pixth, 1);

    if (ppixm)
        *ppixm = pixm;
    else
        pixDestroy(&pixm);
    pixDestroy(&pixms);
    if (ppixth)
        *ppixth = pixth;
    else
        pixDestroy(&pixth);
    if (ppixd)
        *ppixd = pixd;
    else
        pixDestroy(&pixd);
    pixDestroy(&pixg);
    pixDestroy(&pixsc);
    return 0;
}
Beispiel #6
0
/*!
 *  bilateralCreate()
 *
 *      Input:  pixs (8 bpp gray, no colormap)
 *              spatial_stdev  (of gaussian kernel; in pixels, > 0.5)
 *              range_stdev  (of gaussian range kernel; > 5.0; typ. 50.0)
 *              ncomps (number of intermediate sums J(k,x); in [4 ... 30])
 *              reduction  (1, 2 or 4)
 *      Return: bil, or null on error
 *
 *  Notes:
 *      (1) This initializes a bilateral filtering operation, generating all
 *          the data required.  It takes most of the time in the bilateral
 *          filtering operation.
 *      (2) See bilateral.h for details of the algorithm.
 *      (3) See pixBilateral() for constraints on input parameters, which
 *          are not checked here.
 */
static L_BILATERAL *
bilateralCreate(PIX *pixs,
                l_float32 spatial_stdev,
                l_float32 range_stdev,
                l_int32 ncomps,
                l_int32 reduction) {
    l_int32 w, ws, wd, h, hs, hd, i, j, k, index;
    l_int32 border, minval, maxval, spatial_size;
    l_int32 halfwidth, wpls, wplt, wpld, kval, nval, dval;
    l_float32 sstdev, fval1, fval2, denom, sum, norm, kern;
    l_int32 *nc, *kindex;
    l_float32 *kfract, *range, *spatial;
    l_uint32 *datas, *datat, *datad, *lines, *linet, *lined;
    L_BILATERAL *bil;
    PIX *pixt, *pixt2, *pixsc, *pixd;
    PIXA *pixac;

    PROCNAME("bilateralCreate");

    sstdev = spatial_stdev / (l_float32) reduction;  /* reduced spat. stdev */
    if ((bil = (L_BILATERAL *) CALLOC(1, sizeof(L_BILATERAL))) == NULL)
        return (L_BILATERAL *) ERROR_PTR("bil not made", procName, NULL);
    bil->spatial_stdev = sstdev;
    bil->range_stdev = range_stdev;
    bil->reduction = reduction;
    bil->ncomps = ncomps;

    if (reduction == 1) {
        pixt = pixClone(pixs);
    } else if (reduction == 2) {
        pixt = pixScaleAreaMap2(pixs);
    } else {  /* reduction == 4) */
        pixt2 = pixScaleAreaMap2(pixs);
        pixt = pixScaleAreaMap2(pixt2);
        pixDestroy(&pixt2);
    }

    pixGetExtremeValue(pixt, 1, L_SELECT_MIN, NULL, NULL, NULL, &minval);
    pixGetExtremeValue(pixt, 1, L_SELECT_MAX, NULL, NULL, NULL, &maxval);
    bil->minval = minval;
    bil->maxval = maxval;

    border = (l_int32)(2 * sstdev + 1);
    pixsc = pixAddMirroredBorder(pixt, border, border, border, border);
    bil->pixsc = pixsc;
    pixDestroy(&pixt);
    bil->pixs = pixClone(pixs);


    /* -------------------------------------------------------------------- *
     * Generate arrays for interpolation of J(k,x):
     *  (1.0 - kfract[.]) * J(kindex[.], x) + kfract[.] * J(kindex[.] + 1, x),
     * where I(x) is the index into kfract[] and kindex[],
     * and x is an index into the 2D image array.
     * -------------------------------------------------------------------- */
    /* nc is the set of k values to be used in J(k,x) */
    nc = (l_int32 *) CALLOC(ncomps, sizeof(l_int32));
    for (i = 0; i < ncomps; i++)
        nc[i] = minval + i * (maxval - minval) / (ncomps - 1);
    bil->nc = nc;

    /* kindex maps from intensity I(x) to the lower k index for J(k,x) */
    kindex = (l_int32 *) CALLOC(256, sizeof(l_int32));
    for (i = minval, k = 0; i <= maxval && k < ncomps - 1; k++) {
        fval2 = nc[k + 1];
        while (i < fval2) {
            kindex[i] = k;
            i++;
        }
    }
    kindex[maxval] = ncomps - 2;
    bil->kindex = kindex;

    /* kfract maps from intensity I(x) to the fraction of J(k+1,x) used */
    kfract = (l_float32 *) CALLOC(256, sizeof(l_float32));  /* from lower */
    for (i = minval, k = 0; i <= maxval && k < ncomps - 1; k++) {
        fval1 = nc[k];
        fval2 = nc[k + 1];
        while (i < fval2) {
            kfract[i] = (l_float32)(i - fval1) / (l_float32)(fval2 - fval1);
            i++;
        }
    }
    kfract[maxval] = 1.0;
    bil->kfract = kfract;

#if  DEBUG_BILATERAL
    for (i = minval; i <= maxval; i++)
      fprintf(stderr, "kindex[%d] = %d; kfract[%d] = %5.3f\n",
              i, kindex[i], i, kfract[i]);
    for (i = 0; i < ncomps; i++)
      fprintf(stderr, "nc[%d] = %d\n", i, nc[i]);
#endif  /* DEBUG_BILATERAL */


    /* -------------------------------------------------------------------- *
     *             Generate 1-D kernel arrays (spatial and range)           *
     * -------------------------------------------------------------------- */
    spatial_size = 2 * sstdev + 1;
    spatial = (l_float32 *) CALLOC(spatial_size, sizeof(l_float32));
    denom = 2. * sstdev * sstdev;
    for (i = 0; i < spatial_size; i++)
        spatial[i] = expf(-(l_float32)(i * i) / denom);
    bil->spatial = spatial;

    range = (l_float32 *) CALLOC(256, sizeof(l_float32));
    denom = 2. * range_stdev * range_stdev;
    for (i = 0; i < 256; i++)
        range[i] = expf(-(l_float32)(i * i) / denom);
    bil->range = range;


    /* -------------------------------------------------------------------- *
     *            Generate principal bilateral component images             *
     * -------------------------------------------------------------------- */
    pixac = pixaCreate(ncomps);
    pixGetDimensions(pixsc, &ws, &hs, NULL);
    datas = pixGetData(pixsc);
    wpls = pixGetWpl(pixsc);
    pixGetDimensions(pixs, &w, &h, NULL);
    wd = (w + reduction - 1) / reduction;
    hd = (h + reduction - 1) / reduction;
    halfwidth = (l_int32)(2.0 * sstdev);
    for (index = 0; index < ncomps; index++) {
        pixt = pixCopy(NULL, pixsc);
        datat = pixGetData(pixt);
        wplt = pixGetWpl(pixt);
        kval = nc[index];
        /* Separable convolutions: horizontal first */
        for (i = 0; i < hd; i++) {
            lines = datas + (border + i) * wpls;
            linet = datat + (border + i) * wplt;
            for (j = 0; j < wd; j++) {
                sum = 0.0;
                norm = 0.0;
                for (k = -halfwidth; k <= halfwidth; k++) {
                    nval = GET_DATA_BYTE(lines, border + j + k);
                    kern = spatial[L_ABS(k)] * range[L_ABS(kval - nval)];
                    sum += kern * nval;
                    norm += kern;
                }
                dval = (l_int32)((sum / norm) + 0.5);
                SET_DATA_BYTE(linet, border + j, dval);
            }
        }
        /* Vertical convolution */
        pixd = pixCreate(wd, hd, 8);
        datad = pixGetData(pixd);
        wpld = pixGetWpl(pixd);
        for (i = 0; i < hd; i++) {
            linet = datat + (border + i) * wplt;
            lined = datad + i * wpld;
            for (j = 0; j < wd; j++) {
                sum = 0.0;
                norm = 0.0;
                for (k = -halfwidth; k <= halfwidth; k++) {
                    nval = GET_DATA_BYTE(linet + k * wplt, border + j);
                    kern = spatial[L_ABS(k)] * range[L_ABS(kval - nval)];
                    sum += kern * nval;
                    norm += kern;
                }
                dval = (l_int32)((sum / norm) + 0.5);
                SET_DATA_BYTE(lined, j, dval);
            }
        }
        pixDestroy(&pixt);
        pixaAddPix(pixac, pixd, L_INSERT);
    }
    bil->pixac = pixac;
    bil->lineset = (l_uint32 ***) pixaGetLinePtrs(pixac, NULL);

    return bil;
}
/*!
 * \brief   pixTilingGetTile()
 *
 * \param[in]    pt pixtiling
 * \param[in]    i tile row index
 * \param[in]    j tile column index
 * \return  pixd tile with appropriate boundary (overlap) pixels added,
 *                    or NULL on error
 */
PIX *
pixTilingGetTile(PIXTILING  *pt,
                 l_int32     i,
                 l_int32     j)
{
l_int32  wpix, hpix, wt, ht, nx, ny;
l_int32  xoverlap, yoverlap, wtlast, htlast;
l_int32  left, top, xtraleft, xtraright, xtratop, xtrabot, width, height;
BOX     *box;
PIX     *pixs, *pixt, *pixd;

    PROCNAME("pixTilingGetTile");

    if (!pt)
        return (PIX *)ERROR_PTR("pt not defined", procName, NULL);
    if ((pixs = pt->pix) == NULL)
        return (PIX *)ERROR_PTR("pix not found", procName, NULL);
    pixTilingGetCount(pt, &nx, &ny);
    if (i < 0 || i >= ny)
        return (PIX *)ERROR_PTR("invalid row index i", procName, NULL);
    if (j < 0 || j >= nx)
        return (PIX *)ERROR_PTR("invalid column index j", procName, NULL);

        /* Grab the tile with as much overlap as exists within the
         * input pix.   First, compute the (left, top) coordinates.  */
    pixGetDimensions(pixs, &wpix, &hpix, NULL);
    pixTilingGetSize(pt, &wt, &ht);
    xoverlap = pt->xoverlap;
    yoverlap = pt->yoverlap;
    wtlast = wpix - wt * (nx - 1);
    htlast = hpix - ht * (ny - 1);
    left = L_MAX(0, j * wt - xoverlap);
    top = L_MAX(0, i * ht - yoverlap);

        /* Get the width and height of the tile, including whatever
         * overlap is available. */
    if (nx == 1)
        width = wpix;
    else if (j == 0)
        width = wt + xoverlap;
    else if (j == nx - 1)
        width = wtlast + xoverlap;
    else
        width = wt + 2 * xoverlap;

    if (ny == 1)
        height = hpix;
    else if (i == 0)
        height = ht + yoverlap;
    else if (i == ny - 1)
        height = htlast + yoverlap;
    else
        height = ht + 2 * yoverlap;
    box = boxCreate(left, top, width, height);
    pixt = pixClipRectangle(pixs, box, NULL);
    boxDestroy(&box);

        /* If no overlap, do not add any special case borders */
    if (xoverlap == 0 && yoverlap == 0)
        return pixt;

        /* Add overlap as a mirrored border, in the 8 special cases where
         * the tile touches the border of the input pix.  The xtratop (etc)
         * parameters are required where the tile is either full width
         * or full height.  */
    xtratop = xtrabot = xtraleft = xtraright = 0;
    if (nx == 1)
        xtraleft = xtraright = xoverlap;
    if (ny == 1)
        xtratop = xtrabot = yoverlap;
    if (i == 0 && j == 0)
        pixd = pixAddMirroredBorder(pixt, xoverlap, xtraright,
                                    yoverlap, xtrabot);
    else if (i == 0 && j == nx - 1)
        pixd = pixAddMirroredBorder(pixt, xtraleft, xoverlap,
                                    yoverlap, xtrabot);
    else if (i == ny - 1 && j == 0)
        pixd = pixAddMirroredBorder(pixt, xoverlap, xtraright,
                                    xtratop, yoverlap);
    else if (i == ny - 1 && j == nx - 1)
        pixd = pixAddMirroredBorder(pixt, xtraleft, xoverlap,
                                    xtratop, yoverlap);
    else if (i == 0)
        pixd = pixAddMirroredBorder(pixt, 0, 0, yoverlap, xtrabot);
    else if (i == ny - 1)
        pixd = pixAddMirroredBorder(pixt, 0, 0, xtratop, yoverlap);
    else if (j == 0)
        pixd = pixAddMirroredBorder(pixt, xoverlap, xtraright, 0, 0);
    else if (j == nx - 1)
        pixd = pixAddMirroredBorder(pixt, xtraleft, xoverlap, 0, 0);
    else
        pixd = pixClone(pixt);
    pixDestroy(&pixt);

    return pixd;
}
Beispiel #8
0
int main(int    argc,
         char **argv)
{
FPIX         *fpix1, *fpix2, *fpix3, *fpix4;
PIX          *pix1, *pix2, *pix3, *pix4, *pix5, *pix6, *pix7, *pix8;
L_REGPARAMS  *rp;

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

        /* Test orthogonal rotations */
    pix1 = pixRead("marge.jpg");
    pix2 = pixConvertTo8(pix1, 0);
    fpix1 = pixConvertToFPix(pix2, 1);

    fpix2 = fpixRotateOrth(fpix1, 1);
    pix3 = fpixConvertToPix(fpix2, 8, L_CLIP_TO_ZERO, 0);
    pix4 = pixRotateOrth(pix2, 1);
    regTestComparePix(rp, pix3, pix4);  /* 0 */
    pixDisplayWithTitle(pix3, 100, 100, NULL, rp->display);

    fpix3 = fpixRotateOrth(fpix1, 2);
    pix5 = fpixConvertToPix(fpix3, 8, L_CLIP_TO_ZERO, 0);
    pix6 = pixRotateOrth(pix2, 2);
    regTestComparePix(rp, pix5, pix6);  /* 1 */
    pixDisplayWithTitle(pix5, 560, 100, NULL, rp->display);

    fpix4 = fpixRotateOrth(fpix1, 3);
    pix7 = fpixConvertToPix(fpix4, 8, L_CLIP_TO_ZERO, 0);
    pix8 = pixRotateOrth(pix2, 3);
    regTestComparePix(rp, pix7, pix8);  /* 2 */
    pixDisplayWithTitle(pix7, 1170, 100, NULL, rp->display);
    pixDisplayWithTitle(pix2, 560, 580, NULL, rp->display);

    pixDestroy(&pix1);
    pixDestroy(&pix2);
    pixDestroy(&pix3);
    pixDestroy(&pix4);
    pixDestroy(&pix5);
    pixDestroy(&pix6);
    pixDestroy(&pix7);
    pixDestroy(&pix8);
    fpixDestroy(&fpix1);
    fpixDestroy(&fpix2);
    fpixDestroy(&fpix3);
    fpixDestroy(&fpix4);

        /* Test adding various borders */
    pix1 = pixRead("marge.jpg");
    pix2 = pixConvertTo8(pix1, 0);
    fpix1 = pixConvertToFPix(pix2, 1);

    fpix2 = fpixAddMirroredBorder(fpix1, 21, 21, 25, 25);
    pix3 = fpixConvertToPix(fpix2, 8, L_CLIP_TO_ZERO, 0);
    pix4 = pixAddMirroredBorder(pix2, 21, 21, 25, 25);
    regTestComparePix(rp, pix3, pix4);  /* 3 */
    pixDisplayWithTitle(pix3, 100, 1000, NULL, rp->display);

    fpix3 = fpixAddContinuedBorder(fpix1, 21, 21, 25, 25);
    pix5 = fpixConvertToPix(fpix3, 8, L_CLIP_TO_ZERO, 0);
    pix6 = pixAddContinuedBorder(pix2, 21, 21, 25, 25);
    regTestComparePix(rp, pix5, pix6);  /* 4 */
    pixDisplayWithTitle(pix5, 750, 1000, NULL, rp->display);

    pixDestroy(&pix1);
    pixDestroy(&pix2);
    pixDestroy(&pix3);
    pixDestroy(&pix4);
    pixDestroy(&pix5);
    pixDestroy(&pix6);
    fpixDestroy(&fpix1);
    fpixDestroy(&fpix2);
    fpixDestroy(&fpix3);
    return regTestCleanup(rp);
}
Beispiel #9
0
/*!
 *  pixRankFilterGray()
 *
 *      Input:  pixs (8 bpp; no colormap)
 *              wf, hf  (width and height of filter; each is >= 1)
 *              rank (in [0.0 ... 1.0])
 *      Return: pixd (of rank values), or null on error
 *
 *  Notes:
 *      (1) This defines, for each pixel in pixs, a neighborhood of
 *          pixels given by a rectangle "centered" on the pixel.
 *          This set of wf*hf pixels has a distribution of values,
 *          and if they are sorted in increasing order, we choose
 *          the pixel such that rank*(wf*hf-1) pixels have a lower
 *          or equal value and (1-rank)*(wf*hf-1) pixels have an equal
 *          or greater value.
 *      (2) By this definition, the rank = 0.0 pixel has the lowest
 *          value, and the rank = 1.0 pixel has the highest value.
 *      (3) We add mirrored boundary pixels to avoid boundary effects,
 *          and put the filter center at (0, 0).
 *      (4) This dispatches to grayscale erosion or dilation if the
 *          filter dimensions are odd and the rank is 0.0 or 1.0, rsp.
 *      (5) Returns a copy if both wf and hf are 1.
 *      (6) Uses row-major or column-major incremental updates to the
 *          histograms depending on whether hf > wf or hv <= wf, rsp.
 */
PIX  *
pixRankFilterGray(PIX       *pixs,
                  l_int32    wf,
                  l_int32    hf,
                  l_float32  rank)
{
l_int32    w, h, d, i, j, k, m, n, rankloc, wplt, wpld, val, sum;
l_int32   *histo, *histo16;
l_uint32  *datat, *linet, *datad, *lined;
PIX       *pixt, *pixd;

    PROCNAME("pixRankFilterGray");

    if (!pixs)
        return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
    if (pixGetColormap(pixs) != NULL)
        return (PIX *)ERROR_PTR("pixs has colormap", procName, NULL);
    pixGetDimensions(pixs, &w, &h, &d);
    if (d != 8)
        return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
    if (wf < 1 || hf < 1)
        return (PIX *)ERROR_PTR("wf < 1 || hf < 1", procName, NULL);
    if (rank < 0.0 || rank > 1.0)
        return (PIX *)ERROR_PTR("rank must be in [0.0, 1.0]", procName, NULL);
    if (wf == 1 && hf == 1)   /* no-op */
        return pixCopy(NULL, pixs);

        /* For rank = 0.0, this is a grayscale erosion, and for rank = 1.0,
         * a dilation.  Grayscale morphology operations are implemented
         * for filters of odd dimension, so we dispatch to grayscale
         * morphology if both wf and hf are odd.  Otherwise, we
         * slightly adjust the rank (to get the correct behavior) and
         * use the slower rank filter here. */
    if (wf % 2 && hf % 2) {
        if (rank == 0.0)
            return pixErodeGray(pixs, wf, hf);
        else if (rank == 1.0)
            return pixDilateGray(pixs, wf, hf);
    }
    if (rank == 0.0) rank = 0.0001;
    if (rank == 1.0) rank = 0.9999;

        /* Add wf/2 to each side, and hf/2 to top and bottom of the
         * image, mirroring for accuracy and to avoid special-casing
         * the boundary. */
    if ((pixt = pixAddMirroredBorder(pixs, wf / 2, wf / 2, hf / 2, hf / 2))
        == NULL)
        return (PIX *)ERROR_PTR("pixt not made", procName, NULL);

        /* Set up the two histogram arrays. */
    histo = (l_int32 *)CALLOC(256, sizeof(l_int32));
    histo16 = (l_int32 *)CALLOC(16, sizeof(l_int32));
    rankloc = (l_int32)(rank * wf * hf);

        /* Place the filter center at (0, 0).  This is just a
         * convenient location, because it allows us to perform
         * the rank filter over x:(0 ... w - 1) and y:(0 ... h - 1). */
    pixd = pixCreateTemplate(pixs);
    datat = pixGetData(pixt);
    wplt = pixGetWpl(pixt);
    datad = pixGetData(pixd);
    wpld = pixGetWpl(pixd);

        /* If hf > wf, it's more efficient to use row-major scanning.
         * Otherwise, traverse the image in use column-major order.  */
    if (hf > wf) {
        for (j = 0; j < w; j++) {  /* row-major */
                /* Start each column with clean histogram arrays. */
            for (n = 0; n < 256; n++)
                histo[n] = 0;
            for (n = 0; n < 16; n++)
                histo16[n] = 0;

            for (i = 0; i < h; i++) {  /* fast scan on columns */
                    /* Update the histos for the new location */
                lined = datad + i * wpld;
                if (i == 0) {  /* do full histo */
                    for (k = 0; k < hf; k++) {
                        linet = datat + (i + k) * wplt;
                        for (m = 0; m < wf; m++) {
                            val = GET_DATA_BYTE(linet, j + m);
                            histo[val]++;
                            histo16[val >> 4]++;
                        }
                    }
                } else {  /* incremental update */
                    linet = datat + (i - 1) * wplt;
                    for (m = 0; m < wf; m++) {  /* remove top line */
                        val = GET_DATA_BYTE(linet, j + m);
                        histo[val]--;
                        histo16[val >> 4]--;
                    }
                    linet = datat + (i + hf -  1) * wplt;
                    for (m = 0; m < wf; m++) {  /* add bottom line */
                        val = GET_DATA_BYTE(linet, j + m);
                        histo[val]++;
                        histo16[val >> 4]++;
                    }
                }

                    /* Find the rank value */
                sum = 0;
                for (n = 0; n < 16; n++) {  /* search over coarse histo */
                    sum += histo16[n];
                    if (sum > rankloc) {
                        sum -= histo16[n];
                        break;
                    }
                }
                k = 16 * n;  /* starting value in fine histo */
                for (m = 0; m < 16; m++) {
                    sum += histo[k];
                    if (sum > rankloc) {
                        SET_DATA_BYTE(lined, j, k);
                        break;
                    }
                    k++;
                }
            }
        }
    } else {  /* wf >= hf */