Ejemplo n.º 1
0
/*!
 *  pixRotateAMGrayCorner()
 *
 *      Input:  pixs
 *              angle (radians; clockwise is positive)
 *              grayval (0 to bring in BLACK, 255 for WHITE)
 *      Return: pixd, or null on error
 *
 *  Notes:
 *      (1) Rotates the image about the UL corner.
 *      (2) A positive angle gives a clockwise rotation.
 *      (3) Specify the grayvalue to be brought in from outside the image.
 */
PIX *
pixRotateAMGrayCorner(PIX       *pixs,
                      l_float32  angle,
                      l_uint8    grayval)
{
l_int32    w, h, wpls, wpld;
l_uint32  *datas, *datad;
PIX       *pixd;

    PROCNAME("pixRotateAMGrayCorner");

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

    if (L_ABS(angle) < VERY_SMALL_ANGLE)
        return pixClone(pixs);

    pixGetDimensions(pixs, &w, &h, NULL);
    datas = pixGetData(pixs);
    wpls = pixGetWpl(pixs);
    pixd = pixCreateTemplate(pixs);
    datad = pixGetData(pixd);
    wpld = pixGetWpl(pixd);

    rotateAMGrayCornerLow(datad, w, h, wpld, datas, wpls, angle, grayval);

    return pixd;
}
Ejemplo n.º 2
0
/*!
 *  pixRotateAMColorFast()
 *
 *      Input:  pixs
 *              angle (radians; clockwise is positive)
 *              colorval (e.g., 0 to bring in BLACK, 0xffffff00 for WHITE)
 *      Return: pixd, or null on error
 *
 *  Notes:
 *      (1) This rotates a color image about the image center.
 *      (2) A positive angle gives a clockwise rotation.
 *      (3) It uses area mapping, dividing each pixel into
 *          16 subpixels.
 *      (4) It is about 10% to 20% faster than the more accurate linear
 *          interpolation function pixRotateAMColor(),
 *          which uses 256 subpixels.
 *      (5) For some reason it shifts the image center.
 *          No attempt is made to rotate the alpha component.
 *
 *  *** Warning: implicit assumption about RGB component ordering ***
 */
PIX *
pixRotateAMColorFast(PIX       *pixs,
                     l_float32  angle,
                     l_uint32   colorval)
{
l_int32    w, h, wpls, wpld;
l_uint32  *datas, *datad;
PIX       *pixd;

    PROCNAME("pixRotateAMColorFast");

    if (!pixs)
        return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
    if (pixGetDepth(pixs) != 32)
        return (PIX *)ERROR_PTR("pixs must be 32 bpp", procName, NULL);

    if (L_ABS(angle) < MIN_ANGLE_TO_ROTATE)
        return pixClone(pixs);

    pixGetDimensions(pixs, &w, &h, NULL);
    datas = pixGetData(pixs);
    wpls = pixGetWpl(pixs);
    pixd = pixCreateTemplate(pixs);
    datad = pixGetData(pixd);
    wpld = pixGetWpl(pixd);

    rotateAMColorFastLow(datad, w, h, wpld, datas, wpls, angle, colorval);
    return pixd;
}
Ejemplo n.º 3
0
// Helper to remove an enclosing circle from an image.
// If there isn't one, then the image will most likely get badly mangled.
// The returned pix must be pixDestroyed after use. NULL may be returned
// if the image doesn't meet the trivial conditions that it uses to determine
// success.
static Pix* RemoveEnclosingCircle(Pix* pixs) {
  Pix* pixsi = pixInvert(NULL, pixs);
  Pix* pixc = pixCreateTemplate(pixs);
  pixSetOrClearBorder(pixc, 1, 1, 1, 1, PIX_SET);
  pixSeedfillBinary(pixc, pixc, pixsi, 4);
  pixInvert(pixc, pixc);
  pixDestroy(&pixsi);
  Pix* pixt = pixAnd(NULL, pixs, pixc);
  l_int32 max_count;
  pixCountConnComp(pixt, 8, &max_count);
  // The count has to go up before we start looking for the minimum.
  l_int32 min_count = MAX_INT32;
  Pix* pixout = NULL;
  for (int i = 1; i < kMaxCircleErosions; i++) {
    pixDestroy(&pixt);
    pixErodeBrick(pixc, pixc, 3, 3);
    pixt = pixAnd(NULL, pixs, pixc);
    l_int32 count;
    pixCountConnComp(pixt, 8, &count);
    if (i == 1 || count > max_count) {
      max_count = count;
      min_count = count;
    } else if (i > 1 && count < min_count) {
      min_count = count;
      pixDestroy(&pixout);
      pixout = pixCopy(NULL, pixt);  // Save the best.
    } else if (count >= min_count) {
      break;  // We have passed by the best.
    }
  }
  pixDestroy(&pixt);
  pixDestroy(&pixc);
  return pixout;
}
Ejemplo n.º 4
0
static PIX *
pixUninterlaceGIF(PIX  *pixs)
{
l_int32    w, h, d, wpl, j, k, srow, drow;
l_uint32  *datas, *datad, *lines, *lined;
PIX       *pixd;

    PROCNAME("pixUninterlaceGIF");

    if (!pixs)
        return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);

    pixGetDimensions(pixs, &w, &h, &d);
    wpl = pixGetWpl(pixs);
    pixd = pixCreateTemplate(pixs);
    datas = pixGetData(pixs);
    datad = pixGetData(pixd);
    for (k = 0, srow = 0; k < 4; k++) {
        for (drow = InterlacedOffset[k]; drow < h;
             drow += InterlacedJumps[k], srow++) {
            lines = datas + srow * wpl;
            lined = datad + drow * wpl;
            for (j = 0; j < w; j++)
                memcpy(lined, lines, 4 * wpl);
        }
    }

    return pixd;
}
Ejemplo n.º 5
0
main(int    argc,
     char **argv)
{
l_int32      i, index;
l_float32    cputime, epo;
char        *filein, *fileout;
PIX         *pixs, *pixd;
SEL         *sel;
SELA        *sela;
static char  mainName[] = "morphtest1";

    if (argc != 3)
	exit(ERROR_INT(" Syntax:  morphtest1 filein fileout", mainName, 1));

    filein = argv[1];
    fileout = argv[2];

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

    /* ------------------------   Timing  -------------------------------*/
#if 1
    selaFindSelByName(sela, "sel_9h", &index, &sel);
    selWriteStream(stderr, sel);
    pixd = pixCreateTemplate(pixs);

    startTimer();
    for (i = 0; i < NTIMES; i++)  {
	pixDilate(pixd, pixs, sel);
/*	if ((i % 10) == 0) fprintf(stderr, "%d iters\n", i); */
    }
    cputime = stopTimer();
        /* Get the elementary pixel operations/sec */
    epo = BASIC_OPS * SEL_SIZE * NTIMES * IMAGE_SIZE /(cputime * CPU_SPEED);

    fprintf(stderr, "Time: %7.3f sec\n", cputime);
    fprintf(stderr, "Speed: %7.3f epo/cycle\n", epo);
    pixWrite(fileout, pixd, IFF_PNG);
    pixDestroy(&pixd);
#endif

    /* ------------------  Example operation from repository --------------*/
#if 1
	/* Select a structuring element */
    selaFindSelByName(sela, "sel_50h", &index, &sel);
    selWriteStream(stderr, sel);

        /* Do these operations.  See below for other ops
	 * that can be substituted here. */
    pixd = pixOpen(NULL, pixs, sel);
    pixXor(pixd, pixd, pixs);
    pixWrite(fileout, pixd, IFF_PNG);
    pixDestroy(&pixd);
#endif

    pixDestroy(&pixs);
    exit(0);
}
Ejemplo n.º 6
0
/*!
 *  pixFHMTGen_1()
 *
 *      Input:  pixd (usual 3 choices: null, == pixs, != pixs)
 *              pixs (1 bpp)
 *              sel name
 *      Return: pixd
 *
 *  Notes:
 *      (1) This is a dwa implementation of the hit-miss transform
 *          on pixs by the sel.
 *      (2) The sel must be limited in size to not more than 31 pixels
 *          about the origin.  It must have at least one hit, and it
 *          can have any number of misses.
 *      (3) This handles all required setting of the border pixels
 *          before erosion and dilation.
 */
PIX *
pixFHMTGen_1(PIX   *pixd,
             PIX   *pixs,
             char  *selname)
{
l_int32    i, index, found, w, h, wpls, wpld;
l_uint32  *datad, *datas, *datat;
PIX       *pixt;

    PROCNAME("pixFHMTGen_1");

    if (!pixs)
        return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
    if (pixGetDepth(pixs) != 1)
        return (PIX *)ERROR_PTR("pixs must be 1 bpp", procName, pixd);

    found = FALSE;
    for (i = 0; i < NUM_SELS_GENERATED; i++) {
        if (strcmp(selname, SEL_NAMES[i]) == 0) {
            found = TRUE;
            index = i;
            break;
        }
    }
    if (found == FALSE)
        return (PIX *)ERROR_PTR("sel index not found", procName, pixd);

    if (!pixd) {
        if ((pixd = pixCreateTemplate(pixs)) == NULL)
            return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
    }
    else  /* for in-place or pre-allocated */
        pixResizeImageData(pixd, pixs);
    wpls = pixGetWpl(pixs);
    wpld = pixGetWpl(pixd);

        /*  The images must be surrounded with 32 additional border
         *  pixels, that we'll read from.  We fabricate a "proper"
         *  image as the subimage within the border, having the
         *  following parameters:  */
    w = pixGetWidth(pixs) - 64;
    h = pixGetHeight(pixs) - 64;
    datas = pixGetData(pixs) + 32 * wpls + 1;
    datad = pixGetData(pixd) + 32 * wpld + 1;

    if (pixd == pixs) {  /* need temp image if in-place */
        if ((pixt = pixCopy(NULL, pixs)) == NULL)
            return (PIX *)ERROR_PTR("pixt not made", procName, pixd);
        datat = pixGetData(pixt) + 32 * wpls + 1;
        fhmtgen_low_1(datad, w, h, wpld, datat, wpls, index);
        pixDestroy(&pixt);
    }
    else {  /* not in-place */
        fhmtgen_low_1(datad, w, h, wpld, datas, wpls, index);
    }

    return pixd;
}
Ejemplo n.º 7
0
/*!
 *  pixAdaptiveMeanFilter()
 *
 *      Input:  pixs   (8 bpp grayscale)
 *              wc, hc (half width/height of convolution kernel)
 *              varn   (value of overall noise variance)
 *      Return: pixd (8 bpp, filtered image)
 *
 *  Notes:
 *      (1) The filter reduces gaussian noise, achieving results similar
 *          to the arithmetic and geometric mean filters but avoiding the
 *          considerable image blurring effect introduced by those filters.
 *      (2) The filter can be expressed mathematically by:
 *            f'(x, y) = g(x, y) - varN / varL * [ g(x, y) - meanL ]
 *          where:
 *            -- g(x, y) is the pixel at the center of local region S of
 *               width (2 * wc + 1) and height (2 * wh + 1)
 *            -- varN and varL are the overall noise variance (given in input)
 *               and local variance of S, respectively
 *            -- meanL is the local mean of S
 *      (3) Typically @varn is estimated by studying the PDFs produced by
 *          the camera or equipment sensors.
 */
PIX *
pixAdaptiveMeanFilter(PIX       *pixs,
					  l_int32    wc,
					  l_int32    hc,
					  l_float32  varn)
{
	l_int32    i, j, w, h, d, wplt, wpld, wincr, hincr;
	l_uint32   val;
	l_uint32  *datat, *datad, *linet, *lined;
	l_float32  norm, meanl, varl, ratio;
	PIX       *pixt, *pixd;
	
    PROCNAME("pixAdaptiveMeanFilter");
    
    if (!pixs)
        return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
    pixGetDimensions(pixs, &w, &h, &d);
    if (d != 8)
        return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
    if (wc < 1 || hc < 1)
        return (PIX *)ERROR_PTR("wc and hc not >= 1", procName, NULL);
	
	/* Add wc to each side, and hc to top and bottom of the image,
	 * mirroring for accuracy and to avoid special-casing the boundary. */
    if ((pixt = pixAddMirroredBorder(pixs, wc, wc, hc, hc)) == NULL)
        return (PIX *)ERROR_PTR("pixt not made", procName, NULL);
	
	/* Place the filter center at (0, 0).  This is just a
	 * convenient location, because it allows us to perform
	 * the filtering over x:(0 ... w - 1) and y:(0 ... h - 1). */
	pixd = pixCreateTemplate(pixs);
	wplt = pixGetWpl(pixt);
    wpld = pixGetWpl(pixd);
	datat = pixGetData(pixt);
    datad = pixGetData(pixd);
	
    wincr = 2 * wc + 1;
    hincr = 2 * hc + 1;
	norm = 1.0 / (wincr * hincr);
	for (i = 0; i < h; i++) {
        linet = datat + (i + hc) * wplt;
		lined = datad + i * wpld;
        for (j = 0; j < w; j++) {
            /* Calculate mean intensity value */
			meanl = calculateLocalMeanLow(datat, wplt, wincr, hincr, i, j);
			/* Calculate local variance */
			varl = calculateLocalVarianceLow(datat, wplt, wincr, hincr, i, j, meanl);
			/* Account for special case in which varN is more than varL */
			ratio = (varn > varl) ? 1 : varn / varl;
			val = GET_DATA_BYTE(linet, j + wc);
			SET_DATA_BYTE(lined, j, (l_uint8) (val - ratio * (val - meanl)));
        } 
    }
	
	pixDestroy(&pixt);	
    return pixd;
}
Ejemplo n.º 8
0
/*!
 *  pixSelectByWidthHeightRatio()
 *
 *      Input:  pixs (1 bpp)
 *              thresh (threshold ratio of width/height)
 *              connectivity (4 or 8)
 *              type (L_SELECT_IF_LT, L_SELECT_IF_GT,
 *                    L_SELECT_IF_LTE, L_SELECT_IF_GTE)
 *              &changed (<optional return> 1 if changed; 0 if clone returned)
 *      Return: pixd, or null on error
 *
 *  Notes:
 *      (1) The args specify constraints on the width-to-height ratio
 *          for components that are kept.
 *      (2) If unchanged, returns a copy of pixs.  Otherwise,
 *          returns a new pix with the filtered components.
 *      (3) This filters components based on the width-to-height ratios.
 *      (4) Use L_SELECT_IF_LT or L_SELECT_IF_LTE to save components
 *          with less than the threshold ratio, and
 *          L_SELECT_IF_GT or L_SELECT_IF_GTE to remove them.
 */
PIX *
pixSelectByWidthHeightRatio(PIX       *pixs,
                            l_float32  thresh,
                            l_int32    connectivity,
                            l_int32    type,
                            l_int32   *pchanged)
{
l_int32  w, h, empty, changed, count;
BOXA    *boxa;
PIX     *pixd;
PIXA    *pixas, *pixad;

    PROCNAME("pixSelectByWidthHeightRatio");

    if (!pixs)
        return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
    if (connectivity != 4 && connectivity != 8)
        return (PIX *)ERROR_PTR("connectivity not 4 or 8", procName, NULL);
    if (type != L_SELECT_IF_LT && type != L_SELECT_IF_GT &&
        type != L_SELECT_IF_LTE && type != L_SELECT_IF_GTE)
        return (PIX *)ERROR_PTR("invalid type", procName, NULL);
    if (pchanged) *pchanged = FALSE;
    
        /* Check if any components exist */
    pixZero(pixs, &empty);
    if (empty)
        return pixCopy(NULL, pixs);

        /* Filter components */
    boxa = pixConnComp(pixs, &pixas, connectivity); 
    pixad = pixaSelectByWidthHeightRatio(pixas, thresh, type, &changed);
    boxaDestroy(&boxa);
    pixaDestroy(&pixas);

        /* Render the result */
    if (!changed) {
        pixaDestroy(&pixad);
        return pixCopy(NULL, pixs);
    }
    else {
        if (pchanged) *pchanged = TRUE;
        pixGetDimensions(pixs, &w, &h, NULL);
        count = pixaGetCount(pixad);
        if (count == 0)  /* return empty pix */
            pixd = pixCreateTemplate(pixs);
        else {
            pixd = pixaDisplay(pixad, w, h);
            pixCopyResolution(pixd, pixs);
            pixCopyColormap(pixd, pixs);
            pixCopyText(pixd, pixs);
            pixCopyInputFormat(pixd, pixs);
        }
        pixaDestroy(&pixad);
        return pixd;
    }
}
Ejemplo n.º 9
0
/*!
 *  bilateralApply()
 *
 *      Input:  bil
 *      Return: pixd
 */
static PIX *
bilateralApply(L_BILATERAL  *bil)
{
l_int32      i, j, k, ired, jred, w, h, wpls, wpld, ncomps, reduction;
l_int32      vals, vald, lowval, hival;
l_int32     *kindex;
l_float32    fract;
l_float32   *kfract;
l_uint32    *lines, *lined, *datas, *datad;
l_uint32  ***lineset = NULL;  /* for set of PBC */
PIX         *pixs, *pixd;
PIXA        *pixac;

    PROCNAME("bilateralApply");

    if (!bil)
        return (PIX *)ERROR_PTR("bil not defined", procName, NULL);
    pixs = bil->pixs;
    ncomps = bil->ncomps;
    kindex = bil->kindex;
    kfract = bil->kfract;
    reduction = bil->reduction;
    pixac = bil->pixac;
    lineset = bil->lineset;
    if (pixaGetCount(pixac) != ncomps)
        return (PIX *)ERROR_PTR("PBC images do not exist", procName, NULL);

    if ((pixd = pixCreateTemplate(pixs)) == NULL)
        return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
    datas = pixGetData(pixs);
    wpls = pixGetWpl(pixs);
    datad = pixGetData(pixd);
    wpld = pixGetWpl(pixd);
    pixGetDimensions(pixs, &w, &h, NULL);
    for (i = 0; i < h; i++) {
        lines = datas + i * wpls;
        lined = datad + i * wpld;
        ired = i / reduction;
        for (j = 0; j < w; j++) {
            jred = j / reduction;
            vals = GET_DATA_BYTE(lines, j);
            k = kindex[vals];
            lowval = GET_DATA_BYTE(lineset[k][ired], jred);
            hival = GET_DATA_BYTE(lineset[k + 1][ired], jred);
            fract = kfract[vals];
            vald = (l_int32)((1.0 - fract) * lowval + fract * hival + 0.5);
            SET_DATA_BYTE(lined, j, vald);
        }
    }

    return pixd;
}
Ejemplo n.º 10
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;
}
Ejemplo n.º 11
0
/*!
 *  pixCopy()
 *
 *      Input:  pixd (<optional>; can be null, or equal to pixs,
 *                    or different from pixs)
 *              pixs
 *      Return: pixd, or null on error
 *
 *  Notes:
 *      (1) There are three cases:
 *            (a) pixd == null  (makes a new pix; refcount = 1)
 *            (b) pixd == pixs  (no-op)
 *            (c) pixd != pixs  (data copy; no change in refcount)
 *          If the refcount of pixd > 1, case (c) will side-effect
 *          these handles.
 *      (2) The general pattern of use is:
 *             pixd = pixCopy(pixd, pixs);
 *          This will work for all three cases.
 *          For clarity when the case is known, you can use:
 *            (a) pixd = pixCopy(NULL, pixs);
 *            (c) pixCopy(pixd, pixs);
 *      (3) For case (c), we check if pixs and pixd are the same
 *          size (w,h,d).  If so, the data is copied directly.
 *          Otherwise, the data is reallocated to the correct size
 *          and the copy proceeds.  The refcount of pixd is unchanged.
 *      (4) This operation, like all others that may involve a pre-existing
 *          pixd, will side-effect any existing clones of pixd.
 */
PIX *
pixCopy(PIX  *pixd,   /* can be null */
        PIX  *pixs)
{
l_int32    bytes;
l_uint32  *datas, *datad;

    PROCNAME("pixCopy");

    if (!pixs)
        return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
    if (pixs == pixd)
        return pixd;

        /* Total bytes in image data */
    bytes = 4 * pixGetWpl(pixs) * pixGetHeight(pixs);

        /* If we're making a new pix ... */
    if (!pixd) {
        if ((pixd = pixCreateTemplate(pixs)) == NULL)
            return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
        datas = pixGetData(pixs);
        datad = pixGetData(pixd);
        memcpy((char *)datad, (char *)datas, bytes);
        return pixd;
    }

        /* Reallocate image data if sizes are different */
    if (pixResizeImageData(pixd, pixs) == 1)
        return (PIX *)ERROR_PTR("reallocation of data failed", procName, NULL);

        /* Copy non-image data fields */
    pixCopyColormap(pixd, pixs);
    pixCopyResolution(pixd, pixs);
    pixCopyInputFormat(pixd, pixs);
    pixCopyText(pixd, pixs);

        /* Copy image data */
    datas = pixGetData(pixs);
    datad = pixGetData(pixd);
    memcpy((char*)datad, (char*)datas, bytes);
    return pixd;
}
Ejemplo n.º 12
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;
}
Ejemplo n.º 13
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;
}
Ejemplo n.º 14
0
static PIX *
ReconstructByValue(L_REGPARAMS  *rp,
                   const char   *fname)
{
l_int32   i, n, rval, gval, bval;
PIX      *pixs, *pixm, *pixd;
PIXCMAP  *cmap;

    pixs = pixRead(fname);
    cmap = pixGetColormap(pixs);
    n = pixcmapGetCount(cmap);
    pixd = pixCreateTemplate(pixs);
    for (i = 0; i < n; i++) {
        pixm = pixGenerateMaskByValue(pixs, i, 1);
        pixcmapGetColor(cmap, i, &rval, &gval, &bval);
        pixSetMaskedCmap(pixd, pixm, 0, 0, rval, gval, bval);
        pixDestroy(&pixm);
    }

    regTestComparePix(rp, pixs, pixd);
    pixDestroy(&pixs);
    return pixd;
}
Ejemplo n.º 15
0
/*!
 *  pixRotateAMColorCorner()
 *
 *      Input:  pixs
 *              angle (radians; clockwise is positive)
 *              colorval (e.g., 0 to bring in BLACK, 0xffffff00 for WHITE)
 *      Return: pixd, or null on error
 *
 *  Notes:
 *      (1) Rotates the image about the UL corner.
 *      (2) A positive angle gives a clockwise rotation.
 *      (3) Specify the color to be brought in from outside the image.
 */
PIX *
pixRotateAMColorCorner(PIX       *pixs,
                       l_float32  angle,
                       l_uint32   fillval)
{
l_int32    w, h, wpls, wpld;
l_uint32  *datas, *datad;
PIX       *pix1, *pix2, *pixd;

    PROCNAME("pixRotateAMColorCorner");

    if (!pixs)
        return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
    if (pixGetDepth(pixs) != 32)
        return (PIX *)ERROR_PTR("pixs must be 32 bpp", procName, NULL);

    if (L_ABS(angle) < MIN_ANGLE_TO_ROTATE)
        return pixClone(pixs);

    pixGetDimensions(pixs, &w, &h, NULL);
    datas = pixGetData(pixs);
    wpls = pixGetWpl(pixs);
    pixd = pixCreateTemplate(pixs);
    datad = pixGetData(pixd);
    wpld = pixGetWpl(pixd);

    rotateAMColorCornerLow(datad, w, h, wpld, datas, wpls, angle, fillval);
    if (pixGetSpp(pixs) == 4) {
        pix1 = pixGetRGBComponent(pixs, L_ALPHA_CHANNEL);
        pix2 = pixRotateAMGrayCorner(pix1, angle, 255);  /* bring in opaque */
        pixSetRGBComponent(pixd, pix2, L_ALPHA_CHANNEL);
        pixDestroy(&pix1);
        pixDestroy(&pix2);
    }

    return pixd;
}
Ejemplo n.º 16
0
static PIX *
FakeReconstructByBand(L_REGPARAMS  *rp,
                      const char   *fname)
{
l_int32   i, jlow, jup, n, nbands;
l_int32   rval1, gval1, bval1, rval2, gval2, bval2, rval, gval, bval;
PIX      *pixs, *pixm, *pixd;
PIXCMAP  *cmaps, *cmapd;

    pixs = pixRead(fname);
    cmaps = pixGetColormap(pixs);
    n = pixcmapGetCount(cmaps);
    nbands = (n + 1) / 2;
    pixd = pixCreateTemplate(pixs);
    cmapd = pixcmapCreate(pixGetDepth(pixs));
    pixSetColormap(pixd, cmapd);
    for (i = 0; i < nbands; i++) {
        jlow = 2 * i;
        jup = L_MIN(jlow + 1, n - 1);
        pixm = pixGenerateMaskByBand(pixs, jlow, jup, 1, 1);

            /* Get average color in the band */
        pixcmapGetColor(cmaps, jlow, &rval1, &gval1, &bval1);
        pixcmapGetColor(cmaps, jup, &rval2, &gval2, &bval2);
        rval = (rval1 + rval2) / 2;
        gval = (gval1 + gval2) / 2;
        bval = (bval1 + bval2) / 2;

        pixcmapAddColor(cmapd, rval, gval, bval);
        pixSetMaskedCmap(pixd, pixm, 0, 0, rval, gval, bval);
        pixDestroy(&pixm);
    }

    pixDestroy(&pixs);
    return pixd;
}
Ejemplo n.º 17
0
main(int    argc,
     char **argv)
{
l_int32      x, y, i, j, k, w, h, w2, w4, w8, w16, w32, wpl, nerrors;
l_int32      count1, count2, count3, ret, val1, val2;
l_uint32     val32;
l_uint32    *data, *line, *line1, *line2, *data1, *data2;
void       **lines1, **linet1, **linet2;
PIX         *pixs, *pixt1, *pixt2;
static char  mainName[] = "lowaccess_reg";

    pixs = pixRead("feyn.tif");   /* width divisible by 16 */
    pixGetDimensions(pixs, &w, &h, NULL);
    data = pixGetData(pixs);
    wpl = pixGetWpl(pixs);
    lines1 = pixGetLinePtrs(pixs, NULL);

        /* Get timing for the 3 different methods */
    startTimer();
    for (k = 0; k < 10; k++) {
        count1 = 0;
        for (i = 0; i < h; i++) {
            for (j = 0; j < w; j++) {
                if (GET_DATA_BIT(lines1[i], j))
                    count1++;
            }
        }
    }
    fprintf(stderr, "Time with line ptrs     = %5.3f sec, count1 = %d\n",
            stopTimer(), count1);

    startTimer();
    for (k = 0; k < 10; k++) {
        count2 = 0;
        for (i = 0; i < h; i++) {
            line = data + i * wpl;
            for (j = 0; j < w; j++) {
               if (l_getDataBit(line, j))
                    count2++;
            }
        }
    }
    fprintf(stderr, "Time with l_get*        = %5.3f sec, count2 = %d\n",
            stopTimer(), count2);

    startTimer();
    for (k = 0; k < 10; k++) {
        count3 = 0;
        for (i = 0; i < h; i++) {
            for (j = 0; j < w; j++) {
                pixGetPixel(pixs, j, i, &val32);
                count3 += val32;
            }
        }
    }
    fprintf(stderr, "Time with pixGetPixel() = %5.3f sec, count3 = %d\n",
            stopTimer(), count3);

    pixt1 = pixCreateTemplate(pixs);
    data1 = pixGetData(pixt1);
    linet1 = pixGetLinePtrs(pixt1, NULL);
    pixt2 = pixCreateTemplate(pixs);
    data2 = pixGetData(pixt2);
    linet2 = pixGetLinePtrs(pixt2, NULL);

    nerrors = 0;

        /* Test different methods for 1 bpp */
    count1 = 0;
    for (i = 0; i < h; i++) {
        for (j = 0; j < w; j++) {
            val1 = GET_DATA_BIT(lines1[i], j);
            count1 += val1;
            if (val1) SET_DATA_BIT(linet1[i], j);
        }
    }
    count2 = 0;
    for (i = 0; i < h; i++) {
        line = data + i * wpl;
        line2 = data2 + i * wpl;
        for (j = 0; j < w; j++) {
            val2 = l_getDataBit(line, j);
            count2 += val2;
            if (val2) l_setDataBit(line2, j);
        }
    }
    ret = compareResults(pixs, pixt1, pixt2, count1, count2, "1 bpp");
    nerrors += ret;

        /* Test different methods for 2 bpp */
    count1 = 0;
    w2 = w / 2;
    for (i = 0; i < h; i++) {
        for (j = 0; j < w2; j++) {
            val1 = GET_DATA_DIBIT(lines1[i], j);
            count1 += val1;
            val1 += 0xbbbbbbbc;
            SET_DATA_DIBIT(linet1[i], j, val1);
        }
    }
    count2 = 0;
    for (i = 0; i < h; i++) {
        line = data + i * wpl;
        line2 = data2 + i * wpl;
        for (j = 0; j < w2; j++) {
            val2 = l_getDataDibit(line, j);
            count2 += val2;
            val2 += 0xbbbbbbbc;
            l_setDataDibit(line2, j, val2);
        }
    }
    ret = compareResults(pixs, pixt1, pixt2, count1, count2, "2 bpp");
    nerrors += ret;

        /* Test different methods for 4 bpp */
    count1 = 0;
    w4 = w / 4;
    for (i = 0; i < h; i++) {
        for (j = 0; j < w4; j++) {
            val1 = GET_DATA_QBIT(lines1[i], j);
            count1 += val1;
            val1 += 0xbbbbbbb0;
            SET_DATA_QBIT(linet1[i], j, val1);
        }
    }
    count2 = 0;
    for (i = 0; i < h; i++) {
        line = data + i * wpl;
        line2 = data2 + i * wpl;
        for (j = 0; j < w4; j++) {
            val2 = l_getDataQbit(line, j);
            count2 += val2;
            val2 += 0xbbbbbbb0;
            l_setDataQbit(line2, j, val2);
        }
    }
    ret = compareResults(pixs, pixt1, pixt2, count1, count2, "4 bpp");
    nerrors += ret;

        /* Test different methods for 8 bpp */
    count1 = 0;
    w8 = w / 8;
    for (i = 0; i < h; i++) {
        for (j = 0; j < w8; j++) {
            val1 = GET_DATA_BYTE(lines1[i], j);
            count1 += val1;
            val1 += 0xbbbbbb00;
            SET_DATA_BYTE(linet1[i], j, val1);
        }
    }
    count2 = 0;
    for (i = 0; i < h; i++) {
        line = data + i * wpl;
        line2 = data2 + i * wpl;
        for (j = 0; j < w8; j++) {
            val2 = l_getDataByte(line, j);
            count2 += val2;
            val2 += 0xbbbbbb00;
            l_setDataByte(line2, j, val2);
        }
    }
    ret = compareResults(pixs, pixt1, pixt2, count1, count2, "8 bpp");
    nerrors += ret;

        /* Test different methods for 16 bpp */
    count1 = 0;
    w16 = w / 16;
    for (i = 0; i < h; i++) {
        for (j = 0; j < w16; j++) {
            val1 = GET_DATA_TWO_BYTES(lines1[i], j);
            count1 += val1;
            val1 += 0xbbbb0000;
            SET_DATA_TWO_BYTES(linet1[i], j, val1);
        }
    }
    count2 = 0;
    for (i = 0; i < h; i++) {
        line = data + i * wpl;
        line2 = data2 + i * wpl;
        for (j = 0; j < w16; j++) {
            val2 = l_getDataTwoBytes(line, j);
            count2 += val2;
            val2 += 0xbbbb0000;
            l_setDataTwoBytes(line2, j, val2);
        }
    }
    ret = compareResults(pixs, pixt1, pixt2, count1, count2, "16 bpp");
    nerrors += ret;

        /* Test different methods for 32 bpp */
    count1 = 0;
    w32 = w / 32;
    for (i = 0; i < h; i++) {
        for (j = 0; j < w32; j++) {
            val1 = GET_DATA_FOUR_BYTES(lines1[i], j);
            count1 += val1 & 0xfff;
            SET_DATA_FOUR_BYTES(linet1[i], j, val1);
        }
    }
    count2 = 0;
    for (i = 0; i < h; i++) {
        line = data + i * wpl;
        line2 = data2 + i * wpl;
        for (j = 0; j < w32; j++) {
            val2 = l_getDataFourBytes(line, j);
            count2 += val2 & 0xfff;
            l_setDataFourBytes(line2, j, val2);
        }
    }
    ret = compareResults(pixs, pixt1, pixt2, count1, count2, "32 bpp");
    nerrors += ret;

    if (!nerrors)
        fprintf(stderr, "****  No errors  ****\n");
    else
        fprintf(stderr, "****  %d errors found!  ****\n", nerrors);

    pixDestroy(&pixs);
    pixDestroy(&pixt1);
    pixDestroy(&pixt2);
    lept_free(lines1);
    lept_free(linet1);
    lept_free(linet2);
    return 0;
}
Ejemplo n.º 18
0
int main(int    argc,
         char **argv)
{
l_int32      type, comptype, d1, d2, same, first, last;
l_float32    fract, diff, rmsdiff;
char        *filein1, *filein2, *fileout;
GPLOT       *gplot;
NUMA        *na1, *na2;
PIX         *pixs1, *pixs2, *pixd;
static char  mainName[] = "comparetest";

    if (argc != 5)
        return ERROR_INT(" Syntax:  comparetest filein1 filein2 type fileout",
                         mainName, 1);

    filein1 = argv[1];
    filein2 = argv[2];
    type = atoi(argv[3]);
    pixd = NULL;
    fileout = argv[4];
    l_pngSetReadStrip16To8(0);

    if ((pixs1 = pixRead(filein1)) == NULL)
        return ERROR_INT("pixs1 not made", mainName, 1);
    if ((pixs2 = pixRead(filein2)) == NULL)
        return ERROR_INT("pixs2 not made", mainName, 1);
    d1 = pixGetDepth(pixs1);
    d2 = pixGetDepth(pixs2);

    if (d1 == 1 && d2 == 1) {
        pixEqual(pixs1, pixs2, &same);
        if (same) {
            fprintf(stderr, "Images are identical\n");
            pixd = pixCreateTemplate(pixs1);  /* write empty pix for diff */
        }
        else {
            if (type == 0)
                comptype = L_COMPARE_XOR;
            else
                comptype = L_COMPARE_SUBTRACT;
            pixCompareBinary(pixs1, pixs2, comptype, &fract, &pixd);
            fprintf(stderr, "Fraction of different pixels: %10.6f\n", fract);
        }
        pixWrite(fileout, pixd, IFF_PNG);
    }
    else {
        if (type == 0)
            comptype = L_COMPARE_ABS_DIFF;
        else
            comptype = L_COMPARE_SUBTRACT;
        pixCompareGrayOrRGB(pixs1, pixs2, comptype, GPLOT_X11, &same, &diff,
                            &rmsdiff, &pixd);
        if (type == 0) {
            if (same)
                fprintf(stderr, "Images are identical\n");
            else {
                fprintf(stderr, "Images differ: <diff> = %10.6f\n", diff);
                fprintf(stderr, "               <rmsdiff> = %10.6f\n", rmsdiff);
            }
        }
        else {  /* subtraction */
            if (same)
                fprintf(stderr, "pixs2 strictly greater than pixs1\n");
            else {
                fprintf(stderr, "Images differ: <diff> = %10.6f\n", diff);
                fprintf(stderr, "               <rmsdiff> = %10.6f\n", rmsdiff);
            }
        }
        if (d1 != 16)
            pixWrite(fileout, pixd, IFF_JFIF_JPEG);
        else
            pixWrite(fileout, pixd, IFF_PNG);

        if (d1 != 16 && !same) {
            na1 = pixCompareRankDifference(pixs1, pixs2, 1);
            if (na1) {
                fprintf(stderr, "na1[150] = %20.10f\n", na1->array[150]);
                fprintf(stderr, "na1[200] = %20.10f\n", na1->array[200]);
                fprintf(stderr, "na1[250] = %20.10f\n", na1->array[250]);
                numaGetNonzeroRange(na1, 0.00005, &first, &last);
                fprintf(stderr, "Nonzero diff range: first = %d, last = %d\n",
                        first, last);
                na2 = numaClipToInterval(na1, first, last);
                gplot = gplotCreate("/tmp/junkrank", GPLOT_X11,
                                    "Pixel Rank Difference", "pixel val",
                                    "rank");
                gplotAddPlot(gplot, NULL, na2, GPLOT_LINES, "rank");
                gplotMakeOutput(gplot);
                gplotDestroy(&gplot);
                numaDestroy(&na1);
                numaDestroy(&na2);
            }
        }
    }

    pixDestroy(&pixs1);
    pixDestroy(&pixs2);
    pixDestroy(&pixd);
    return 0;
}
Ejemplo n.º 19
0
static void
TestDistance(PIXA         *pixa,
             PIX          *pixs,
             l_int32       conn,
             l_int32       depth,
             l_int32       bc,
             l_int32      *pcount,
             L_REGPARAMS  *rp)
{
PIX  *pixt1, *pixt2, *pixt3, *pixt4, *pixt5;

        /* Test the distance function and display */
    pixInvert(pixs, pixs);
    pixt1 = pixDistanceFunction(pixs, conn, depth, bc);
    regTestWritePixAndCheck(pixt1, IFF_PNG, pcount, rp);
    pixSaveTiled(pixt1, pixa, 1, 1, 20, 0);
    pixInvert(pixs, pixs);
    pixt2 = pixMaxDynamicRange(pixt1, L_LOG_SCALE);
    regTestWritePixAndCheck(pixt2, IFF_JFIF_JPEG, pcount, rp);
    pixSaveTiled(pixt2, pixa, 1, 0, 20, 0);
    pixDestroy(&pixt1);
    pixDestroy(&pixt2);

	/* Test the distance function and display with contour rendering */
    pixInvert(pixs, pixs);
    pixt1 = pixDistanceFunction(pixs, conn, depth, bc);
    regTestWritePixAndCheck(pixt1, IFF_PNG, pcount, rp);
    pixSaveTiled(pixt1, pixa, 1, 1, 20, 0);
    pixInvert(pixs, pixs);
    pixt2 = pixRenderContours(pixt1, 2, 4, 1);  /* binary output */
    regTestWritePixAndCheck(pixt2, IFF_PNG, pcount, rp);
    pixSaveTiled(pixt2, pixa, 1, 0, 20, 0);
    pixt3 = pixRenderContours(pixt1, 2, 4, depth);
    pixt4 = pixMaxDynamicRange(pixt3, L_LINEAR_SCALE);
    regTestWritePixAndCheck(pixt4, IFF_JFIF_JPEG, pcount, rp);
    pixSaveTiled(pixt4, pixa, 1, 0, 20, 0);
    pixt5 = pixMaxDynamicRange(pixt3, L_LOG_SCALE);
    regTestWritePixAndCheck(pixt5, IFF_JFIF_JPEG, pcount, rp);
    pixSaveTiled(pixt5, pixa, 1, 0, 20, 0);
    pixDestroy(&pixt1);
    pixDestroy(&pixt2);
    pixDestroy(&pixt3);
    pixDestroy(&pixt4);
    pixDestroy(&pixt5);

	/* Label all pixels in each c.c. with a color equal to the
         * max distance of any pixel within that c.c. from the bg.
         * Note that we've normalized so the dynamic range extends
         * to 255.  For the image here, each unit of distance is
         * represented by about 21 grayscale units.  The largest
         * distance is 12.  */
    if (depth == 8) {
        pixt1 = pixDistanceFunction(pixs, conn, depth, bc);
        pixt4 = pixMaxDynamicRange(pixt1, L_LOG_SCALE);
        regTestWritePixAndCheck(pixt4, IFF_JFIF_JPEG, pcount, rp);
        pixSaveTiled(pixt4, pixa, 1, 1, 20, 0);
        pixt2 = pixCreateTemplate(pixt1);
        pixSetMasked(pixt2, pixs, 255);
        regTestWritePixAndCheck(pixt2, IFF_JFIF_JPEG, pcount, rp);
        pixSaveTiled(pixt2, pixa, 1, 0, 20, 0);
        pixSeedfillGray(pixt1, pixt2, 4);
        pixt3 = pixMaxDynamicRange(pixt1, L_LINEAR_SCALE);
        regTestWritePixAndCheck(pixt3, IFF_JFIF_JPEG, pcount, rp);
        pixSaveTiled(pixt3, pixa, 1, 0, 20, 0);
        pixDestroy(&pixt1);
        pixDestroy(&pixt2);
        pixDestroy(&pixt3);
        pixDestroy(&pixt4);
    }

    return;
}
Ejemplo n.º 20
0
/*!
 * Note: this method is generally inferior to pixHasColorRegions(); it
 *       is retained as a reference only
 *
 * \brief   pixFindColorRegionsLight()
 *
 * \param[in]    pixs        32 bpp rgb
 * \param[in]    pixm        [optional] 1 bpp mask image
 * \param[in]    factor      subsample factor; integer >= 1
 * \param[in]    darkthresh  threshold to eliminate dark pixels (e.g., text)
 *                           from consideration; typ. 70; -1 for default.
 * \param[in]    lightthresh threshold for minimum gray value at 95% rank
 *                           near white; typ. 220; -1 for default
 * \param[in]    mindiff     minimum difference from 95% rank value, used
 *                           to count darker pixels; typ. 50; -1 for default
 * \param[in]    colordiff   minimum difference in (max - min) component to
 *                           qualify as a color pixel; typ. 40; -1 for default
 * \param[out]   pcolorfract fraction of 'color' pixels found
 * \param[out]   pcolormask1 [optional] mask over background color, if any
 * \param[out]   pcolormask2 [optional] filtered mask over background color
 * \param[out]   pixadb      [optional] debug intermediate results
 * \return  0 if OK, 1 on error
 *
 * <pre>
 * Notes:
 *      (1) This function tries to determine if there is a significant
 *          color or darker region on a scanned page image where part
 *          of the image is very close to "white".  It will also allow
 *          extraction of small regions of lightly colored pixels.
 *          If the background is darker (and reddish), use instead
 *          pixHasColorRegions2().
 *      (2) If %pixm exists, only pixels under fg are considered. Typically,
 *          the inverse of %pixm would have fg pixels over a photograph.
 *      (3) There are four thresholds.
 *          * %darkthresh: ignore pixels darker than this (typ. fg text).
 *            We make a 1 bpp mask of these pixels, and then dilate it to
 *            remove all vestiges of fg from their vicinity.
 *          * %lightthresh: let val95 be the pixel value for which 95%
 *            of the non-masked pixels have a lower value (darker) of
 *            their min component.  Then if val95 is darker than
 *            %lightthresh, the image is not considered to have a
 *            light bg, and this returns 0.0 for %colorfract.
 *          * %mindiff: we are interested in the fraction of pixels that
 *            have two conditions.  The first is that their min component
 *            is at least %mindiff darker than val95.
 *          * %colordiff: the second condition is that the max-min diff
 *            of the pixel components exceeds %colordiff.
 *      (4) This returns in %pcolorfract the fraction of pixels that have
 *          both a min component that is at least %mindiff below that at the
 *          95% rank value (where 100% rank is the lightest value), and
 *          a max-min diff that is at least %colordiff.  Without the
 *          %colordiff constraint, gray pixels of intermediate value
 *          could get flagged by this function.
 *      (5) No masks are returned unless light color pixels are found.
 *          If colorfract > 0.0 and %pcolormask1 is defined, this returns
 *          a 1 bpp mask with fg pixels over the color background.
 *          This mask may have some holes in it.
 *      (6) If colorfract > 0.0 and %pcolormask2 is defined, this returns
 *          a filtered version of colormask1.  The two changes are
 *            (a) small holes have been filled
 *            (b) components near the border have been removed.
 *          The latter insures that dark pixels near the edge of the
 *          image are not included.
 *      (7) To generate a boxa of rectangular regions from the overlap
 *          of components in the filtered mask:
 *                boxa1 = pixConnCompBB(colormask2, 8);
 *                boxa2 = boxaCombineOverlaps(boxa1);
 *          This is done here in debug mode.
 * </pre>
 */
static l_int32
pixFindColorRegionsLight(PIX        *pixs,
                         PIX        *pixm,
                         l_int32     factor,
                         l_int32     darkthresh,
                         l_int32     lightthresh,
                         l_int32     mindiff,
                         l_int32     colordiff,
                         l_float32  *pcolorfract,
                         PIX       **pcolormask1,
                         PIX       **pcolormask2,
                         PIXA       *pixadb)
{
l_int32    lightbg, w, h, count;
l_float32  ratio, val95, rank;
BOXA      *boxa1, *boxa2;
NUMA      *nah;
PIX       *pix1, *pix2, *pix3, *pix4, *pix5, *pixm1, *pixm2, *pixm3;

    PROCNAME("pixFindColorRegionsLight");

    if (pcolormask1) *pcolormask1 = NULL;
    if (pcolormask2) *pcolormask2 = NULL;
    if (!pcolorfract)
        return ERROR_INT("&colorfract not defined", procName, 1);
    *pcolorfract = 0.0;
    if (!pixs || pixGetDepth(pixs) != 32)
        return ERROR_INT("pixs not defined or not 32 bpp", procName, 1);
    if (factor < 1) factor = 1;
    if (darkthresh < 0) darkthresh = 70;  /* defaults */
    if (lightthresh < 0) lightthresh = 220;
    if (mindiff < 0) mindiff = 50;
    if (colordiff < 0) colordiff = 40;

        /* Check if pixm covers most of the image.  If so, just return. */
    pixGetDimensions(pixs, &w, &h, NULL);
    if (pixm) {
        pixCountPixels(pixm, &count, NULL);
        ratio = (l_float32)count / ((l_float32)(w) * h);
        if (ratio > 0.7) {
            if (pixadb) L_INFO("pixm has big fg: %f5.2\n", procName, ratio);
            return 0;
        }
    }

        /* Make a mask pixm1 over the dark pixels in the image:
         * convert to gray using the average of the components;
         * threshold using %darkthresh; do a small dilation;
         * combine with pixm. */
    pix1 = pixConvertRGBToGray(pixs, 0.33, 0.34, 0.33);
    if (pixadb) pixaAddPix(pixadb, pixs, L_COPY);
    if (pixadb) pixaAddPix(pixadb, pix1, L_COPY);
    pixm1 = pixThresholdToBinary(pix1, darkthresh);
    pixDilateBrick(pixm1, pixm1, 7, 7);
    if (pixadb) pixaAddPix(pixadb, pixm1, L_COPY);
    if (pixm) {
        pixOr(pixm1, pixm1, pixm);
        if (pixadb) pixaAddPix(pixadb, pixm1, L_COPY);
    }
    pixDestroy(&pix1);

        /* Convert to gray using the minimum component value and
         * find the gray value at rank 0.95, that represents the light
         * pixels in the image.  If it is too dark, quit. */
    pix1 = pixConvertRGBToGrayMinMax(pixs, L_SELECT_MIN);
    pix2 = pixInvert(NULL, pixm1);  /* pixels that are not dark */
    pixGetRankValueMasked(pix1, pix2, 0, 0, factor, 0.95, &val95, &nah);
    pixDestroy(&pix2);
    if (pixadb) {
        L_INFO("val at 0.95 rank = %5.1f\n", procName, val95);
        gplotSimple1(nah, GPLOT_PNG, "/tmp/lept/histo1", "gray histo");
        pix3 = pixRead("/tmp/lept/histo1.png");
        pix4 = pixExpandReplicate(pix3, 2);
        pixaAddPix(pixadb, pix4, L_INSERT);
        pixDestroy(&pix3);
    }
    lightbg = (l_int32)val95 >= lightthresh;
    numaDestroy(&nah);
    if (!lightbg) {
        pixDestroy(&pix1);
        pixDestroy(&pixm1);
        return 0;
    }

        /* Make mask pixm2 over pixels that are darker than val95 - mindiff. */
    pixm2 = pixThresholdToBinary(pix1, val95 - mindiff);
    if (pixadb) pixaAddPix(pixadb, pixm2, L_COPY);
    pixDestroy(&pix1);

        /* Make a mask pixm3 over pixels that have some color saturation,
         * with a (max - min) component difference >= %colordiff,
         * and combine using AND with pixm2. */
    pix2 = pixConvertRGBToGrayMinMax(pixs, L_CHOOSE_MAXDIFF);
    pixm3 = pixThresholdToBinary(pix2, colordiff);
    pixDestroy(&pix2);
    pixInvert(pixm3, pixm3);  /* need pixels above threshold */
    if (pixadb) pixaAddPix(pixadb, pixm3, L_COPY);
    pixAnd(pixm2, pixm2, pixm3);
    if (pixadb) pixaAddPix(pixadb, pixm2, L_COPY);
    pixDestroy(&pixm3);

        /* Subtract the dark pixels represented by pixm1.
         * pixm2 now holds all the color pixels of interest  */
    pixSubtract(pixm2, pixm2, pixm1);
    pixDestroy(&pixm1);
    if (pixadb) pixaAddPix(pixadb, pixm2, L_COPY);

        /* But we're not quite finished.  Remove pixels from any component
         * that is touching the image border.  False color pixels can
         * sometimes be found there if the image is much darker near
         * the border, due to oxidation or reduced illumination. */
    pixm3 = pixRemoveBorderConnComps(pixm2, 8);
    pixDestroy(&pixm2);
    if (pixadb) pixaAddPix(pixadb, pixm3, L_COPY);

        /* Get the fraction of light color pixels */
    pixCountPixels(pixm3, &count, NULL);
    *pcolorfract = (l_float32)count / (w * h);
    if (pixadb) {
        if (count == 0)
            L_INFO("no light color pixels found\n", procName);
        else
            L_INFO("fraction of light color pixels = %5.3f\n", procName,
                   *pcolorfract);
    }

        /* Debug: extract the color pixels from pixs */
    if (pixadb && count > 0) {
            /* Use pixm3 to extract the color pixels */
        pix3 = pixCreateTemplate(pixs);
        pixSetAll(pix3);
        pixCombineMasked(pix3, pixs, pixm3);
        pixaAddPix(pixadb, pix3, L_INSERT);

            /* Use additional filtering to extract the color pixels */
        pix3 = pixCloseSafeBrick(NULL, pixm3, 15, 15);
        pixaAddPix(pixadb, pix3, L_INSERT);
        pix5 = pixCreateTemplate(pixs);
        pixSetAll(pix5);
        pixCombineMasked(pix5, pixs, pix3);
        pixaAddPix(pixadb, pix5, L_INSERT);

            /* Get the combined bounding boxes of the mask components
             * in pix3, and extract those pixels from pixs. */
        boxa1 = pixConnCompBB(pix3, 8);
        boxa2 = boxaCombineOverlaps(boxa1, NULL);
        pix4 = pixCreateTemplate(pix3);
        pixMaskBoxa(pix4, pix4, boxa2, L_SET_PIXELS);
        pixaAddPix(pixadb, pix4, L_INSERT);
        pix5 = pixCreateTemplate(pixs);
        pixSetAll(pix5);
        pixCombineMasked(pix5, pixs, pix4);
        pixaAddPix(pixadb, pix5, L_INSERT);
        boxaDestroy(&boxa1);
        boxaDestroy(&boxa2);
        pixaAddPix(pixadb, pixs, L_COPY);
    }

        /* Optional colormask returns */
    if (pcolormask2 && count > 0)
        *pcolormask2 = pixCloseSafeBrick(NULL, pixm3, 15, 15);
    if (pcolormask1 && count > 0)
        *pcolormask1 = pixm3;
    else
        pixDestroy(&pixm3);
    return 0;
}
Ejemplo n.º 21
0
/*!
 *  pixErodeGray()
 *
 *      Input:  pixs
 *              hsize  (of Sel; must be odd; origin implicitly in center)
 *              vsize  (ditto)
 *      Return: pixd
 *
 *  Notes:
 *      (1) Sel is a brick with all elements being hits
 *      (2) If hsize = vsize = 1, just returns a copy.
 */
PIX *
pixErodeGray(PIX     *pixs,
             l_int32  hsize,
             l_int32  vsize)
{
l_uint8   *buffer, *minarray;
l_int32    w, h, wplb, wplt;
l_int32    leftpix, rightpix, toppix, bottompix, maxsize;
l_uint32  *datab, *datat;
PIX       *pixb, *pixt, *pixd;

    PROCNAME("pixErodeGray");

    if (!pixs)
        return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
    if (pixGetDepth(pixs) != 8)
        return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
    if (hsize < 1 || vsize < 1)
        return (PIX *)ERROR_PTR("hsize or vsize < 1", procName, NULL);
    if ((hsize & 1) == 0 ) {
        L_WARNING("horiz sel size must be odd; increasing by 1", procName);
        hsize++;
    }
    if ((vsize & 1) == 0 ) {
        L_WARNING("vert sel size must be odd; increasing by 1", procName);
        vsize++;
    }

    if (hsize == 1 && vsize == 1)
        return pixCopy(NULL, pixs);

    if (vsize == 1) {  /* horizontal sel */
        leftpix = (hsize + 1) / 2;
        rightpix = (3 * hsize + 1) / 2;
        toppix = 0;
        bottompix = 0;
    }
    else if (hsize == 1) {  /* vertical sel */
        leftpix = 0;
        rightpix = 0;
        toppix = (vsize + 1) / 2;
        bottompix = (3 * vsize + 1) / 2;
    }
    else {
        leftpix = (hsize + 1) / 2;
        rightpix = (3 * hsize + 1) / 2;
        toppix = (vsize + 1) / 2;
        bottompix = (3 * vsize + 1) / 2;
    }

    if ((pixb = pixAddBorderGeneral(pixs,
                leftpix, rightpix, toppix, bottompix, 255)) == NULL)
        return (PIX *)ERROR_PTR("pixb not made", procName, NULL);
    if ((pixt = pixCreateTemplate(pixb)) == NULL)
        return (PIX *)ERROR_PTR("pixt not made", procName, NULL);
    
    pixGetDimensions(pixt, &w, &h, NULL);
    datab = pixGetData(pixb);
    datat = pixGetData(pixt);
    wplb = pixGetWpl(pixb);
    wplt = pixGetWpl(pixt);

    if ((buffer = (l_uint8 *)CALLOC(L_MAX(w, h), sizeof(l_uint8))) == NULL)
        return (PIX *)ERROR_PTR("buffer not made", procName, NULL);
    maxsize = L_MAX(hsize, vsize);
    if ((minarray = (l_uint8 *)CALLOC(2 * maxsize, sizeof(l_uint8))) == NULL)
        return (PIX *)ERROR_PTR("minarray not made", procName, NULL);

    if (vsize == 1)
        erodeGrayLow(datat, w, h, wplt, datab, wplb, hsize, L_HORIZ,
                     buffer, minarray);
    else if (hsize == 1)
        erodeGrayLow(datat, w, h, wplt, datab, wplb, vsize, L_VERT,
                     buffer, minarray);
    else {
        erodeGrayLow(datat, w, h, wplt, datab, wplb, hsize, L_HORIZ,
                     buffer, minarray);
        pixSetOrClearBorder(pixt, leftpix, rightpix, toppix, bottompix,
                            PIX_SET);
        erodeGrayLow(datab, w, h, wplb, datat, wplt, vsize, L_VERT,
                     buffer, minarray);
        pixDestroy(&pixt);
        pixt = pixClone(pixb);
    }

    if ((pixd = pixRemoveBorderGeneral(pixt,
                leftpix, rightpix, toppix, bottompix)) == NULL)
        return (PIX *)ERROR_PTR("pixd not made", procName, NULL);

    FREE(buffer);
    FREE(minarray);
    pixDestroy(&pixb);
    pixDestroy(&pixt);
    return pixd;
}
Ejemplo n.º 22
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;
}
Ejemplo n.º 23
0
int main(int    argc,
         char **argv)
{
l_int32       i, j, k, w, h, w2, w4, w8, w16, w32, wpl;
l_int32       count1, count2, count3;
l_uint32      val32, val1, val2;
l_uint32     *data1, *line1, *data2, *line2;
void        **lines1, **linet1, **linet2;
PIX          *pixs, *pix1, *pix2;
L_REGPARAMS  *rp;

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

    pixs = pixRead("feyn-fract.tif");
    pixGetDimensions(pixs, &w, &h, NULL);
    data1 = pixGetData(pixs);
    wpl = pixGetWpl(pixs);
    lines1 = pixGetLinePtrs(pixs, NULL);

        /* Get timing for the 3 different methods */
    startTimer();
    for (k = 0; k < 10; k++) {
        count1 = 0;
        for (i = 0; i < h; i++) {
            for (j = 0; j < w; j++) {
                if (GET_DATA_BIT(lines1[i], j))
                    count1++;
            }
        }
    }
    fprintf(stderr, "Time with line ptrs     = %5.3f sec, count1 = %d\n",
            stopTimer(), count1);

    startTimer();
    for (k = 0; k < 10; k++) {
        count2 = 0;
        for (i = 0; i < h; i++) {
            line1 = data1 + i * wpl;
            for (j = 0; j < w; j++) {
               if (l_getDataBit(line1, j))
                    count2++;
            }
        }
    }
    fprintf(stderr, "Time with l_get*        = %5.3f sec, count2 = %d\n",
            stopTimer(), count2);

    startTimer();
    for (k = 0; k < 10; k++) {
        count3 = 0;
        for (i = 0; i < h; i++) {
            for (j = 0; j < w; j++) {
                pixGetPixel(pixs, j, i, &val32);
                count3 += val32;
            }
        }
    }
    fprintf(stderr, "Time with pixGetPixel() = %5.3f sec, count3 = %d\n",
            stopTimer(), count3);

    pix1 = pixCreateTemplate(pixs);
    linet1 = pixGetLinePtrs(pix1, NULL);
    pix2 = pixCreateTemplate(pixs);
    data2 = pixGetData(pix2);
    linet2 = pixGetLinePtrs(pix2, NULL);

        /* ------------------------------------------------- */
        /*           Test different methods for 1 bpp        */
        /* ------------------------------------------------- */
    count1 = 0;
    for (i = 0; i < h; i++) {
        for (j = 0; j < w; j++) {
            val1 = GET_DATA_BIT(lines1[i], j);
            count1 += val1;
            if (val1) SET_DATA_BIT(linet1[i], j);
        }
    }
    count2 = 0;
    for (i = 0; i < h; i++) {
        line1 = data1 + i * wpl;
        line2 = data2 + i * wpl;
        for (j = 0; j < w; j++) {
            val2 = l_getDataBit(line1, j);
            count2 += val2;
            if (val2) l_setDataBit(line2, j);
        }
    }
    CompareResults(pixs, pix1, pix2, count1, count2, "1 bpp", rp);

        /* ------------------------------------------------- */
        /*           Test different methods for 2 bpp        */
        /* ------------------------------------------------- */
    count1 = 0;
    w2 = w / 2;
    for (i = 0; i < h; i++) {
        for (j = 0; j < w2; j++) {
            val1 = GET_DATA_DIBIT(lines1[i], j);
            count1 += val1;
            val1 += 0xbbbbbbbc;
            SET_DATA_DIBIT(linet1[i], j, val1);
        }
    }
    count2 = 0;
    for (i = 0; i < h; i++) {
        line1 = data1 + i * wpl;
        line2 = data2 + i * wpl;
        for (j = 0; j < w2; j++) {
            val2 = l_getDataDibit(line1, j);
            count2 += val2;
            val2 += 0xbbbbbbbc;
            l_setDataDibit(line2, j, val2);
        }
    }
    CompareResults(pixs, pix1, pix2, count1, count2, "2 bpp", rp);

        /* ------------------------------------------------- */
        /*           Test different methods for 4 bpp        */
        /* ------------------------------------------------- */
    count1 = 0;
    w4 = w / 4;
    for (i = 0; i < h; i++) {
        for (j = 0; j < w4; j++) {
            val1 = GET_DATA_QBIT(lines1[i], j);
            count1 += val1;
            val1 += 0xbbbbbbb0;
            SET_DATA_QBIT(linet1[i], j, val1);
        }
    }
    count2 = 0;
    for (i = 0; i < h; i++) {
        line1 = data1 + i * wpl;
        line2 = data2 + i * wpl;
        for (j = 0; j < w4; j++) {
            val2 = l_getDataQbit(line1, j);
            count2 += val2;
            val2 += 0xbbbbbbb0;
            l_setDataQbit(line2, j, val2);
        }
    }
    CompareResults(pixs, pix1, pix2, count1, count2, "4 bpp", rp);

        /* ------------------------------------------------- */
        /*           Test different methods for 8 bpp        */
        /* ------------------------------------------------- */
    count1 = 0;
    w8 = w / 8;
    for (i = 0; i < h; i++) {
        for (j = 0; j < w8; j++) {
            val1 = GET_DATA_BYTE(lines1[i], j);
            count1 += val1;
            val1 += 0xbbbbbb00;
            SET_DATA_BYTE(linet1[i], j, val1);
        }
    }
    count2 = 0;
    for (i = 0; i < h; i++) {
        line1 = data1 + i * wpl;
        line2 = data2 + i * wpl;
        for (j = 0; j < w8; j++) {
            val2 = l_getDataByte(line1, j);
            count2 += val2;
            val2 += 0xbbbbbb00;
            l_setDataByte(line2, j, val2);
        }
    }
    CompareResults(pixs, pix1, pix2, count1, count2, "8 bpp", rp);

        /* ------------------------------------------------- */
        /*          Test different methods for 16 bpp        */
        /* ------------------------------------------------- */
    count1 = 0;
    w16 = w / 16;
    for (i = 0; i < h; i++) {
        for (j = 0; j < w16; j++) {
            val1 = GET_DATA_TWO_BYTES(lines1[i], j);
            count1 += val1;
            val1 += 0xbbbb0000;
            SET_DATA_TWO_BYTES(linet1[i], j, val1);
        }
    }
    count2 = 0;
    for (i = 0; i < h; i++) {
        line1 = data1 + i * wpl;
        line2 = data2 + i * wpl;
        for (j = 0; j < w16; j++) {
            val2 = l_getDataTwoBytes(line1, j);
            count2 += val2;
            val2 += 0xbbbb0000;
            l_setDataTwoBytes(line2, j, val2);
        }
    }
    CompareResults(pixs, pix1, pix2, count1, count2, "16 bpp", rp);

        /* ------------------------------------------------- */
        /*          Test different methods for 32 bpp        */
        /* ------------------------------------------------- */
    count1 = 0;
    w32 = w / 32;
    for (i = 0; i < h; i++) {
        for (j = 0; j < w32; j++) {
            val1 = GET_DATA_FOUR_BYTES(lines1[i], j);
            count1 += val1 & 0xfff;
            SET_DATA_FOUR_BYTES(linet1[i], j, val1);
        }
    }
    count2 = 0;
    for (i = 0; i < h; i++) {
        line1 = data1 + i * wpl;
        line2 = data2 + i * wpl;
        for (j = 0; j < w32; j++) {
            val2 = l_getDataFourBytes(line1, j);
            count2 += val2 & 0xfff;
            l_setDataFourBytes(line2, j, val2);
        }
    }
    CompareResults(pixs, pix1, pix2, count1, count2, "32 bpp", rp);
    pixDestroy(&pixs);
    pixDestroy(&pix1);
    pixDestroy(&pix2);
    lept_free(lines1);
    lept_free(linet1);
    lept_free(linet2);
    return regTestCleanup(rp);
}
Ejemplo n.º 24
0
    pixDestroy(&pixd);
#endif

    pixDestroy(&pixs);
    return 0;
}


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

/* -------------------------------------------------------------------- *
 *                 Repository for selecting various operations          *
 *                              that might be used                      *
 * -------------------------------------------------------------------- */
#if 0
    pixd = pixCreateTemplate(pixs);

    pixd = pixDilate(NULL, pixs, sel);
    pixd = pixErode(NULL, pixs, sel);
    pixd = pixOpen(NULL, pixs, sel);
    pixd = pixClose(NULL, pixs, sel);

    pixDilate(pixd, pixs, sel);
    pixErode(pixd, pixs, sel);
    pixOpen(pixd, pixs, sel);
    pixClose(pixd, pixs, sel);

    pixAnd(pixd, pixd, pixs);
    pixOr(pixd, pixd, pixs);
    pixXor(pixd, pixd, pixs);
    pixSubtract(pixd, pixd, pixs);
Ejemplo n.º 25
0
/*!
 *  pixThinGeneral()
 *
 *      Input:  pixs (1 bpp)
 *              type (L_THIN_FG, L_THIN_BG)
 *              sela (of Sels for parallel composite HMTs)
 *              maxiters (max number of iters allowed; use 0 to iterate
 *                        until completion)
 *      Return: pixd, or null on error
 *
 *  Notes:
 *      (1) See notes in pixThin().  That function chooses among
 *          the best of the Sels for thinning.
 *      (2) This is a general function that takes a Sela of HMTs
 *          that are used in parallel for thinning from each
 *          of four directions.  One iteration consists of four
 *          such parallel thins.
 */
PIX *
pixThinGeneral(PIX     *pixs,
               l_int32  type,
               SELA    *sela,
               l_int32  maxiters)
{
l_int32  i, j, r, nsels, same;
PIXA    *pixahmt;
PIX    **pixhmt;  /* array owned by pixahmt; do not destroy! */
PIX     *pixd, *pixt;
SEL     *sel, *selr;

    PROCNAME("pixThinGeneral");

    if (!pixs)
        return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
    if (pixGetDepth(pixs) != 1)
        return (PIX *)ERROR_PTR("pixs not 1 bpp", procName, NULL);
    if (type != L_THIN_FG && type != L_THIN_BG)
        return (PIX *)ERROR_PTR("invalid fg/bg type", procName, NULL);
    if (!sela)
        return (PIX *)ERROR_PTR("sela not defined", procName, NULL);
    if (maxiters == 0) maxiters = 10000;

        /* Set up array of temp pix to hold hmts */
    nsels = selaGetCount(sela);
    pixahmt = pixaCreate(nsels);
    for (i = 0; i < nsels; i++) {
        pixt = pixCreateTemplate(pixs);
        pixaAddPix(pixahmt, pixt, L_INSERT);
    }
    pixhmt = pixaGetPixArray(pixahmt);
    if (!pixhmt)
        return (PIX *)ERROR_PTR("pixhmt array not made", procName, NULL);

#if  DEBUG_SELS
    pixt = selaDisplayInPix(sela, 35, 3, 15, 4);
    pixDisplayWithTitle(pixt, 100, 100, "allsels", 1);
    pixDestroy(&pixt);
#endif  /* DEBUG_SELS */

        /* Set up initial image for fg thinning */
    if (type == L_THIN_FG)
        pixd = pixCopy(NULL, pixs);
    else  /* bg thinning */
        pixd = pixInvert(NULL, pixs);

        /* Thin the fg, with up to maxiters iterations */
    for (i = 0; i < maxiters; i++) {
        pixt = pixCopy(NULL, pixd);  /* test for completion */
        for (r = 0; r < 4; r++) {  /* over 90 degree rotations of Sels */
            for (j = 0; j < nsels; j++) {  /* over individual sels in sela */
                sel = selaGetSel(sela, j);  /* not a copy */
                selr = selRotateOrth(sel, r);
                pixHMT(pixhmt[j], pixd, selr);
                selDestroy(&selr);
                if (j > 0)
                    pixOr(pixhmt[0], pixhmt[0], pixhmt[j]);  /* accum result */
            }
            pixSubtract(pixd, pixd, pixhmt[0]);  /* remove result */
        }
        pixEqual(pixd, pixt, &same);
        pixDestroy(&pixt);
        if (same) {
            L_INFO("%d iterations to completion\n", procName, i);
            break;
        }
    }

    if (type == L_THIN_BG)
        pixInvert(pixd, pixd);

    pixaDestroy(&pixahmt);
    return pixd;
}
Ejemplo n.º 26
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;
}
Ejemplo n.º 27
0
l_int32 main(int argc,
             char **argv) {
    l_int32 i, n;
    l_float32 a, b, c, d, e;
    NUMA *nax, *nafit;
    PIX *pixs, *pixn, *pixg, *pixb, *pixt1, *pixt2;
    PIXA *pixa;
    PTA *pta, *ptad;
    PTAA *ptaa1, *ptaa2;

    pixs = pixRead("cat-35.jpg");
/*    pixs = pixRead("zanotti-78.jpg"); */

    /* Normalize for varying background and binarize */
    pixn = pixBackgroundNormSimple(pixs, NULL, NULL);
    pixg = pixConvertRGBToGray(pixn, 0.5, 0.3, 0.2);
    pixb = pixThresholdToBinary(pixg, 130);
    pixDestroy(&pixn);
    pixDestroy(&pixg);

    /* Get the textline centers */
    pixa = pixaCreate(6);
    ptaa1 = dewarpGetTextlineCenters(pixb, 0);
    pixt1 = pixCreateTemplate(pixs);
    pixSetAll(pixt1);
    pixt2 = pixDisplayPtaa(pixt1, ptaa1);
    pixWrite("/tmp/textline1.png", pixt2, IFF_PNG);
    pixDisplayWithTitle(pixt2, 0, 100, "textline centers 1", 1);
    pixaAddPix(pixa, pixt2, L_INSERT);
    pixDestroy(&pixt1);

    /* Remove short lines */
    fprintf(stderr, "Num all lines = %d\n", ptaaGetCount(ptaa1));
    ptaa2 = dewarpRemoveShortLines(pixb, ptaa1, 0.8, 0);
    pixt1 = pixCreateTemplate(pixs);
    pixSetAll(pixt1);
    pixt2 = pixDisplayPtaa(pixt1, ptaa2);
    pixWrite("/tmp/textline2.png", pixt2, IFF_PNG);
    pixDisplayWithTitle(pixt2, 300, 100, "textline centers 2", 1);
    pixaAddPix(pixa, pixt2, L_INSERT);
    pixDestroy(&pixt1);
    n = ptaaGetCount(ptaa2);
    fprintf(stderr, "Num long lines = %d\n", n);
    ptaaDestroy(&ptaa1);
    pixDestroy(&pixb);

    /* Long lines over input image */
    pixt1 = pixCopy(NULL, pixs);
    pixt2 = pixDisplayPtaa(pixt1, ptaa2);
    pixWrite("/tmp/textline3.png", pixt2, IFF_PNG);
    pixDisplayWithTitle(pixt2, 600, 100, "textline centers 3", 1);
    pixaAddPix(pixa, pixt2, L_INSERT);
    pixDestroy(&pixt1);

    /* Quadratic fit to curve */
    pixt1 = pixCopy(NULL, pixs);
    for (i = 0; i < n; i++) {
        pta = ptaaGetPta(ptaa2, i, L_CLONE);
        ptaGetArrays(pta, &nax, NULL);
        ptaGetQuadraticLSF(pta, &a, &b, &c, &nafit);
        fprintf(stderr, "Quadratic: a = %10.6f, b = %7.3f, c = %7.3f\n",
                a, b, c);
        ptad = ptaCreateFromNuma(nax, nafit);
        pixDisplayPta(pixt1, pixt1, ptad);
        ptaDestroy(&pta);
        ptaDestroy(&ptad);
        numaDestroy(&nax);
        numaDestroy(&nafit);
    }
    pixWrite("/tmp/textline4.png", pixt1, IFF_PNG);
    pixDisplayWithTitle(pixt1, 900, 100, "textline centers 4", 1);
    pixaAddPix(pixa, pixt1, L_INSERT);

    /* Cubic fit to curve */
    pixt1 = pixCopy(NULL, pixs);
    for (i = 0; i < n; i++) {
        pta = ptaaGetPta(ptaa2, i, L_CLONE);
        ptaGetArrays(pta, &nax, NULL);
        ptaGetCubicLSF(pta, &a, &b, &c, &d, &nafit);
        fprintf(stderr, "Cubic: a = %10.6f, b = %10.6f, c = %7.3f, d = %7.3f\n",
                a, b, c, d);
        ptad = ptaCreateFromNuma(nax, nafit);
        pixDisplayPta(pixt1, pixt1, ptad);
        ptaDestroy(&pta);
        ptaDestroy(&ptad);
        numaDestroy(&nax);
        numaDestroy(&nafit);
    }
    pixWrite("/tmp/textline5.png", pixt1, IFF_PNG);
    pixDisplayWithTitle(pixt1, 1200, 100, "textline centers 5", 1);
    pixaAddPix(pixa, pixt1, L_INSERT);

    /* Quartic fit to curve */
    pixt1 = pixCopy(NULL, pixs);
    for (i = 0; i < n; i++) {
        pta = ptaaGetPta(ptaa2, i, L_CLONE);
        ptaGetArrays(pta, &nax, NULL);
        ptaGetQuarticLSF(pta, &a, &b, &c, &d, &e, &nafit);
        fprintf(stderr,
                "Quartic: a = %7.3f, b = %7.3f, c = %9.5f, d = %7.3f, e = %7.3f\n",
                a, b, c, d, e);
        ptad = ptaCreateFromNuma(nax, nafit);
        pixDisplayPta(pixt1, pixt1, ptad);
        ptaDestroy(&pta);
        ptaDestroy(&ptad);
        numaDestroy(&nax);
        numaDestroy(&nafit);
    }
    pixWrite("/tmp/textline6.png", pixt1, IFF_PNG);
    pixDisplayWithTitle(pixt1, 1500, 100, "textline centers 6", 1);
    pixaAddPix(pixa, pixt1, L_INSERT);

    pixaConvertToPdf(pixa, 300, 0.5, L_JPEG_ENCODE, 75,
                     "LS fittings to textlines", "/tmp/dewarp_fittings.pdf");

    pixaDestroy(&pixa);
    pixDestroy(&pixs);
    ptaaDestroy(&ptaa2);
    return 0;
}
Ejemplo n.º 28
0
/*!
 *  pixApplyVerticalDisparity()
 *
 *      Input:  pixs (1, 8 or 32 bpp)
 *              fpix (vertical disparity array)
 *      Return: pixd (modified by fpix), or null on error
 *
 *  Notes:
 *      (1) This applies the vertical disparity array to the specified
 *          image.  For src pixels above the image, we use the pixels
 *          in the first raster line.
 */
PIX *
pixApplyVerticalDisparity(PIX   *pixs,
                          FPIX  *fpix)
{
l_int32     i, j, w, h, d, fw, fh, wpld, wplf, isrc, val8;
l_uint32   *datad, *lined;
l_float32  *dataf, *linef;
void      **lineptrs;
PIX        *pixd;

    PROCNAME("pixApplyVerticalDisparity");

    if (!pixs)
        return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
    if (!fpix)
        return (PIX *)ERROR_PTR("fpix not defined", procName, NULL);
    pixGetDimensions(pixs, &w, &h, &d);
    if (d != 1 && d != 8 && d != 32)
        return (PIX *)ERROR_PTR("pix not 1, 8 or 32 bpp", procName, NULL);
    fpixGetDimensions(fpix, &fw, &fh);
    if (fw < w || fh < h) {
        fprintf(stderr, "fw = %d, w = %d, fh = %d, h = %d\n", fw, w, fh, h);
        return (PIX *)ERROR_PTR("invalid fpix size", procName, NULL);
    }

    pixd = pixCreateTemplate(pixs);
    datad = pixGetData(pixd);
    dataf = fpixGetData(fpix);
    wpld = pixGetWpl(pixd);
    wplf = fpixGetWpl(fpix);
    if (d == 1) {
        lineptrs = pixGetLinePtrs(pixs, NULL);
        for (i = 0; i < h; i++) {
            lined = datad + i * wpld;
            linef = dataf + i * wplf;
            for (j = 0; j < w; j++) {
                isrc = (l_int32)(i - linef[j] + 0.5);
                if (isrc < 0) isrc = 0;
                if (isrc > h - 1) isrc = h - 1;
                if (GET_DATA_BIT(lineptrs[isrc], j))
                    SET_DATA_BIT(lined, j);
            }
        }
    }
    else if (d == 8) {
        lineptrs = pixGetLinePtrs(pixs, NULL);
        for (i = 0; i < h; i++) {
            lined = datad + i * wpld;
            linef = dataf + i * wplf;
            for (j = 0; j < w; j++) {
                isrc = (l_int32)(i - linef[j] + 0.5);
                if (isrc < 0) isrc = 0;
                if (isrc > h - 1) isrc = h - 1;
                val8 = GET_DATA_BYTE(lineptrs[isrc], j);
                SET_DATA_BYTE(lined, j, val8);
            }
        }
    }
    else {  /* d == 32 */
        lineptrs = pixGetLinePtrs(pixs, NULL);
        for (i = 0; i < h; i++) {
            lined = datad + i * wpld;
            linef = dataf + i * wplf;
            for (j = 0; j < w; j++) {
                isrc = (l_int32)(i - linef[j] + 0.5);
                if (isrc < 0) isrc = 0;
                if (isrc > h - 1) isrc = h - 1;
                lined[j] = GET_DATA_FOUR_BYTES(lineptrs[isrc], j);
            }
        }
    }

    FREE(lineptrs);
    return pixd;
}
Ejemplo n.º 29
0
int main(int    argc,
         char **argv)
{
l_uint8      *data;
l_int32       w, h, n1, n2, n, i, minval, maxval;
l_int32       ncolors, rval, gval, bval, equal;
l_int32      *rmap, *gmap, *bmap;
l_uint32      color;
l_float32     gamma;
BOX          *box;
FILE         *fp;
PIX          *pix1, *pix2, *pix3, *pix4, *pix5, *pix6;
PIX          *pixs, *pixb, *pixg, *pixc, *pixd;
PIX          *pixg2, *pixcs1, *pixcs2, *pixd1, *pixd2;
PIXA         *pixa, *pixa2, *pixa3;
PIXCMAP      *cmap, *cmap2;
RGBA_QUAD    *cta;
L_REGPARAMS  *rp;

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

    /* ------------------------ (1) ----------------------------*/
        /* Blend with a white background */
    pix1 = pixRead("books_logo.png");
    pixDisplayWithTitle(pix1, 100, 0, NULL, rp->display);
    pix2 = pixAlphaBlendUniform(pix1, 0xffffff00);
    pixDisplayWithTitle(pix2, 100, 150, NULL, rp->display);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 0 */
    regTestWritePixAndCheck(rp, pix2, IFF_PNG);  /* 1 */

        /* Generate an alpha layer based on the white background */
    pix3 = pixSetAlphaOverWhite(pix2);
    pixSetSpp(pix3, 3);
    pixWrite("/tmp/alphaops.2.png", pix3, IFF_PNG);  /* without alpha */
    regTestCheckFile(rp, "/tmp/alphaops.2.png");   /* 2 */
    pixSetSpp(pix3, 4);
    regTestWritePixAndCheck(rp, pix3, IFF_PNG);  /* 3, with alpha */
    pixDisplayWithTitle(pix3, 100, 300, NULL, rp->display);

        /* Render on a light yellow background */
    pix4 = pixAlphaBlendUniform(pix3, 0xffffe000);
    regTestWritePixAndCheck(rp, pix4, IFF_PNG);  /* 4 */
    pixDisplayWithTitle(pix4, 100, 450, NULL, rp->display);
    pixDestroy(&pix1);
    pixDestroy(&pix2);
    pixDestroy(&pix3);
    pixDestroy(&pix4);

    /* ------------------------ (2) ----------------------------*/
    lept_rmdir("alpha");
    lept_mkdir("alpha");
        /* Make the transparency (alpha) layer.
         * pixs is the mask.  We turn it into a transparency (alpha)
         * layer by converting to 8 bpp.  A small convolution fuzzes
         * the mask edges so that you don't see the pixels. */
    pixs = pixRead("feyn-fract.tif");
    pixGetDimensions(pixs, &w, &h, NULL);
    pixg = pixConvert1To8(NULL, pixs, 0, 255);
    pixg2 = pixBlockconvGray(pixg, NULL, 1, 1);
    regTestWritePixAndCheck(rp, pixg2, IFF_JFIF_JPEG);  /* 5 */
    pixDisplayWithTitle(pixg2, 0, 0, "alpha", rp->display);

        /* Make the viewable image.
         * pixc is the image that we see where the alpha layer is
         * opaque -- i.e., greater than 0.  Scale it to the same
         * size as the mask.  To visualize what this will look like
         * when displayed over a black background, create the black
         * background image, pixb, and do the blending with pixcs1
         * explicitly using the alpha layer pixg2. */
    pixc = pixRead("tetons.jpg");
    pixcs1 = pixScaleToSize(pixc, w, h);
    regTestWritePixAndCheck(rp, pixcs1, IFF_JFIF_JPEG);  /* 6 */
    pixDisplayWithTitle(pixcs1, 300, 0, "viewable", rp->display);
    pixb = pixCreateTemplate(pixcs1);  /* black */
    pixd1 = pixBlendWithGrayMask(pixb, pixcs1, pixg2, 0, 0);
    regTestWritePixAndCheck(rp, pixd1, IFF_JFIF_JPEG);  /* 7 */
    pixDisplayWithTitle(pixd1, 600, 0, "alpha-blended 1", rp->display);

        /* Embed the alpha layer pixg2 into the color image pixc.
         * Write it out as is.  Then clean pixcs1 (to 0) under the fully
         * transparent part of the alpha layer, and write that result
         * out as well. */
    pixSetRGBComponent(pixcs1, pixg2, L_ALPHA_CHANNEL);
    pixWrite("/tmp/alpha/pixcs1.png", pixcs1, IFF_PNG);
    pixcs2 = pixSetUnderTransparency(pixcs1, 0, 0);
    pixWrite("/tmp/alpha/pixcs2.png", pixcs2, IFF_PNG);

        /* What will this look like over a black background?
         * Do the blending explicitly and display.  It should
         * look identical to the blended result pixd1 before cleaning. */
    pixd2 = pixBlendWithGrayMask(pixb, pixcs2, pixg2, 0, 0);
    regTestWritePixAndCheck(rp, pixd2, IFF_JFIF_JPEG);  /* 8 */
    pixDisplayWithTitle(pixd2, 0, 400, "alpha blended 2", rp->display);

        /* Read the two images back, ignoring the transparency layer.
         * The uncleaned image will come back identical to pixcs1.
         * However, the cleaned image will be black wherever
         * the alpha layer was fully transparent.  It will
         * look the same when viewed through the alpha layer,
         * but have much better compression. */
    pix1 = pixRead("/tmp/alpha/pixcs1.png");  /* just pixcs1 */
    pix2 = pixRead("/tmp/alpha/pixcs2.png");  /* cleaned under transparent */
    n1 = nbytesInFile("/tmp/alpha/pixcs1.png");
    n2 = nbytesInFile("/tmp/alpha/pixcs2.png");
    fprintf(stderr, " Original: %d bytes\n Cleaned: %d bytes\n", n1, n2);
    regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG);  /* 9 */
    regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG);  /* 10 */
    pixDisplayWithTitle(pix1, 300, 400, "without alpha", rp->display);
    pixDisplayWithTitle(pix2, 600, 400, "cleaned under transparent",
                        rp->display);

    pixa = pixaCreate(0);
    pixSaveTiled(pixg2, pixa, 1.0, 1, 20, 32);
    pixSaveTiled(pixcs1, pixa, 1.0, 1, 20, 0);
    pixSaveTiled(pix1, pixa, 1.0, 0, 20, 0);
    pixSaveTiled(pixd1, pixa, 1.0, 1, 20, 0);
    pixSaveTiled(pixd2, pixa, 1.0, 0, 20, 0);
    pixSaveTiled(pix2, pixa, 1.0, 1, 20, 0);
    pixd = pixaDisplay(pixa, 0, 0);
    regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG);  /* 11 */
    pixDisplayWithTitle(pixd, 200, 200, "composite", rp->display);
    pixWrite("/tmp/alpha/alpha.png", pixd, IFF_JFIF_JPEG);
    pixDestroy(&pixd);
    pixaDestroy(&pixa);
    pixDestroy(&pixs);
    pixDestroy(&pixb);
    pixDestroy(&pixg);
    pixDestroy(&pixg2);
    pixDestroy(&pixc);
    pixDestroy(&pixcs1);
    pixDestroy(&pixcs2);
    pixDestroy(&pixd);
    pixDestroy(&pixd1);
    pixDestroy(&pixd2);
    pixDestroy(&pix1);
    pixDestroy(&pix2);

    /* ------------------------ (3) ----------------------------*/
    color = 0xffffa000;
    gamma = 1.0;
    minval = 0;
    maxval = 200;
    box = boxCreate(0, 85, 600, 100);
    pixa = pixaCreate(6);
    pix1 = pixRead("blend-green1.jpg");
    pixaAddPix(pixa, pix1, L_INSERT);
    pix1 = pixRead("blend-green2.png");
    pixaAddPix(pixa, pix1, L_INSERT);
    pix1 = pixRead("blend-green3.png");
    pixaAddPix(pixa, pix1, L_INSERT);
    pix1 = pixRead("blend-orange.jpg");
    pixaAddPix(pixa, pix1, L_INSERT);
    pix1 = pixRead("blend-yellow.jpg");
    pixaAddPix(pixa, pix1, L_INSERT);
    pix1 = pixRead("blend-red.png");
    pixaAddPix(pixa, pix1, L_INSERT);
    n = pixaGetCount(pixa);
    pixa2 = pixaCreate(n);
    pixa3 = pixaCreate(n);
    for (i = 0; i < n; i++) {
        pix1 = pixaGetPix(pixa, i, L_CLONE);
        pix2 = DoBlendTest(pix1, box, color, gamma, minval, maxval, 1);
        regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG);  /* 12, 14, ... 22 */
        pixDisplayWithTitle(pix2, 150 * i, 0, NULL, rp->display);
        pixaAddPix(pixa2, pix2, L_INSERT);
        pix2 = DoBlendTest(pix1, box, color, gamma, minval, maxval, 2);
        regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG);  /* 13, 15, ... 23 */
        pixDisplayWithTitle(pix2, 150 * i, 200, NULL, rp->display);
        pixaAddPix(pixa3, pix2, L_INSERT);
        pixDestroy(&pix1);
    }
    if (rp->display) {
        pixaConvertToPdf(pixa2, 0, 0.75, L_FLATE_ENCODE, 0, "blend 1 test",
                         "/tmp/alpha/blending1.pdf");
        pixaConvertToPdf(pixa3, 0, 0.75, L_FLATE_ENCODE, 0, "blend 2 test",
                         "/tmp/alpha/blending2.pdf");
    }
    pixaDestroy(&pixa);
    pixaDestroy(&pixa2);
    pixaDestroy(&pixa3);
    boxDestroy(&box);

    /* ------------------------ (4) ----------------------------*/
        /* Use one image as the alpha component for a second image */
    pix1 = pixRead("test24.jpg");
    pix2 = pixRead("marge.jpg");
    pix3 = pixScale(pix2, 1.9, 2.2);
    pix4 = pixConvertTo8(pix3, 0);
    pixSetRGBComponent(pix1, pix4, L_ALPHA_CHANNEL);
    regTestWritePixAndCheck(rp, pix1, IFF_PNG);  /* 24 */
    pixDisplayWithTitle(pix1, 600, 0, NULL, rp->display);

        /* Set the alpha value in a colormap to bval */
    pix5 = pixOctreeColorQuant(pix1, 128, 0);
    cmap = pixGetColormap(pix5);
    pixcmapToArrays(cmap, &rmap, &gmap, &bmap, NULL);
    n = pixcmapGetCount(cmap);
    for (i = 0; i < n; i++) {
        pixcmapGetColor(cmap, i, &rval, &gval, &bval);
        cta = (RGBA_QUAD *)cmap->array;
        cta[i].alpha = bval;
    }

        /* Test binary serialization/deserialization of colormap with alpha */
    pixcmapSerializeToMemory(cmap, 4, &ncolors, &data);
    cmap2 = pixcmapDeserializeFromMemory(data, 4, ncolors);
    CmapEqual(cmap, cmap2, &equal);
    regTestCompareValues(rp, TRUE, equal, 0.0);  /* 25 */
    pixcmapDestroy(&cmap2);
    lept_free(data);

        /* Test ascii serialization/deserialization of colormap with alpha */
    fp = fopenWriteStream("/tmp/alpha/cmap.4", "w");
    pixcmapWriteStream(fp, cmap);
    fclose(fp);
    fp = fopenReadStream("/tmp/alpha/cmap.4");
    cmap2 = pixcmapReadStream(fp);
    fclose(fp);
    CmapEqual(cmap, cmap2, &equal);
    regTestCompareValues(rp, TRUE, equal, 0.0);  /* 26 */
    pixcmapDestroy(&cmap2);

        /* Test r/w for cmapped pix with non-opaque alpha */
    pixDisplayWithTitle(pix5, 900, 0, NULL, rp->display);
    regTestWritePixAndCheck(rp, pix5, IFF_PNG);  /* 27 */
    pixWrite("/tmp/alpha/fourcomp.png", pix5, IFF_PNG);
    pix6 = pixRead("/tmp/alpha/fourcomp.png");
    regTestComparePix(rp, pix5, pix6);  /* 28 */
    pixDestroy(&pix1);
    pixDestroy(&pix2);
    pixDestroy(&pix3);
    pixDestroy(&pix4);
    pixDestroy(&pix5);
    pixDestroy(&pix6);
    lept_free(rmap);
    lept_free(gmap);
    lept_free(bmap);
    return regTestCleanup(rp);
}
Ejemplo n.º 30
0
/*!
 *  pixGetTextlineCenters()
 *
 *      Input:  pixs (1 bpp)
 *              debugflag (1 for debug output)
 *      Return: ptaa (of center values of textlines)
 *
 *  Notes:
 *      (1) This in general does not have a point for each value
 *          of x, because there will be gaps between words.
 *          It doesn't matter because we will fit a quadratic to the
 *          points that we do have.
 */
PTAA *
pixGetTextlineCenters(PIX     *pixs,
                      l_int32  debugflag)
{
l_int32   i, w, h, bx, by, nsegs;
BOXA     *boxa;
PIX      *pix, *pixt1, *pixt2, *pixt3;
PIXA     *pixa1, *pixa2;
PTA      *pta;
PTAA     *ptaa;

    PROCNAME("pixGetTextlineCenters");

    if (!pixs || pixGetDepth(pixs) != 1)
        return (PTAA *)ERROR_PTR("pixs undefined or not 1 bpp", procName, NULL);
    pixGetDimensions(pixs, &w, &h, NULL);

        /* Filter to solidify the text lines within the x-height region,
         * and to remove most of the ascenders and descenders. */
    pixt1 = pixMorphSequence(pixs, "c15.1 + o15.1 + c30.1", 0);
    pixDisplayWithTitle(pixt1, 0, 800, "pix1", debugflag);

        /* Get the 8-connected components ... */
    boxa = pixConnComp(pixt1, &pixa1, 8);
    pixDestroy(&pixt1);
    boxaDestroy(&boxa);
    if (pixaGetCount(pixa1) == 0) {
        pixaDestroy(&pixa1);
        return NULL;
    }

        /* ... and remove the short and thin c.c */
    pixa2 = pixaSelectBySize(pixa1, 100, 4, L_SELECT_IF_BOTH,
                                   L_SELECT_IF_GT, 0);
    if ((nsegs = pixaGetCount(pixa2)) == 0) {
        pixaDestroy(&pixa2);
        return NULL;
    }
    if (debugflag) {
        pixt2 = pixaDisplay(pixa2, w, h);
        pixDisplayWithTitle(pixt2, 800, 800, "pix2", 1);
        pixDestroy(&pixt2);
    }

        /* For each c.c., get the weighted center of each vertical column.
         * The result is a set of points going approximately through
         * the center of the x-height part of the text line.  */
    ptaa = ptaaCreate(nsegs);
    for (i = 0; i < nsegs; i++) {
        pixaGetBoxGeometry(pixa2, i, &bx, &by, NULL, NULL);
        pix = pixaGetPix(pixa2, i, L_CLONE);
        pta = pixGetMeanVerticals(pix, bx, by);
        ptaaAddPta(ptaa, pta, L_INSERT);
        pixDestroy(&pix);
    }
    if (debugflag) {
        pixt3 = pixCreateTemplate(pixt2);
        pix = pixDisplayPtaa(pixt3, ptaa);
        pixDisplayWithTitle(pix, 0, 1400, "pix3", 1);
        pixDestroy(&pix);
        pixDestroy(&pixt3);
    }

    pixaDestroy(&pixa1);
    pixaDestroy(&pixa2);
    return ptaa;
}