Exemplo n.º 1
0
/*!
 *  boxRotateOrth()
 *
 *      Input:  box
 *              w, h (of image in which the box is embedded)
 *              rotation (0 = noop, 1 = 90 deg, 2 = 180 deg, 3 = 270 deg;
 *                        all rotations are clockwise)
 *      Return: boxd, or null on error
 *
 *  Notes:
 *      (1) Rotate the image with the embedded box by the specified amount.
 *      (2) After rotation, the rotated box is always measured with
 *          respect to the UL corner of the image.
 */
BOX *
boxRotateOrth(BOX     *box,
              l_int32  w,
              l_int32  h,
              l_int32  rotation)
{
l_int32  bx, by, bw, bh, xdist, ydist;

    PROCNAME("boxRotateOrth");

    if (!box)
        return (BOX *)ERROR_PTR("box not defined", procName, NULL);
    if (rotation == 0)
        return boxCopy(box);
    if (rotation < 1 || rotation > 3)
        return (BOX *)ERROR_PTR("rotation not in {0,1,2,3}", procName, NULL);

    boxGetGeometry(box, &bx, &by, &bw, &bh);
    if (bw <= 0 || bh <= 0)  /* invalid */
        return boxCreate(0, 0, 0, 0);
    ydist = h - by - bh;  /* below box */
    xdist = w - bx - bw;  /* to right of box */
    if (rotation == 1)   /* 90 deg cw */
        return boxCreate(ydist, bx, bh, bw);
    else if (rotation == 2)  /* 180 deg cw */
        return boxCreate(xdist, ydist, bw, bh);
    else  /*  rotation == 3, 270 deg cw */
        return boxCreate(by, xdist, bh, bw);
}
Exemplo n.º 2
0
main(int    argc,
     char **argv)
{
char       *filein, *fileout;
l_int32     d;
BOX        *box1, *box2, *box3, *box4;
BOXA       *boxa;
PIX        *pixs, *pixt1, *pixt2, *pixt3;
PTA        *pta;
static char     mainName[] = "graphicstest";

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

    filein = argv[1];
    fileout = argv[2];
    if ((pixs = pixRead(filein)) == NULL)
        exit(ERROR_INT(" Syntax: pixs not made", mainName, 1));
    d = pixGetDepth(pixs);
    if (d <= 8)
        pixt1 = pixConvertTo32(pixs);
    else
        pixt1 = pixClone(pixs);

        /* Paint on RGB */
    pixRenderLineArb(pixt1, 450, 20, 850, 320, 5, 200, 50, 125);
    pixRenderLineArb(pixt1, 30, 40, 440, 40, 5, 100, 200, 25);
    pixRenderLineBlend(pixt1, 30, 60, 440, 70, 5, 115, 200, 120, 0.3);
    pixRenderLineBlend(pixt1, 30, 600, 440, 670, 9, 215, 115, 30, 0.5);
    pixRenderLineBlend(pixt1, 130, 700, 540, 770, 9, 255, 255, 250, 0.4);
    pixRenderLineBlend(pixt1, 130, 800, 540, 870, 9, 0, 0, 0, 0.4);
    box1 = boxCreate(70, 80, 300, 245);
    box2 = boxCreate(470, 180, 150, 205);
    box3 = boxCreate(520, 220, 160, 220);
    box4 = boxCreate(570, 260, 160, 220);
    boxa = boxaCreate(3);
    boxaAddBox(boxa, box2, L_INSERT);
    boxaAddBox(boxa, box3, L_INSERT);
    boxaAddBox(boxa, box4, L_INSERT);
    pixRenderBoxArb(pixt1, box1, 3, 200, 200, 25);
    pixRenderBoxaBlend(pixt1, boxa, 17, 200, 200, 25, 0.4, 1);
    pta = ptaCreate(5);
    ptaAddPt(pta, 250, 300);
    ptaAddPt(pta, 350, 450);
    ptaAddPt(pta, 400, 600);
    ptaAddPt(pta, 212, 512);
    ptaAddPt(pta, 180, 375);
    pixRenderPolylineBlend(pixt1, pta, 17, 25, 200, 200, 0.5, 1, 1);
    pixWrite(fileout, pixt1, IFF_JFIF_JPEG);
    pixDisplay(pixt1, 200, 200);

    pixDestroy(&pixs);
    pixDestroy(&pixt1);
    boxDestroy(&box1);
    boxaDestroy(&boxa);
    ptaDestroy(&pta);
    pixDestroy(&pixs);
    return 0;
}
Exemplo n.º 3
0
/*!
 *  boxOverlapRegion()
 *
 *      Input:  box1, box2 (two boxes)
 *      Return: box (of overlap region between input boxes),
 *              or null if no overlap or on error
 */
BOX *
boxOverlapRegion(BOX  *box1,
                 BOX  *box2)
{
l_int32  x, y, w, h, left1, left2, top1, top2, right1, right2, bot1, bot2;

    PROCNAME("boxOverlapRegion");

    if (!box1)
        return (BOX *)ERROR_PTR("box1 not defined", procName, NULL);
    if (!box2)
        return (BOX *)ERROR_PTR("box2 not defined", procName, NULL);

    left1 = box1->x;
    left2 = box2->x;
    top1 = box1->y;
    top2 = box2->y;
    right1 = box1->x + box1->w - 1;
    bot1 = box1->y + box1->h - 1;
    right2 = box2->x + box2->w - 1;
    bot2 = box2->y + box2->h - 1;
    if ((bot2 < top1) || (bot1 < top2) ||
         (right1 < left2) || (right2 < left1))
        return NULL;

    x = (left1 > left2) ? left1 : left2;
    y = (top1 > top2) ? top1 : top2;
    w = L_MIN(right1 - x + 1, right2 - x + 1);
    h = L_MIN(bot1 - y + 1, bot2 - y + 1);
    return boxCreate(x, y, w, h);
}
Exemplo n.º 4
0
void EquationDetectBase::RenderSpecialText(Pix* pix,
                                           BLOBNBOX* blob) {
  ASSERT_HOST(pix != nullptr && pixGetDepth(pix) == 32 && blob != nullptr);
  const TBOX& tbox = blob->bounding_box();
  int height = pixGetHeight(pix);
  const int box_width = 5;

  // Coordinate translation: tesseract use left bottom as the original, while
  // leptonica uses left top as the original.
  Box *box = boxCreate(tbox.left(), height - tbox.top(),
                         tbox.width(), tbox.height());
  switch (blob->special_text_type()) {
    case BSTT_MATH:  // Red box.
      pixRenderBoxArb(pix, box, box_width, 255, 0, 0);
      break;
    case BSTT_DIGIT:  // cyan box.
      pixRenderBoxArb(pix, box, box_width, 0, 255, 255);
      break;
    case BSTT_ITALIC:  // Green box.
      pixRenderBoxArb(pix, box, box_width, 0, 255, 0);
      break;
    case BSTT_UNCLEAR:  // blue box.
      pixRenderBoxArb(pix, box, box_width, 0, 255, 0);
      break;
    case BSTT_NONE:
    default:
      // yellow box.
      pixRenderBoxArb(pix, box, box_width, 255, 255, 0);
      break;
  }
  boxDestroy(&box);
}
Exemplo n.º 5
0
int ignore_alpha_at_edge(png_byte *alpha, unsigned char* indata, int w, int h, PIX *in, PIX **out)
{
	int i, j, index, start_y, end_y;
	int find_end_x = CCX_FALSE;
	BOX* cropWindow;
	for (j = 1; j < w-1; j++)
	{
		for (i = 0; i < h; i++)
		{
			index = indata[i * w + (j)];
			if(alpha[index] != 0)
			{
				if(find_end_x == CCX_FALSE)
				{
					start_y = j;
					find_end_x = CCX_TRUE;
				}
				else
				{
					end_y = j;
				}
			}
		}
	}
	cropWindow = boxCreate(start_y, 0, (w - (start_y + ( w - end_y) )), h - 1);
	*out = pixClipRectangle(in, cropWindow, NULL);
	boxDestroy(&cropWindow);

	return 0;
}
Exemplo n.º 6
0
/*!
 *  boxaSplitEvenOdd()
 *
 *      Input:  boxa
 *              &boxae, &boxao (<return> save even and odd boxes in their
 *                 separate boxa, setting the other type to invalid boxes.)
 *      Return: 0 if OK, 1 on error
 *
 *  Notes:
 *      (1) For example, boxae copies of the even boxes, in their original
 *          location, that are in boxa.  Invalid boxes are placed
 *          in the odd array locations.
 *
 */
l_int32
boxaSplitEvenOdd(BOXA   *boxa,
                 BOXA  **pboxae,
                 BOXA  **pboxao)
{
l_int32  i, n;
BOX     *box, *boxt;

    PROCNAME("boxaSplitEvenOdd");

    if (!pboxae || !pboxao)
        return ERROR_INT("&boxae and &boxao not defined", procName, 1);
    *pboxae = *pboxao = NULL;
    if (!boxa)
        return ERROR_INT("boxa not defined", procName, 1);

    n = boxaGetCount(boxa);
    *pboxae = boxaCreate(n);
    *pboxao = boxaCreate(n);
    for (i = 0; i < n; i++) {
        box = boxaGetBox(boxa, i, L_COPY);
        boxt = boxCreate(0, 0, 0, 0);  /* empty placeholder */
        if ((i & 1) == 0) {
            boxaAddBox(*pboxae, box, L_INSERT);
            boxaAddBox(*pboxao, boxt, L_INSERT);
        }
        else {
            boxaAddBox(*pboxae, boxt, L_INSERT);
            boxaAddBox(*pboxao, box, L_INSERT);
        }
    }
    return 0;
}
Exemplo n.º 7
0
void DoJp2kTest1(L_REGPARAMS  *rp,
                 const char   *fname)
{
char  buf[256];
l_int32  w, h;
BOX     *box;
PIX     *pix1, *pix2, *pix3;

    pix1 = pixRead(fname);
    pixGetDimensions(pix1, &w, &h, NULL);
    box = boxCreate(w / 4, h / 4, w / 2, h / 2);
    snprintf(buf, sizeof(buf), "/tmp/lept/jp2kio.%03d.jp2", rp->index + 1);
    pixWrite(buf, pix1, IFF_JP2);
    regTestCheckFile(rp, buf);
    pix2 = pixRead(buf);
    pixDisplayWithTitle(pix2, 0, 100, "1", rp->display);
    pixDestroy(&pix1);
    pixDestroy(&pix2);

    pix1 = pixReadJp2k(buf, 1, box, 0, 0);  /* just read the box region */
    snprintf(buf, sizeof(buf), "/tmp/lept/jp2kio.%03d.jp2", rp->index + 1);
    pixWriteJp2k(buf, pix1, 38, 0, 0, 0);
    regTestCheckFile(rp, buf);
    pix2 = pixRead(buf);
    regTestWritePixAndCheck(rp, pix2, IFF_JP2);
    pixDisplayWithTitle(pix2, 500, 100, "2", rp->display);
    pix3 = pixReadJp2k(buf, 2, NULL, 0, 0);  /* read image at 2x reduction */
    regTestWritePixAndCheck(rp, pix3, IFF_JP2);
    pixDisplayWithTitle(pix3, 1000, 100, "3", rp->display);
    pixDestroy(&pix1);
    pixDestroy(&pix2);
    pixDestroy(&pix3);
    return;
}
Exemplo n.º 8
0
/*!
 * \brief   boxaaQuadtreeRegions()
 *
 * \param[in]    w, h     size of pix that is being quadtree-ized
 * \param[in]    nlevels  number of levels in quadtree
 * \return  baa for quadtree regions at each level, or NULL on error
 *
 * <pre>
 * Notes:
 *      (1) The returned boxaa has %nlevels of boxa, each containing
 *          the set of rectangles at that level.  The rectangle at
 *          level 0 is the entire region; at level 1 the region is
 *          divided into 4 rectangles, and at level n there are n^4
 *          rectangles.
 *      (2) At each level, the rectangles in the boxa are in "raster"
 *          order, with LR (fast scan) and TB (slow scan).
 * </pre>
 */
BOXAA *
boxaaQuadtreeRegions(l_int32  w,
                     l_int32  h,
                     l_int32  nlevels)
{
l_int32   i, j, k, maxpts, nside, nbox, bw, bh;
l_int32  *xstart, *xend, *ystart, *yend;
BOX      *box;
BOXA     *boxa;
BOXAA    *baa;

    PROCNAME("boxaaQuadtreeRegions");

    if (nlevels < 1)
        return (BOXAA *)ERROR_PTR("nlevels must be >= 1", procName, NULL);
    if (w < (1 << (nlevels - 1)))
        return (BOXAA *)ERROR_PTR("w doesn't support nlevels", procName, NULL);
    if (h < (1 << (nlevels - 1)))
        return (BOXAA *)ERROR_PTR("h doesn't support nlevels", procName, NULL);

    baa = boxaaCreate(nlevels);
    maxpts = 1 << (nlevels - 1);
    xstart = (l_int32 *)LEPT_CALLOC(maxpts, sizeof(l_int32));
    xend = (l_int32 *)LEPT_CALLOC(maxpts, sizeof(l_int32));
    ystart = (l_int32 *)LEPT_CALLOC(maxpts, sizeof(l_int32));
    yend = (l_int32 *)LEPT_CALLOC(maxpts, sizeof(l_int32));
    for (k = 0; k < nlevels; k++) {
        nside = 1 << k;  /* number of boxes in each direction */
        for (i = 0; i < nside; i++) {
            xstart[i] = (w - 1) * i / nside;
            if (i > 0) xstart[i]++;
            xend[i] = (w - 1) * (i + 1) / nside;
            ystart[i] = (h - 1) * i / nside;
            if (i > 0) ystart[i]++;
            yend[i] = (h - 1) * (i + 1) / nside;
#if DEBUG_BOXES
            fprintf(stderr,
               "k = %d, xs[%d] = %d, xe[%d] = %d, ys[%d] = %d, ye[%d] = %d\n",
                    k, i, xstart[i], i, xend[i], i, ystart[i], i, yend[i]);
#endif  /* DEBUG_BOXES */
        }
        nbox = 1 << (2 * k);
        boxa = boxaCreate(nbox);
        for (i = 0; i < nside; i++) {
            bh = yend[i] - ystart[i] + 1;
            for (j = 0; j < nside; j++) {
                bw = xend[j] - xstart[j] + 1;
                box = boxCreate(xstart[j], ystart[i], bw, bh);
                boxaAddBox(boxa, box, L_INSERT);
            }
        }
        boxaaAddBoxa(baa, boxa, L_INSERT);
    }

    LEPT_FREE(xstart);
    LEPT_FREE(xend);
    LEPT_FREE(ystart);
    LEPT_FREE(yend);
    return baa;
}
Exemplo n.º 9
0
/**
 * Returns an image of the current object at the given level in greyscale
 * if available in the input. To guarantee a binary image use BinaryImage.
 * NOTE that in order to give the best possible image, the bounds are
 * expanded slightly over the binary connected component, by the supplied
 * padding, so the top-left position of the returned image is returned
 * in (left,top). These will most likely not match the coordinates
 * returned by BoundingBox.
 * Use pixDestroy to delete the image after use.
 */
Pix* PageIterator::GetImage(PageIteratorLevel level, int padding,
                            int* left, int* top) const {
  int right, bottom;
  if (!BoundingBox(level, left, top, &right, &bottom))
    return NULL;
  Pix* pix = tesseract_->pix_grey();
  if (pix == NULL)
    return GetBinaryImage(level);

  // Expand the box.
  *left = MAX(*left - padding, 0);
  *top = MAX(*top - padding, 0);
  right = MIN(right + padding, rect_width_);
  bottom = MIN(bottom + padding, rect_height_);
  Box* box = boxCreate(*left, *top, right - *left, bottom - *top);
  Pix* grey_pix = pixClipRectangle(pix, box, NULL);
  boxDestroy(&box);
  if (level == RIL_BLOCK) {
    Pix* mask = it_->block()->block->render_mask();
    Pix* expanded_mask = pixCreate(right - *left, bottom - *top, 1);
    pixRasterop(expanded_mask, padding, padding,
                pixGetWidth(mask), pixGetHeight(mask),
                PIX_SRC, mask, 0, 0);
    pixDestroy(&mask);
    pixDilateBrick(expanded_mask, expanded_mask, 2*padding + 1, 2*padding + 1);
    pixInvert(expanded_mask, expanded_mask);
    pixSetMasked(grey_pix, expanded_mask, 255);
    pixDestroy(&expanded_mask);
  }
  return grey_pix;
}
Exemplo n.º 10
0
/*!
 *  boxAdjustSides()
 *
 *      Input:  boxd  (<optional>; this can be null, equal to boxs,
 *                     or different from boxs)
 *              boxs  (starting box; to have sides adjusted)
 *              delleft, delright, deltop, delbot (changes in location of
 *                                                 each side)
 *      Return: boxd, or null on error or if the computed boxd has
 *              width or height <= 0.
 *
 *  Notes:
 *      (1) Set boxd == NULL to get new box; boxd == boxs for in-place;
 *          or otherwise to resize existing boxd.
 *      (2) For usage, suggest one of these:
 *               boxd = boxAdjustSides(NULL, boxs, ...);   // new
 *               boxAdjustSides(boxs, boxs, ...);          // in-place
 *               boxAdjustSides(boxd, boxs, ...);          // other
 *      (1) New box dimensions are cropped at left and top to x >= 0 and y >= 0.
 *      (2) For example, to expand in-place by 20 pixels on each side, use
 *             boxAdjustSides(box, box, -20, 20, -20, 20);
 */
BOX *
boxAdjustSides(BOX     *boxd,
               BOX     *boxs,
               l_int32  delleft,
               l_int32  delright,
               l_int32  deltop,
               l_int32  delbot)
{
l_int32  x, y, w, h, xl, xr, yt, yb, wnew, hnew;

    PROCNAME("boxAdjustSides");

    if (!boxs)
        return (BOX *)ERROR_PTR("boxs not defined", procName, NULL);

    boxGetGeometry(boxs, &x, &y, &w, &h);
    xl = L_MAX(0, x + delleft);
    yt = L_MAX(0, y + deltop);
    xr = x + w + delright;  /* one pixel beyond right edge */
    yb = y + h + delbot;    /* one pixel below bottom edge */
    wnew = xr - xl;
    hnew = yb - yt;
    
    if (wnew < 1 || hnew < 1)
        return (BOX *)ERROR_PTR("boxd has 0 area", procName, NULL);

    if (!boxd)
        return boxCreate(xl, yt, wnew, hnew);
    else {
        boxSetGeometry(boxd, xl, yt, wnew, hnew);
        return boxd;
    }
}
/*!
 *  boxaReadStream()
 *
 *      Input:  stream
 *      Return: boxa, or null on error
 */
BOXA *
boxaReadStream(FILE  *fp)
{
l_int32  n, i, x, y, w, h, version;
l_int32  ignore;
BOX     *box;
BOXA    *boxa;

    PROCNAME("boxaReadStream");

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

    if (fscanf(fp, "\nBoxa Version %d\n", &version) != 1)
        return (BOXA *)ERROR_PTR("not a boxa file", procName, NULL);
    if (version != BOXA_VERSION_NUMBER)
        return (BOXA *)ERROR_PTR("invalid boxa version", procName, NULL);
    if (fscanf(fp, "Number of boxes = %d\n", &n) != 1)
        return (BOXA *)ERROR_PTR("not a boxa file", procName, NULL);

    if ((boxa = boxaCreate(n)) == NULL)
        return (BOXA *)ERROR_PTR("boxa not made", procName, NULL);

    for (i = 0; i < n; i++) {
        if (fscanf(fp, "  Box[%d]: x = %d, y = %d, w = %d, h = %d\n",
                &ignore, &x, &y, &w, &h) != 5)
            return (BOXA *)ERROR_PTR("box descr not valid", procName, NULL);
        if ((box = boxCreate(x, y, w, h)) == NULL)
            return (BOXA *)ERROR_PTR("box not made", procName, NULL);
        boxaAddBox(boxa, box, L_INSERT);
    }

    return boxa;
}
Exemplo n.º 12
0
Box *CubeSearchObject::CharBox(int start_pt, int end_pt) {
  if (!init_ && !Init())
    return NULL;
  if (!IsValidSegmentRange(start_pt, end_pt)) {
    fprintf(stderr, "Cube ERROR (CubeSearchObject::CharBox): invalid "
            "segment range (%d, %d)\n", start_pt, end_pt);
    return NULL;
  }

  // create a char samp object from the specified range of segments,
  // extract its dimensions into a leptonica box, and delete it
  bool left_most;
  bool right_most;
  CharSamp *samp = CharSamp::FromConComps(segments_, start_pt + 1,
                                          end_pt - start_pt, NULL,
                                          &left_most, &right_most, hgt_);
  if (!samp)
    return NULL;
  if (kUseCroppedChars) {
    CharSamp *cropped_samp = samp->Crop();
    delete samp;
    if (!cropped_samp) {
      return NULL;
    }
    samp = cropped_samp;
  }
  Box *box = boxCreate(samp->Left(), samp->Top(),
                       samp->Width(), samp->Height());
  delete samp;
  return box;
}
Exemplo n.º 13
0
/*!
 *  boxaGetRankSize()
 *
 *      Input:  boxa
 *              fract (use 0.0 for smallest, 1.0 for largest)
 *      Return: box (with rank values for x, y, w, h), or null on error
 *              or if the boxa is empty (has no valid boxes)
 *
 *  Notes:
 *      (1) This function does not assume that all boxes in the boxa are valid
 *      (2) The four box parameters are sorted independently.
 *          For rank order, the width and height are sorted in increasing
 *          order.  But what does it mean to sort x and y in "rank order"?
 *          If the boxes are of comparable size and somewhat
 *          aligned (e.g., from multiple images), it makes some sense
 *          to give a "rank order" for x and y by sorting them in
 *          decreasing order.  But in general, the interpretation of a rank
 *          order on x and y is highly application dependent.  In summary:
 *             - x and y are sorted in decreasing order
 *             - w and h are sorted in increasing order
 */
BOX *
boxaGetRankSize(BOXA      *boxa,
                l_float32  fract)
{
l_float32  xval, yval, wval, hval;
NUMA      *nax, *nay, *naw, *nah;
BOX       *box;

    PROCNAME("boxaGetRankSize");

    if (!boxa)
        return (BOX *)ERROR_PTR("boxa not defined", procName, NULL);
    if (fract < 0.0 || fract > 1.0)
        return (BOX *)ERROR_PTR("fract not in [0.0 ... 1.0]", procName, NULL);
    if (boxaGetValidCount(boxa) == 0)
        return (BOX *)ERROR_PTR("no valid boxes in boxa", procName, NULL);

    boxaExtractAsNuma(boxa, &nax, &nay, &naw, &nah, 0);  /* valid boxes only */

    numaGetRankValue(nax, 1.0 - fract, NULL, 1, &xval);
    numaGetRankValue(nay, 1.0 - fract, NULL, 1, &yval);
    numaGetRankValue(naw, fract, NULL, 1, &wval);
    numaGetRankValue(nah, fract, NULL, 1, &hval);
    box = boxCreate((l_int32)xval, (l_int32)yval, (l_int32)wval, (l_int32)hval);

    numaDestroy(&nax);
    numaDestroy(&nay);
    numaDestroy(&naw);
    numaDestroy(&nah);
    return box;
}
Exemplo n.º 14
0
BOX* M_Utils::getColPartImCoords(ColPartition* cp, PIX* im) {
  BLOBNBOX_CLIST* blobnboxes = cp->boxes();
  CLIST_ITERATOR bbox_it(blobnboxes);
  l_int32 height = (l_int32)im->h;
  l_int32 left = INT_MAX;
  l_int32 right = INT_MIN;
  l_int32 top = INT_MAX;
  l_int32 bottom = INT_MIN;
  l_int32 l, r, t, b;
  for (bbox_it.mark_cycle_pt (); !bbox_it.cycled_list();
      bbox_it.forward()) {
    BLOBNBOX* blobnbox = (BLOBNBOX*)bbox_it.data();
    l = (l_int32)blobnbox->cblob()->bounding_box().left();
    r = (l_int32)blobnbox->cblob()->bounding_box().right();
    t = height - (l_int32)blobnbox->cblob()->bounding_box().top();
    b = height - (l_int32)blobnbox->cblob()->bounding_box().bottom();
    if(l < left)
      left = l;
    if(r > right)
      right = r;
    if(t < top)
      top = t;
    if(b > bottom)
      bottom = b;
  }
  BOX* boxret = boxCreate(left, top, right-left, bottom-top);
  return boxret;
}
Exemplo n.º 15
0
jint Java_com_googlecode_leptonica_android_Box_nativeCreate(JNIEnv *env, jclass clazz, jint x, jint y, jint w,
                                                jint h) {
  LOGV(__FUNCTION__);

  BOX *box = boxCreate((l_int32) x, (l_int32) y, (l_int32) w, (l_int32) h);

  return (jint) box;
}
Exemplo n.º 16
0
BOX* M_Utils::getBlobBoxImCoords(BLOBNBOX* blob, PIX* im) {
  l_int32 height = (l_int32)im->h;
  l_int32 left = (l_int32)blob->cblob()->bounding_box().left();
  l_int32 top = height - (l_int32)blob->cblob()->bounding_box().top();
  l_int32 right = (l_int32)blob->cblob()->bounding_box().right();
  l_int32 bottom = height - (l_int32)blob->cblob()->bounding_box().bottom();
  return boxCreate(left, top, right-left, bottom-top);
}
Exemplo n.º 17
0
BOX* M_Utils::tessTBoxToImBox(TBOX* box, PIX* im) {
  l_int32 height = (l_int32)im->h;
  l_int32 left = (l_int32)box->left();
  l_int32 top = height - (l_int32)box->top();
  l_int32 right = (l_int32)box->right();
  l_int32 bottom = height - (l_int32)box->bottom();
  return boxCreate(left, top, right-left, bottom-top);
}
Exemplo n.º 18
0
/*!
 *  boxTransform()
 *
 *      Input:  box
 *              shiftx, shifty
 *              scalex, scaley
 *      Return: boxd, or null on error
 *
 *  Notes:
 *      (1) This is a very simple function that first shifts, then scales.
 *      (2) If the box is invalid, a new invalid box is returned.
 */
BOX *
boxTransform(BOX       *box,
             l_int32    shiftx,
             l_int32    shifty,
             l_float32  scalex,
             l_float32  scaley)
{
    PROCNAME("boxTransform");

    if (!box)
        return (BOX *)ERROR_PTR("box not defined", procName, NULL);
    if (box->w <= 0 || box->h <= 0)
        return boxCreate(0, 0, 0, 0);
    else
        return boxCreate((l_int32)(scalex * (box->x + shiftx) + 0.5),
                         (l_int32)(scaley * (box->y + shifty) + 0.5),
                         (l_int32)(L_MAX(1.0, scalex * box->w + 0.5)),
                         (l_int32)(L_MAX(1.0, scaley * box->h + 0.5)));
}
Exemplo n.º 19
0
 native_data_t() {
   currentTextBox = boxCreate(0, 0, 0, 0);
   lastProgress = 0;
   pix = NULL;
   data = NULL;
   debug = false;
   cachedEnv = NULL;
   cachedObject = NULL;
   cancel_ocr = false;
 }
Exemplo n.º 20
0
// Finds horizontal line objects in the given pix.
// Uses the given resolution to determine size thresholds instead of any
// that may be present in the pix.
// The output vectors are owned by the list and Frozen (cannot refit) by
// having no boxes, as there is no need to refit or merge separator lines.
void LineFinder::FindHorizontalLines(int resolution,  Pix* pix,
                                     TabVector_LIST* vectors) {
#ifdef HAVE_LIBLEPT
  Pix* line_pix;
  Boxa* boxes = GetHLineBoxes(resolution, pix, &line_pix);
  C_BLOB_LIST line_cblobs;
  int width = pixGetWidth(pix);
  int height = pixGetHeight(pix);
  ConvertBoxaToBlobs(height, width, &boxes, &line_cblobs);
  // Make the BLOBNBOXes from the C_BLOBs.
  BLOBNBOX_LIST line_bblobs;
  C_BLOB_IT blob_it(&line_cblobs);
  BLOBNBOX_IT bbox_it(&line_bblobs);
  for (blob_it.mark_cycle_pt(); !blob_it.cycled_list(); blob_it.forward()) {
    C_BLOB* cblob = blob_it.data();
    BLOBNBOX* bblob = new BLOBNBOX(cblob);
    bbox_it.add_to_end(bblob);
  }
  ICOORD bleft(0, 0);
  ICOORD tright(height, width);
  int vertical_x, vertical_y;
  FindLineVectors(bleft, tright, &line_bblobs, &vertical_x, &vertical_y,
                  vectors);
  if (!vectors->empty()) {
    // Some lines were found, so erase the unused blobs from the line image
    // and then subtract the line image from the source.
    bbox_it.move_to_first();
    for (bbox_it.mark_cycle_pt(); !bbox_it.cycled_list(); bbox_it.forward()) {
      BLOBNBOX* blob = bbox_it.data();
      if (blob->left_tab_type() == TT_UNCONFIRMED) {
        const TBOX& box = blob->bounding_box();
        // Coords are in tess format so filp x and y and then covert
        // to leptonica by height -y.
        Box* pixbox = boxCreate(box.bottom(), height - box.right(),
                                box.height(), box.width());
        pixClearInRect(line_pix, pixbox);
        boxDestroy(&pixbox);
      }
    }
    pixDilateBrick(line_pix, line_pix, 3, 1);
    pixSubtract(pix, pix, line_pix);
    if (textord_tabfind_show_vlines)
      pixWrite("hlinesclean.png", line_pix, IFF_PNG);
    ICOORD vertical;
    vertical.set_with_shrink(vertical_x, vertical_y);
    TabVector::MergeSimilarTabVectors(vertical, vectors, NULL);
    // Iterate the vectors to flip them.
    TabVector_IT h_it(vectors);
    for (h_it.mark_cycle_pt(); !h_it.cycled_list(); h_it.forward()) {
      h_it.data()->XYFlip();
    }
  }
  pixDestroy(&line_pix);
#endif
}
Exemplo n.º 21
0
// Helper gets the image of a rectangle, using the block.re_rotation() if
// needed to get to the image, and rotating the result back to horizontal
// layout. (CJK characters will be on their left sides) The vertical text flag
// is set in the returned ImageData if the text was originally vertical, which
// can be used to invoke a different CJK recognition engine. The revised_box
// is also returned to enable calculation of output bounding boxes.
ImageData* Tesseract::GetRectImage(const TBOX& box, const BLOCK& block,
                                   int padding, TBOX* revised_box) const {
  TBOX wbox = box;
  wbox.pad(padding, padding);
  *revised_box = wbox;
  // Number of clockwise 90 degree rotations needed to get back to tesseract
  // coords from the clipped image.
  int num_rotations = 0;
  if (block.re_rotation().y() > 0.0f)
    num_rotations = 1;
  else if (block.re_rotation().x() < 0.0f)
    num_rotations = 2;
  else if (block.re_rotation().y() < 0.0f)
    num_rotations = 3;
  // Handle two cases automatically: 1 the box came from the block, 2 the box
  // came from a box file, and refers to the image, which the block may not.
  if (block.bounding_box().major_overlap(*revised_box))
    revised_box->rotate(block.re_rotation());
  // Now revised_box always refers to the image.
  // BestPix is never colormapped, but may be of any depth.
  Pix* pix = BestPix();
  int width = pixGetWidth(pix);
  int height = pixGetHeight(pix);
  TBOX image_box(0, 0, width, height);
  // Clip to image bounds;
  *revised_box &= image_box;
  if (revised_box->null_box()) return NULL;
  Box* clip_box = boxCreate(revised_box->left(), height - revised_box->top(),
                            revised_box->width(), revised_box->height());
  Pix* box_pix = pixClipRectangle(pix, clip_box, NULL);
  if (box_pix == NULL) return NULL;
  boxDestroy(&clip_box);
  if (num_rotations > 0) {
    Pix* rot_pix = pixRotateOrth(box_pix, num_rotations);
    pixDestroy(&box_pix);
    box_pix = rot_pix;
  }
  // Convert sub-8-bit images to 8 bit.
  int depth = pixGetDepth(box_pix);
  if (depth < 8) {
    Pix* grey;
    grey = pixConvertTo8(box_pix, false);
    pixDestroy(&box_pix);
    box_pix = grey;
  }
  bool vertical_text = false;
  if (num_rotations > 0) {
    // Rotated the clipped revised box back to internal coordinates.
    FCOORD rotation(block.re_rotation().x(), -block.re_rotation().y());
    revised_box->rotate(rotation);
    if (num_rotations != 2)
      vertical_text = true;
  }
  return new ImageData(vertical_text, box_pix);
}
Exemplo n.º 22
0
/*!
 * \brief   recogRescoreDidResult()
 *
 * \param[in]    recog with LUT's pre-computed
 * \param[out]   ppixdb [optional] debug result; can be null
 * \return  0 if OK, 1 on error
 *
 * <pre>
 * Notes:
 *      (1) This does correlation matching with all templates using the
 *          viterbi path segmentation.
 * </pre>
 */
static l_int32
recogRescoreDidResult(L_RECOG  *recog,
                      PIX     **ppixdb)
{
l_int32    i, n, w2, h1, templ, x, xloc, dely, index;
char      *text;
l_float32  score;
BOX       *box1;
PIX       *pixs, *pix1;
L_RDID    *did;

    PROCNAME("recogRescoreDidResult");

    if (ppixdb) *ppixdb = NULL;
    if (!recog)
        return ERROR_INT("recog not defined", procName, 1);
    if ((did = recogGetDid(recog)) == NULL)
        return ERROR_INT("did not defined", procName, 1);
    if (did->fullarrays == 0)
        return ERROR_INT("did full arrays not made", procName, 1);
    if ((n = numaGetCount(did->naxloc)) == 0)
        return ERROR_INT("no elements in path", procName, 1);

    pixs = did->pixs;
    h1 = pixGetHeight(pixs);
    for (i = 0; i < n; i++) {
        numaGetIValue(did->natempl, i, &templ);
        numaGetIValue(did->naxloc, i, &xloc);
        numaGetIValue(did->nadely, i, &dely);
        pixaGetPixDimensions(recog->pixa_u, templ, &w2, NULL, NULL);
        /* TODO: try to fix xloc - 4, etc. */
        x = L_MAX(xloc, 0);
        box1 = boxCreate(x, dely, w2, h1);
        pix1 = pixClipRectangle(pixs, box1, NULL);
        recogIdentifyPix(recog, pix1, NULL);
        recogTransferRchToDid(recog, x, dely);
        if (ppixdb) {
            rchExtract(recog->rch, &index, &score, &text,
                       NULL, NULL, NULL, NULL);
            fprintf(stderr, "text = %s, index = %d, score = %5.3f\n",
                    text, index, score);
        }
        pixDestroy(&pix1);
        boxDestroy(&box1);
        LEPT_FREE(text);
    }

/*    numaWriteStream(stderr, recog->did->nadely_r);  */

    if (ppixdb)
        *ppixdb = recogShowPath(recog, 1);

    return 0;
}
Exemplo n.º 23
0
/*!
 *  boxCreateValid()
 *
 *      Input:  x, y, w, h
 *      Return: box, or null on error
 *
 *  Notes:
 *      (1) This returns NULL if either w = 0 or h = 0.
 */
BOX *
boxCreateValid(l_int32  x,
               l_int32  y,
               l_int32  w,
               l_int32  h)
{
    PROCNAME("boxCreateValid");

    if (w <= 0 || h <= 0)
        return (BOX *)ERROR_PTR("w and h not both > 0", procName, NULL);
    return boxCreate(x, y, w, h);
}
Exemplo n.º 24
0
/*!
 * \brief   ptaConvertToBoxa()
 *
 * \param[in]    pta
 * \param[in]    ncorners   2 or 4 for the representation of each box
 * \return  boxa with one box for each 2 or 4 points in the pta,
 *                    or NULL on error
 *
 * <pre>
 * Notes:
 *      (1) For 2 corners, the order of the 2 points is UL, LR.
 *          For 4 corners, the order of points is UL, UR, LL, LR.
 *      (2) Each derived box is the minimum size containing all corners.
 * </pre>
 */
BOXA *
ptaConvertToBoxa(PTA     *pta,
                 l_int32  ncorners)
{
l_int32  i, n, nbox, x1, y1, x2, y2, x3, y3, x4, y4, x, y, xmax, ymax;
BOX     *box;
BOXA    *boxa;

    PROCNAME("ptaConvertToBoxa");

    if (!pta)
        return (BOXA *)ERROR_PTR("pta not defined", procName, NULL);
    if (ncorners != 2 && ncorners != 4)
        return (BOXA *)ERROR_PTR("ncorners not 2 or 4", procName, NULL);
    n = ptaGetCount(pta);
    if (n % ncorners != 0)
        return (BOXA *)ERROR_PTR("size % ncorners != 0", procName, NULL);
    nbox = n / ncorners;
    if ((boxa = boxaCreate(nbox)) == NULL)
        return (BOXA *)ERROR_PTR("boxa not made", procName, NULL);
    for (i = 0; i < n; i += ncorners) {
        ptaGetIPt(pta, i, &x1, &y1);
        ptaGetIPt(pta, i + 1, &x2, &y2);
        if (ncorners == 2) {
            box = boxCreate(x1, y1, x2 - x1 + 1, y2 - y1 + 1);
            boxaAddBox(boxa, box, L_INSERT);
            continue;
        }
        ptaGetIPt(pta, i + 2, &x3, &y3);
        ptaGetIPt(pta, i + 3, &x4, &y4);
        x = L_MIN(x1, x3);
        y = L_MIN(y1, y2);
        xmax = L_MAX(x2, x4);
        ymax = L_MAX(y3, y4);
        box = boxCreate(x, y, xmax - x + 1, ymax - y + 1);
        boxaAddBox(boxa, box, L_INSERT);
    }

    return boxa;
}
Exemplo n.º 25
0
/**
 * Returns a binary image of the current object at the given level.
 * The position and size match the return from BoundingBoxInternal, and so this
 * could be upscaled with respect to the original input image.
 * Use pixDestroy to delete the image after use.
 * The following methods are used to generate the images:
 * RIL_BLOCK: mask the page image with the block polygon.
 * RIL_TEXTLINE: Clip the rectangle of the line box from the page image.
 * TODO(rays) fix this to generate and use a line polygon.
 * RIL_WORD: Clip the rectangle of the word box from the page image.
 * RIL_SYMBOL: Render the symbol outline to an image for cblobs (prior
 * to recognition) or the bounding box otherwise.
 * A reconstruction of the original image (using xor to check for double
 * representation) should be reasonably accurate,
 * apart from removed noise, at the block level. Below the block level, the
 * reconstruction will be missing images and line separators.
 * At the symbol level, kerned characters will be invade the bounding box
 * if rendered after recognition, making an xor reconstruction inaccurate, but
 * an or construction better. Before recognition, symbol-level reconstruction
 * should be good, even with xor, since the images come from the connected
 * components.
 */
Pix* PageIterator::GetBinaryImage(PageIteratorLevel level) const {
  int left, top, right, bottom;
  if (!BoundingBoxInternal(level, &left, &top, &right, &bottom))
    return NULL;
  Pix* pix = NULL;
  switch (level) {
    case RIL_BLOCK:
    case RIL_PARA:
      int bleft, btop, bright, bbottom;
      BoundingBoxInternal(RIL_BLOCK, &bleft, &btop, &bright, &bbottom);
      pix = it_->block()->block->render_mask();
      // AND the mask and the image.
      pixRasterop(pix, 0, 0, pixGetWidth(pix), pixGetHeight(pix),
                  PIX_SRC & PIX_DST, tesseract_->pix_binary(),
                  bleft, btop);
      if (level == RIL_PARA) {
        // RIL_PARA needs further attention:
        //   clip the paragraph from the block mask.
        Box* box = boxCreate(left - bleft, top - btop,
                             right - left, bottom - top);
        Pix* pix2 = pixClipRectangle(pix, box, NULL);
        boxDestroy(&box);
        pixDestroy(&pix);
        pix = pix2;
      }
      break;
    case RIL_TEXTLINE:
    case RIL_WORD:
    case RIL_SYMBOL:
      if (level == RIL_SYMBOL && cblob_it_ != NULL &&
          cblob_it_->data()->area() != 0)
        return cblob_it_->data()->render();
      // Just clip from the bounding box.
      Box* box = boxCreate(left, top, right - left, bottom - top);
      pix = pixClipRectangle(tesseract_->pix_binary(), box, NULL);
      boxDestroy(&box);
      break;
  }
  return pix;
}
Exemplo n.º 26
0
int main(int    argc,
         char **argv)
{
char        *dirin, *dirout, *infile, *outfile, *tail;
l_int32      i, nfiles, border, x, y, w, h, xb, yb, wb, hb;
BOX         *box1, *box2;
BOXA        *boxa1, *boxa2;
PIX         *pixs, *pixt1, *pixd;
SARRAY      *safiles;
static char  mainName[] = "croptext";

    if (argc != 4)
        return ERROR_INT("Syntax: croptext dirin border dirout", mainName, 1);
    dirin = argv[1];
    border = atoi(argv[2]);
    dirout = argv[3];

    setLeptDebugOK(1);
    safiles = getSortedPathnamesInDirectory(dirin, NULL, 0, 0);
    nfiles = sarrayGetCount(safiles);

    for (i = 0; i < nfiles; i++) {
        infile = sarrayGetString(safiles, i, L_NOCOPY);
        splitPathAtDirectory(infile, NULL, &tail);
        outfile = genPathname(dirout, tail);
        pixs = pixRead(infile);
        pixt1 = pixMorphSequence(pixs, "r11 + c10.40 + o5.5 + x4", 0);
        boxa1 = pixConnComp(pixt1, NULL, 8);
        if (boxaGetCount(boxa1) == 0) {
            fprintf(stderr, "Warning: no components on page %s\n", tail);
            continue;
        }
        boxa2 = boxaSort(boxa1, L_SORT_BY_AREA, L_SORT_DECREASING, NULL);
        box1 = boxaGetBox(boxa2, 0, L_CLONE);
        boxGetGeometry(box1, &x, &y, &w, &h);
        xb = L_MAX(0, x - border);
        yb = L_MAX(0, y - border);
        wb = w + 2 * border;
        hb = h + 2 * border;
        box2 = boxCreate(xb, yb, wb, hb);
        pixd = pixClipRectangle(pixs, box2, NULL);
        pixWrite(outfile, pixd, IFF_TIFF_G4);

        pixDestroy(&pixs);
        pixDestroy(&pixt1);
        pixDestroy(&pixd);
        boxaDestroy(&boxa1);
        boxaDestroy(&boxa2);
    }

    return 0;
}
Exemplo n.º 27
0
unsigned long long getImagePhash_px( PIX *pix_orig, char *tmpFilename ) {

  int free_8 = 0;

  // Convert colour images down to grey
  PIX *pix8;
  if( pixGetDepth(pix_orig) > 8 ) {
    pix8 = pixScaleRGBToGrayFast( pix_orig, 1, COLOR_GREEN );
    if( pix8 == NULL ) {
      printf("Covertion to 8bit, did not go well.");
      return  0;
    }
    free_8 = 1;
  }
  else {
    // already gray
    free_8 = 0;
    pix8 = pix_orig;
  }

  int width = pixGetWidth( pix8 );
  int height = pixGetHeight( pix8 );
  BOX* box = boxCreate(1, 1, width-2, height-2);
  PIX* pixc = pixClipRectangle(pix8, box, NULL);
  if(free_8 == 1) {
    pixDestroy( &pix8 );
  }


  PIX *pix8s = pixScale(pixc, 0.2, 0.2);
  pixDestroy( &pixc );

  // Convert image down to binary (no gray)
/*  PIX *pix1 = pixThresholdToBinary( pix8s, 200 );
  if( pix1 == NULL ) {
    printf( "Covertion to 1bit, did not go well.");
    pixDestroy( &pix8s );
    return 0;
  }
  pixDestroy( &pix8s );
*/
  // Save the file for pHash processnig
  pixWrite( tmpFilename, pix8s, IFF_JFIF_JPEG);
  pixDestroy( &pix8s );

  unsigned long long ret = calculateImagePhash( tmpFilename );
  //unlink(tmpFilename);

  return ret;
}
Exemplo n.º 28
0
main(int    argc,
     char **argv)
{
    l_int32       i, k, x, y, w, h;
    BOX          *box;
    BOXA         *boxa1, *boxa2;
    PIX          *pix1, *pix2, *pixd;
    PIXA         *pixa;
    L_REGPARAMS  *rp;

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

    for (k = 0; k < 7; k++) {
        srand(45617);
        pixa = pixaCreate(2);
        boxa1 = boxaCreate(0);
        for (i = 0; i < 500; i++) {
            x = (l_int32)(600.0 * (l_float64)rand() / (l_float64)RAND_MAX);
            y = (l_int32)(600.0 * (l_float64)rand() / (l_float64)RAND_MAX);
            w = (l_int32)
                (1.0 + maxsize[k] * (l_float64)rand() / (l_float64)RAND_MAX);
            h = (l_int32)
                (1.0 + maxsize[k] * (l_float64)rand() / (l_float64)RAND_MAX);
            box = boxCreate(x, y, w, h);
            boxaAddBox(boxa1, box, L_INSERT);
        }

        pix1 = pixCreate(660, 660, 1);
        pixRenderBoxa(pix1, boxa1, 1, L_SET_PIXELS);
        pixaAddPix(pixa, pix1, L_INSERT);
        boxa2 = boxaCombineOverlaps(boxa1);
        pix2 = pixCreate(660, 660, 1);
        pixRenderBoxa(pix2, boxa2, 1, L_SET_PIXELS);
        pixaAddPix(pixa, pix2, L_INSERT);

        pixd = pixaDisplayTiledInRows(pixa, 1, 1500, 1.0, 0, 50, 2);
        pixDisplayWithTitle(pixd, 100, 100 + 100 * k, NULL, rp->display);
        regTestWritePixAndCheck(rp, pixd, IFF_PNG);
        fprintf(stderr, "%d: n_init = %d, n_final = %d\n",
                k, boxaGetCount(boxa1), boxaGetCount(boxa2));
        pixDestroy(&pixd);
        boxaDestroy(&boxa1);
        boxaDestroy(&boxa2);
        pixaDestroy(&pixa);
    }

    regTestCleanup(rp);
    return 0;
}
/*!
 *  boxCopy()
 *
 *      Input:  box
 *      Return: copy of box, or null on error
 */
BOX *
boxCopy(BOX  *box)
{
BOX  *boxc;

    PROCNAME("boxCopy");

    if (!box)
        return (BOX *)ERROR_PTR("box not defined", procName, NULL);

    boxc = boxCreate(box->x, box->y, box->w, box->h);

    return boxc;
}
Exemplo n.º 30
0
/*!
 *  boxaaGetExtent()
 *
 *      Input:  boxaa
 *              &w  (<optional return> width)
 *              &h  (<optional return> height)
 *              &box (<optional return>, minimum box containing all boxa
 *                    in boxaa)
 *      Return: 0 if OK, 1 on error
 *
 *  Notes:
 *      (1) The returned w and h are the minimum size image
 *          that would contain all boxes untranslated.
 */
l_int32
boxaaGetExtent(BOXAA    *boxaa,
               l_int32  *pw,
               l_int32  *ph,
               BOX     **pbox)
{
l_int32  i, j, n, m, x, y, w, h, xmax, ymax, xmin, ymin, found;
BOXA    *boxa;

    PROCNAME("boxaaGetExtent");

    if (!pw && !ph && !pbox)
        return ERROR_INT("no ptrs defined", procName, 1);
    if (pbox) *pbox = NULL;
    if (pw) *pw = 0;
    if (ph) *ph = 0;
    if (!boxaa)
        return ERROR_INT("boxaa not defined", procName, 1);

    n = boxaaGetCount(boxaa);
    if (n == 0)
        return ERROR_INT("no boxa in boxaa", procName, 1);

    xmax = ymax = 0;
    xmin = ymin = 100000000;
    found = FALSE;
    for (i = 0; i < n; i++) {
        boxa = boxaaGetBoxa(boxaa, i, L_CLONE);
        m = boxaGetCount(boxa);
        for (j = 0; j < m; j++) {
            boxaGetBoxGeometry(boxa, j, &x, &y, &w, &h);
            if (w <= 0 || h <= 0)
                continue;
            found = TRUE;
            xmin = L_MIN(xmin, x);
            ymin = L_MIN(ymin, y);
            xmax = L_MAX(xmax, x + w);
            ymax = L_MAX(ymax, y + h);
        }
    }
    if (!found)
        return ERROR_INT("no valid boxes in boxaa", procName, 1);
    if (pw) *pw = xmax;
    if (ph) *ph = ymax;
    if (pbox)
      *pbox = boxCreate(xmin, ymin, xmax - xmin, ymax - ymin);

    return 0;
}