void Java_com_example_ocr_Pixa_nativeMergeAndReplacePix(JNIEnv *env, jclass clazz, jint nativePixa, jint indexA, jint indexB) { PIXA *pixa = (PIXA *) nativePixa; l_int32 op; l_int32 x, y, w, h; l_int32 dx, dy, dw, dh; PIX *pixs, *pixd; BOX *boxA, *boxB, *boxd; boxA = pixaGetBox(pixa, indexA, L_CLONE); boxB = pixaGetBox(pixa, indexB, L_CLONE); boxd = boxBoundingRegion(boxA, boxB); boxGetGeometry(boxd, &x, &y, &w, &h); pixd = pixCreate(w, h, 1); op = PIX_SRC | PIX_DST; pixs = pixaGetPix(pixa, indexA, L_CLONE); boxGetGeometry(boxA, &dx, &dy, &dw, &dh); pixRasterop(pixd, dx - x, dy - y, dw, dh, op, pixs, 0, 0); pixDestroy(&pixs); boxDestroy(&boxA); pixs = pixaGetPix(pixa, indexB, L_CLONE); boxGetGeometry(boxB, &dx, &dy, &dw, &dh); pixRasterop(pixd, dx - x, dy - y, dw, dh, op, pixs, 0, 0); pixDestroy(&pixs); boxDestroy(&boxB); pixaReplacePix(pixa, indexA, pixd, boxd); }
/********************************************************************** * create_cube_box_word * * Fill the given BoxWord with boxes from character bounding * boxes. The char_boxes have local coordinates w.r.t. the * word bounding box, i.e., the left-most character bbox of each word * has (0,0) left-top coord, but the BoxWord must be defined in page * coordinates. **********************************************************************/ bool Tesseract::create_cube_box_word(Boxa *char_boxes, int num_chars, TBOX word_box, BoxWord* box_word) { if (!box_word) { if (cube_debug_level > 0) { tprintf("Cube WARNING (create_cube_box_word): Invalid box_word.\n"); } return false; } // Find the x-coordinate of left-most char_box, which could be // nonzero if the word image was padded before recognition took place. int x_offset = -1; for (int i = 0; i < num_chars; ++i) { Box* char_box = boxaGetBox(char_boxes, i, L_CLONE); if (x_offset < 0 || char_box->x < x_offset) { x_offset = char_box->x; } boxDestroy(&char_box); } for (int i = 0; i < num_chars; ++i) { Box* char_box = boxaGetBox(char_boxes, i, L_CLONE); TBOX tbox = char_box_to_tbox(char_box, word_box, x_offset); boxDestroy(&char_box); box_word->InsertBox(i, tbox); } return true; }
/*! * boxaEqual() * * Input: boxa1 * boxa2 * maxdist * &naindex (<optional return> index array of correspondences * &same (<return> 1 if equal; 0 otherwise) * Return 0 if OK, 1 on error * * Notes: * (1) The two boxa are the "same" if they contain the same * boxes and each box is within @maxdist of its counterpart * in their positions within the boxa. This allows for * small rearrangements. Use 0 for maxdist if the boxa * must be identical. * (2) This applies only to geometry and ordering; refcounts * are not considered. * (3) @maxdist allows some latitude in the ordering of the boxes. * For the boxa to be the "same", corresponding boxes must * be within @maxdist of each other. Note that for large * @maxdist, we should use a hash function for efficiency. * (4) naindex[i] gives the position of the box in boxa2 that * corresponds to box i in boxa1. It is only returned if the * boxa are equal. */ l_int32 boxaEqual(BOXA *boxa1, BOXA *boxa2, l_int32 maxdist, NUMA **pnaindex, l_int32 *psame) { l_int32 i, j, n, jstart, jend, found, samebox; l_int32 *countarray; BOX *box1, *box2; NUMA *na; PROCNAME("boxaEqual"); if (pnaindex) *pnaindex = NULL; if (!psame) return ERROR_INT("&same not defined", procName, 1); *psame = 0; if (!boxa1 || !boxa2) return ERROR_INT("boxa1 and boxa2 not both defined", procName, 1); n = boxaGetCount(boxa1); if (n != boxaGetCount(boxa2)) return 0; countarray = (l_int32 *)CALLOC(n, sizeof(l_int32)); na = numaMakeConstant(0.0, n); for (i = 0; i < n; i++) { box1 = boxaGetBox(boxa1, i, L_CLONE); jstart = L_MAX(0, i - maxdist); jend = L_MIN(n-1, i + maxdist); found = FALSE; for (j = jstart; j <= jend; j++) { box2 = boxaGetBox(boxa2, j, L_CLONE); boxEqual(box1, box2, &samebox); if (samebox && countarray[j] == 0) { countarray[j] = 1; numaReplaceNumber(na, i, j); found = TRUE; boxDestroy(&box2); break; } boxDestroy(&box2); } boxDestroy(&box1); if (!found) { numaDestroy(&na); FREE(countarray); return 0; } } *psame = 1; if (pnaindex) *pnaindex = na; else numaDestroy(&na); FREE(countarray); return 0; }
/*! * boxaGetCoverage() * * Input: boxa * wc, hc (dimensions of overall clipping rectangle with UL * corner at (0, 0) that is covered by the boxes. * exactflag (1 for guaranteeing an exact result; 0 for getting * an exact result only if the boxes do not overlap) * &fract (<return> sum of box area as fraction of w * h) * Return: 0 if OK, 1 on error * * Notes: * (1) The boxes in boxa are clipped to the input rectangle. * (2) * When @exactflag == 1, we generate a 1 bpp pix of size * wc x hc, paint all the boxes black, and count the fg pixels. * This can take 1 msec on a large page with many boxes. * * When @exactflag == 0, we clip each box to the wc x hc region * and sum the resulting areas. This is faster. * * The results are the same when none of the boxes overlap * within the wc x hc region. */ l_int32 boxaGetCoverage(BOXA *boxa, l_int32 wc, l_int32 hc, l_int32 exactflag, l_float32 *pfract) { l_int32 i, n, x, y, w, h, sum; BOX *box, *boxc; PIX *pixt; PROCNAME("boxaGetCoverage"); if (!pfract) return ERROR_INT("&fract not defined", procName, 1); *pfract = 0.0; if (!boxa) return ERROR_INT("boxa not defined", procName, 1); n = boxaGetCount(boxa); if (n == 0) return ERROR_INT("no boxes in boxa", procName, 1); if (exactflag == 0) { /* quick and dirty */ sum = 0; for (i = 0; i < n; i++) { box = boxaGetBox(boxa, i, L_CLONE); if ((boxc = boxClipToRectangle(box, wc, hc)) != NULL) { boxGetGeometry(boxc, NULL, NULL, &w, &h); sum += w * h; boxDestroy(&boxc); } boxDestroy(&box); } } else { /* slower and exact */ pixt = pixCreate(wc, hc, 1); for (i = 0; i < n; i++) { box = boxaGetBox(boxa, i, L_CLONE); boxGetGeometry(box, &x, &y, &w, &h); pixRasterop(pixt, x, y, w, h, PIX_SET, NULL, 0, 0); boxDestroy(&box); } pixCountPixels(pixt, &sum, NULL); pixDestroy(&pixt); } *pfract = (l_float32)sum / (l_float32)(wc * hc); return 0; }
/*! * boxaGetNearestToPt() * * Input: boxa * x, y (point) * Return box (box with centroid closest to the given point [x,y]), * or NULL if no boxes in boxa) * * Notes: * (1) Uses euclidean distance between centroid and point. */ BOX * boxaGetNearestToPt(BOXA *boxa, l_int32 x, l_int32 y) { l_int32 i, n, minindex; l_float32 delx, dely, dist, mindist, cx, cy; BOX *box; PROCNAME("boxaGetNearestToPt"); if (!boxa) return (BOX *)ERROR_PTR("boxa not defined", procName, NULL); if ((n = boxaGetCount(boxa)) == 0) return (BOX *)ERROR_PTR("n = 0", procName, NULL); mindist = 1000000000.; minindex = 0; for (i = 0; i < n; i++) { box = boxaGetBox(boxa, i, L_CLONE); boxGetCenter(box, &cx, &cy); delx = (l_float32)(cx - x); dely = (l_float32)(cy - y); dist = delx * delx + dely * dely; if (dist < mindist) { minindex = i; mindist = dist; } boxDestroy(&box); } return boxaGetBox(boxa, minindex, L_COPY); }
/*! * boxOverlapFraction() * * Input: box1, box2 (two boxes) * &fract (<return> the fraction of box2 overlapped by box1) * Return: 0 if OK, 1 on error. * * Notes: * (1) The result depends on the order of the input boxes, * because the overlap is taken as a fraction of box2. */ l_int32 boxOverlapFraction(BOX *box1, BOX *box2, l_float32 *pfract) { l_int32 w2, h2, w, h; BOX *boxo; PROCNAME("boxOverlapFraction"); if (!pfract) return ERROR_INT("&fract not defined", procName, 1); *pfract = 0.0; if (!box1) return ERROR_INT("box1 not defined", procName, 1); if (!box2) return ERROR_INT("box2 not defined", procName, 1); if ((boxo = boxOverlapRegion(box1, box2)) == NULL) /* no overlap */ return 0; boxGetGeometry(box2, NULL, NULL, &w2, &h2); boxGetGeometry(boxo, NULL, NULL, &w, &h); *pfract = (l_float32)(w * h) / (l_float32)(w2 * h2); boxDestroy(&boxo); return 0; }
/*! * boxaClipToBox() * * Input: boxas * box (for clipping) * Return boxad (boxa with boxes in boxas clipped to box), * or null on error * * Notes: * (1) All boxes in boxa not intersecting with box are removed, and * the remaining boxes are clipped to box. */ BOXA * boxaClipToBox(BOXA *boxas, BOX *box) { l_int32 i, n; BOX *boxt, *boxo; BOXA *boxad; PROCNAME("boxaClipToBox"); if (!boxas) return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL); if (!box) return (BOXA *)ERROR_PTR("box not defined", procName, NULL); if ((n = boxaGetCount(boxas)) == 0) return boxaCreate(1); /* empty */ boxad = boxaCreate(0); for (i = 0; i < n; i++) { boxt = boxaGetBox(boxas, i, L_CLONE); if ((boxo = boxOverlapRegion(box, boxt)) != NULL) boxaAddBox(boxad, boxo, L_INSERT); boxDestroy(&boxt); } return boxad; }
/*! * boxaIntersectsBox() * * Input: boxas * box (for intersecting) * Return boxad (boxa with all boxes in boxas that intersect box), * or null on error * * Notes: * (1) All boxes in boxa that intersect with box (i.e., are completely * or partially contained in box) are retained. */ BOXA * boxaIntersectsBox(BOXA *boxas, BOX *box) { l_int32 i, n, val; BOX *boxt; BOXA *boxad; PROCNAME("boxaIntersectsBox"); if (!boxas) return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL); if (!box) return (BOXA *)ERROR_PTR("box not defined", procName, NULL); if ((n = boxaGetCount(boxas)) == 0) return boxaCreate(1); /* empty */ boxad = boxaCreate(0); for (i = 0; i < n; i++) { boxt = boxaGetBox(boxas, i, L_CLONE); boxIntersects(box, boxt, &val); if (val == 1) boxaAddBox(boxad, boxt, L_COPY); boxDestroy(&boxt); /* destroy the clone */ } return boxad; }
// create a union of two arbitrary pix Pix *CubeLineSegmenter::PixUnion(Pix *dest_pix, Box *dest_box, Pix *src_pix, Box *src_box) { // compute dimensions of union rect BOX *union_box = boxBoundingRegion(src_box, dest_box); // create the union pix Pix *union_pix = pixCreate(union_box->w, union_box->h, src_pix->d); if (union_pix == NULL) { return NULL; } // blt the src and dest pix pixRasterop(union_pix, src_box->x - union_box->x, src_box->y - union_box->y, src_box->w, src_box->h, PIX_SRC | PIX_DST, src_pix, 0, 0); pixRasterop(union_pix, dest_box->x - union_box->x, dest_box->y - union_box->y, dest_box->w, dest_box->h, PIX_SRC | PIX_DST, dest_pix, 0, 0); // replace the dest_box *dest_box = *union_box; boxDestroy(&union_box); return union_pix; }
/** * 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; }
/*! * boxaRotateOrth() * * Input: boxa * w, h (of image in which the boxa is embedded) * rotation (0 = noop, 1 = 90 deg, 2 = 180 deg, 3 = 270 deg; * all rotations are clockwise) * Return: boxad, or null on error * * Notes: * (1) See boxRotateOrth() for details. */ BOXA * boxaRotateOrth(BOXA *boxas, l_int32 w, l_int32 h, l_int32 rotation) { l_int32 i, n; BOX *boxs, *boxd; BOXA *boxad; PROCNAME("boxaRotateOrth"); if (!boxas) return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL); if (rotation == 0) return boxaCopy(boxas, L_COPY); if (rotation < 1 || rotation > 3) return (BOXA *)ERROR_PTR("rotation not in {0,1,2,3}", procName, NULL); n = boxaGetCount(boxas); if ((boxad = boxaCreate(n)) == NULL) return (BOXA *)ERROR_PTR("boxad not made", procName, NULL); for (i = 0; i < n; i++) { if ((boxs = boxaGetBox(boxas, i, L_CLONE)) == NULL) return (BOXA *)ERROR_PTR("boxs not found", procName, NULL); boxd = boxRotateOrth(boxs, w, h, rotation); boxDestroy(&boxs); boxaAddBox(boxad, boxd, L_INSERT); } return boxad; }
/*! * boxaGetBoxGeometry() * * Input: boxa * index (to the index-th box) * &x, &y, &w, &h (<optional return>; each can be null) * Return: 0 if OK, 1 on error */ l_int32 boxaGetBoxGeometry(BOXA *boxa, l_int32 index, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph) { BOX *box; PROCNAME("boxaGetBoxGeometry"); if (px) *px = 0; if (py) *py = 0; if (pw) *pw = 0; if (ph) *ph = 0; if (!boxa) return ERROR_INT("boxa not defined", procName, 1); if (index < 0 || index >= boxa->n) return ERROR_INT("index not valid", procName, 1); if ((box = boxaGetBox(boxa, index, L_CLONE)) == NULL) return ERROR_INT("box not found!", procName, 1); boxGetGeometry(box, px, py, pw, ph); boxDestroy(&box); return 0; }
/*! * boxaWriteStream() * * Input: stream * boxa * Return: 0 if OK, 1 on error */ l_int32 boxaWriteStream(FILE *fp, BOXA *boxa) { l_int32 n, i; BOX *box; PROCNAME("boxaWriteStream"); if (!fp) return ERROR_INT("stream not defined", procName, 1); if (!boxa) return ERROR_INT("boxa not defined", procName, 1); n = boxaGetCount(boxa); fprintf(fp, "\nBoxa Version %d\n", BOXA_VERSION_NUMBER); fprintf(fp, "Number of boxes = %d\n", n); for (i = 0; i < n; i++) { if ((box = boxaGetBox(boxa, i, L_CLONE)) == NULL) return ERROR_INT("box not found", procName, 1); fprintf(fp, " Box[%d]: x = %d, y = %d, w = %d, h = %d\n", i, box->x, box->y, box->w, box->h); boxDestroy(&box); } return 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); }
/*! * pixAddWithIndicator() * * Input: pixs (1 bpp pix from which components are added; in-place) * pixa (of connected components, some of which will be put * into pixs) * na (numa indicator: add components corresponding to 1s) * Return: 0 if OK, 1 on error * * Notes: * (1) This complements pixRemoveWithIndicator(). Here, the selected * components are added to pixs. */ l_int32 pixAddWithIndicator(PIX *pixs, PIXA *pixa, NUMA *na) { l_int32 i, n, ival, x, y, w, h; BOX *box; PIX *pix; PROCNAME("pixAddWithIndicator"); if (!pixs) return ERROR_INT("pixs not defined", procName, 1); if (!pixa) return ERROR_INT("pixa not defined", procName, 1); if (!na) return ERROR_INT("na not defined", procName, 1); n = pixaGetCount(pixa); if (n != numaGetCount(na)) return ERROR_INT("pixa and na sizes not equal", procName, 1); for (i = 0; i < n; i++) { numaGetIValue(na, i, &ival); if (ival == 1) { pix = pixaGetPix(pixa, i, L_CLONE); box = pixaGetBox(pixa, i, L_CLONE); boxGetGeometry(box, &x, &y, &w, &h); pixRasterop(pixs, x, y, w, h, PIX_SRC | PIX_DST, pix, 0, 0); boxDestroy(&box); pixDestroy(&pix); } } return 0; }
void Java_com_googlecode_leptonica_android_Box_nativeDestroy(JNIEnv *env, jclass clazz, jint nativeBox) { LOGV(__FUNCTION__); BOX *box = (BOX *) nativeBox; boxDestroy(&box); }
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; }
/*! * boxaTransform() * * Input: boxa * shiftx, shifty * scalex, scaley * Return: boxad, or null on error * * Notes: * (1) This is a very simple function that first shifts, then scales. */ BOXA * boxaTransform(BOXA *boxas, l_int32 shiftx, l_int32 shifty, l_float32 scalex, l_float32 scaley) { l_int32 i, n; BOX *boxs, *boxd; BOXA *boxad; PROCNAME("boxaTransform"); if (!boxas) return (BOXA *)ERROR_PTR("boxas not defined", procName, NULL); n = boxaGetCount(boxas); if ((boxad = boxaCreate(n)) == NULL) return (BOXA *)ERROR_PTR("boxad not made", procName, NULL); for (i = 0; i < n; i++) { if ((boxs = boxaGetBox(boxas, i, L_CLONE)) == NULL) return (BOXA *)ERROR_PTR("boxs not found", procName, NULL); boxd = boxTransform(boxs, shiftx, shifty, scalex, scaley); boxDestroy(&boxs); boxaAddBox(boxad, boxd, L_INSERT); } return boxad; }
/*! * \brief boxaConvertToPta() * * \param[in] boxa * \param[in] ncorners 2 or 4 for the representation of each box * \return pta with %ncorners points for each box in the boxa, * or NULL on error * * <pre> * Notes: * (1) If ncorners == 2, we select the UL and LR corners. * Otherwise we save all 4 corners in this order: UL, UR, LL, LR. * (2) Other boxa --> pta functions are: * * boxaExtractAsPta(): allows extraction of any dimension * and/or side location, with each in a separate pta. * * boxaExtractCorners(): extracts any of the four corners as a pta. * </pre> */ PTA * boxaConvertToPta(BOXA *boxa, l_int32 ncorners) { l_int32 i, n; BOX *box; PTA *pta, *pta1; PROCNAME("boxaConvertToPta"); if (!boxa) return (PTA *)ERROR_PTR("boxa not defined", procName, NULL); if (ncorners != 2 && ncorners != 4) return (PTA *)ERROR_PTR("ncorners not 2 or 4", procName, NULL); n = boxaGetCount(boxa); if ((pta = ptaCreate(n)) == NULL) return (PTA *)ERROR_PTR("pta not made", procName, NULL); for (i = 0; i < n; i++) { box = boxaGetBox(boxa, i, L_COPY); pta1 = boxConvertToPta(box, ncorners); ptaJoin(pta, pta1, 0, -1); boxDestroy(&box); ptaDestroy(&pta1); } return pta; }
/*! * \brief boxaGetSizes() * * \param[in] boxa * \param[out] pnaw [optional] widths of valid boxes * \param[out] pnah [optional] heights of valid boxes * \return 0 if OK, 1 on error */ l_ok boxaGetSizes(BOXA *boxa, NUMA **pnaw, NUMA **pnah) { l_int32 i, n, w, h; BOX *box; PROCNAME("boxaGetSizes"); if (pnaw) *pnaw = NULL; if (pnah) *pnah = NULL; if (!pnaw && !pnah) return ERROR_INT("no output requested", procName, 1); if (!boxa) return ERROR_INT("boxa not defined", procName, 1); n = boxaGetValidCount(boxa); if (pnaw) *pnaw = numaCreate(n); if (pnah) *pnah = numaCreate(n); for (i = 0; i < n; i++) { box = boxaGetValidBox(boxa, i, L_COPY); if (box) { boxGetGeometry(box, NULL, NULL, &w, &h); if (pnaw) numaAddNumber(*pnaw, w); if (pnah) numaAddNumber(*pnah, h); boxDestroy(&box); } } return 0; }
/*! * boxaDestroy() * * Input: &boxa (<will be set to null before returning>) * Return: void * * Note: * - Decrements the ref count and, if 0, destroys the boxa. * - Always nulls the input ptr. */ void boxaDestroy(BOXA **pboxa) { l_int32 i; BOXA *boxa; PROCNAME("boxaDestroy"); if (pboxa == NULL) { L_WARNING("ptr address is null!", procName); return; } if ((boxa = *pboxa) == NULL) return; /* Decrement the ref count. If it is 0, destroy the boxa. */ boxa->refcount--; if (boxa->refcount <= 0) { for (i = 0; i < boxa->n; i++) boxDestroy(&boxa->box[i]); FREE(boxa->box); FREE(boxa); } *pboxa = NULL; return; }
/*! * boxaaWriteStream() * * Input: stream * boxaa * Return: 0 if OK, 1 on error */ l_int32 boxaaWriteStream(FILE *fp, BOXAA *baa) { l_int32 n, i, x, y, w, h; BOX *box; BOXA *boxa; PROCNAME("boxaaWriteStream"); if (!fp) return ERROR_INT("stream not defined", procName, 1); if (!baa) return ERROR_INT("baa not defined", procName, 1); n = boxaaGetCount(baa); fprintf(fp, "\nBoxaa Version %d\n", BOXAA_VERSION_NUMBER); fprintf(fp, "Number of boxa = %d\n", n); for (i = 0; i < n; i++) { if ((boxa = boxaaGetBoxa(baa, i, L_CLONE)) == NULL) return ERROR_INT("boxa not found", procName, 1); boxaGetExtent(boxa, NULL, NULL, &box); boxGetGeometry(box, &x, &y, &w, &h); fprintf(fp, "\nBoxa[%d] extent: x = %d, y = %d, w = %d, h = %d", i, x, y, w, h); boxaWriteStream(fp, boxa); boxDestroy(&box); boxaDestroy(&boxa); } return 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; }
/*! * pixMeanInRectangle() * * Input: pix (8 bpp) * box (region to compute mean value) * pixma (mean accumulator) * &val (<return> mean value * Return: 0 if OK, 1 on error * * Notes: * (1) This function is intended to be used for many rectangles * on the same image. It can find the mean within a * rectangle in O(1), independent of the size of the rectangle. */ l_int32 pixMeanInRectangle(PIX *pixs, BOX *box, PIX *pixma, l_float32 *pval) { l_int32 w, h, bx, by, bw, bh; l_uint32 val00, val01, val10, val11; l_float32 norm; BOX *boxc; PROCNAME("pixMeanInRectangle"); if (!pval) return ERROR_INT("&val not defined", procName, 1); *pval = 0.0; if (!pixs || pixGetDepth(pixs) != 8) return ERROR_INT("pixs not defined", procName, 1); if (!box) return ERROR_INT("box not defined", procName, 1); if (!pixma) return ERROR_INT("pixma not defined", procName, 1); /* Clip rectangle to image */ pixGetDimensions(pixs, &w, &h, NULL); boxc = boxClipToRectangle(box, w, h); boxGetGeometry(boxc, &bx, &by, &bw, &bh); boxDestroy(&boxc); if (bw == 0 || bh == 0) return ERROR_INT("no pixels in box", procName, 1); /* Use up to 4 points in the accumulator */ norm = 1.0 / (bw * bh); if (bx > 0 && by > 0) { pixGetPixel(pixma, bx + bw - 1, by + bh - 1, &val11); pixGetPixel(pixma, bx + bw - 1, by - 1, &val10); pixGetPixel(pixma, bx - 1, by + bh - 1, &val01); pixGetPixel(pixma, bx - 1, by - 1, &val00); *pval = norm * (val11 - val01 + val00 - val10); } else if (by > 0) { /* bx == 0 */ pixGetPixel(pixma, bw - 1, by + bh - 1, &val11); pixGetPixel(pixma, bw - 1, by - 1, &val10); *pval = norm * (val11 - val10); } else if (bx > 0) { /* by == 0 */ pixGetPixel(pixma, bx + bw - 1, bh - 1, &val11); pixGetPixel(pixma, bx - 1, bh - 1, &val01); *pval = norm * (val11 - val01); } else { /* bx == 0 && by == 0 */ pixGetPixel(pixma, bw - 1, bh - 1, &val11); *pval = norm * val11; } return 0; }
/*! * \brief pixQuadtreeMean() * * \param[in] pixs 8 bpp, no colormap * \param[in] nlevels in quadtree; max allowed depends on image size * \param[in] *pix_ma input mean accumulator; can be null * \param[out] *pfpixa mean values in quadtree * \return 0 if OK, 1 on error * * <pre> * Notes: * (1) The returned fpixa has %nlevels of fpix, each containing * the mean values at its level. Level 0 has a * single value; level 1 has 4 values; level 2 has 16; etc. * </pre> */ l_int32 pixQuadtreeMean(PIX *pixs, l_int32 nlevels, PIX *pix_ma, FPIXA **pfpixa) { l_int32 i, j, w, h, size, n; l_float32 val; BOX *box; BOXA *boxa; BOXAA *baa; FPIX *fpix; PIX *pix_mac; PROCNAME("pixQuadtreeMean"); if (!pfpixa) return ERROR_INT("&fpixa not defined", procName, 1); *pfpixa = NULL; if (!pixs || pixGetDepth(pixs) != 8) return ERROR_INT("pixs not defined or not 8 bpp", procName, 1); pixGetDimensions(pixs, &w, &h, NULL); if (nlevels > quadtreeMaxLevels(w, h)) return ERROR_INT("nlevels too large for image", procName, 1); if (!pix_ma) pix_mac = pixBlockconvAccum(pixs); else pix_mac = pixClone(pix_ma); if (!pix_mac) return ERROR_INT("pix_mac not made", procName, 1); if ((baa = boxaaQuadtreeRegions(w, h, nlevels)) == NULL) { pixDestroy(&pix_mac); return ERROR_INT("baa not made", procName, 1); } *pfpixa = fpixaCreate(nlevels); for (i = 0; i < nlevels; i++) { boxa = boxaaGetBoxa(baa, i, L_CLONE); size = 1 << i; n = boxaGetCount(boxa); /* n == size * size */ fpix = fpixCreate(size, size); for (j = 0; j < n; j++) { box = boxaGetBox(boxa, j, L_CLONE); pixMeanInRectangle(pixs, box, pix_mac, &val); fpixSetPixel(fpix, j % size, j / size, val); boxDestroy(&box); } fpixaAddFPix(*pfpixa, fpix, L_INSERT); boxaDestroy(&boxa); } pixDestroy(&pix_mac); boxaaDestroy(&baa); return 0; }
Pix* blurDetect(Pix* pixs){ PixBlurDetect blurDetector(false); l_float32 blurValue; Box* maxBlurLoc = NULL; Pix* pixBlended = blurDetector.makeBlurIndicator(pixs, &blurValue, &maxBlurLoc); boxDestroy(&maxBlurLoc); printf("blur = %.2f\n", blurValue); return pixBlended; }
void M_Utils::dispHlTBoxRegion(TBOX tbox, PIX* im) { BOX* box = tessTBoxToImBox(&tbox, im); PIX* imcpy = pixCopy(NULL, im); imcpy = pixConvertTo32(imcpy); Lept_Utils::fillBoxForeground(imcpy, box, LayoutEval::RED); pixDisplay(imcpy, 100, 100); pixDestroy(&imcpy); boxDestroy(&box); }
// Refreshes the words in the segmentation block list by using blobs in the // input block list. // The segmentation block list must be set. void ShiroRekhaSplitter::RefreshSegmentationWithNewBlobs( C_BLOB_LIST* new_blobs) { // The segmentation block list must have been specified. ASSERT_HOST(segmentation_block_list_); if (devanagari_split_debuglevel > 0) { tprintf("Before refreshing blobs:\n"); PrintSegmentationStats(segmentation_block_list_); tprintf("New Blobs found: %d\n", new_blobs->length()); } C_BLOB_LIST not_found_blobs; RefreshWordBlobsFromNewBlobs(segmentation_block_list_, new_blobs, ((devanagari_split_debugimage && debug_image_) ? ¬_found_blobs : NULL)); if (devanagari_split_debuglevel > 0) { tprintf("After refreshing blobs:\n"); PrintSegmentationStats(segmentation_block_list_); } if (devanagari_split_debugimage && debug_image_) { // Plot out the original blobs for which no match was found in the new // all_blobs list. C_BLOB_IT not_found_it(¬_found_blobs); for (not_found_it.mark_cycle_pt(); !not_found_it.cycled_list(); not_found_it.forward()) { C_BLOB* not_found = not_found_it.data(); TBOX not_found_box = not_found->bounding_box(); Box* box_to_plot = GetBoxForTBOX(not_found_box); pixRenderBoxArb(debug_image_, box_to_plot, 1, 255, 0, 255); boxDestroy(&box_to_plot); } // Plot out the blobs unused from all blobs. C_BLOB_IT all_blobs_it(new_blobs); for (all_blobs_it.mark_cycle_pt(); !all_blobs_it.cycled_list(); all_blobs_it.forward()) { C_BLOB* a_blob = all_blobs_it.data(); Box* box_to_plot = GetBoxForTBOX(a_blob->bounding_box()); pixRenderBoxArb(debug_image_, box_to_plot, 3, 0, 127, 0); boxDestroy(&box_to_plot); } } }
LeptPrepareFile::~LeptPrepareFile() { pixDestroy(&pixRotate000); pixDestroy(&pixRotate090); pixDestroy(&pixRotate180); pixDestroy(&pixRotate270); pixDestroy(&pix); pixDestroy(&pixClear); boxDestroy(&boxFirstCrop); }
// Given an input pix, and a box, the sides of the box are shrunk inwards until // they bound any black pixels found within the original box. // The function converts between tesseract coords and the pix coords assuming // that this pix is full resolution equal in size to the original image. // Returns an empty box if there are no black pixels in the source box. static TBOX BoundsWithinBox(Pix* pix, const TBOX& box) { int im_height = pixGetHeight(pix); Box* input_box = boxCreate(box.left(), im_height - box.top(), box.width(), box.height()); Box* output_box = NULL; pixClipBoxToForeground(pix, input_box, NULL, &output_box); TBOX result_box; if (output_box != NULL) { l_int32 x, y, width, height; boxGetGeometry(output_box, &x, &y, &width, &height); result_box.set_left(x); result_box.set_right(x + width); result_box.set_top(im_height - y); result_box.set_bottom(result_box.top() - height); boxDestroy(&output_box); } boxDestroy(&input_box); return result_box; }