Example #1
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;
}
Example #2
0
Pix* reduce2(Pix* pix){
    return pixScaleAreaMap2(pix);
}