Пример #1
0
/*!
 *  kernelCreateFromPix()
 *
 *      Input:  pix
 *              cy, cx (origin of kernel)
 *      Return: kernel, or null on error
 *
 *  Notes:
 *      (1) The origin must be positive and within the dimensions of the pix.
 */
L_KERNEL *
kernelCreateFromPix(PIX         *pix,
                    l_int32      cy,
                    l_int32      cx)
{
l_int32    i, j, w, h, d;
l_uint32   val;
L_KERNEL  *kel;

    PROCNAME("kernelCreateFromPix");

    if (!pix)
        return (L_KERNEL *)ERROR_PTR("pix not defined", procName, NULL);
    pixGetDimensions(pix, &w, &h, &d);
    if (d != 8)
        return (L_KERNEL *)ERROR_PTR("pix not 8 bpp", procName, NULL);
    if (cy < 0 || cx < 0 || cy >= h || cx >= w)
        return (L_KERNEL *)ERROR_PTR("(cy, cx) invalid", procName, NULL);

    kel = kernelCreate(h, w);
    kernelSetOrigin(kel, cy, cx);
    for (i = 0; i < h; i++) {
        for (j = 0; j < w; j++) {
            pixGetPixel(pix, j, i, &val);
            kernelSetElement(kel, i, j, (l_float32)val);
        }
    }

    return kel;
}
Пример #2
0
/*!
 *  kernelNormalize()
 *
 *      Input:  kels (source kel, to be normalized)
 *              normsum (desired sum of elements in keld)
 *      Return: keld (normalized version of kels), or null on error
 *                   or if sum of elements is very close to 0)
 *
 *  Notes:
 *      (1) If the sum of kernel elements is close to 0, do not
 *          try to calculate the normalized kernel.  Instead,
 *          return a copy of the input kernel, with a warning.
 */
L_KERNEL *
kernelNormalize(L_KERNEL  *kels,
                l_float32  normsum)
{
l_int32    i, j, sx, sy, cx, cy;
l_float32  sum, factor;
L_KERNEL  *keld;

    PROCNAME("kernelNormalize");

    if (!kels)
        return (L_KERNEL *)ERROR_PTR("kels not defined", procName, NULL);

    kernelGetSum(kels, &sum);
    if (L_ABS(sum) < 0.00001) {
        L_WARNING("null sum; not normalizing; returning a copy\n", procName);
        return kernelCopy(kels);
    }

    kernelGetParameters(kels, &sy, &sx, &cy, &cx);
    if ((keld = kernelCreate(sy, sx)) == NULL)
        return (L_KERNEL *)ERROR_PTR("keld not made", procName, NULL);
    keld->cy = cy;
    keld->cx = cx;

    factor = normsum / sum;
    for (i = 0; i < sy; i++)
        for (j = 0; j < sx; j++)
            keld->data[i][j] = factor * kels->data[i][j];

    return keld;
}
Пример #3
0
/*!
 *  kernelReadStream()
 *
 *      Input:  stream
 *      Return: kernel, or null on error
 */
L_KERNEL *
kernelReadStream(FILE  *fp)
{
l_int32    sy, sx, cy, cx, i, j, ret, version, ignore;
L_KERNEL  *kel;

    PROCNAME("kernelReadStream");

    if (!fp)
        return (L_KERNEL *)ERROR_PTR("stream not defined", procName, NULL);

    ret = fscanf(fp, "  Kernel Version %d\n", &version);
    if (ret != 1)
        return (L_KERNEL *)ERROR_PTR("not a kernel file", procName, NULL);
    if (version != KERNEL_VERSION_NUMBER)
        return (L_KERNEL *)ERROR_PTR("invalid kernel version", procName, NULL);

    if (fscanf(fp, "  sy = %d, sx = %d, cy = %d, cx = %d\n",
            &sy, &sx, &cy, &cx) != 4)
        return (L_KERNEL *)ERROR_PTR("dimensions not read", procName, NULL);

    if ((kel = kernelCreate(sy, sx)) == NULL)
        return (L_KERNEL *)ERROR_PTR("kel not made", procName, NULL);
    kernelSetOrigin(kel, cy, cx);

    for (i = 0; i < sy; i++) {
        for (j = 0; j < sx; j++)
            ignore = fscanf(fp, "%15f", &kel->data[i][j]);
        ignore = fscanf(fp, "\n");
    }
    ignore = fscanf(fp, "\n");

    return kel;
}
Пример #4
0
/*!
 *  makeDoGKernel()
 *
 *      Input:  halfheight, halfwidth (sx = 2 * halfwidth + 1, etc)
 *              stdev (standard deviation of narrower gaussian)
 *              ratio (of stdev for wide filter to stdev for narrow one)
 *      Return: kernel, or null on error
 *
 *  Notes:
 *      (1) The DoG (difference of gaussians) is a wavelet mother
 *          function with null total sum.  By subtracting two blurred
 *          versions of the image, it acts as a bandpass filter for
 *          frequencies passed by the narrow gaussian but stopped
 *          by the wide one.See:
 *               http://en.wikipedia.org/wiki/Difference_of_Gaussians
 *      (2) The kernel size (sx, sy) = (2 * halfwidth + 1, 2 * halfheight + 1).
 *      (3) The kernel center (cx, cy) = (halfwidth, halfheight).
 *      (4) The halfwidth and halfheight are typically equal, and
 *          are typically several times larger than the standard deviation.
 *      (5) The ratio is the ratio of standard deviations of the wide
 *          to narrow gaussian.  It must be >= 1.0; 1.0 is a no-op.
 *      (6) Because the kernel is a null sum, it must be invoked without
 *          normalization in pixConvolve().
 */
L_KERNEL *
makeDoGKernel(l_int32    halfheight,
              l_int32    halfwidth,
              l_float32  stdev,
              l_float32  ratio)
{
l_int32    sx, sy, i, j;
l_float32  pi, squaredist, highnorm, lownorm, val;
L_KERNEL  *kel;

    PROCNAME("makeDoGKernel");

    sx = 2 * halfwidth + 1;
    sy = 2 * halfheight + 1;
    if ((kel = kernelCreate(sy, sx)) == NULL)
        return (L_KERNEL *)ERROR_PTR("kel not made", procName, NULL);
    kernelSetOrigin(kel, halfheight, halfwidth);

    pi = 3.1415926535;
    for (i = 0; i < sy; i++) {
        for (j = 0; j < sx; j++) {
            squaredist = (l_float32)((i - halfheight) * (i - halfheight) +
                                     (j - halfwidth) * (j - halfwidth));
            highnorm = 1. / (2 * stdev * stdev);
            lownorm = highnorm / (ratio * ratio);
            val = (highnorm / pi) * expf(-(highnorm * squaredist))
                  - (lownorm / pi) * expf(-(lownorm * squaredist));
            kernelSetElement(kel, i, j, val);
        }
    }

    return kel;
}
Пример #5
0
/*!
 *  makeGaussianKernel()
 *
 *      Input:  halfheight, halfwidth (sx = 2 * halfwidth + 1, etc)
 *              stdev (standard deviation)
 *              max (value at (cx,cy))
 *      Return: kernel, or null on error
 *
 *  Notes:
 *      (1) The kernel size (sx, sy) = (2 * halfwidth + 1, 2 * halfheight + 1).
 *      (2) The kernel center (cx, cy) = (halfwidth, halfheight).
 *      (3) The halfwidth and halfheight are typically equal, and
 *          are typically several times larger than the standard deviation.
 *      (4) If pixConvolve() is invoked with normalization (the sum of
 *          kernel elements = 1.0), use 1.0 for max (or any number that's
 *          not too small or too large).
 */
L_KERNEL *
makeGaussianKernel(l_int32    halfheight,
                   l_int32    halfwidth,
                   l_float32  stdev,
                   l_float32  max)
{
l_int32    sx, sy, i, j;
l_float32  val;
L_KERNEL  *kel;

    PROCNAME("makeGaussianKernel");

    sx = 2 * halfwidth + 1;
    sy = 2 * halfheight + 1;
    if ((kel = kernelCreate(sy, sx)) == NULL)
        return (L_KERNEL *)ERROR_PTR("kel not made", procName, NULL);
    kernelSetOrigin(kel, halfheight, halfwidth);
    for (i = 0; i < sy; i++) {
        for (j = 0; j < sx; j++) {
            val = expf(-(l_float32)((i - halfheight) * (i - halfheight) +
                                    (j - halfwidth) * (j - halfwidth)) /
                        (2. * stdev * stdev));
            kernelSetElement(kel, i, j, max * val);
        }
    }

    return kel;
}
Пример #6
0
/*!
 *  kernelCreateFromString()
 *
 *      Input:  height, width
 *              cy, cx   (origin)
 *              kdata
 *      Return: kernel of the given size, or null on error
 *
 *  Notes:
 *      (1) The data is an array of chars, in row-major order, giving
 *          space separated integers in the range [-255 ... 255].
 *      (2) The only other formatting limitation is that you must
 *          leave space between the last number in each row and
 *          the double-quote.  If possible, it's also nice to have each
 *          line in the string represent a line in the kernel; e.g.,
 *              static const char *kdata =
 *                  " 20   50   20 "
 *                  " 70  140   70 "
 *                  " 20   50   20 ";
 */
L_KERNEL *
kernelCreateFromString(l_int32      h,
                       l_int32      w,
                       l_int32      cy,
                       l_int32      cx,
                       const char  *kdata)
{
l_int32    n, i, j, index;
l_float32  val;
L_KERNEL  *kel;
NUMA      *na;

    PROCNAME("kernelCreateFromString");

    if (h < 1)
        return (L_KERNEL *)ERROR_PTR("height must be > 0", procName, NULL);
    if (w < 1)
        return (L_KERNEL *)ERROR_PTR("width must be > 0", procName, NULL);
    if (cy < 0 || cy >= h)
        return (L_KERNEL *)ERROR_PTR("cy invalid", procName, NULL);
    if (cx < 0 || cx >= w)
        return (L_KERNEL *)ERROR_PTR("cx invalid", procName, NULL);

    kel = kernelCreate(h, w);
    kernelSetOrigin(kel, cy, cx);
    na = parseStringForNumbers(kdata, " \t\n");
    n = numaGetCount(na);
    if (n != w * h) {
        numaDestroy(&na);
	fprintf(stderr, "w = %d, h = %d, num ints = %d\n", w, h, n);
        return (L_KERNEL *)ERROR_PTR("invalid integer data", procName, NULL);
    }

    index = 0;
    for (i = 0; i < h; i++) {
        for (j = 0; j < w; j++) {
            numaGetFValue(na, index, &val);
            kernelSetElement(kel, i, j, val);
	    index++;
        }
    }

    numaDestroy(&na);
    return kel;
}
Пример #7
0
/*!
 *  makeRangeKernel()
 *
 *      Input:  range_stdev (> 0)
 *      Return: kel, or null on error
 *
 *  Notes:
 *      (1) Creates a one-sided Gaussian kernel with the given
 *          standard deviation.  At grayscale difference of one stdev,
 *          the kernel falls to 0.6, and to 0.01 at three stdev.
 *      (2) A typical input number might be 20.  Then pixels whose
 *          value differs by 60 from the center pixel have their
 *          weight in the convolution reduced by a factor of about 0.01.
 */
L_KERNEL *
makeRangeKernel(l_float32 range_stdev) {
    l_int32 x;
    l_float32 val, denom;
    L_KERNEL *kel;

    PROCNAME("makeRangeKernel");

    if (range_stdev <= 0.0)
        return (L_KERNEL *) ERROR_PTR("invalid stdev <= 0", procName, NULL);

    denom = 2. * range_stdev * range_stdev;
    if ((kel = kernelCreate(1, 256)) == NULL)
        return (L_KERNEL *) ERROR_PTR("kel not made", procName, NULL);
    kernelSetOrigin(kel, 0, 0);
    for (x = 0; x < 256; x++) {
        val = expf(-(l_float32)(x * x) / denom);
        kernelSetElement(kel, 0, x, val);
    }
    return kel;
}
Пример #8
0
/*!
 *  kernelCopy()
 *
 *      Input:  kels (source kernel)
 *      Return: keld (copy of kels), or null on error
 */
L_KERNEL *
kernelCopy(L_KERNEL  *kels)
{
l_int32    i, j, sx, sy, cx, cy;
L_KERNEL  *keld;

    PROCNAME("kernelCopy");

    if (!kels)
        return (L_KERNEL *)ERROR_PTR("kels not defined", procName, NULL);

    kernelGetParameters(kels, &sy, &sx, &cy, &cx);
    if ((keld = kernelCreate(sy, sx)) == NULL)
        return (L_KERNEL *)ERROR_PTR("keld not made", procName, NULL);
    keld->cy = cy;
    keld->cx = cx;
    for (i = 0; i < sy; i++)
        for (j = 0; j < sx; j++)
            keld->data[i][j] = kels->data[i][j];

    return keld;
}
Пример #9
0
/*!
 *  makeFlatKernel()
 *
 *      Input:  height, width
 *              cy, cx (origin of kernel)
 *      Return: kernel, or null on error
 *
 *  Notes:
 *      (1) This is the same low-pass filtering kernel that is used
 *          in the block convolution functions.
 *      (2) The kernel origin (@cy, @cx) is typically placed as near
 *          the center of the kernel as possible.  If height and
 *          width are odd, then using cy = height / 2 and
 *          cx = width / 2 places the origin at the exact center.
 *      (3) This returns a normalized kernel.
 */
L_KERNEL *
makeFlatKernel(l_int32  height,
               l_int32  width,
               l_int32  cy,
               l_int32  cx)
{
l_int32    i, j;
l_float32  normval;
L_KERNEL  *kel;

    PROCNAME("makeFlatKernel");

    if ((kel = kernelCreate(height, width)) == NULL)
        return (L_KERNEL *)ERROR_PTR("kel not made", procName, NULL);
    kernelSetOrigin(kel, cy, cx);
    normval = 1.0 / (l_float32)(height * width);
    for (i = 0; i < height; i++) {
        for (j = 0; j < width; j++) {
            kernelSetElement(kel, i, j, normval);
        }
    }

    return kel;
}
Пример #10
0
/*!
 *  kernelCreateFromFile()
 *
 *      Input:  filename
 *      Return: kernel, or null on error
 *
 *  Notes:
 *      (1) The file contains, in the following order:
 *           - Any number of comment lines starting with '#' are ignored
 *           - The height and width of the kernel
 *           - The y and x values of the kernel origin
 *           - The kernel data, formatted as lines of numbers (integers
 *             or floats) for the kernel values in row-major order,
 *             and with no other punctuation.
 *             (Note: this differs from kernelCreateFromString(),
 *             where each line must begin and end with a double-quote
 *             to tell the compiler it's part of a string.)
 *           - The kernel specification ends when a blank line,
 *             a comment line, or the end of file is reached.
 *      (2) All lines must be left-justified.
 *      (3) See kernelCreateFromString() for a description of the string
 *          format for the kernel data.  As an example, here are the lines
 *          of a valid kernel description file  In the file, all lines
 *          are left-justified:
 *                    # small 3x3 kernel
 *                    3 3
 *                    1 1
 *                    25.5   51    24.3
 *                    70.2  146.3  73.4
 *                    20     50.9  18.4
 */
L_KERNEL *
kernelCreateFromFile(const char  *filename)
{
char      *filestr, *line;
l_int32    nlines, i, j, first, index, w, h, cx, cy, n;
l_float32  val;
size_t     size;
NUMA      *na, *nat;
SARRAY    *sa;
L_KERNEL  *kel;

    PROCNAME("kernelCreateFromFile");

    if (!filename)
        return (L_KERNEL *)ERROR_PTR("filename not defined", procName, NULL);

    filestr = (char *)l_binaryRead(filename, &size);
    sa = sarrayCreateLinesFromString(filestr, 1);
    FREE(filestr);
    nlines = sarrayGetCount(sa);

        /* Find the first data line. */
    for (i = 0; i < nlines; i++) {
        line = sarrayGetString(sa, i, L_NOCOPY);
        if (line[0] != '#') {
            first = i;
            break;
        }
    }

        /* Find the kernel dimensions and origin location. */
    line = sarrayGetString(sa, first, L_NOCOPY);
    if (sscanf(line, "%d %d", &h, &w) != 2)
        return (L_KERNEL *)ERROR_PTR("error reading h,w", procName, NULL);
    line = sarrayGetString(sa, first + 1, L_NOCOPY);
    if (sscanf(line, "%d %d", &cy, &cx) != 2)
        return (L_KERNEL *)ERROR_PTR("error reading cy,cx", procName, NULL);

        /* Extract the data.  This ends when we reach eof, or when we
         * encounter a line of data that is either a null string or
         * contains just a newline. */
    na = numaCreate(0);
    for (i = first + 2; i < nlines; i++) {
        line = sarrayGetString(sa, i, L_NOCOPY);
        if (line[0] == '\0' || line[0] == '\n' || line[0] == '#')
            break;
        nat = parseStringForNumbers(line, " \t\n");
        numaJoin(na, nat, 0, -1);
        numaDestroy(&nat);
    }
    sarrayDestroy(&sa);

    n = numaGetCount(na);
    if (n != w * h) {
        numaDestroy(&na);
        fprintf(stderr, "w = %d, h = %d, num ints = %d\n", w, h, n);
        return (L_KERNEL *)ERROR_PTR("invalid integer data", procName, NULL);
    }

    kel = kernelCreate(h, w);
    kernelSetOrigin(kel, cy, cx);
    index = 0;
    for (i = 0; i < h; i++) {
        for (j = 0; j < w; j++) {
            numaGetFValue(na, index, &val);
            kernelSetElement(kel, i, j, val);
            index++;
        }
    }

    numaDestroy(&na);
    return kel;
}
Пример #11
0
int main(int    argc,
         char **argv)
{
l_int32       i, j, sizex, sizey, bias;
FPIX         *fpixv, *fpixrv;
L_KERNEL     *kel1, *kel2, *kel3x, *kel3y;
PIX          *pixs, *pixacc, *pixg, *pixt, *pixd;
PIX          *pixb, *pixm, *pixms, *pixrv, *pix1, *pix2, *pix3, *pix4;
L_REGPARAMS  *rp;

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

        /* Test pixBlockconvGray() on 8 bpp */
    pixs = pixRead("test8.jpg");
    pixacc = pixBlockconvAccum(pixs);
    pixd = pixBlockconvGray(pixs, pixacc, 3, 5);
    regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG);  /* 0 */
    pixDisplayWithTitle(pixd, 100, 0, NULL, rp->display);
    pixDestroy(&pixacc);
    pixDestroy(&pixd);

        /* Test pixBlockconv() on 8 bpp */
    pixd = pixBlockconv(pixs, 9, 8);
    regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG);  /* 1 */
    pixDisplayWithTitle(pixd, 200, 0, NULL, rp->display);
    pixDestroy(&pixd);
    pixDestroy(&pixs);

        /* Test pixBlockrank() on 1 bpp */
    pixs = pixRead("test1.png");
    pixacc = pixBlockconvAccum(pixs);
    for (i = 0; i < 3; i++) {
        pixd = pixBlockrank(pixs, pixacc, 4, 4, 0.25 + 0.25 * i);
        regTestWritePixAndCheck(rp, pixd, IFF_PNG);  /* 2 - 4 */
        pixDisplayWithTitle(pixd, 300 + 100 * i, 0, NULL, rp->display);
        pixDestroy(&pixd);
    }

        /* Test pixBlocksum() on 1 bpp */
    pixd = pixBlocksum(pixs, pixacc, 16, 16);
    regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG);  /* 5 */
    pixDisplayWithTitle(pixd, 700, 0, NULL, rp->display);
    pixDestroy(&pixd);
    pixDestroy(&pixacc);
    pixDestroy(&pixs);

        /* Test pixCensusTransform() */
    pixs = pixRead("test24.jpg");
    pixg = pixScaleRGBToGrayFast(pixs, 2, COLOR_GREEN);
    pixd = pixCensusTransform(pixg, 10, NULL);
    regTestWritePixAndCheck(rp, pixd, IFF_PNG);  /* 6 */
    pixDisplayWithTitle(pixd, 800, 0, NULL, rp->display);
    pixDestroy(&pixd);

        /* Test generic convolution with kel1 */
    kel1 = kernelCreateFromString(5, 5, 2, 2, kel1str);
    pixd = pixConvolve(pixg, kel1, 8, 1);
    regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG);  /* 7 */
    pixDisplayWithTitle(pixd, 100, 500, NULL, rp->display);
    pixDestroy(&pixd);

        /* Test convolution with flat rectangular kel */
    kel2 = kernelCreate(11, 11);
    kernelSetOrigin(kel2, 5, 5);
    for (i = 0; i < 11; i++) {
        for (j = 0; j < 11; j++)
            kernelSetElement(kel2, i, j, 1);
    }
    pixd = pixConvolve(pixg, kel2, 8, 1);
    regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG);  /* 8 */
    pixDisplayWithTitle(pixd, 200, 500, NULL, rp->display);
    pixDestroy(&pixd);
    kernelDestroy(&kel1);
    kernelDestroy(&kel2);

        /* Test pixBlockconv() on 32 bpp */
    pixt = pixScaleBySampling(pixs, 0.5, 0.5);
    pixd = pixBlockconv(pixt, 4, 6);
    regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG);  /* 9 */
    pixDisplayWithTitle(pixd, 300, 500, NULL, rp->display);
    pixDestroy(&pixt);
    pixDestroy(&pixs);
    pixDestroy(&pixg);
    pixDestroy(&pixd);

        /* Test bias convolution non-separable with kel2 */
    pixs = pixRead("marge.jpg");
    pixg = pixScaleRGBToGrayFast(pixs, 2, COLOR_GREEN);
    kel2 = kernelCreateFromString(5, 5, 2, 2, kel2str);
    pixd = pixConvolveWithBias(pixg, kel2, NULL, TRUE, &bias);
    regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG);  /* 10 */
    pixDisplayWithTitle(pixd, 400, 500, NULL, rp->display);
    fprintf(stderr, "bias = %d\n", bias);
    kernelDestroy(&kel2);
    pixDestroy(&pixd);

        /* Test bias convolution separable with kel3x and kel3y */
    kel3x = kernelCreateFromString(1, 5, 0, 2, kel3xstr);
    kel3y = kernelCreateFromString(7, 1, 3, 0, kel3ystr);
    pixd = pixConvolveWithBias(pixg, kel3x, kel3y, TRUE, &bias);
    regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG);  /* 11 */
    pixDisplayWithTitle(pixd, 500, 500, NULL, rp->display);
    fprintf(stderr, "bias = %d\n", bias);
    kernelDestroy(&kel3x);
    kernelDestroy(&kel3y);
    pixDestroy(&pixd);
    pixDestroy(&pixs);
    pixDestroy(&pixg);

        /* Test pixWindowedMean() and pixWindowedMeanSquare() on 8 bpp */
    pixs = pixRead("feyn-fract2.tif");
    pixg = pixConvertTo8(pixs, 0);
    sizex = 5;
    sizey = 20;
    pixb = pixAddBorderGeneral(pixg, sizex + 1, sizex + 1,
                               sizey + 1, sizey + 1, 0);
    pixm = pixWindowedMean(pixb, sizex, sizey, 1, 1);
    pixms = pixWindowedMeanSquare(pixb, sizex, sizey, 1);
    regTestWritePixAndCheck(rp, pixm, IFF_JFIF_JPEG);  /* 12 */
    pixDisplayWithTitle(pixm, 100, 0, NULL, rp->display);
    pixDestroy(&pixs);
    pixDestroy(&pixb);

        /* Test pixWindowedVariance() on 8 bpp */
    pixWindowedVariance(pixm, pixms, &fpixv, &fpixrv);
    pixrv = fpixConvertToPix(fpixrv, 8, L_CLIP_TO_ZERO, 1);
    regTestWritePixAndCheck(rp, pixrv, IFF_JFIF_JPEG);  /* 13 */
    pixDisplayWithTitle(pixrv, 100, 250, NULL, rp->display);
    pix1 = fpixDisplayMaxDynamicRange(fpixv);
    pix2 = fpixDisplayMaxDynamicRange(fpixrv);
    pixDisplayWithTitle(pix1, 100, 500, "Variance", rp->display);
    pixDisplayWithTitle(pix2, 100, 750, "RMS deviation", rp->display);
    regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG);  /* 14 */
    regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG);  /* 15 */
    fpixDestroy(&fpixv);
    fpixDestroy(&fpixrv);
    pixDestroy(&pixm);
    pixDestroy(&pixms);
    pixDestroy(&pixrv);

        /* Test again all windowed functions with simpler interface */
    pixWindowedStats(pixg, sizex, sizey, 0, NULL, NULL, &fpixv, &fpixrv);
    pix3 = fpixDisplayMaxDynamicRange(fpixv);
    pix4 = fpixDisplayMaxDynamicRange(fpixrv);
    regTestComparePix(rp, pix1, pix3);  /* 16 */
    regTestComparePix(rp, pix2, pix4);  /* 17 */
    pixDestroy(&pixg);
    pixDestroy(&pix1);
    pixDestroy(&pix2);
    pixDestroy(&pix3);
    pixDestroy(&pix4);
    fpixDestroy(&fpixv);
    fpixDestroy(&fpixrv);

    return regTestCleanup(rp);
}
Пример #12
0
int main(int    argc,
         char **argv)
{
char          textstr[256];
l_int32       w, h, d, i;
l_uint32      srcval, dstval;
l_float32     scalefact, sat, fract;
L_BMF        *bmf8;
L_KERNEL     *kel;
NUMA         *na;
PIX          *pix, *pixs, *pixs1, *pixs2, *pixd;
PIX          *pixt0, *pixt1, *pixt2, *pixt3, *pixt4;
PIXA         *pixa, *pixaf;
L_REGPARAMS  *rp;

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

    pix = pixRead(filein);
    pixGetDimensions(pix, &w, &h, &d);
    if (d != 32)
        return ERROR_INT("file not 32 bpp", argv[0], 1);
    scalefact = (l_float32)WIDTH / (l_float32)w;
    pixs = pixScale(pix, scalefact, scalefact);
    w = pixGetWidth(pixs);
    pixaf = pixaCreate(5);

        /* TRC: vary gamma */
    pixa = pixaCreate(20);
    for (i = 0; i < 20; i++) {
        pixt0 = pixGammaTRC(NULL, pixs, 0.3 + 0.15 * i, 0, 255);
        pixaAddPix(pixa, pixt0, L_INSERT);
    }
    pixt1 = pixaDisplayTiledAndScaled(pixa, 32, w, 5, 0, 10, 2);
    pixSaveTiled(pixt1, pixaf, 1.0, 1, 20, 32);
    regTestWritePixAndCheck(rp, pixt1, IFF_PNG);  /* 0 */
    pixDisplayWithTitle(pixt1, 0, 100, "TRC Gamma", rp->display);
    pixDestroy(&pixt1);
    pixaDestroy(&pixa);

        /* TRC: vary black point */
    pixa = pixaCreate(20);
    for (i = 0; i < 20; i++) {
        pixt0 = pixGammaTRC(NULL, pixs, 1.0, 5 * i, 255);
        pixaAddPix(pixa, pixt0, L_INSERT);
    }
    pixt1 = pixaDisplayTiledAndScaled(pixa, 32, w, 5, 0, 10, 2);
    pixSaveTiled(pixt1, pixaf, 1.0, 1, 20, 0);
    regTestWritePixAndCheck(rp, pixt1, IFF_PNG);  /* 1 */
    pixDisplayWithTitle(pixt1, 300, 100, "TRC", rp->display);
    pixDestroy(&pixt1);
    pixaDestroy(&pixa);

        /* Vary hue */
    pixa = pixaCreate(20);
    for (i = 0; i < 20; i++) {
        pixt0 = pixModifyHue(NULL, pixs, 0.01 + 0.05 * i);
        pixaAddPix(pixa, pixt0, L_INSERT);
    }
    pixt1 = pixaDisplayTiledAndScaled(pixa, 32, w, 5, 0, 10, 2);
    pixSaveTiled(pixt1, pixaf, 1.0, 1, 20, 0);
    regTestWritePixAndCheck(rp, pixt1, IFF_PNG);  /* 2 */
    pixDisplayWithTitle(pixt1, 600, 100, "Hue", rp->display);
    pixDestroy(&pixt1);
    pixaDestroy(&pixa);

        /* Vary saturation */
    pixa = pixaCreate(20);
    na = numaCreate(20);
    for (i = 0; i < 20; i++) {
        pixt0 = pixModifySaturation(NULL, pixs, -0.9 + 0.1 * i);
        pixMeasureSaturation(pixt0, 1, &sat);
        pixaAddPix(pixa, pixt0, L_INSERT);
        numaAddNumber(na, sat);
    }
    pixt1 = pixaDisplayTiledAndScaled(pixa, 32, w, 5, 0, 10, 2);
    pixSaveTiled(pixt1, pixaf, 1.0, 1, 20, 0);
    gplotSimple1(na, GPLOT_PNG, "/tmp/regout/enhance.7", "Average Saturation");
    regTestWritePixAndCheck(rp, pixt1, IFF_PNG);  /* 3 */
    pixDisplayWithTitle(pixt1, 900, 100, "Saturation", rp->display);
    numaDestroy(&na);
    pixDestroy(&pixt1);
    pixaDestroy(&pixa);

        /* Vary contrast */
    pixa = pixaCreate(20);
    for (i = 0; i < 20; i++) {
        pixt0 = pixContrastTRC(NULL, pixs, 0.1 * i);
        pixaAddPix(pixa, pixt0, L_INSERT);
    }
    pixt1 = pixaDisplayTiledAndScaled(pixa, 32, w, 5, 0, 10, 2);
    pixSaveTiled(pixt1, pixaf, 1.0, 1, 20, 0);
    regTestWritePixAndCheck(rp, pixt1, IFF_PNG);  /* 4 */
    pixDisplayWithTitle(pixt1, 0, 400, "Contrast", rp->display);
    pixDestroy(&pixt1);
    pixaDestroy(&pixa);

        /* Vary sharpening */
    pixa = pixaCreate(20);
    for (i = 0; i < 20; i++) {
        pixt0 = pixUnsharpMasking(pixs, 3, 0.01 + 0.15 * i);
        pixaAddPix(pixa, pixt0, L_INSERT);
    }
    pixt1 = pixaDisplayTiledAndScaled(pixa, 32, w, 5, 0, 10, 2);
    pixSaveTiled(pixt1, pixaf, 1.0, 1, 20, 0);
    regTestWritePixAndCheck(rp, pixt1, IFF_PNG);  /* 5 */
    pixDisplayWithTitle(pixt1, 300, 400, "Sharp", rp->display);
    pixDestroy(&pixt1);
    pixaDestroy(&pixa);

        /* Hue constant mapping to lighter background */
    pixa = pixaCreate(11);
    bmf8 = bmfCreate("fonts", 8);
    pixt0 = pixRead("candelabrum-11.jpg");
    composeRGBPixel(230, 185, 144, &srcval);  /* select typical bg pixel */
    for (i = 0; i <= 10; i++) {
        fract = 0.10 * i;
        pixelFractionalShift(230, 185, 144, fract, &dstval);
        pixt1 = pixLinearMapToTargetColor(NULL, pixt0, srcval, dstval);
        snprintf(textstr, 50, "Fract = %5.1f", fract);
        pixt2 = pixAddSingleTextblock(pixt1, bmf8, textstr, 0xff000000,
                                      L_ADD_BELOW, NULL);
        pixSaveTiledOutline(pixt2, pixa, 1.0, (i % 4 == 0) ? 1 : 0, 30, 2, 32);
        pixDestroy(&pixt1);
        pixDestroy(&pixt2);
    }
    pixDestroy(&pixt0);

    pixd = pixaDisplay(pixa, 0, 0);
    regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG);  /* 6 */
    pixDisplayWithTitle(pixd, 600, 400, "Constant hue", rp->display);
    bmfDestroy(&bmf8);
    pixaDestroy(&pixa);
    pixDestroy(&pixd);

        /* Delayed testing of saturation plot */
    regTestCheckFile(rp, "/tmp/regout/enhance.7.png");  /* 7 */

        /* Display results */
    pixd = pixaDisplay(pixaf, 0, 0);
    regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG);  /* 8 */
    pixDisplayWithTitle(pixd, 100, 100, "All", rp->display);
    pixDestroy(&pixd);
    pixaDestroy(&pixaf);

    pixDestroy(&pix);
    pixDestroy(&pixs);

    /* -----------------------------------------------*
     *           Test global color transforms         *
     * -----------------------------------------------*/
        /* Make identical cmap and rgb images */
    pix = pixRead("wet-day.jpg");
    pixs1 = pixOctreeColorQuant(pix, 200, 0);
    pixs2 = pixRemoveColormap(pixs1, REMOVE_CMAP_TO_FULL_COLOR);
    regTestComparePix(rp, pixs1, pixs2);  /* 9 */

        /* Make a diagonal color transform matrix */
    kel = kernelCreate(3, 3);
    kernelSetElement(kel, 0, 0, 0.7);
    kernelSetElement(kel, 1, 1, 0.4);
    kernelSetElement(kel, 2, 2, 1.3);

        /* Apply to both cmap and rgb images. */
    pixt1 = pixMultMatrixColor(pixs1, kel);
    pixt2 = pixMultMatrixColor(pixs2, kel);
    regTestComparePix(rp, pixt1, pixt2);  /* 10 */
    kernelDestroy(&kel);

        /* Apply the same transform in the simpler interface */
    pixt3 = pixMultConstantColor(pixs1, 0.7, 0.4, 1.3);
    pixt4 = pixMultConstantColor(pixs2, 0.7, 0.4, 1.3);
    regTestComparePix(rp, pixt3, pixt4);  /* 11 */
    regTestComparePix(rp, pixt1, pixt3);  /* 12 */
    regTestWritePixAndCheck(rp, pixt1, IFF_JFIF_JPEG);  /* 13 */

    pixDestroy(&pix);
    pixDestroy(&pixs1);
    pixDestroy(&pixs2);
    pixDestroy(&pixt1);
    pixDestroy(&pixt2);
    pixDestroy(&pixt3);
    pixDestroy(&pixt4);
    return regTestCleanup(rp);
}
Пример #13
0
main(int    argc,
     char **argv)
{
l_int32      i, j, wc, hc, d;
L_KERNEL    *kel1, *kel2;
PIX         *pixs, *pixg, *pixacc, *pixd, *pixt;
char        *filein, *fileout;
static char  mainName[] = "convolvetest";

    if (argc != 5)
	exit(ERROR_INT(" Syntax:  convolvetest filein wc hc fileout", mainName, 1));

    filein = argv[1];
    wc = atoi(argv[2]);
    hc = atoi(argv[3]);
    fileout = argv[4];

    if ((pixs = pixRead(filein)) == NULL)
	exit(ERROR_INT("pix not made", mainName, 1));

#if 0  /* Measure speed */
    pixacc = pixBlockconvAccum(pixs);
    for (i = 0; i < NTIMES; i++) {
	pixd = pixBlockconvGray(pixs, pixacc, wc, hc);
	if ((i+1) % 10 == 0)
	    fprintf(stderr, "%d iters\n", i + 1);
	pixDestroy(&pixd);
    }
    pixd = pixBlockconvGray(pixs, pixacc, wc, hc);
    pixWrite(fileout, pixd, IFF_JFIF_JPEG);
    pixDestroy(&pixacc);
#endif

#if 0  /* Test pixBlockconvGray() */
    pixacc = pixBlockconvAccum(pixs);
    pixd = pixBlockconvGray(pixs, pixacc, wc, hc);
    pixWrite(fileout, pixd, IFF_JFIF_JPEG);
    pixDestroy(&pixacc);
#endif

#if 0  /* Test pixBlockconv() */
    pixd = pixBlockconv(pixs, wc, hc);
    pixWrite(fileout, pixd, IFF_JFIF_JPEG);
#endif

#if 0  /* Test pixBlockrank() */
    pixacc = pixBlockconvAccum(pixs);
    pixd = pixBlockrank(pixs, pixacc, wc, hc, 0.5);
    pixWrite(fileout, pixd, IFF_TIFF_G4);
    pixDestroy(&pixacc);
#endif

#if 0  /* Test pixBlocksum() */
    pixacc = pixBlockconvAccum(pixs);
    pixd = pixBlocksum(pixs, pixacc, wc, hc);
    pixInvert(pixd, pixd);
    pixWrite(fileout, pixd, IFF_JFIF_JPEG);
    pixDestroy(&pixacc);
#endif

#if 0  /* Test pixCensusTransform() */
    d = pixGetDepth(pixs);
    if (d == 32)
        pixt = pixConvertRGBToLuminance(pixs);
    else
        pixt = pixClone(pixs);
    pixacc = pixBlockconvAccum(pixt);
    pixd = pixCensusTransform(pixt, wc, NULL);
    pixDestroy(&pixt);
    pixDestroy(&pixacc);
    pixWrite(fileout, pixd, IFF_PNG);
#endif

#if 1   /* Test generic convolution with kel1 */
    if (pixGetDepth(pixs) == 32)
        pixg = pixScaleRGBToGrayFast(pixs, 2, COLOR_GREEN);
    else
        pixg = pixScale(pixs, 0.5, 0.5);
    pixDisplay(pixg, 0, 600);
    kel1 = kernelCreateFromString(5, 5, 2, 2, kdatastr);
    pixd = pixConvolve(pixg, kel1, 8, 1);
    pixDisplay(pixd, 700, 0);
    pixWrite("/tmp/junkpixd4.bmp", pixd, IFF_BMP);
    pixDestroy(&pixd);
    kernelDestroy(&kel1);

        /* Test convolution with flat rectangular kel */
    kel2 = kernelCreate(11, 11);
    kernelSetOrigin(kel2, 5, 5);
    for (i = 0; i < 11; i++) {
        for (j = 0; j < 11; j++)
            kernelSetElement(kel2, i, j, 1);
    }
    startTimer();
    pixd = pixConvolve(pixg, kel2, 8, 1);
    fprintf(stderr, "Generic convolution: %7.3f sec\n", stopTimer());
    pixDisplay(pixd, 1200, 0);
    pixWrite("/tmp/junkpixd5.bmp", pixd, IFF_BMP);
    startTimer();
    pixt = pixBlockconv(pixg, 5, 5);
    fprintf(stderr, "Block convolution: %7.3f sec\n", stopTimer());
    pixDisplay(pixd, 1200, 600);
    pixWrite("/tmp/junkpixd6.bmp", pixt, IFF_BMP);
    pixCompareGray(pixd, pixt, L_COMPARE_ABS_DIFF, GPLOT_X11, NULL,
                   NULL, NULL, NULL);
    pixDestroy(&pixg);
    pixDestroy(&pixt);
    kernelDestroy(&kel2);
#endif

    pixDestroy(&pixs);
    pixDestroy(&pixd);
    return 0;
}
Пример #14
0
int main(int    argc,
         char **argv)
{
l_int32      i, j, wc, hc, d, bias;
L_KERNEL    *kel1, *kel2, *kel3x, *kel3y;
PIX         *pix, *pixs, *pixg, *pixacc, *pixd, *pixt;
char        *filein, *fileout;
static char  mainName[] = "convolvetest";

    if (argc != 5)
        return ERROR_INT(" Syntax:  convolvetest filein wc hc fileout",
                         mainName, 1);

    filein = argv[1];
    wc = atoi(argv[2]);
    hc = atoi(argv[3]);
    fileout = argv[4];
    if ((pix = pixRead(filein)) == NULL)
        return ERROR_INT("pix not made", mainName, 1);
    d = pixGetDepth(pix);
    if (d != 1 && d != 8 && d != 32)
        pixs = pixConvertTo8(pix, 0);
    else
        pixs = pixClone(pix);
    pixDestroy(&pix);
    d = pixGetDepth(pixs);

    if (d == 8 && (ALL || 0)) {
            /* Measure speed */
        pixacc = pixBlockconvAccum(pixs);
        for (i = 0; i < NTIMES; i++) {
            pixd = pixBlockconvGray(pixs, pixacc, wc, hc);
            if ((i+1) % 10 == 0)
                fprintf(stderr, "%d iters\n", i + 1);
            pixDestroy(&pixd);
        }
        pixd = pixBlockconvGray(pixs, pixacc, wc, hc);
        pixWrite(fileout, pixd, IFF_JFIF_JPEG);
        pixDestroy(&pixacc);
    }
    if (d == 8 && (ALL || 0)) {
            /* Test pixBlockconvGray() */
        pixacc = pixBlockconvAccum(pixs);
        pixd = pixBlockconvGray(pixs, pixacc, wc, hc);
        pixWrite(fileout, pixd, IFF_JFIF_JPEG);
        pixDestroy(&pixacc);
    }
    if (ALL || 0) {
            /* Test pixBlockconv() */
        pixd = pixBlockconv(pixs, wc, hc);
        pixWrite(fileout, pixd, IFF_JFIF_JPEG);
    }
    if (d == 1 && (ALL || 0)) {
            /* Test pixBlockrank() */
        pixacc = pixBlockconvAccum(pixs);
        pixd = pixBlockrank(pixs, pixacc, wc, hc, 0.5);
        pixWrite(fileout, pixd, IFF_TIFF_G4);
        pixDestroy(&pixacc);
    }
    if (d == 1 && (ALL || 0)) {
            /* Test pixBlocksum() */
        pixacc = pixBlockconvAccum(pixs);
        pixd = pixBlocksum(pixs, pixacc, wc, hc);
        pixInvert(pixd, pixd);
        pixWrite(fileout, pixd, IFF_JFIF_JPEG);
        pixDestroy(&pixacc);
    }
    if (ALL || 0) {
            /* Test pixCensusTransform() */
        d = pixGetDepth(pixs);
        if (d == 32)
            pixt = pixConvertRGBToLuminance(pixs);
        else
            pixt = pixClone(pixs);
        pixacc = pixBlockconvAccum(pixt);
        pixd = pixCensusTransform(pixt, wc, NULL);
        pixDestroy(&pixt);
        pixDestroy(&pixacc);
        pixWrite(fileout, pixd, IFF_PNG);
    }
    if (ALL || 0) {
            /* Test generic convolution with kel1 */
        lept_mkdir("lept");
        if (pixGetDepth(pixs) == 32)
            pixg = pixScaleRGBToGrayFast(pixs, 2, COLOR_GREEN);
        else
            pixg = pixScale(pixs, 0.5, 0.5);
        pixDisplay(pixg, 0, 600);
        kel1 = kernelCreateFromString(5, 5, 2, 2, kel1str);
        pixd = pixConvolve(pixg, kel1, 8, 1);
        pixDisplay(pixd, 700, 0);
        pixWrite("/tmp/lept/convol_d4.bmp", pixd, IFF_BMP);
        pixDestroy(&pixd);
        kernelDestroy(&kel1);

            /* Test convolution with flat rectangular kel */
        kel2 = kernelCreate(11, 11);
        kernelSetOrigin(kel2, 5, 5);
        for (i = 0; i < 11; i++) {
            for (j = 0; j < 11; j++)
                kernelSetElement(kel2, i, j, 1);
        }
        startTimer();
        pixd = pixConvolve(pixg, kel2, 8, 1);
        fprintf(stderr, "Generic convolution: %7.3f sec\n", stopTimer());
        pixDisplay(pixd, 1200, 0);
        pixWrite("/tmp/lept/convol_d5.bmp", pixd, IFF_BMP);
        startTimer();
        pixt = pixBlockconv(pixg, 5, 5);
        fprintf(stderr, "Block convolution: %7.3f sec\n", stopTimer());
        pixDisplay(pixd, 1200, 600);
        pixWrite("/tmp/lept/convol_d6.bmp", pixt, IFF_BMP);
        pixCompareGray(pixd, pixt, L_COMPARE_ABS_DIFF, GPLOT_X11, NULL,
                       NULL, NULL, NULL);
        pixDestroy(&pixg);
        pixDestroy(&pixt);
        kernelDestroy(&kel2);
    }
    if (ALL || 0) {
            /* Test bias convolution with kel2 */
        if (pixGetDepth(pixs) == 32)
            pixg = pixScaleRGBToGrayFast(pixs, 2, COLOR_GREEN);
        else
            pixg = pixScale(pixs, 0.5, 0.5);
        pixDisplay(pixg, 0, 600);
        kel2 = kernelCreateFromString(5, 5, 2, 2, kel2str);
        pixd = pixConvolveWithBias(pixg, kel2, NULL, TRUE, &bias);
        pixDisplay(pixd, 700, 0);
        fprintf(stderr, "bias = %d\n", bias);
        pixWrite("/tmp/lept/convol_d6.png", pixd, IFF_PNG);
        pixDestroy(&pixg);
        kernelDestroy(&kel2);
        pixDestroy(&pixd);
    }
    if (ALL || 1) {
            /* Test separable bias convolution with kel3x, kel3y */
        if (pixGetDepth(pixs) == 32)
            pixg = pixScaleRGBToGrayFast(pixs, 2, COLOR_GREEN);
        else
            pixg = pixScale(pixs, 0.5, 0.5);
        pixDisplay(pixg, 0, 600);
        kel3x = kernelCreateFromString(1, 5, 0, 2, kel3xstr);
        kel3y = kernelCreateFromString(7, 1, 3, 0, kel3ystr);
        pixd = pixConvolveWithBias(pixg, kel3x, kel3y, TRUE, &bias);
        pixDisplay(pixd, 700, 0);
        fprintf(stderr, "bias = %d\n", bias);
        pixWrite("/tmp/lept/convol_d7.png", pixd, IFF_PNG);
        pixDestroy(&pixg);
        kernelDestroy(&kel3x);
        kernelDestroy(&kel3y);
        pixDestroy(&pixd);
    }

    pixDestroy(&pixs);
    return 0;
}