Пример #1
0
/*!
 *  pixRasteropHip()
 *
 *      Input:  pixd (in-place operation)
 *              by  (top of horizontal band)
 *              bh  (height of horizontal band)
 *              hshift (horizontal shift of band; hshift > 0 is to right)
 *              incolor (L_BRING_IN_WHITE, L_BRING_IN_BLACK)
 *      Return: 0 if OK; 1 on error
 *
 *  Notes:
 *      (1) This rasterop translates a horizontal band of the
 *          image either left or right, bringing in either white
 *          or black pixels from outside the image.
 *      (2) The horizontal band extends the full width of pixd.
 *      (3) If a colormap exists, the nearest color to white or black
 *          is brought in.
 */
l_int32
pixRasteropHip(PIX     *pixd,
               l_int32  by,
               l_int32  bh,
               l_int32  hshift,
               l_int32  incolor)
{
l_int32   w, h, d, index, op;
PIX      *pixt;
PIXCMAP  *cmap;

    PROCNAME("pixRasteropHip");

    if (!pixd)
        return ERROR_INT("pixd not defined", procName, 1);
    if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
        return ERROR_INT("invalid value for incolor", procName, 1);
    if (bh <= 0)
        return ERROR_INT("bh must be > 0", procName, 1);

    if (hshift == 0)
        return 0;

    pixGetDimensions(pixd, &w, &h, &d);
    rasteropHipLow(pixGetData(pixd), h, d, pixGetWpl(pixd), by, bh, hshift);

    cmap = pixGetColormap(pixd);
    if (!cmap) {
        if ((d == 1 && incolor == L_BRING_IN_BLACK) ||
            (d > 1 && incolor == L_BRING_IN_WHITE))
            op = PIX_SET;
        else
            op = PIX_CLR;

            /* Set the pixels brought in at left or right */
        if (hshift > 0)
            pixRasterop(pixd, 0, by, hshift, bh, op, NULL, 0, 0);
        else  /* hshift < 0 */
            pixRasterop(pixd, w + hshift, by, -hshift, bh, op, NULL, 0, 0);
        return 0;
    }

        /* Get the nearest index and fill with that */
    if (incolor == L_BRING_IN_BLACK)
        pixcmapGetRankIntensity(cmap, 0.0, &index);
    else  /* white */
        pixcmapGetRankIntensity(cmap, 1.0, &index);
    pixt = pixCreate(L_ABS(hshift), bh, d);
    pixSetAllArbitrary(pixt, index);
    if (hshift > 0)
        pixRasterop(pixd, 0, by, hshift, bh, PIX_SRC, pixt, 0, 0);
    else  /* hshift < 0 */
        pixRasterop(pixd, w + hshift, by, -hshift, bh, PIX_SRC, pixt, 0, 0);
    pixDestroy(&pixt);
    return 0;
}
Пример #2
0
/*!
 *  pixBilinearColor()
 *
 *      Input:  pixs (32 bpp)
 *              vc  (vector of 8 coefficients for bilinear transformation)
 *              colorval (e.g., 0 to bring in BLACK, 0xffffff00 for WHITE)
 *      Return: pixd, or null on error
 */
PIX *
pixBilinearColor(PIX *pixs,
                 l_float32 *vc,
                 l_uint32 colorval) {
    l_int32 i, j, w, h, d, wpls, wpld;
    l_uint32 val;
    l_uint32 *datas, *datad, *lined;
    l_float32 x, y;
    PIX *pix1, *pix2, *pixd;

    PROCNAME("pixBilinearColor");

    if (!pixs)
        return (PIX *) ERROR_PTR("pixs not defined", procName, NULL);
    pixGetDimensions(pixs, &w, &h, &d);
    if (d != 32)
        return (PIX *) ERROR_PTR("pixs must be 32 bpp", procName, NULL);
    if (!vc)
        return (PIX *) ERROR_PTR("vc not defined", procName, NULL);

    datas = pixGetData(pixs);
    wpls = pixGetWpl(pixs);
    pixd = pixCreateTemplate(pixs);
    pixSetAllArbitrary(pixd, colorval);
    datad = pixGetData(pixd);
    wpld = pixGetWpl(pixd);

    /* Iterate over destination pixels */
    for (i = 0; i < h; i++) {
        lined = datad + i * wpld;
        for (j = 0; j < w; j++) {
            /* Compute float src pixel location corresponding to (i,j) */
            bilinearXformPt(vc, j, i, &x, &y);
            linearInterpolatePixelColor(datas, wpls, w, h, x, y, colorval,
                                        &val);
            *(lined + j) = val;
        }
    }

    /* If rgba, transform the pixs alpha channel and insert in pixd */
    if (pixGetSpp(pixs) == 4) {
        pix1 = pixGetRGBComponent(pixs, L_ALPHA_CHANNEL);
        pix2 = pixBilinearGray(pix1, vc, 255);  /* bring in opaque */
        pixSetRGBComponent(pixd, pix2, L_ALPHA_CHANNEL);
        pixDestroy(&pix1);
        pixDestroy(&pix2);
    }

    return pixd;
}
Пример #3
0
/*!
 *  pixaDisplayUnsplit()
 *
 *      Input:  pixa
 *              nx   (number of mosaic cells horizontally)
 *              ny   (number of mosaic cells vertically)
 *              borderwidth  (of added border on all sides)
 *              bordercolor  (in our RGBA format: 0xrrggbbaa)
 *      Return: pix of tiled images, or null on error
 *
 *  Notes:
 *      (1) This is a logical inverse of pixaSplitPix().  It
 *          constructs a pix from a mosaic of tiles, all of equal size.
 *      (2) For added generality, a border of arbitrary color can
 *          be added to each of the tiles.
 *      (3) In use, pixa will typically have either been generated
 *          from pixaSplitPix() or will derived from a pixa that
 *          was so generated.
 *      (4) All pix in the pixa must be of equal depth, and, if
 *          colormapped, have the same colormap.
 */
PIX *
pixaDisplayUnsplit(PIXA     *pixa,
                   l_int32   nx,
                   l_int32   ny,
                   l_int32   borderwidth,
                   l_uint32  bordercolor)
{
l_int32  w, h, d, wt, ht;
l_int32  i, j, k, x, y, n;
PIX     *pixt, *pixd;

    PROCNAME("pixaDisplayUnsplit");

    if (!pixa)
        return (PIX *)ERROR_PTR("pixa not defined", procName, NULL);
    if (nx <= 0 || ny <= 0)
        return (PIX *)ERROR_PTR("nx and ny must be > 0", procName, NULL);
    if ((n = pixaGetCount(pixa)) == 0)
        return (PIX *)ERROR_PTR("no components", procName, NULL);
    if (n != nx * ny)
        return (PIX *)ERROR_PTR("n != nx * ny", procName, NULL);
    borderwidth = L_MAX(0, borderwidth);

    pixaGetPixDimensions(pixa, 0, &wt, &ht, &d);
    w = nx * (wt + 2 * borderwidth);
    h = ny * (ht + 2 * borderwidth);

    if ((pixd = pixCreate(w, h, d)) == NULL)
        return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
    pixt = pixaGetPix(pixa, 0, L_CLONE);
    pixCopyColormap(pixd, pixt);
    pixDestroy(&pixt);
    if (borderwidth > 0)
        pixSetAllArbitrary(pixd, bordercolor);

    y = borderwidth;
    for (i = 0, k = 0; i < ny; i++) {
        x = borderwidth;
        for (j = 0; j < nx; j++, k++) {
            pixt = pixaGetPix(pixa, k, L_CLONE);
            pixRasterop(pixd, x, y, wt, ht, PIX_SRC, pixt, 0, 0);
            pixDestroy(&pixt);
            x += wt + 2 * borderwidth;
        }
        y += ht + 2 * borderwidth;
    }

    return pixd;
}
/*!
 *  pixInitAccumulate()
 *
 *      Input:  w, h (of accumulate array)
 *              offset (initialize the 32 bpp to have this
 *                      value; not more than 0x40000000)
 *      Return: pixd (32 bpp), or null on error
 *
 *  Notes:
 *      (1) The offset must be >= 0.
 *      (2) The offset is used so that we can do arithmetic
 *          with negative number results on l_uint32 data; it
 *          prevents the l_uint32 data from going negative.
 *      (3) Because we use l_int32 intermediate data results,
 *          these should never exceed the max of l_int32 (0x7fffffff).
 *          We do not permit the offset to be above 0x40000000,
 *          which is half way between 0 and the max of l_int32.
 *      (4) The same offset should be used for initialization,
 *          multiplication by a constant, and final extraction!
 *      (5) If you're only adding positive values, offset can be 0.
 */
PIX *
pixInitAccumulate(l_int32   w,
                  l_int32   h,
                  l_uint32  offset)
{
PIX  *pixd;

    PROCNAME("pixInitAccumulate");

    if ((pixd = pixCreate(w, h, 32)) == NULL)
        return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
    if (offset > 0x40000000)
        offset = 0x40000000;
    pixSetAllArbitrary(pixd, offset);
    return pixd;
}
Пример #5
0
// Helper writes a grey image to a file for use by scrollviewer.
// Normally for speed we don't display the image in the layout debug windows.
// If textord_debug_images is true, we draw the image as a background to some
// of the debug windows. printable determines whether these
// images are optimized for printing instead of screen display.
static void WriteDebugBackgroundImage(bool printable, Pix* pix_binary) {
  Pix* grey_pix = pixCreate(pixGetWidth(pix_binary),
                            pixGetHeight(pix_binary), 8);
  // Printable images are light grey on white, but for screen display
  // they are black on dark grey so the other colors show up well.
  if (printable) {
    pixSetAll(grey_pix);
    pixSetMasked(grey_pix, pix_binary, 192);
  } else {
    pixSetAllArbitrary(grey_pix, 64);
    pixSetMasked(grey_pix, pix_binary, 0);
  }
  AlignedBlob::IncrementDebugPix();
  pixWrite(AlignedBlob::textord_debug_pix().string(), grey_pix, IFF_PNG);
  pixDestroy(&grey_pix);
}
Пример #6
0
/*!
 *  pixaSplitPix()
 *
 *      Input:  pixs  (with individual components on a lattice)
 *              nx   (number of mosaic cells horizontally)
 *              ny   (number of mosaic cells vertically)
 *              borderwidth  (of added border on all sides)
 *              bordercolor  (in our RGBA format: 0xrrggbbaa)
 *      Return: pixa, or null on error
 *
 *  Notes:
 *      (1) This is a variant on pixaCreateFromPix(), where we
 *          simply divide the image up into (approximately) equal
 *          subunits.  If you want the subimages to have essentially
 *          the same aspect ratio as the input pix, use nx = ny.
 *      (2) If borderwidth is 0, we ignore the input bordercolor and
 *          redefine it to white.
 *      (3) The bordercolor is always used to initialize each tiled pix,
 *          so that if the src is clipped, the unblitted part will
 *          be this color.  This avoids 1 pixel wide black stripes at the
 *          left and lower edges.
 */
PIXA *
pixaSplitPix(PIX      *pixs,
             l_int32   nx,
             l_int32   ny,
             l_int32   borderwidth,
             l_uint32  bordercolor)
{
l_int32  w, h, d, cellw, cellh, i, j;
PIX     *pixt;
PIXA    *pixa;

    PROCNAME("pixaSplitPix");

    if (!pixs)
        return (PIXA *)ERROR_PTR("pixs not defined", procName, NULL);
    if (nx <= 0 || ny <= 0)
        return (PIXA *)ERROR_PTR("nx and ny must be > 0", procName, NULL);
    borderwidth = L_MAX(0, borderwidth);

    if ((pixa = pixaCreate(nx * ny)) == NULL)
        return (PIXA *)ERROR_PTR("pixa not made", procName, NULL);
    pixGetDimensions(pixs, &w, &h, &d);
    cellw = (w + nx - 1) / nx;  /* round up */
    cellh = (h + ny - 1) / ny;

    for (i = 0; i < ny; i++) {
        for (j = 0; j < nx; j++) {
            if ((pixt = pixCreate(cellw + 2 * borderwidth,
                                  cellh + 2 * borderwidth, d)) == NULL)
                return (PIXA *)ERROR_PTR("pixt not made", procName, NULL);
            pixCopyColormap(pixt, pixs);
            if (borderwidth == 0) {  /* initialize full image to white */
                if (d == 1)
                    pixClearAll(pixt);
                else
                    pixSetAll(pixt);
            }
            else
                pixSetAllArbitrary(pixt, bordercolor);
            pixRasterop(pixt, borderwidth, borderwidth, cellw, cellh,
                        PIX_SRC, pixs, j * cellw, i * cellh);
            pixaAddPix(pixa, pixt, L_INSERT);
        }
    }

    return pixa;
}
Пример #7
0
/*!
 *  pixProjectiveColor()
 *
 *      Input:  pixs (32 bpp)
 *              vc  (vector of 8 coefficients for projective transformation)
 *              colorval (e.g., 0 to bring in BLACK, 0xffffff00 for WHITE)
 *      Return: pixd, or null on error
 */
PIX *
pixProjectiveColor(PIX        *pixs,
                   l_float32  *vc,
                   l_uint32    colorval)
{
l_int32    i, j, w, h, d, wpls, wpld;
l_uint32   val;
l_uint32  *datas, *datad, *lined;
l_float32  x, y;
PIX       *pixd;

    PROCNAME("pixProjectiveColor");

    if (!pixs)
        return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
    pixGetDimensions(pixs, &w, &h, &d);
    if (d != 32)
        return (PIX *)ERROR_PTR("pixs must be 32 bpp", procName, NULL);
    if (!vc)
        return (PIX *)ERROR_PTR("vc not defined", procName, NULL);

    datas = pixGetData(pixs);
    wpls = pixGetWpl(pixs);
    pixd = pixCreateTemplate(pixs);
    pixSetAllArbitrary(pixd, colorval);
    datad = pixGetData(pixd);
    wpld = pixGetWpl(pixd);

        /* Iterate over destination pixels */
    for (i = 0; i < h; i++) {
        lined = datad + i * wpld;
        for (j = 0; j < w; j++) {
                /* Compute float src pixel location corresponding to (i,j) */
            projectiveXformPt(vc, j, i, &x, &y);
            linearInterpolatePixelColor(datas, wpls, w, h, x, y, colorval,
                                        &val);
            *(lined + j) = val;
        }
    }

    return pixd;
}
Пример #8
0
/*!
 *  pixProjectiveGray()
 *
 *      Input:  pixs (8 bpp)
 *              vc  (vector of 8 coefficients for projective transformation)
 *              grayval (0 to bring in BLACK, 255 for WHITE)
 *      Return: pixd, or null on error
 */
PIX *
pixProjectiveGray(PIX        *pixs,
                  l_float32  *vc,
                  l_uint8     grayval)
{
l_int32    i, j, w, h, wpls, wpld, val;
l_uint32  *datas, *datad, *lined;
l_float32  x, y;
PIX       *pixd;

    PROCNAME("pixProjectiveGray");

    if (!pixs)
        return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
    pixGetDimensions(pixs, &w, &h, NULL);
    if (pixGetDepth(pixs) != 8)
        return (PIX *)ERROR_PTR("pixs must be 8 bpp", procName, NULL);
    if (!vc)
        return (PIX *)ERROR_PTR("vc not defined", procName, NULL);

    datas = pixGetData(pixs);
    wpls = pixGetWpl(pixs);
    pixd = pixCreateTemplate(pixs);
    pixSetAllArbitrary(pixd, grayval);
    datad = pixGetData(pixd);
    wpld = pixGetWpl(pixd);

        /* Iterate over destination pixels */
    for (i = 0; i < h; i++) {
        lined = datad + i * wpld;
        for (j = 0; j < w; j++) {
                /* Compute float src pixel location corresponding to (i,j) */
            projectiveXformPt(vc, j, i, &x, &y);
            linearInterpolatePixelGray(datas, wpls, w, h, x, y, grayval, &val);
            SET_DATA_BYTE(lined, j, val);
        }
    }

    return pixd;
}
Пример #9
0
/*!
 *  wshedCreate()
 *
 *      Input:  pixs  (8 bpp source)
 *              pixm  (1 bpp 'marker' seed)
 *              mindepth (minimum depth; anything less is not saved)
 *              debugflag (1 for debug output)
 *      Return: WShed, or null on error
 *
 *  Notes:
 *      (1) It is not necessary for the fg pixels in the seed image
 *          be at minima, or that they be isolated.  We extract a
 *          single pixel from each connected component, and a seed
 *          anywhere in a watershed will eventually label the watershed
 *          when the filling level reaches it.
 *      (2) Set mindepth to some value to ignore noise in pixs that
 *          can create small local minima.  Any watershed shallower
 *          than mindepth, even if it has a seed, will not be saved;
 *          It will either be incorporated in another watershed or
 *          eliminated.
 */
L_WSHED *
wshedCreate(PIX     *pixs,
            PIX     *pixm,
            l_int32  mindepth,
            l_int32  debugflag)
{
l_int32   w, h;
L_WSHED  *wshed;

    PROCNAME("wshedCreate");

    if (!pixs)
        return (L_WSHED *)ERROR_PTR("pixs is not defined", procName, NULL);
    if (pixGetDepth(pixs) != 8)
        return (L_WSHED *)ERROR_PTR("pixs is not 8 bpp", procName, NULL);
    if (!pixm)
        return (L_WSHED *)ERROR_PTR("pixm is not defined", procName, NULL);
    if (pixGetDepth(pixm) != 1)
        return (L_WSHED *)ERROR_PTR("pixm is not 1 bpp", procName, NULL);
    pixGetDimensions(pixs, &w, &h, NULL);
    if (pixGetWidth(pixm) != w || pixGetHeight(pixm) != h)
        return (L_WSHED *)ERROR_PTR("pixs/m sizes are unequal", procName, NULL);

    if ((wshed = (L_WSHED *)CALLOC(1, sizeof(L_WSHED))) == NULL)
        return (L_WSHED *)ERROR_PTR("wshed not made", procName, NULL);

    wshed->pixs = pixClone(pixs);
    wshed->pixm = pixClone(pixm);
    wshed->mindepth = L_MAX(1, mindepth);
    wshed->pixlab = pixCreate(w, h, 32);
    pixSetAllArbitrary(wshed->pixlab, MAX_LABEL_VALUE);
    wshed->pixt = pixCreate(w, h, 1);
    wshed->lines8 = pixGetLinePtrs(pixs, NULL);
    wshed->linem1 = pixGetLinePtrs(pixm, NULL);
    wshed->linelab32 = pixGetLinePtrs(wshed->pixlab, NULL);
    wshed->linet1 = pixGetLinePtrs(wshed->pixt, NULL);
    wshed->debug = debugflag;
    return wshed;
}
Пример #10
0
/*!
 *  pixaccCreate()
 *
 *      Input:  w, h (of 32 bpp internal Pix)
 *              negflag (0 if only positive numbers are involved;
 *                       1 if there will be negative numbers)
 *      Return: pixacc, or null on error
 *
 *  Notes:
 *      (1) Use @negflag = 1 for safety if any negative numbers are going
 *          to be used in the chain of operations.  Negative numbers
 *          arise, e.g., by subtracting a pix, or by adding a pix
 *          that has been pre-multiplied by a negative number.
 *      (2) Initializes the internal 32 bpp pix, similarly to the
 *          initialization in pixInitAccumulate().
 */
PIXACC *
pixaccCreate(l_int32 w,
             l_int32 h,
             l_int32 negflag) {
    PIXACC *pixacc;

    PROCNAME("pixaccCreate");

    if ((pixacc = (PIXACC *) CALLOC(1, sizeof(PIXACC))) == NULL)
        return (PIXACC *) ERROR_PTR("pixacc not made", procName, NULL);
    pixacc->w = w;
    pixacc->h = h;

    if ((pixacc->pix = pixCreate(w, h, 32)) == NULL)
        return (PIXACC *) ERROR_PTR("pix not made", procName, NULL);

    if (negflag) {
        pixacc->offset = 0x40000000;
        pixSetAllArbitrary(pixacc->pix, pixacc->offset);
    }

    return pixacc;
}
Пример #11
0
int main(int argc,
         char **argv) {
    char dilateseq[BUF_SIZE], erodeseq[BUF_SIZE];
    char openseq[BUF_SIZE], closeseq[BUF_SIZE];
    char wtophatseq[BUF_SIZE], btophatseq[BUF_SIZE];
    char *filein;
    l_int32 w, h, d;
    PIX *pixs, *pixt, *pixt2, *pixt3, *pixt3a, *pixt4;
    PIX *pixg, *pixd, *pixd1, *pixd2, *pixd3;
    PIXACC *pacc;
    PIXCMAP *cmap;
    static char mainName[] = "graymorph1_reg";

    if (argc != 2)
        return ERROR_INT(" Syntax:  graymorph1_reg filein", mainName, 1);

    filein = argv[1];
    if ((pixs = pixRead(filein)) == NULL)
        return ERROR_INT("pixs not made", mainName, 1);
    pixGetDimensions(pixs, &w, &h, &d);
    if (d != 8)
        return ERROR_INT("pixs not 8 bpp", mainName, 1);

    /* -------- Test gray morph, including interpreter ------------ */
    pixd = pixDilateGray(pixs, WSIZE, HSIZE);
    sprintf(dilateseq, "D%d.%d", WSIZE, HSIZE);
    pixg = pixGrayMorphSequence(pixs, dilateseq, HORIZ_SEP, 0);
    pixCompare(pixd, pixg, "results are the same", "results are different");
    pixDestroy(&pixg);
    pixDestroy(&pixd);

    pixd = pixErodeGray(pixs, WSIZE, HSIZE);
    sprintf(erodeseq, "E%d.%d", WSIZE, HSIZE);
    pixg = pixGrayMorphSequence(pixs, erodeseq, HORIZ_SEP, 100);
    pixCompare(pixd, pixg, "results are the same", "results are different");
    pixDestroy(&pixg);
    pixDestroy(&pixd);

    pixd = pixOpenGray(pixs, WSIZE, HSIZE);
    sprintf(openseq, "O%d.%d", WSIZE, HSIZE);
    pixg = pixGrayMorphSequence(pixs, openseq, HORIZ_SEP, 200);
    pixCompare(pixd, pixg, "results are the same", "results are different");
    pixDestroy(&pixg);
    pixDestroy(&pixd);

    pixd = pixCloseGray(pixs, WSIZE, HSIZE);
    sprintf(closeseq, "C%d.%d", WSIZE, HSIZE);
    pixg = pixGrayMorphSequence(pixs, closeseq, HORIZ_SEP, 300);
    pixCompare(pixd, pixg, "results are the same", "results are different");
    pixDestroy(&pixg);
    pixDestroy(&pixd);

    pixd = pixTophat(pixs, WSIZE, HSIZE, L_TOPHAT_WHITE);
    sprintf(wtophatseq, "Tw%d.%d", WSIZE, HSIZE);
    pixg = pixGrayMorphSequence(pixs, wtophatseq, HORIZ_SEP, 400);
    pixCompare(pixd, pixg, "results are the same", "results are different");
    pixDestroy(&pixg);
    pixDestroy(&pixd);

    pixd = pixTophat(pixs, WSIZE, HSIZE, L_TOPHAT_BLACK);
    sprintf(btophatseq, "Tb%d.%d", WSIZE, HSIZE);
    pixg = pixGrayMorphSequence(pixs, btophatseq, HORIZ_SEP, 500);
    pixCompare(pixd, pixg, "results are the same", "results are different");
    pixDestroy(&pixg);

    /* ------------- Test erode/dilate duality -------------- */
    pixd = pixDilateGray(pixs, WSIZE, HSIZE);
    pixInvert(pixs, pixs);
    pixd2 = pixErodeGray(pixs, WSIZE, HSIZE);
    pixInvert(pixd2, pixd2);
    pixCompare(pixd, pixd2, "results are the same", "results are different");
    pixDestroy(&pixd);
    pixDestroy(&pixd2);

    /* ------------- Test open/close duality -------------- */
    pixd = pixOpenGray(pixs, WSIZE, HSIZE);
    pixInvert(pixs, pixs);
    pixd2 = pixCloseGray(pixs, WSIZE, HSIZE);
    pixInvert(pixd2, pixd2);
    pixCompare(pixd, pixd2, "results are the same", "results are different");
    pixDestroy(&pixd);
    pixDestroy(&pixd2);

    /* ------------- Test tophat duality -------------- */
    pixd = pixTophat(pixs, WSIZE, HSIZE, L_TOPHAT_WHITE);
    pixInvert(pixs, pixs);
    pixd2 = pixTophat(pixs, WSIZE, HSIZE, L_TOPHAT_BLACK);
    pixCompare(pixd, pixd2, "Correct: images are duals",
               "Error: images are not duals");
    pixDestroy(&pixd);
    pixDestroy(&pixd2);
    pixInvert(pixs, pixs);

    pixd = pixGrayMorphSequence(pixs, "Tw9.5", HORIZ_SEP, 100);
    pixInvert(pixs, pixs);
    pixd2 = pixGrayMorphSequence(pixs, "Tb9.5", HORIZ_SEP, 300);
    pixCompare(pixd, pixd2, "Correct: images are duals",
               "Error: images are not duals");
    pixDestroy(&pixd);
    pixDestroy(&pixd2);

    /* ------------- Test opening/closing for large sels -------------- */
    pixd = pixGrayMorphSequence(pixs,
                                "C9.9 + C19.19 + C29.29 + C39.39 + C49.49", HORIZ_SEP, 100);
    pixDestroy(&pixd);
    pixd = pixGrayMorphSequence(pixs,
                                "O9.9 + O19.19 + O29.29 + O39.39 + O49.49", HORIZ_SEP, 400);
    pixDestroy(&pixd);

    /* ---------- Closing plus white tophat result ------------ *
     *            Parameters: wsize, hsize = 9, 29             *
     * ---------------------------------------------------------*/
    pixd = pixCloseGray(pixs, 9, 9);
    pixd1 = pixTophat(pixd, 9, 9, L_TOPHAT_WHITE);
    pixd2 = pixGrayMorphSequence(pixs, "C9.9 + TW9.9", HORIZ_SEP, 0);
    pixCompare(pixd1, pixd2, "correct: same", "wrong: different");
    pixd3 = pixMaxDynamicRange(pixd1, L_LINEAR_SCALE);
    pixDisplayWrite(pixd3, 1);
    pixDestroy(&pixd);
    pixDestroy(&pixd1);
    pixDestroy(&pixd2);
    pixDestroy(&pixd3);
    pixd = pixCloseGray(pixs, 29, 29);
    pixd1 = pixTophat(pixd, 29, 29, L_TOPHAT_WHITE);
    pixd2 = pixGrayMorphSequence(pixs, "C29.29 + Tw29.29", HORIZ_SEP, 0);
    pixCompare(pixd1, pixd2, "correct: same", "wrong: different");
    pixd3 = pixMaxDynamicRange(pixd1, L_LINEAR_SCALE);
    pixDisplayWrite(pixd3, 1);
    pixDestroy(&pixd);
    pixDestroy(&pixd1);
    pixDestroy(&pixd2);
    pixDestroy(&pixd3);

    /* --------- hdome with parameter height = 100 ------------*/
    pixd = pixHDome(pixs, 100, 4);
    pixd2 = pixMaxDynamicRange(pixd, L_LINEAR_SCALE);
    pixDisplayWrite(pixd2, 1);
    pixDestroy(&pixd2);

    /* ----- Contrast enhancement with morph parameters 9, 9 -------*/
    pixd1 = pixInitAccumulate(w, h, 0x8000);
    pixAccumulate(pixd1, pixs, L_ARITH_ADD);
    pixMultConstAccumulate(pixd1, 3., 0x8000);
    pixd2 = pixOpenGray(pixs, 9, 9);
    pixAccumulate(pixd1, pixd2, L_ARITH_SUBTRACT);
    pixDestroy(&pixd2);
    pixd2 = pixCloseGray(pixs, 9, 9);
    pixAccumulate(pixd1, pixd2, L_ARITH_SUBTRACT);
    pixDestroy(&pixd2);
    pixd = pixFinalAccumulate(pixd1, 0x8000, 8);
    pixDisplayWrite(pixd, 1);
    pixDestroy(&pixd1);

    /* Do the same thing with the Pixacc */
    pacc = pixaccCreate(w, h, 1);
    pixaccAdd(pacc, pixs);
    pixaccMultConst(pacc, 3.);
    pixd1 = pixOpenGray(pixs, 9, 9);
    pixaccSubtract(pacc, pixd1);
    pixDestroy(&pixd1);
    pixd1 = pixCloseGray(pixs, 9, 9);
    pixaccSubtract(pacc, pixd1);
    pixDestroy(&pixd1);
    pixd2 = pixaccFinal(pacc, 8);
    pixaccDestroy(&pacc);
    pixDisplayWrite(pixd2, 1);

    pixCompare(pixd, pixd2, "Correct: same", "Wrong: different");
    pixDestroy(&pixd);
    pixDestroy(&pixd2);


    /* ----  Tophat result on feynman stamp, to extract diagrams ----- */
    pixDestroy(&pixs);
    pixs = pixRead("feynman-stamp.jpg");

    /* Make output image to hold five intermediate images */
    w = pixGetWidth(pixs);
    h = pixGetHeight(pixs);
    pixd = pixCreate(5 * w + 18, h + 6, 32);  /* composite output image */
    pixSetAllArbitrary(pixd, 0x0000ff00);  /* set to blue */

    /* Paste in the input image */
    pixt = pixRemoveColormap(pixs, REMOVE_CMAP_TO_FULL_COLOR);
    pixRasterop(pixd, 3, 3, w, h, PIX_SRC, pixt, 0, 0);  /* 1st one */
/*    pixWrite("/tmp/junkgray.jpg", pixt, IFF_JFIF_JPEG); */
    pixDestroy(&pixt);

    /* Paste in the grayscale version */
    cmap = pixGetColormap(pixs);
    if (cmap)
        pixt = pixRemoveColormap(pixs, REMOVE_CMAP_TO_GRAYSCALE);
    else
        pixt = pixConvertRGBToGray(pixs, 0.33, 0.34, 0.33);
    pixt2 = pixConvertTo32(pixt);  /* 8 --> 32 bpp */
    pixRasterop(pixd, w + 6, 3, w, h, PIX_SRC, pixt2, 0, 0);  /* 2nd one */
    pixDestroy(&pixt2);

    /* Paste in a log dynamic range scaled version of the white tophat */
    pixt2 = pixTophat(pixt, 3, 3, L_TOPHAT_WHITE);
    pixt3a = pixMaxDynamicRange(pixt2, L_LOG_SCALE);
    pixt3 = pixConvertTo32(pixt3a);
    pixRasterop(pixd, 2 * w + 9, 3, w, h, PIX_SRC, pixt3, 0, 0);  /* 3rd */
/*    pixWrite("/tmp/junktophat.jpg", pixt2, IFF_JFIF_JPEG); */
    pixDestroy(&pixt3);
    pixDestroy(&pixt3a);
    pixDestroy(&pixt);

    /* Stretch the range and threshold to binary; paste it in */
    pixt3a = pixGammaTRC(NULL, pixt2, 1.0, 0, 80);
    pixt3 = pixThresholdToBinary(pixt3a, 70);
    pixt4 = pixConvertTo32(pixt3);
    pixRasterop(pixd, 3 * w + 12, 3, w, h, PIX_SRC, pixt4, 0, 0);  /* 4th */
/*    pixWrite("/tmp/junkbin.png", pixt3, IFF_PNG); */
    pixDestroy(&pixt2);
    pixDestroy(&pixt3a);
    pixDestroy(&pixt4);

    /* Invert; this is the final result */
    pixInvert(pixt3, pixt3);
    pixt4 = pixConvertTo32(pixt3);
    pixRasterop(pixd, 4 * w + 15, 3, w, h, PIX_SRC, pixt4, 0, 0);  /* 5th */
    pixWrite("/tmp/junkbininvert.png", pixt3, IFF_PNG);
    pixDisplayWrite(pixd, 1);
/*    pixWrite("/tmp/junkall.jpg", pixd, IFF_JFIF_JPEG); */
    pixDestroy(&pixt3);
    pixDestroy(&pixt4);
    pixDestroy(&pixd);

    pixDisplayMultiple("/tmp/display/file*");
    pixDestroy(&pixs);
    return 0;
}
Пример #12
0
int main(int    argc,
         char **argv)
{
char          dilateseq[512], erodeseq[512];
char          openseq[512], closeseq[512];
char          wtophatseq[512], btophatseq[512];
l_int32       w, h;
PIX          *pixs, *pix1, *pix2, *pix3, *pix4, *pix5;
PIXA         *pixa;
PIXACC       *pacc;
PIXCMAP      *cmap;
L_REGPARAMS  *rp;

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

    pixs = pixRead("aneurisms8.jpg");
    pixa = pixaCreate(0);

    /* =========================================================== */

    /* -------- Test gray morph, including interpreter ------------ */
    pix1 = pixDilateGray(pixs, WSIZE, HSIZE);
    sprintf(dilateseq, "D%d.%d", WSIZE, HSIZE);
    pix2 = pixGrayMorphSequence(pixs, dilateseq, 0, 0);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 0 */
    regTestComparePix(rp, pix1, pix2);  /* 1 */
    pixaAddPix(pixa, pix1, L_INSERT);
    pixDestroy(&pix2);

    pix1 = pixErodeGray(pixs, WSIZE, HSIZE);
    sprintf(erodeseq, "E%d.%d", WSIZE, HSIZE);
    pix2 = pixGrayMorphSequence(pixs, erodeseq, 0, 100);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 2 */
    regTestComparePix(rp, pix1, pix2);  /* 3 */
    pixaAddPix(pixa, pix1, L_INSERT);
    pixDestroy(&pix2);

    pix1 = pixOpenGray(pixs, WSIZE, HSIZE);
    sprintf(openseq, "O%d.%d", WSIZE, HSIZE);
    pix2 = pixGrayMorphSequence(pixs, openseq, 0, 200);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 4 */
    regTestComparePix(rp, pix1, pix2);  /* 5 */
    pixaAddPix(pixa, pix1, L_INSERT);
    pixDestroy(&pix2);

    pix1 = pixCloseGray(pixs, WSIZE, HSIZE);
    sprintf(closeseq, "C%d.%d", WSIZE, HSIZE);
    pix2 = pixGrayMorphSequence(pixs, closeseq, 0, 300);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 6 */
    regTestComparePix(rp, pix1, pix2);  /* 7 */
    pixaAddPix(pixa, pix1, L_INSERT);
    pixDestroy(&pix2);

    pix1 = pixTophat(pixs, WSIZE, HSIZE, L_TOPHAT_WHITE);
    sprintf(wtophatseq, "Tw%d.%d", WSIZE, HSIZE);
    pix2 = pixGrayMorphSequence(pixs, wtophatseq, 0, 400);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 8 */
    regTestComparePix(rp, pix1, pix2);  /* 9 */
    pixaAddPix(pixa, pix1, L_INSERT);
    pixDestroy(&pix2);

    pix1 = pixTophat(pixs, WSIZE, HSIZE, L_TOPHAT_BLACK);
    sprintf(btophatseq, "Tb%d.%d", WSIZE, HSIZE);
    pix2 = pixGrayMorphSequence(pixs, btophatseq, 0, 500);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 10 */
    regTestComparePix(rp, pix1, pix2);  /* 11 */
    pixaAddPix(pixa, pix1, L_INSERT);
    pixDestroy(&pix2);

    /* ------------- Test erode/dilate duality -------------- */
    pix1 = pixDilateGray(pixs, WSIZE, HSIZE);
    pix2 = pixInvert(NULL, pixs);
    pix3 = pixErodeGray(pix2, WSIZE, HSIZE);
    pixInvert(pix3, pix3);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 12 */
    regTestComparePix(rp, pix1, pix3);  /* 13 */
    pixaAddPix(pixa, pix1, L_INSERT);
    pixDestroy(&pix2);
    pixDestroy(&pix3);

    /* ------------- Test open/close duality -------------- */
    pix1 = pixOpenGray(pixs, WSIZE, HSIZE);
    pix2 = pixInvert(NULL, pixs);
    pix3 = pixCloseGray(pix2, WSIZE, HSIZE);
    pixInvert(pix3, pix3);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 14 */
    regTestComparePix(rp, pix1, pix3);  /* 15 */
    pixaAddPix(pixa, pix1, L_INSERT);
    pixDestroy(&pix2);
    pixDestroy(&pix3);

    /* ------------- Test tophat duality -------------- */
    pix1 = pixTophat(pixs, WSIZE, HSIZE, L_TOPHAT_WHITE);
    pix2 = pixInvert(NULL, pixs);
    pix3 = pixTophat(pix2, WSIZE, HSIZE, L_TOPHAT_BLACK);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 16 */
    regTestComparePix(rp, pix1, pix3);  /* 17 */
    pixaAddPix(pixa, pix1, L_INSERT);
    pixDestroy(&pix2);
    pixDestroy(&pix3);

    pix1 = pixGrayMorphSequence(pixs, "Tw9.5", 0, 100);
    pix2 = pixInvert(NULL, pixs);
    pix3 = pixGrayMorphSequence(pix2, "Tb9.5", 0, 300);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 18 */
    regTestComparePix(rp, pix1, pix3);  /* 19 */
    pixaAddPix(pixa, pix1, L_INSERT);
    pixDestroy(&pix2);
    pixDestroy(&pix3);


    /* ------------- Test opening/closing for large sels -------------- */
    pix1 = pixGrayMorphSequence(pixs,
            "C9.9 + C19.19 + C29.29 + C39.39 + C49.49", 0, 100);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 20 */
    pixaAddPix(pixa, pix1, L_INSERT);
    pix1 = pixGrayMorphSequence(pixs,
            "O9.9 + O19.19 + O29.29 + O39.39 + O49.49", 0, 400);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 21 */
    pixaAddPix(pixa, pix1, L_INSERT);

    pix1 = pixaDisplayTiledInColumns(pixa, 4, 1.0, 20, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 22 */
    pixDisplayWithTitle(pix1, 0, 0, NULL, rp->display);
    pixaDestroy(&pixa);
    pixDestroy(&pix1);

    /* =========================================================== */

    pixa = pixaCreate(0);
    /* ---------- Closing plus white tophat result ------------ *
     *            Parameters: wsize, hsize = 9, 29             *
     * ---------------------------------------------------------*/
    pix1 = pixCloseGray(pixs, 9, 9);
    pix2 = pixTophat(pix1, 9, 9, L_TOPHAT_WHITE);
    pix3 = pixGrayMorphSequence(pixs, "C9.9 + TW9.9", 0, 0);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 23 */
    regTestComparePix(rp, pix2, pix3);  /* 24 */
    pixaAddPix(pixa, pix1, L_INSERT);
    pix1 = pixMaxDynamicRange(pix2, L_LINEAR_SCALE);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 25 */
    pixaAddPix(pixa, pix1, L_INSERT);
    pixDestroy(&pix2);
    pixDestroy(&pix3);

    pix1 = pixCloseGray(pixs, 29, 29);
    pix2 = pixTophat(pix1, 29, 29, L_TOPHAT_WHITE);
    pix3 = pixGrayMorphSequence(pixs, "C29.29 + Tw29.29", 0, 0);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 26 */
    regTestComparePix(rp, pix2, pix3);  /* 27 */
    pixaAddPix(pixa, pix1, L_INSERT);
    pix1 = pixMaxDynamicRange(pix2, L_LINEAR_SCALE);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 28 */
    pixaAddPix(pixa, pix1, L_INSERT);
    pixDestroy(&pix2);
    pixDestroy(&pix3);

    /* --------- hdome with parameter height = 100 ------------*/
    pix1 = pixHDome(pixs, 100, 4);
    pix2 = pixMaxDynamicRange(pix1, L_LINEAR_SCALE);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 29 */
    regTestWritePixAndCheck(rp, pix2, IFF_PNG);  /* 30 */
    pixaAddPix(pixa, pix1, L_INSERT);
    pixaAddPix(pixa, pix2, L_INSERT);

    /* ----- Contrast enhancement with morph parameters 9, 9 -------*/
    pixGetDimensions(pixs, &w, &h, NULL);
    pix1 = pixInitAccumulate(w, h, 0x8000);
    pixAccumulate(pix1, pixs, L_ARITH_ADD);
    pixMultConstAccumulate(pix1, 3., 0x8000);
    pix2 = pixOpenGray(pixs, 9, 9);
    regTestWritePixAndCheck(rp, pix2, IFF_PNG);  /* 31 */
    pixaAddPix(pixa, pix2, L_INSERT);
    pixAccumulate(pix1, pix2, L_ARITH_SUBTRACT);

    pix2 = pixCloseGray(pixs, 9, 9);
    regTestWritePixAndCheck(rp, pix2, IFF_PNG);  /* 32 */
    pixaAddPix(pixa, pix2, L_INSERT);
    pixAccumulate(pix1, pix2, L_ARITH_SUBTRACT);
    pix2 = pixFinalAccumulate(pix1, 0x8000, 8);
    regTestWritePixAndCheck(rp, pix2, IFF_PNG);  /* 33 */
    pixaAddPix(pixa, pix2, L_INSERT);
    pixDestroy(&pix1);

        /* Do the same thing with the Pixacc */
    pacc = pixaccCreate(w, h, 1);
    pixaccAdd(pacc, pixs);
    pixaccMultConst(pacc, 3.);
    pix1 = pixOpenGray(pixs, 9, 9);
    pixaccSubtract(pacc, pix1);
    pixDestroy(&pix1);
    pix1 = pixCloseGray(pixs, 9, 9);
    pixaccSubtract(pacc, pix1);
    pixDestroy(&pix1);
    pix1 = pixaccFinal(pacc, 8);
    pixaccDestroy(&pacc);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 34 */
    pixaAddPix(pixa, pix1, L_INSERT);
    regTestComparePix(rp, pix1, pix2);  /* 35 */

    pix1 = pixaDisplayTiledInColumns(pixa, 4, 1.0, 20, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 36 */
    pixDisplayWithTitle(pix1, 1100, 0, NULL, rp->display);
    pixaDestroy(&pixa);
    pixDestroy(&pix1);
    pixDestroy(&pixs);

    /* =========================================================== */

    pixa = pixaCreate(0);

    /* ----  Tophat result on feynman stamp, to extract diagrams ----- */
    pixs = pixRead("feynman-stamp.jpg");
    pixGetDimensions(pixs, &w, &h, NULL);

        /* Make output image to hold five intermediate images */
    pix1 = pixCreate(5 * w + 18, h + 6, 32);  /* composite output image */
    pixSetAllArbitrary(pix1, 0x0000ff00);  /* set to blue */

        /* Paste in the input image */
    pix2 = pixRemoveColormap(pixs, REMOVE_CMAP_TO_FULL_COLOR);
    pixRasterop(pix1, 3, 3, w, h, PIX_SRC, pix2, 0, 0);  /* 1st one */
    regTestWritePixAndCheck(rp, pix2, IFF_PNG);  /* 37 */
    pixaAddPix(pixa, pix2, L_INSERT);

        /* Paste in the grayscale version */
    cmap = pixGetColormap(pixs);
    if (cmap)
        pix2 = pixRemoveColormap(pixs, REMOVE_CMAP_TO_GRAYSCALE);
    else
        pix2 = pixConvertRGBToGray(pixs, 0.33, 0.34, 0.33);
    pix3 = pixConvertTo32(pix2);  /* 8 --> 32 bpp */
    pixRasterop(pix1, w + 6, 3, w, h, PIX_SRC, pix3, 0, 0);  /* 2nd one */
    regTestWritePixAndCheck(rp, pix3, IFF_PNG);  /* 38 */
    pixaAddPix(pixa, pix3, L_INSERT);

         /* Paste in a log dynamic range scaled version of the white tophat */
    pix3 = pixTophat(pix2, 3, 3, L_TOPHAT_WHITE);
    pix4 = pixMaxDynamicRange(pix3, L_LOG_SCALE);
    pix5 = pixConvertTo32(pix4);
    pixRasterop(pix1, 2 * w + 9, 3, w, h, PIX_SRC, pix5, 0, 0);  /* 3rd */
    regTestWritePixAndCheck(rp, pix5, IFF_PNG);  /* 39 */
    pixaAddPix(pixa, pix5, L_INSERT);
    pixDestroy(&pix2);
    pixDestroy(&pix4);

        /* Stretch the range and threshold to binary; paste it in */
    pix2 = pixGammaTRC(NULL, pix3, 1.0, 0, 80);
    pix4 = pixThresholdToBinary(pix2, 70);
    pix5 = pixConvertTo32(pix4);
    pixRasterop(pix1, 3 * w + 12, 3, w, h, PIX_SRC, pix5, 0, 0);  /* 4th */
    regTestWritePixAndCheck(rp, pix5, IFF_PNG);  /* 40 */
    pixaAddPix(pixa, pix5, L_INSERT);
    pixDestroy(&pix2);
    pixDestroy(&pix3);

        /* Invert; this is the final result */
    pixInvert(pix4, pix4);
    pix5 = pixConvertTo32(pix4);
    pixRasterop(pix1, 4 * w + 15, 3, w, h, PIX_SRC, pix5, 0, 0);  /* 5th */
    regTestWritePixAndCheck(rp, pix5, IFF_PNG);  /* 41 */
    pixaAddPix(pixa, pix5, L_INSERT);
    pixDestroy(&pix1);
    pixDestroy(&pix4);

    pix1 = pixaDisplayTiledInRows(pixa, 32, 1700, 1.0, 0, 20, 2);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 42 */
    pixDisplayWithTitle(pix1, 0, 800, NULL, rp->display);
    pixaDestroy(&pixa);
    pixDestroy(&pix1);
    pixDestroy(&pixs);

    return regTestCleanup(rp);
}
Пример #13
0
main(int    argc,
     char **argv)
{
l_int32       i, j, x, y, val;
PIX          *pixsq, *pixs, *pixc, *pixd;
PIXA         *pixa;
L_REGPARAMS  *rp;

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

    pixsq = pixCreate(3, 3, 32);
    pixSetAllArbitrary(pixsq, 0x00ff0000);
    pixa = pixaCreate(6);

        /* Moderately dense */
    pixs = pixCreate(300, 300, 8);
    for (i = 0; i < 100; i++) {
        x = (153 * i * i * i + 59) % 299;
        y = (117 * i * i * i + 241) % 299;
        val = (97 * i + 74) % 256;
        pixSetPixel(pixs, x, y, val);
    }

    pixd = pixSeedspread(pixs, 4);  /* 4-cc */
    pixc = pixConvertTo32(pixd);
    for (i = 0; i < 100; i++) {
        x = (153 * i * i * i + 59) % 299;
        y = (117 * i * i * i + 241) % 299;
        pixRasterop(pixc, x - 1, y - 1, 3, 3, PIX_SRC, pixsq, 0, 0);
    }
    pixSaveTiled(pixc, pixa, REDUCTION, 1, 20, 32);
    regTestWritePixAndCheck(rp, pixc, IFF_PNG);  /* 0 */
    pixDisplayWithTitle(pixc, 100, 100, "4-cc", rp->display);
    pixDestroy(&pixd);
    pixDestroy(&pixc);

    pixd = pixSeedspread(pixs, 8);  /* 8-cc */
    pixc = pixConvertTo32(pixd);
    for (i = 0; i < 100; i++) {
        x = (153 * i * i * i + 59) % 299;
        y = (117 * i * i * i + 241) % 299;
        pixRasterop(pixc, x - 1, y - 1, 3, 3, PIX_SRC, pixsq, 0, 0);
    }
    pixSaveTiled(pixc, pixa, REDUCTION, 0, 20, 0);
    regTestWritePixAndCheck(rp, pixc, IFF_PNG);  /* 1 */
    pixDisplayWithTitle(pixc, 410, 100, "8-cc", rp->display);
    pixDestroy(&pixd);
    pixDestroy(&pixc);
    pixDestroy(&pixs);

        /* Regular lattice */
    pixs = pixCreate(200, 200, 8);
    for (i = 5; i <= 195; i += 10) {
        for (j = 5; j <= 195; j += 10) {
            pixSetPixel(pixs, i, j, (7 * i + 17 * j) % 255);
        }
    }
    pixd = pixSeedspread(pixs, 4);  /* 4-cc */
    pixc = pixConvertTo32(pixd);
    for (i = 5; i <= 195; i += 10) {
        for (j = 5; j <= 195; j += 10) {
            pixRasterop(pixc, j - 1, i - 1, 3, 3, PIX_SRC, pixsq, 0, 0);
        }
    }
    pixSaveTiled(pixc, pixa, REDUCTION, 1, 20, 0);
    regTestWritePixAndCheck(rp, pixc, IFF_PNG);  /* 2 */
    pixDisplayWithTitle(pixc, 100, 430, "4-cc", rp->display);
    pixDestroy(&pixd);
    pixDestroy(&pixc);

    pixd = pixSeedspread(pixs, 8);  /* 8-cc */
    pixc = pixConvertTo32(pixd);
    for (i = 5; i <= 195; i += 10) {
        for (j = 5; j <= 195; j += 10) {
            pixRasterop(pixc, j - 1, i - 1, 3, 3, PIX_SRC, pixsq, 0, 0);
        }
    }
    pixSaveTiled(pixc, pixa, REDUCTION, 0, 20, 0);
    regTestWritePixAndCheck(rp, pixc, IFF_PNG);  /* 3 */
    pixDisplayWithTitle(pixc, 310, 430, "8-cc", rp->display);
    pixDestroy(&pixd);
    pixDestroy(&pixc);
    pixDestroy(&pixs);

        /* Very sparse points */
    pixs = pixCreate(200, 200, 8);
    pixSetPixel(pixs, 60, 20, 90);
    pixSetPixel(pixs, 160, 40, 130);
    pixSetPixel(pixs, 80, 80, 205);
    pixSetPixel(pixs, 40, 160, 115);
    pixd = pixSeedspread(pixs, 4);  /* 4-cc */
    pixc = pixConvertTo32(pixd);
    pixRasterop(pixc, 60 - 1, 20 - 1, 3, 3, PIX_SRC, pixsq, 0, 0);
    pixRasterop(pixc, 160 - 1, 40 - 1, 3, 3, PIX_SRC, pixsq, 0, 0);
    pixRasterop(pixc, 80 - 1, 80 - 1, 3, 3, PIX_SRC, pixsq, 0, 0);
    pixRasterop(pixc, 40 - 1, 160 - 1, 3, 3, PIX_SRC, pixsq, 0, 0);
    pixSaveTiled(pixc, pixa, REDUCTION, 1, 20, 0);
    regTestWritePixAndCheck(rp, pixc, IFF_PNG);  /* 4 */
    pixDisplayWithTitle(pixc, 100, 600, "4-cc", rp->display);
    pixDestroy(&pixd);
    pixDestroy(&pixc);

    pixd = pixSeedspread(pixs, 8);  /* 8-cc */
    pixc = pixConvertTo32(pixd);
    pixRasterop(pixc, 60 - 1, 20 - 1, 3, 3, PIX_SRC, pixsq, 0, 0);
    pixRasterop(pixc, 160 - 1, 40 - 1, 3, 3, PIX_SRC, pixsq, 0, 0);
    pixRasterop(pixc, 80 - 1, 80 - 1, 3, 3, PIX_SRC, pixsq, 0, 0);
    pixRasterop(pixc, 40 - 1, 160 - 1, 3, 3, PIX_SRC, pixsq, 0, 0);
    pixSaveTiled(pixc, pixa, REDUCTION, 0, 20, 0);
    regTestWritePixAndCheck(rp, pixc, IFF_PNG);  /* 5 */
    pixDisplayWithTitle(pixc, 310, 660, "8-cc", rp->display);
    pixDestroy(&pixd);
    pixDestroy(&pixc);
    pixDestroy(&pixs);
    pixDestroy(&pixsq);

    pixd = pixaDisplay(pixa, 0, 0);
    regTestWritePixAndCheck(rp, pixd, IFF_PNG);  /* 6 */
    pixDisplayWithTitle(pixc, 720, 100, "Final", rp->display);

    pixaDestroy(&pixa);
    pixDestroy(&pixd);
    return regTestCleanup(rp);
}
Пример #14
0
int main(int    argc,
         char **argv)
{
char          label[512];
l_int32       rval, gval, bval, w, h, i, j, rwhite, gwhite, bwhite, count;
l_uint32      pixel;
GPLOT        *gplot1, *gplot2;
NUMA         *naseq, *na;
NUMAA        *naa1, *naa2;
PIX          *pixs, *pixt, *pixt0, *pixt1, *pixt2;
PIX          *pixr, *pixg, *pixb;  /* for color content extraction */
PIXA         *pixa, *pixat;
PIXCMAP      *cmap;
L_REGPARAMS  *rp;

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

        /* Generate a pdf of results when called with display */
    pixa = pixaCreate(0);

        /* Generate colors by sampling hue with max sat and value.
         * This image has been saved as 19-colors.png.  */
    pixat = pixaCreate(19);
    for (i = 0; i < 19; i++) {
        convertHSVToRGB((240 * i / 18), 255, 255, &rval, &gval, &bval);
        composeRGBPixel(rval, gval, bval, &pixel);
        pixt1 = pixCreate(50, 100, 32);
        pixSetAllArbitrary(pixt1, pixel);
        pixaAddPix(pixat, pixt1, L_INSERT);
    }
    pixt2 = pixaDisplayTiledInRows(pixat, 32, 1100, 1.0, 0, 0, 0);
    regTestWritePixAndCheck(rp, pixt2, IFF_PNG);  /* 0 */
    pixaAddPix(pixa, pixt2, L_INSERT);
    pixaDestroy(&pixat);

        /* Colorspace conversion in rgb */
    pixs = pixRead("wyom.jpg");
    pixaAddPix(pixa, pixs, L_INSERT);
    pixt = pixConvertRGBToHSV(NULL, pixs);
    regTestWritePixAndCheck(rp, pixt, IFF_JFIF_JPEG);  /* 1 */
    pixaAddPix(pixa, pixt, L_COPY);
    pixConvertHSVToRGB(pixt, pixt);
    regTestWritePixAndCheck(rp, pixt, IFF_JFIF_JPEG);  /* 2 */
    pixaAddPix(pixa, pixt, L_INSERT);

        /* Colorspace conversion on a colormap */
    pixt = pixOctreeQuantNumColors(pixs, 25, 0);
    regTestWritePixAndCheck(rp, pixt, IFF_JFIF_JPEG);  /* 3 */
    pixaAddPix(pixa, pixt, L_COPY);
    cmap = pixGetColormap(pixt);
    if (rp->display) pixcmapWriteStream(stderr, cmap);
    pixcmapConvertRGBToHSV(cmap);
    if (rp->display) pixcmapWriteStream(stderr, cmap);
    regTestWritePixAndCheck(rp, pixt, IFF_JFIF_JPEG);  /* 4 */
    pixaAddPix(pixa, pixt, L_COPY);
    pixcmapConvertHSVToRGB(cmap);
    if (rp->display) pixcmapWriteStream(stderr, cmap);
    regTestWritePixAndCheck(rp, pixt, IFF_JFIF_JPEG);  /* 5 */
    pixaAddPix(pixa, pixt, L_INSERT);

        /* Color content extraction */
    pixColorContent(pixs, 0, 0, 0, 0, &pixr, &pixg, &pixb);
    regTestWritePixAndCheck(rp, pixr, IFF_JFIF_JPEG);  /* 6 */
    pixaAddPix(pixa, pixr, L_INSERT);
    regTestWritePixAndCheck(rp, pixg, IFF_JFIF_JPEG);  /* 7 */
    pixaAddPix(pixa, pixg, L_INSERT);
    regTestWritePixAndCheck(rp, pixb, IFF_JFIF_JPEG);  /* 8 */
    pixaAddPix(pixa, pixb, L_INSERT);

        /* Color content measurement.  This tests the global
         * mapping of (r,g,b) --> (white), for 20 different
         * values of (r,g,b).   For each mappings, we compute
         * the color magnitude and threshold it at six values.
         * For each of those six thresholds, we plot the
         * fraction of pixels that exceeds the threshold
         * color magnitude, where the red value (mapped to
         * white) goes between 100 and 195.  */
    pixat = pixaCreate(20);
    naseq = numaMakeSequence(100, 5, 20);
    naa1 = numaaCreate(6);
    naa2 = numaaCreate(6);
    for (i = 0; i < 6; i++) {
        na = numaCreate(20);
        numaaAddNuma(naa1, na, L_COPY);
        numaaAddNuma(naa2, na, L_INSERT);
    }
    pixGetDimensions(pixs, &w, &h, NULL);
    for (i = 0; i < 20; i++) {
        rwhite = 100 + 5 * i;
        gwhite = 200 - 5 * i;
        bwhite = 150;
        pixt0 = pixGlobalNormRGB(NULL, pixs, rwhite, gwhite, bwhite, 255);
        pixaAddPix(pixat, pixt0, L_INSERT);
        pixt1 = pixColorMagnitude(pixs, rwhite, gwhite, bwhite,
                                  L_MAX_DIFF_FROM_AVERAGE_2);
        for (j = 0; j < 6; j++) {
            pixt2 = pixThresholdToBinary(pixt1, 30 + 10 * j);
            pixInvert(pixt2, pixt2);
            pixCountPixels(pixt2, &count, NULL);
            na = numaaGetNuma(naa1, j, L_CLONE);
            numaAddNumber(na, (l_float32)count / (l_float32)(w * h));
            numaDestroy(&na);
            pixDestroy(&pixt2);
        }
        pixDestroy(&pixt1);
        pixt1 = pixColorMagnitude(pixs, rwhite, gwhite, bwhite,
                                  L_MAX_MIN_DIFF_FROM_2);
        for (j = 0; j < 6; j++) {
            pixt2 = pixThresholdToBinary(pixt1, 30 + 10 * j);
            pixInvert(pixt2, pixt2);
            pixCountPixels(pixt2, &count, NULL);
            na = numaaGetNuma(naa2, j, L_CLONE);
            numaAddNumber(na, (l_float32)count / (l_float32)(w * h));
            numaDestroy(&na);
            pixDestroy(&pixt2);
        }
        pixDestroy(&pixt1);
    }
    gplot1 = gplotCreate("/tmp/regout/colorspace.10", GPLOT_PNG,
                         "Fraction with given color (diff from average)",
                         "white point space for red", "amount of color");
    gplot2 = gplotCreate("/tmp/regout/colorspace.11", GPLOT_PNG,
                         "Fraction with given color (min diff)",
                         "white point space for red", "amount of color");
    for (j = 0; j < 6; j++) {
        na = numaaGetNuma(naa1, j, L_CLONE);
        sprintf(label, "thresh %d", 30 + 10 * j);
        gplotAddPlot(gplot1, naseq, na, GPLOT_LINES, label);
        numaDestroy(&na);
        na = numaaGetNuma(naa2, j, L_CLONE);
        gplotAddPlot(gplot2, naseq, na, GPLOT_LINES, label);
        numaDestroy(&na);
    }
    gplotMakeOutput(gplot1);
    gplotMakeOutput(gplot2);
    gplotDestroy(&gplot1);
    gplotDestroy(&gplot2);
    pixt1 = pixaDisplayTiledAndScaled(pixat, 32, 250, 4, 0, 10, 2);
    regTestWritePixAndCheck(rp, pixt1, IFF_JFIF_JPEG);  /* 9 */
    pixaAddPix(pixa, pixt1, L_INSERT);
    pixDisplayWithTitle(pixt1, 0, 100, "Color magnitude", rp->display);
    pixaDestroy(&pixat);
    numaDestroy(&naseq);
    numaaDestroy(&naa1);
    numaaDestroy(&naa2);

        /* Give gnuplot time to write out the files */
#ifndef  _WIN32
    sleep(1);
#else
    Sleep(1000);
#endif  /* _WIN32 */

        /* Save as golden files, or check against them */
    regTestCheckFile(rp, "/tmp/regout/colorspace.10.png");  /* 10 */
    regTestCheckFile(rp, "/tmp/regout/colorspace.11.png");  /* 11 */

    if (rp->display) {
        pixt = pixRead("/tmp/regout/colorspace.10.png");
        pixaAddPix(pixa, pixt, L_INSERT);
        pixt = pixRead("/tmp/regout/colorspace.11.png");
        pixaAddPix(pixa, pixt, L_INSERT);
        pixaConvertToPdf(pixa, 0, 1.0, 0, 0, "colorspace tests",
                         "/tmp/regout/colorspace.pdf");
        L_INFO("Output pdf: /tmp/regout/colorspace.pdf\n", rp->testname);
    }
    pixaDestroy(&pixa);

    return regTestCleanup(rp);
}
Пример #15
0
int main(int    argc,
         char **argv)
{
char         label[512];
l_int32      rval, gval, bval, w, h, i, j, rwhite, gwhite, bwhite, count;
l_uint32     pixel;
GPLOT       *gplot1, *gplot2;
NUMA        *naseq, *na;
NUMAA       *naa1, *naa2;
PIX         *pixs, *pixt, *pixt0, *pixt1, *pixt2;
PIX         *pixr, *pixg, *pixb;
PIXA        *pixa;
PIXCMAP     *cmap;
static char  mainName[] = "colorspacetest";

    if (argc != 2)
        return ERROR_INT(" Syntax:  colorspacetest filein", mainName, 1);

    if ((pixs = pixRead(argv[1])) == NULL)
        return ERROR_INT("pixs not made", mainName, 1);

        /* Generate colors by sampling hue with max sat and value.
         * This was used to make the color strip 19-colors.png.  */
    pixa = pixaCreate(19);
    for (i = 0; i < 19; i++) {
        convertHSVToRGB((240 * i / 18), 255, 255, &rval, &gval, &bval);
        composeRGBPixel(rval, gval, bval, &pixel);
        pixt1 = pixCreate(50, 100, 32);
        pixSetAllArbitrary(pixt1, pixel);
        pixaAddPix(pixa, pixt1, L_INSERT);
    }
    pixt2 = pixaDisplayTiledInRows(pixa, 32, 1100, 1.0, 0, 0, 0);
    pixDisplayWrite(pixt2, 1);
    pixDestroy(&pixt2);
    pixaDestroy(&pixa);

        /* Colorspace conversion in rgb */
    pixDisplayWrite(pixs, 1);
    pixt = pixConvertRGBToHSV(NULL, pixs);
    pixDisplayWrite(pixt, 1);
    pixConvertHSVToRGB(pixt, pixt);
    pixDisplayWrite(pixt, 1);
    pixDestroy(&pixt);

        /* Colorspace conversion on a colormap */
    pixt = pixOctreeQuantNumColors(pixs, 25, 0);
    pixDisplayWrite(pixt, 1);
    cmap = pixGetColormap(pixt);
    pixcmapWriteStream(stderr, cmap);
    pixcmapConvertRGBToHSV(cmap);
    pixcmapWriteStream(stderr, cmap);
    pixDisplayWrite(pixt, 1);
    pixcmapConvertHSVToRGB(cmap);
    pixcmapWriteStream(stderr, cmap);
    pixDisplayWrite(pixt, 1);
    pixDestroy(&pixt);

        /* Color content extraction */
    pixColorContent(pixs, 0, 0, 0, 0, &pixr, &pixg, &pixb);
    pixDisplayWrite(pixr, 1);
    pixDisplayWrite(pixg, 1);
    pixDisplayWrite(pixb, 1);
    pixDestroy(&pixr);
    pixDestroy(&pixg);
    pixDestroy(&pixb);

        /* Color content measurement */
    pixa = pixaCreate(20);
    naseq = numaMakeSequence(100, 5, 20);
    naa1 = numaaCreate(6);
    naa2 = numaaCreate(6);
    for (i = 0; i < 6; i++) {
        na = numaCreate(20);
        numaaAddNuma(naa1, na, L_COPY);
        numaaAddNuma(naa2, na, L_INSERT);
    }
    pixGetDimensions(pixs, &w, &h, NULL);
    for (i = 0; i < 20; i++) {
        rwhite = 100 + 5 * i;
        gwhite = 200 - 5 * i;
        bwhite = 150;
        pixt0 = pixGlobalNormRGB(NULL, pixs, rwhite, gwhite, bwhite, 255);
        pixaAddPix(pixa, pixt0, L_INSERT);
        pixt1 = pixColorMagnitude(pixs, rwhite, gwhite, bwhite,
                                  L_MAX_DIFF_FROM_AVERAGE_2);
        for (j = 0; j < 6; j++) {
            pixt2 = pixThresholdToBinary(pixt1, 30 + 10 * j);
            pixInvert(pixt2, pixt2);
            pixCountPixels(pixt2, &count, NULL);
            na = numaaGetNuma(naa1, j, L_CLONE);
            numaAddNumber(na, (l_float32)count / (l_float32)(w * h));
            numaDestroy(&na);
            pixDestroy(&pixt2);
        }
        pixDestroy(&pixt1);
        pixt1 = pixColorMagnitude(pixs, rwhite, gwhite, bwhite,
                                  L_MAX_MIN_DIFF_FROM_2);
        for (j = 0; j < 6; j++) {
            pixt2 = pixThresholdToBinary(pixt1, 30 + 10 * j);
            pixInvert(pixt2, pixt2);
            pixCountPixels(pixt2, &count, NULL);
            na = numaaGetNuma(naa2, j, L_CLONE);
            numaAddNumber(na, (l_float32)count / (l_float32)(w * h));
            numaDestroy(&na);
            pixDestroy(&pixt2);
        }
        pixDestroy(&pixt1);
    }
    gplot1 = gplotCreate("/tmp/junkplot1", GPLOT_X11,
                         "Fraction with given color (diff from average)",
                         "white point space for red", "amount of color");
    gplot2 = gplotCreate("/tmp/junkplot2", GPLOT_X11,
                         "Fraction with given color (min diff)",
                         "white point space for red", "amount of color");
    for (j = 0; j < 6; j++) {
        na = numaaGetNuma(naa1, j, L_CLONE);
        sprintf(label, "thresh %d", 30 + 10 * j);
        gplotAddPlot(gplot1, naseq, na, GPLOT_LINES, label);
        numaDestroy(&na);
        na = numaaGetNuma(naa2, j, L_CLONE);
        gplotAddPlot(gplot2, naseq, na, GPLOT_LINES, label);
        numaDestroy(&na);
    }
    gplotMakeOutput(gplot1);
    gplotMakeOutput(gplot2);
    gplotDestroy(&gplot1);
    gplotDestroy(&gplot2);
    pixt1 = pixaDisplayTiledAndScaled(pixa, 32, 250, 4, 0, 10, 2);
    pixWrite("/tmp/junkcolormag", pixt1, IFF_PNG);
    pixDisplayWithTitle(pixt1, 0, 100, "Color magnitude", 1);
    pixDestroy(&pixt1);
    pixaDestroy(&pixa);
    numaDestroy(&naseq);
    numaaDestroy(&naa1);
    numaaDestroy(&naa2);

    pixDisplayMultiple("/tmp/display/file*");

    pixDestroy(&pixs);
    return 0;
}
Пример #16
0
/*!
 *  pixaDisplayOnColor()
 *
 *      Input:  pixa
 *              w, h (if set to 0, determines the size from the
 *                    b.b. of the components in pixa)
 *              color (background color to use)
 *      Return: pix, or null on error
 *
 *  Notes:
 *      (1) This uses the boxes to place each pix in the rendered composite.
 *      (2) Set w = h = 0 to use the b.b. of the components to determine
 *          the size of the returned pix.
 *      (3) If any pix in @pixa are colormapped, or if the pix have
 *          different depths, it returns a 32 bpp pix.  Otherwise,
 *          the depth of the returned pixa equals that of the pix in @pixa.
 *      (4) If the pixa is empty, return null.
 */
PIX *
pixaDisplayOnColor(PIXA     *pixa,
                   l_int32   w,
                   l_int32   h,
                   l_uint32  bgcolor)
{
l_int32  i, n, xb, yb, wb, hb, hascmap, maxdepth, same;
BOXA    *boxa;
PIX     *pixt1, *pixt2, *pixd;
PIXA    *pixat;

    PROCNAME("pixaDisplayOnColor");

    if (!pixa)
        return (PIX *)ERROR_PTR("pixa not defined", procName, NULL);
    if ((n = pixaGetCount(pixa)) == 0)
        return (PIX *)ERROR_PTR("no components", procName, NULL);

        /* If w and h are not input, determine the minimum size
         * required to contain the origin and all c.c. */
    if (w == 0 || h == 0) {
        boxa = pixaGetBoxa(pixa, L_CLONE);
        boxaGetExtent(boxa, &w, &h, NULL);
        boxaDestroy(&boxa);
    }

        /* If any pix have colormaps, or if they have different depths,
         * generate rgb */
    pixaAnyColormaps(pixa, &hascmap);
    pixaGetDepthInfo(pixa, &maxdepth, &same);
    if (hascmap || !same) {
        maxdepth = 32;
        pixat = pixaCreate(n);
        for (i = 0; i < n; i++) {
            pixt1 = pixaGetPix(pixa, i, L_CLONE);
            pixt2 = pixConvertTo32(pixt1);
            pixaAddPix(pixat, pixt2, L_INSERT);
            pixDestroy(&pixt1);
        }
    }
    else 
        pixat = pixaCopy(pixa, L_CLONE);

        /* Make the output pix and set the background color */
    if ((pixd = pixCreate(w, h, maxdepth)) == NULL)
        return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
    if ((maxdepth == 1 && bgcolor > 0) ||
        (maxdepth == 2 && bgcolor >= 0x3) ||
        (maxdepth == 4 && bgcolor >= 0xf) ||
        (maxdepth == 8 && bgcolor >= 0xff) ||
        (maxdepth == 16 && bgcolor >= 0xffff) ||
        (maxdepth == 32 && bgcolor >= 0xffffff00)) {
        pixSetAll(pixd);
    }
    else if (bgcolor > 0)
        pixSetAllArbitrary(pixd, bgcolor);

        /* Blit each pix into its place */
    for (i = 0; i < n; i++) {
        if (pixaGetBoxGeometry(pixat, i, &xb, &yb, &wb, &hb)) {
            L_WARNING("no box found!", procName);
            continue;
        }
        pixt1 = pixaGetPix(pixat, i, L_CLONE);
        pixRasterop(pixd, xb, yb, wb, hb, PIX_SRC, pixt1, 0, 0);
        pixDestroy(&pixt1);
    }

    pixaDestroy(&pixat);
    return pixd;
}
Пример #17
0
main(int    argc,
     char **argv)
{
l_int32       i, j, x, y, rval, gval, bval;
l_uint32      pixel;
l_float32     frval, fgval, fbval;
NUMA         *nahue, *nasat, *napk;
PIX          *pixs, *pixhsv, *pixh, *pixg, *pixf, *pixd;
PIX          *pixr, *pixt1, *pixt2, *pixt3;
PIXA         *pixa, *pixapk;
PTA          *ptapk;
L_REGPARAMS  *rp;
	l_chooseDisplayProg(L_DISPLAY_WITH_XV);

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

        /* Make a graded frame color */
    pixs = pixCreate(650, 900, 32);
    for (i = 0; i < 900; i++) {
        rval = 40 + i / 30;
        for (j = 0; j < 650; j++) {
            gval = 255 - j / 30;
            bval = 70 + j / 30;
            composeRGBPixel(rval, gval, bval, &pixel);
            pixSetPixel(pixs, j, i, pixel);
        }
    }
            
        /* Place an image inside the frame and convert to HSV */
    pixt1 = pixRead("1555-3.jpg");
    pixt2 = pixScale(pixt1, 0.5, 0.5);
    pixRasterop(pixs, 100, 100, 2000, 2000, PIX_SRC, pixt2, 0, 0);
    pixDestroy(&pixt1);
    pixDestroy(&pixt2);
    pixDisplayWithTitle(pixs, 400, 0, "Input image", rp->display);
    pixa = pixaCreate(0);
    pixhsv = pixConvertRGBToHSV(NULL, pixs);

        /* Work in the HS projection of HSV */
    pixh = pixMakeHistoHS(pixhsv, 5, &nahue, &nasat);
    pixg = pixMaxDynamicRange(pixh, L_LOG_SCALE);
    pixf = pixConvertGrayToFalseColor(pixg, 1.0);
    regTestWritePixAndCheck(rp, pixf, IFF_PNG);   /* 0 */
    pixDisplayWithTitle(pixf, 100, 0, "False color HS histo", rp->display);
    pixaAddPix(pixa, pixs, L_COPY);
    pixaAddPix(pixa, pixhsv, L_INSERT);
    pixaAddPix(pixa, pixg, L_INSERT);
    pixaAddPix(pixa, pixf, L_INSERT);
    gplotSimple1(nahue, GPLOT_PNG, "/tmp/junkhue", "Histogram of hue values");
#ifndef  _WIN32
    sleep(1);
#else
    Sleep(1000);
#endif  /* _WIN32 */
    pixt3 = pixRead("/tmp/junkhue.png");
    regTestWritePixAndCheck(rp, pixt3, IFF_PNG);  /* 1 */
    pixDisplayWithTitle(pixt3, 100, 300, "Histo of hue", rp->display);
    pixaAddPix(pixa, pixt3, L_INSERT);
    gplotSimple1(nasat, GPLOT_PNG, "/tmp/junksat",
                 "Histogram of saturation values");
#ifndef  _WIN32
    sleep(1);
#else
    Sleep(1000);
#endif  /* _WIN32 */
    pixt3 = pixRead("/tmp/junksat.png");
    regTestWritePixAndCheck(rp, pixt3, IFF_PNG);  /* 2 */
    pixDisplayWithTitle(pixt3, 100, 800, "Histo of saturation", rp->display);
    pixaAddPix(pixa, pixt3, L_INSERT);
    pixd = pixaDisplayTiledAndScaled(pixa, 32, 270, 7, 0, 30, 3);
    regTestWritePixAndCheck(rp, pixd, IFF_PNG);  /* 3 */
    pixDisplayWithTitle(pixd, 0, 400, "Hue and Saturation Mosaic", rp->display);
    pixDestroy(&pixd);
    pixaDestroy(&pixa);
    numaDestroy(&nahue);
    numaDestroy(&nasat);

        /* Find all the peaks */
    pixFindHistoPeaksHSV(pixh, L_HS_HISTO, 20, 20, 6, 2.0,
                         &ptapk, &napk, &pixapk);
    numaWriteStream(stderr, napk);
    ptaWriteStream(stderr, ptapk, 1);
    pixd = pixaDisplayTiledInRows(pixapk, 32, 1400, 1.0, 0, 30, 2);
    regTestWritePixAndCheck(rp, pixd, IFF_PNG);  /* 4 */
    pixDisplayWithTitle(pixd, 0, 550, "Peaks in HS", rp->display);
    pixDestroy(&pixh);
    pixDestroy(&pixd);
    pixaDestroy(&pixapk);

        /* Make masks for each of the peaks */
    pixa = pixaCreate(0);
    pixr = pixScaleBySampling(pixs, 0.4, 0.4);
    for (i = 0; i < 6; i++) {
        ptaGetIPt(ptapk, i, &x, &y);
        pixt1 = pixMakeRangeMaskHS(pixr, y, 20, x, 20, L_INCLUDE_REGION);
        pixaAddPix(pixa, pixt1, L_INSERT);
        pixGetAverageMaskedRGB(pixr, pixt1, 0, 0, 1, L_MEAN_ABSVAL,
                               &frval, &fgval, &fbval);
        composeRGBPixel((l_int32)frval, (l_int32)fgval, (l_int32)fbval,
                        &pixel);
        pixt2 = pixCreateTemplate(pixr);
        pixSetAll(pixt2);
        pixPaintThroughMask(pixt2, pixt1, 0, 0, pixel);
        pixaAddPix(pixa, pixt2, L_INSERT);
        pixt3 = pixCreateTemplate(pixr);
        pixSetAllArbitrary(pixt3, pixel);
        pixaAddPix(pixa, pixt3, L_INSERT);
    }
    pixd = pixaDisplayTiledAndScaled(pixa, 32, 225, 3, 0, 30, 3);
    regTestWritePixAndCheck(rp, pixd, IFF_PNG);  /* 5 */
    pixDisplayWithTitle(pixd, 600, 0, "Masks over peaks", rp->display);
    pixDestroy(&pixs);
    pixDestroy(&pixr);
    pixDestroy(&pixd);
    pixaDestroy(&pixa);
    ptaDestroy(&ptapk);
    numaDestroy(&napk);

    regTestCleanup(rp);
    return 0;
}
Пример #18
0
/*!
 *  pixProjectivePtaWithAlpha()
 *
 *      Input:  pixs (32 bpp rgb)
 *              ptad  (4 pts of final coordinate space)
 *              ptas  (4 pts of initial coordinate space)
 *              pixg (<optional> 8 bpp, for alpha channel, can be null)
 *              fract (between 0.0 and 1.0, with 0.0 fully transparent
 *                     and 1.0 fully opaque)
 *              border (of pixels added to capture transformed source pixels)
 *      Return: pixd, or null on error
 *
 *  Notes:
 *      (1) The alpha channel is transformed separately from pixs,
 *          and aligns with it, being fully transparent outside the
 *          boundary of the transformed pixs.  For pixels that are fully
 *          transparent, a blending function like pixBlendWithGrayMask()
 *          will give zero weight to corresponding pixels in pixs.
 *      (2) If pixg is NULL, it is generated as an alpha layer that is
 *          partially opaque, using @fract.  Otherwise, it is cropped
 *          to pixs if required and @fract is ignored.  The alpha channel
 *          in pixs is never used.
 *      (3) Colormaps are removed.
 *      (4) When pixs is transformed, it doesn't matter what color is brought
 *          in because the alpha channel will be transparent (0) there.
 *      (5) To avoid losing source pixels in the destination, it may be
 *          necessary to add a border to the source pix before doing
 *          the projective transformation.  This can be any non-negative
 *          number.
 *      (6) The input @ptad and @ptas are in a coordinate space before
 *          the border is added.  Internally, we compensate for this
 *          before doing the projective transform on the image after
 *          the border is added.
 *      (7) The default setting for the border values in the alpha channel
 *          is 0 (transparent) for the outermost ring of pixels and
 *          (0.5 * fract * 255) for the second ring.  When blended over
 *          a second image, this
 *          (a) shrinks the visible image to make a clean overlap edge
 *              with an image below, and
 *          (b) softens the edges by weakening the aliasing there.
 *          Use l_setAlphaMaskBorder() to change these values.
 */
PIX *
pixProjectivePtaWithAlpha(PIX       *pixs,
                          PTA       *ptad,
                          PTA       *ptas,
                          PIX       *pixg,
                          l_float32  fract,
                          l_int32    border)
{
l_int32  ws, hs, d;
PIX     *pixd, *pixb1, *pixb2, *pixg2, *pixga;
PTA     *ptad2, *ptas2;

    PROCNAME("pixProjectivePtaWithAlpha");

    if (!pixs)
        return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
    pixGetDimensions(pixs, &ws, &hs, &d);
    if (d != 32 && pixGetColormap(pixs) == NULL)
        return (PIX *)ERROR_PTR("pixs not cmapped or 32 bpp", procName, NULL);
    if (pixg && pixGetDepth(pixg) != 8) {
        L_WARNING("pixg not 8 bpp; using @fract transparent alpha", procName);
        pixg = NULL;
    }
    if (!pixg && (fract < 0.0 || fract > 1.0)) {
        L_WARNING("invalid fract; using 1.0 (fully transparent)", procName);
        fract = 1.0;
    }
    if (!pixg && fract == 0.0)
        L_WARNING("fully opaque alpha; image will not be blended", procName);
    if (!ptad)
        return (PIX *)ERROR_PTR("ptad not defined", procName, NULL);
    if (!ptas)
        return (PIX *)ERROR_PTR("ptas not defined", procName, NULL);

        /* Add border; the color doesn't matter */
    pixb1 = pixAddBorder(pixs, border, 0);

        /* Transform the ptr arrays to work on the bordered image */
    ptad2 = ptaTransform(ptad, border, border, 1.0, 1.0);
    ptas2 = ptaTransform(ptas, border, border, 1.0, 1.0);

        /* Do separate projective transform of rgb channels of pixs
         * and of pixg */
    pixd = pixProjectivePtaColor(pixb1, ptad2, ptas2, 0);
    if (!pixg) {
        pixg2 = pixCreate(ws, hs, 8);
        if (fract == 1.0)
            pixSetAll(pixg2);
        else
            pixSetAllArbitrary(pixg2, (l_int32)(255.0 * fract));
    }
    else
        pixg2 = pixResizeToMatch(pixg, NULL, ws, hs);
    if (ws > 10 && hs > 10) {  /* see note 7 */
        pixSetBorderRingVal(pixg2, 1,
                            (l_int32)(255.0 * fract * AlphaMaskBorderVals[0]));
        pixSetBorderRingVal(pixg2, 2,
                            (l_int32)(255.0 * fract * AlphaMaskBorderVals[1]));

    }
    pixb2 = pixAddBorder(pixg2, border, 0);  /* must be black border */
    pixga = pixProjectivePtaGray(pixb2, ptad2, ptas2, 0);
    pixSetRGBComponent(pixd, pixga, L_ALPHA_CHANNEL);

    pixDestroy(&pixg2);
    pixDestroy(&pixb1);
    pixDestroy(&pixb2);
    pixDestroy(&pixga);
    ptaDestroy(&ptad2);
    ptaDestroy(&ptas2);
    return pixd;
}
Пример #19
0
/*!
 *  pixRotateWithAlpha()
 *
 *      Input:  pixs (32 bpp rgb or cmapped)
 *              angle (radians; clockwise is positive)
 *              pixg (<optional> 8 bpp, can be null)
 *              fract (between 0.0 and 1.0, with 0.0 fully transparent
 *                     and 1.0 fully opaque)
 *      Return: pixd (32 bpp rgba), or null on error
 *
 *  Notes:
 *      (1) The alpha channel is transformed separately from pixs,
 *          and aligns with it, being fully transparent outside the
 *          boundary of the transformed pixs.  For pixels that are fully
 *          transparent, a blending function like pixBlendWithGrayMask()
 *          will give zero weight to corresponding pixels in pixs.
 *      (2) Rotation is about the center of the image; for very small
 *          rotations, just return a clone.  The dest is automatically
 *          expanded so that no image pixels are lost.
 *      (3) Rotation is by area mapping.  It doesn't matter what
 *          color is brought in because the alpha channel will
 *          be transparent (black) there.
 *      (4) If pixg is NULL, it is generated as an alpha layer that is
 *          partially opaque, using @fract.  Otherwise, it is cropped
 *          to pixs if required and @fract is ignored.  The alpha
 *          channel in pixs is never used.
 *      (4) Colormaps are removed to 32 bpp.
 *      (5) The default setting for the border values in the alpha channel
 *          is 0 (transparent) for the outermost ring of pixels and
 *          (0.5 * fract * 255) for the second ring.  When blended over
 *          a second image, this
 *          (a) shrinks the visible image to make a clean overlap edge
 *              with an image below, and
 *          (b) softens the edges by weakening the aliasing there.
 *          Use l_setAlphaMaskBorder() to change these values.
 *      (6) A subtle use of gamma correction is to remove gamma correction
 *          before rotation and restore it afterwards.  This is done
 *          by sandwiching this function between a gamma/inverse-gamma
 *          photometric transform:
 *              pixt = pixGammaTRCWithAlpha(NULL, pixs, 1.0 / gamma, 0, 255);
 *              pixd = pixRotateWithAlpha(pixt, angle, NULL, fract);
 *              pixGammaTRCWithAlpha(pixd, pixd, gamma, 0, 255);
 *              pixDestroy(&pixt);
 *          This has the side-effect of producing artifacts in the very
 *          dark regions.
 *
 *  *** Warning: implicit assumption about RGB component ordering ***
 */
PIX *
pixRotateWithAlpha(PIX *pixs,
                   l_float32 angle,
                   PIX *pixg,
                   l_float32 fract) {
    l_int32 ws, hs, d, spp;
    PIX *pixd, *pix32, *pixg2, *pixgr;

    PROCNAME("pixRotateWithAlpha");

    if (!pixs)
        return (PIX *) ERROR_PTR("pixs not defined", procName, NULL);
    pixGetDimensions(pixs, &ws, &hs, &d);
    if (d != 32 && pixGetColormap(pixs) == NULL)
        return (PIX *) ERROR_PTR("pixs not cmapped or 32 bpp", procName, NULL);
    if (pixg && pixGetDepth(pixg) != 8) {
        L_WARNING("pixg not 8 bpp; using @fract transparent alpha\n", procName);
        pixg = NULL;
    }
    if (!pixg && (fract < 0.0 || fract > 1.0)) {
        L_WARNING("invalid fract; using fully opaque\n", procName);
        fract = 1.0;
    }
    if (!pixg && fract == 0.0)
        L_WARNING("transparent alpha; image will not be blended\n", procName);

    /* Make sure input to rotation is 32 bpp rgb, and rotate it */
    if (d != 32)
        pix32 = pixConvertTo32(pixs);
    else
        pix32 = pixClone(pixs);
    spp = pixGetSpp(pix32);
    pixSetSpp(pix32, 3);  /* ignore the alpha channel for the rotation */
    pixd = pixRotate(pix32, angle, L_ROTATE_AREA_MAP, L_BRING_IN_WHITE, ws, hs);
    pixSetSpp(pix32, spp);  /* restore initial value in case it's a clone */
    pixDestroy(&pix32);

    /* Set up alpha layer with a fading border and rotate it */
    if (!pixg) {
        pixg2 = pixCreate(ws, hs, 8);
        if (fract == 1.0)
            pixSetAll(pixg2);
        else if (fract > 0.0)
            pixSetAllArbitrary(pixg2, (l_int32)(255.0 * fract));
    } else {
        pixg2 = pixResizeToMatch(pixg, NULL, ws, hs);
    }
    if (ws > 10 && hs > 10) {  /* see note 8 */
        pixSetBorderRingVal(pixg2, 1,
                            (l_int32)(255.0 * fract * AlphaMaskBorderVals[0]));
        pixSetBorderRingVal(pixg2, 2,
                            (l_int32)(255.0 * fract * AlphaMaskBorderVals[1]));
    }
    pixgr = pixRotate(pixg2, angle, L_ROTATE_AREA_MAP,
                      L_BRING_IN_BLACK, ws, hs);

    /* Combine into a 4 spp result */
    pixSetRGBComponent(pixd, pixgr, L_ALPHA_CHANNEL);

    pixDestroy(&pixg2);
    pixDestroy(&pixgr);
    return pixd;
}
Пример #20
0
// Auto page segmentation. Divide the page image into blocks of uniform
// text linespacing and images.
// Width, height and resolution are derived from the input image.
// If the pix is non-NULL, then it is assumed to be the input, and it is
// copied to the image, otherwise the image is used directly.
// The output goes in the blocks list with corresponding TO_BLOCKs in the
// to_blocks list.
// If single_column is true, then no attempt is made to divide the image
// into columns, but multiple blocks are still made if the text is of
// non-uniform linespacing.
int Tesseract::AutoPageSeg(int width, int height, int resolution,
                           bool single_column, IMAGE* image,
                           BLOCK_LIST* blocks, TO_BLOCK_LIST* to_blocks) {
  int vertical_x = 0;
  int vertical_y = 1;
  TabVector_LIST v_lines;
  TabVector_LIST h_lines;
  ICOORD bleft(0, 0);
  Boxa* boxa = NULL;
  Pixa* pixa = NULL;
  // The blocks made by the ColumnFinder. Moved to blocks before return.
  BLOCK_LIST found_blocks;

#ifdef HAVE_LIBLEPT
  if (pix_binary_ != NULL) {
    if (textord_debug_images) {
      Pix* grey_pix = pixCreate(width, height, 8);
      // Printable images are light grey on white, but for screen display
      // they are black on dark grey so the other colors show up well.
      if (textord_debug_printable) {
        pixSetAll(grey_pix);
        pixSetMasked(grey_pix, pix_binary_, 192);
      } else {
        pixSetAllArbitrary(grey_pix, 64);
        pixSetMasked(grey_pix, pix_binary_, 0);
      }
      AlignedBlob::IncrementDebugPix();
      pixWrite(AlignedBlob::textord_debug_pix().string(), grey_pix, IFF_PNG);
      pixDestroy(&grey_pix);
    }
    if (tessedit_dump_pageseg_images)
      pixWrite("tessinput.png", pix_binary_, IFF_PNG);
    // Leptonica is used to find the lines and image regions in the input.
    LineFinder::FindVerticalLines(resolution, pix_binary_,
                                  &vertical_x, &vertical_y, &v_lines);
    LineFinder::FindHorizontalLines(resolution, pix_binary_, &h_lines);
    if (tessedit_dump_pageseg_images)
      pixWrite("tessnolines.png", pix_binary_, IFF_PNG);
    ImageFinder::FindImages(pix_binary_, &boxa, &pixa);
    if (tessedit_dump_pageseg_images)
      pixWrite("tessnoimages.png", pix_binary_, IFF_PNG);
    // Copy the Pix to the IMAGE.
    image->FromPix(pix_binary_);
    if (single_column)
      v_lines.clear();
  }
#endif
  TO_BLOCK_LIST land_blocks, port_blocks;
  TBOX page_box;
  // The rest of the algorithm uses the usual connected components.
  find_components(blocks, &land_blocks, &port_blocks, &page_box);

  TO_BLOCK_IT to_block_it(&port_blocks);
  ASSERT_HOST(!to_block_it.empty());
  for (to_block_it.mark_cycle_pt(); !to_block_it.cycled_list();
       to_block_it.forward()) {
    TO_BLOCK* to_block = to_block_it.data();
    TBOX blkbox = to_block->block->bounding_box();
    if (to_block->line_size >= 2) {
      // Note: if there are multiple blocks, then v_lines, boxa, and pixa
      // are empty on the next iteration, but in this case, we assume
      // that there aren't any interesting line separators or images, since
      // it means that we have a pre-defined unlv zone file.
      ColumnFinder finder(static_cast<int>(to_block->line_size),
                          blkbox.botleft(), blkbox.topright(),
                          &v_lines, &h_lines, vertical_x, vertical_y);
      if (finder.FindBlocks(height, resolution, single_column,
                            to_block, boxa, pixa, &found_blocks, to_blocks) < 0)
        return -1;
      finder.ComputeDeskewVectors(&deskew_, &reskew_);
      boxa = NULL;
      pixa = NULL;
    }
  }
#ifdef HAVE_LIBLEPT
  boxaDestroy(&boxa);
  pixaDestroy(&pixa);
#endif
  blocks->clear();
  BLOCK_IT block_it(blocks);
  // Move the found blocks to the input/output blocks.
  block_it.add_list_after(&found_blocks);

  if (textord_debug_images) {
    // The debug image is no longer needed so delete it.
    unlink(AlignedBlob::textord_debug_pix().string());
  }
  return 0;
}
Пример #21
0
/*!
 *  pixProjectiveSampled()
 *
 *      Input:  pixs (all depths)
 *              vc  (vector of 8 coefficients for projective transformation)
 *              incolor (L_BRING_IN_WHITE, L_BRING_IN_BLACK)
 *      Return: pixd, or null on error
 *
 *  Notes:
 *      (1) Brings in either black or white pixels from the boundary.
 *      (2) Retains colormap, which you can do for a sampled transform..
 *      (3) For 8 or 32 bpp, much better quality is obtained by the
 *          somewhat slower pixProjective().  See that function
 *          for relative timings between sampled and interpolated.
 */
PIX *
pixProjectiveSampled(PIX        *pixs,
                     l_float32  *vc,
                     l_int32     incolor)
{
l_int32     i, j, w, h, d, x, y, wpls, wpld, color, cmapindex;
l_uint32    val;
l_uint32   *datas, *datad, *lines, *lined;
PIX        *pixd;
PIXCMAP    *cmap;

    PROCNAME("pixProjectiveSampled");

    if (!pixs)
        return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
    if (!vc)
        return (PIX *)ERROR_PTR("vc not defined", procName, NULL);
    if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
        return (PIX *)ERROR_PTR("invalid incolor", procName, NULL);
    pixGetDimensions(pixs, &w, &h, &d);
    if (d != 1 && d != 2 && d != 4 && d != 8 && d != 32)
        return (PIX *)ERROR_PTR("depth not 1, 2, 4, 8 or 16", procName, NULL);

        /* Init all dest pixels to color to be brought in from outside */
    pixd = pixCreateTemplate(pixs);
    if ((cmap = pixGetColormap(pixs)) != NULL) {
        if (incolor == L_BRING_IN_WHITE)
            color = 1;
        else
            color = 0;
        pixcmapAddBlackOrWhite(cmap, color, &cmapindex);
        pixSetAllArbitrary(pixd, cmapindex);
    }
    else {
        if ((d == 1 && incolor == L_BRING_IN_WHITE) ||
            (d > 1 && incolor == L_BRING_IN_BLACK))
            pixClearAll(pixd);
        else
            pixSetAll(pixd);
    }

        /* Scan over the dest pixels */
    datas = pixGetData(pixs);
    wpls = pixGetWpl(pixs);
    datad = pixGetData(pixd);
    wpld = pixGetWpl(pixd);
    for (i = 0; i < h; i++) {
        lined = datad + i * wpld;
        for (j = 0; j < w; j++) {
            projectiveXformSampledPt(vc, j, i, &x, &y);
            if (x < 0 || y < 0 || x >=w || y >= h)
                continue;
            lines = datas + y * wpls;
            if (d == 1) {
                val = GET_DATA_BIT(lines, x);
                SET_DATA_BIT_VAL(lined, j, val);
            }
            else if (d == 8) {
                val = GET_DATA_BYTE(lines, x);
                SET_DATA_BYTE(lined, j, val);
            }
            else if (d == 32) {
                lined[j] = lines[x];
            }
            else if (d == 2) {
                val = GET_DATA_DIBIT(lines, x);
                SET_DATA_DIBIT(lined, j, val);
            }
            else if (d == 4) {
                val = GET_DATA_QBIT(lines, x);
                SET_DATA_QBIT(lined, j, val);
            }
        }
    }

    return pixd;
}