本文整理汇总了C++中pixGetHeight函数的典型用法代码示例。如果您正苦于以下问题:C++ pixGetHeight函数的具体用法?C++ pixGetHeight怎么用?C++ pixGetHeight使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了pixGetHeight函数的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: main_find_pattern
int main_find_pattern(int argc,
char **argv)
{
char *filein, *fileout, *patternfile;
l_int32 w, h, i, n;
BOX *box, *boxe;
BOXA *boxa1, *boxa2;
PIX *pixs, *pixp, *pixpe;
PIX *pixd, *pixt1, *pixt2, *pixhmt;
SEL *sel_2h, *sel;
static char mainName[] = "findpattern1";
filein = "feyn.tif";
patternfile = "char.tif";
fileout = "result.findpattern1";
if ((pixs = pixRead(filein)) == NULL)
printf("pixs not made\n");
if ((pixp = pixRead(patternfile)) == NULL)
printf("pixp not made\n");
w = pixGetWidth(pixp);
h = pixGetHeight(pixp);
/* generate the hit-miss Sel with runs */
sel = pixGenerateSelWithRuns(pixp, NumHorLines, NumVertLines, 0,
MinRunlength, 7, 7, 0, 0, &pixpe);
/* display the Sel two ways */
selWriteStream(stderr, sel);
pixt1 = pixDisplayHitMissSel(pixpe, sel, 9, HitColor, MissColor);
pixDisplay(pixt1, 200, 200);
pixWrite("junkpixt", pixt1, IFF_PNG);
/* use the Sel to find all instances in the page */
startTimer();
pixhmt = pixHMT(NULL, pixs, sel);
fprintf(stderr, "Time to find patterns = %7.3f\n", stopTimer());
/* small erosion to remove noise; typically not necessary if
* there are enough elements in the Sel */
sel_2h = selCreateBrick(1, 2, 0, 0, SEL_HIT);
pixt2 = pixErode(NULL, pixhmt, sel_2h);
/* display the result visually by placing the Sel at each
* location found */
pixd = pixDilate(NULL, pixt2, sel);
pixWrite(fileout, pixd, IFF_TIFF_G4);
/* display outut with an outline around each located pattern */
boxa1 = pixConnCompBB(pixt2, 8);
n = boxaGetCount(boxa1);
boxa2 = boxaCreate(n);
for (i = 0; i < n; i++) {
box = boxaGetBox(boxa1, i, L_COPY);
boxe = boxCreate(box->x - w / 2, box->y - h / 2, w + 4, h + 4);
boxaAddBox(boxa2, boxe, L_INSERT);
pixRenderBox(pixs, boxe, 4, L_FLIP_PIXELS);
boxDestroy(&box);
}
pixWrite("junkoutline", pixs, IFF_TIFF_G4);
//boxaWriteStream(stderr, boxa2); //TODO ???
pixDestroy(&pixs);
pixDestroy(&pixp);
pixDestroy(&pixpe);
pixDestroy(&pixt1);
pixDestroy(&pixt2);
pixDestroy(&pixhmt);
pixDestroy(&pixd);
selDestroy(&sel);
selDestroy(&sel_2h);
boxaDestroy(&boxa1);
boxaDestroy(&boxa2);
printf("\n---\nEND\n");
getchar();
return 0;
}
示例2: main
//.........这里部分代码省略.........
/* --------- hdome with parameter height = 100 ------------*/
pixd = pixHDome(pixs, 100, 4);
pixd2 = pixMaxDynamicRange(pixd, L_LINEAR_SCALE);
pixDisplayWrite(pixd2, 1);
pixDestroy(&pixd2);
/* ----- Contrast enhancement with morph parameters 9, 9 -------*/
pixd1 = pixInitAccumulate(w, h, 0x8000);
pixAccumulate(pixd1, pixs, L_ARITH_ADD);
pixMultConstAccumulate(pixd1, 3., 0x8000);
pixd2 = pixOpenGray(pixs, 9, 9);
pixAccumulate(pixd1, pixd2, L_ARITH_SUBTRACT);
pixDestroy(&pixd2);
pixd2 = pixCloseGray(pixs, 9, 9);
pixAccumulate(pixd1, pixd2, L_ARITH_SUBTRACT);
pixDestroy(&pixd2);
pixd = pixFinalAccumulate(pixd1, 0x8000, 8);
pixDisplayWrite(pixd, 1);
pixDestroy(&pixd1);
/* Do the same thing with the Pixacc */
pacc = pixaccCreate(w, h, 1);
pixaccAdd(pacc, pixs);
pixaccMultConst(pacc, 3.);
pixd1 = pixOpenGray(pixs, 9, 9);
pixaccSubtract(pacc, pixd1);
pixDestroy(&pixd1);
pixd1 = pixCloseGray(pixs, 9, 9);
pixaccSubtract(pacc, pixd1);
pixDestroy(&pixd1);
pixd2 = pixaccFinal(pacc, 8);
pixaccDestroy(&pacc);
pixDisplayWrite(pixd2, 1);
pixCompare(pixd, pixd2, "Correct: same", "Wrong: different");
pixDestroy(&pixd);
pixDestroy(&pixd2);
/* ---- Tophat result on feynman stamp, to extract diagrams ----- */
pixDestroy(&pixs);
pixs = pixRead("feynman-stamp.jpg");
/* Make output image to hold five intermediate images */
w = pixGetWidth(pixs);
h = pixGetHeight(pixs);
pixd = pixCreate(5 * w + 18, h + 6, 32); /* composite output image */
pixSetAllArbitrary(pixd, 0x0000ff00); /* set to blue */
/* Paste in the input image */
pixt = pixRemoveColormap(pixs, REMOVE_CMAP_TO_FULL_COLOR);
pixRasterop(pixd, 3, 3, w, h, PIX_SRC, pixt, 0, 0); /* 1st one */
/* pixWrite("/tmp/junkgray.jpg", pixt, IFF_JFIF_JPEG); */
pixDestroy(&pixt);
/* Paste in the grayscale version */
cmap = pixGetColormap(pixs);
if (cmap)
pixt = pixRemoveColormap(pixs, REMOVE_CMAP_TO_GRAYSCALE);
else
pixt = pixConvertRGBToGray(pixs, 0.33, 0.34, 0.33);
pixt2 = pixConvertTo32(pixt); /* 8 --> 32 bpp */
pixRasterop(pixd, w + 6, 3, w, h, PIX_SRC, pixt2, 0, 0); /* 2nd one */
pixDestroy(&pixt2);
/* Paste in a log dynamic range scaled version of the white tophat */
pixt2 = pixTophat(pixt, 3, 3, L_TOPHAT_WHITE);
pixt3a = pixMaxDynamicRange(pixt2, L_LOG_SCALE);
pixt3 = pixConvertTo32(pixt3a);
pixRasterop(pixd, 2 * w + 9, 3, w, h, PIX_SRC, pixt3, 0, 0); /* 3rd */
/* pixWrite("/tmp/junktophat.jpg", pixt2, IFF_JFIF_JPEG); */
pixDestroy(&pixt3);
pixDestroy(&pixt3a);
pixDestroy(&pixt);
/* Stretch the range and threshold to binary; paste it in */
pixt3a = pixGammaTRC(NULL, pixt2, 1.0, 0, 80);
pixt3 = pixThresholdToBinary(pixt3a, 70);
pixt4 = pixConvertTo32(pixt3);
pixRasterop(pixd, 3 * w + 12, 3, w, h, PIX_SRC, pixt4, 0, 0); /* 4th */
/* pixWrite("/tmp/junkbin.png", pixt3, IFF_PNG); */
pixDestroy(&pixt2);
pixDestroy(&pixt3a);
pixDestroy(&pixt4);
/* Invert; this is the final result */
pixInvert(pixt3, pixt3);
pixt4 = pixConvertTo32(pixt3);
pixRasterop(pixd, 4 * w + 15, 3, w, h, PIX_SRC, pixt4, 0, 0); /* 5th */
pixWrite("/tmp/junkbininvert.png", pixt3, IFF_PNG);
pixDisplayWrite(pixd, 1);
/* pixWrite("/tmp/junkall.jpg", pixd, IFF_JFIF_JPEG); */
pixDestroy(&pixt3);
pixDestroy(&pixt4);
pixDestroy(&pixd);
pixDisplayMultiple("/tmp/junk_write_display*");
pixDestroy(&pixs);
return 0;
}
示例3: pixConnCompPixa
/*!
* \brief pixConnCompPixa()
*
* \param[in] pixs 1 bpp
* \param[out] ppixa pixa of each c.c.
* \param[in] connectivity 4 or 8
* \return boxa, or NULL on error
*
* <pre>
* Notes:
* (1) This finds bounding boxes of 4- or 8-connected components
* in a binary image, and saves images of each c.c
* in a pixa array.
* (2) It sets up 2 temporary pix, and for each c.c. that is
* located in raster order, it erases the c.c. from one pix,
* then uses the b.b. to extract the c.c. from the two pix using
* an XOR, and finally erases the c.c. from the second pix.
* (3) A clone of the returned boxa (where all boxes in the array
* are clones) is inserted into the pixa.
* (4) If the input is valid, this always returns a boxa and a pixa.
* If pixs is empty, the boxa and pixa will be empty.
* </pre>
*/
BOXA *
pixConnCompPixa(PIX *pixs,
PIXA **ppixa,
l_int32 connectivity)
{
l_int32 h, iszero;
l_int32 x, y, xstart, ystart;
PIX *pixt1, *pixt2, *pixt3, *pixt4;
PIXA *pixa;
BOX *box;
BOXA *boxa;
L_STACK *stack, *auxstack;
PROCNAME("pixConnCompPixa");
if (!ppixa)
return (BOXA *)ERROR_PTR("&pixa not defined", procName, NULL);
*ppixa = NULL;
if (!pixs || pixGetDepth(pixs) != 1)
return (BOXA *)ERROR_PTR("pixs undefined or not 1 bpp", procName, NULL);
if (connectivity != 4 && connectivity != 8)
return (BOXA *)ERROR_PTR("connectivity not 4 or 8", procName, NULL);
pixa = pixaCreate(0);
*ppixa = pixa;
pixZero(pixs, &iszero);
if (iszero)
return boxaCreate(1); /* return empty boxa */
if ((pixt1 = pixCopy(NULL, pixs)) == NULL)
return (BOXA *)ERROR_PTR("pixt1 not made", procName, NULL);
if ((pixt2 = pixCopy(NULL, pixs)) == NULL)
return (BOXA *)ERROR_PTR("pixt2 not made", procName, NULL);
h = pixGetHeight(pixs);
if ((stack = lstackCreate(h)) == NULL)
return (BOXA *)ERROR_PTR("stack not made", procName, NULL);
if ((auxstack = lstackCreate(0)) == NULL)
return (BOXA *)ERROR_PTR("auxstack not made", procName, NULL);
stack->auxstack = auxstack;
if ((boxa = boxaCreate(0)) == NULL)
return (BOXA *)ERROR_PTR("boxa not made", procName, NULL);
xstart = 0;
ystart = 0;
while (1)
{
if (!nextOnPixelInRaster(pixt1, xstart, ystart, &x, &y))
break;
if ((box = pixSeedfillBB(pixt1, stack, x, y, connectivity)) == NULL)
return (BOXA *)ERROR_PTR("box not made", procName, NULL);
boxaAddBox(boxa, box, L_INSERT);
/* Save the c.c. and remove from pixt2 as well */
pixt3 = pixClipRectangle(pixt1, box, NULL);
pixt4 = pixClipRectangle(pixt2, box, NULL);
pixXor(pixt3, pixt3, pixt4);
pixRasterop(pixt2, box->x, box->y, box->w, box->h, PIX_SRC ^ PIX_DST,
pixt3, 0, 0);
pixaAddPix(pixa, pixt3, L_INSERT);
pixDestroy(&pixt4);
xstart = x;
ystart = y;
}
#if DEBUG
pixCountPixels(pixt1, &iszero, NULL);
fprintf(stderr, "Number of remaining pixels = %d\n", iszero);
pixWrite("junkremain", pixt1, IFF_PNG);
#endif /* DEBUG */
/* Remove old boxa of pixa and replace with a clone copy */
boxaDestroy(&pixa->boxa);
pixa->boxa = boxaCopy(boxa, L_CLONE);
//.........这里部分代码省略.........
示例4: pixGenerateSelBoundary
/*!
* pixGenerateSelBoundary()
*
* Input: pix (1 bpp, typically small, to be used as a pattern)
* hitdist (min distance from fg boundary pixel)
* missdist (min distance from bg boundary pixel)
* hitskip (number of boundary pixels skipped between hits)
* missskip (number of boundary pixels skipped between misses)
* topflag (flag for extra pixels of bg added above)
* botflag (flag for extra pixels of bg added below)
* leftflag (flag for extra pixels of bg added to left)
* rightflag (flag for extra pixels of bg added to right)
* &pixe (<optional return> input pix expanded by extra pixels)
* Return: sel (hit-miss for input pattern), or null on error
*
* Notes:
* (1) All fg elements selected are exactly hitdist pixels away from
* the nearest fg boundary pixel, and ditto for bg elements.
* Valid inputs of hitdist and missdist are 0, 1, 2, 3 and 4.
* For example, a hitdist of 0 puts the hits at the fg boundary.
* Usually, the distances should be > 0 avoid the effect of
* noise at the boundary.
* (2) Set hitskip < 0 if no hits are to be used. Ditto for missskip.
* If both hitskip and missskip are < 0, the sel would be empty,
* and NULL is returned.
* (3) The 4 flags determine whether the sel is increased on that side
* to allow bg misses to be placed all along that boundary.
* The increase in sel size on that side is the minimum necessary
* to allow the misses to be placed at mindist. For text characters,
* the topflag and botflag are typically set to 1, and the leftflag
* and rightflag to 0.
* (4) The input pix, as extended by the extra pixels on selected sides,
* can optionally be returned. For debugging, call
* pixDisplayHitMissSel() to visualize the hit-miss sel superimposed
* on the generating bitmap.
* (5) This is probably the best of the three sel generators, in the
* sense that you have the most flexibility with the smallest number
* of hits and misses.
*/
SEL *
pixGenerateSelBoundary(PIX *pixs,
l_int32 hitdist,
l_int32 missdist,
l_int32 hitskip,
l_int32 missskip,
l_int32 topflag,
l_int32 botflag,
l_int32 leftflag,
l_int32 rightflag,
PIX **ppixe)
{
l_int32 ws, hs, w, h, x, y, ix, iy, i, npt;
PIX *pixt1, *pixt2, *pixt3, *pixfg, *pixbg;
SEL *selh, *selm, *sel_3, *sel;
PTA *ptah, *ptam;
PROCNAME("pixGenerateSelBoundary");
if (ppixe) *ppixe = NULL;
if (!pixs)
return (SEL *)ERROR_PTR("pixs not defined", procName, NULL);
if (pixGetDepth(pixs) != 1)
return (SEL *)ERROR_PTR("pixs not 1 bpp", procName, NULL);
if (hitdist < 0 || hitdist > 4 || missdist < 0 || missdist > 4)
return (SEL *)ERROR_PTR("dist not in {0 .. 4}", procName, NULL);
if (hitskip < 0 && missskip < 0)
return (SEL *)ERROR_PTR("no hits or misses", procName, NULL);
/* Locate the foreground */
pixClipToForeground(pixs, &pixt1, NULL);
if (!pixt1)
return (SEL *)ERROR_PTR("pixt1 not made", procName, NULL);
ws = pixGetWidth(pixt1);
hs = pixGetHeight(pixt1);
w = ws;
h = hs;
/* Crop out a region including the foreground, and add pixels
* on sides depending on the side flags */
if (topflag || botflag || leftflag || rightflag) {
x = y = 0;
if (topflag) {
h += missdist + 1;
y = missdist + 1;
}
if (botflag)
h += missdist + 1;
if (leftflag) {
w += missdist + 1;
x = missdist + 1;
}
if (rightflag)
w += missdist + 1;
pixt2 = pixCreate(w, h, 1);
pixRasterop(pixt2, x, y, ws, hs, PIX_SRC, pixt1, 0, 0);
}
else {
pixt2 = pixClone(pixt1);
}
if (ppixe)
//.........这里部分代码省略.........
示例5: pixGetData
// Adds sub-pixel resolution EdgeOffsets for the outline if the supplied
// pix is 8-bit. Does nothing otherwise.
// Operation: Consider the following near-horizontal line:
// _________
// |________
// |________
// At *every* position along this line, the gradient direction will be close
// to vertical. Extrapoaltion/interpolation of the position of the threshold
// that was used to binarize the image gives a more precise vertical position
// for each horizontal step, and the conflict in step direction and gradient
// direction can be used to ignore the vertical steps.
void C_OUTLINE::ComputeEdgeOffsets(int threshold, Pix* pix) {
if (pixGetDepth(pix) != 8) return;
const l_uint32* data = pixGetData(pix);
int wpl = pixGetWpl(pix);
int width = pixGetWidth(pix);
int height = pixGetHeight(pix);
bool negative = flag(COUT_INVERSE);
delete [] offsets;
offsets = new EdgeOffset[stepcount];
ICOORD pos = start;
ICOORD prev_gradient;
ComputeGradient(data, wpl, pos.x(), height - pos.y(), width, height,
&prev_gradient);
for (int s = 0; s < stepcount; ++s) {
ICOORD step_vec = step(s);
TPOINT pt1(pos);
pos += step_vec;
TPOINT pt2(pos);
ICOORD next_gradient;
ComputeGradient(data, wpl, pos.x(), height - pos.y(), width, height,
&next_gradient);
// Use the sum of the prev and next as the working gradient.
ICOORD gradient = prev_gradient + next_gradient;
// best_diff will be manipulated to be always positive.
int best_diff = 0;
// offset will be the extrapolation of the location of the greyscale
// threshold from the edge with the largest difference, relative to the
// location of the binary edge.
int offset = 0;
if (pt1.y == pt2.y && abs(gradient.y()) * 2 >= abs(gradient.x())) {
// Horizontal step. diff_sign == 1 indicates black above.
int diff_sign = (pt1.x > pt2.x) == negative ? 1 : -1;
int x = MIN(pt1.x, pt2.x);
int y = height - pt1.y;
int best_sum = 0;
int best_y = y;
EvaluateVerticalDiff(data, wpl, diff_sign, x, y, height,
&best_diff, &best_sum, &best_y);
// Find the strongest edge.
int test_y = y;
do {
++test_y;
} while (EvaluateVerticalDiff(data, wpl, diff_sign, x, test_y, height,
&best_diff, &best_sum, &best_y));
test_y = y;
do {
--test_y;
} while (EvaluateVerticalDiff(data, wpl, diff_sign, x, test_y, height,
&best_diff, &best_sum, &best_y));
offset = diff_sign * (best_sum / 2 - threshold) +
(y - best_y) * best_diff;
} else if (pt1.x == pt2.x && abs(gradient.x()) * 2 >= abs(gradient.y())) {
// Vertical step. diff_sign == 1 indicates black on the left.
int diff_sign = (pt1.y > pt2.y) == negative ? 1 : -1;
int x = pt1.x;
int y = height - MAX(pt1.y, pt2.y);
const l_uint32* line = pixGetData(pix) + y * wpl;
int best_sum = 0;
int best_x = x;
EvaluateHorizontalDiff(line, diff_sign, x, width,
&best_diff, &best_sum, &best_x);
// Find the strongest edge.
int test_x = x;
do {
++test_x;
} while (EvaluateHorizontalDiff(line, diff_sign, test_x, width,
&best_diff, &best_sum, &best_x));
test_x = x;
do {
--test_x;
} while (EvaluateHorizontalDiff(line, diff_sign, test_x, width,
&best_diff, &best_sum, &best_x));
offset = diff_sign * (threshold - best_sum / 2) +
(best_x - x) * best_diff;
}
offsets[s].offset_numerator =
static_cast<inT8>(ClipToRange(offset, -MAX_INT8, MAX_INT8));
offsets[s].pixel_diff = static_cast<uinT8>(ClipToRange(best_diff, 0 ,
MAX_UINT8));
if (negative) gradient = -gradient;
// Compute gradient angle quantized to 256 directions, rotated by 64 (pi/2)
// to convert from gradient direction to edge direction.
offsets[s].direction =
Modulo(FCOORD::binary_angle_plus_pi(gradient.angle()) + 64, 256);
prev_gradient = next_gradient;
}
}
示例6: main
int main(int argc,
char **argv)
{
l_int32 i, j, sindex, wb, hb, ws, hs, delx, dely, x, y, y0;
PIX *pixs, *pixb, *pix1, *pix2;
PIXA *pixa;
PIXCMAP *cmap;
setLeptDebugOK(1);
lept_mkdir("lept/blend");
pixa = pixaCreate(0);
pixs = pixRead("rabi.png"); /* blendee */
pixb = pixRead("weasel4.11c.png"); /* blender */
/* Fade the blender */
pixcmapShiftIntensity(pixGetColormap(pixb), FADE_FRACTION);
/* Downscale the input */
wb = pixGetWidth(pixb);
hb = pixGetHeight(pixb);
pix1 = pixScaleToGray4(pixs);
/* Threshold to 5 levels, 4 bpp */
ws = pixGetWidth(pix1);
hs = pixGetHeight(pix1);
pix2 = pixThresholdTo4bpp(pix1, 5, 1);
pixaAddPix(pixa, pix2, L_COPY);
pixaAddPix(pixa, pixb, L_COPY);
cmap = pixGetColormap(pix2);
pixcmapWriteStream(stderr, cmap);
/* Overwrite the white pixels (at sindex in pix2) */
pixcmapGetIndex(cmap, 255, 255, 255, &sindex);
/* Blend the weasel 20 times */
delx = ws / NX;
dely = hs / NY;
for (i = 0; i < NY; i++) {
y = 20 + i * dely;
if (y >= hs + hb)
continue;
for (j = 0; j < NX; j++) {
x = 30 + j * delx;
y0 = y;
if (j & 1) {
y0 = y + dely / 2;
if (y0 >= hs + hb)
continue;
}
if (x >= ws + wb)
continue;
pixBlendCmap(pix2, pixb, x, y0, sindex);
}
}
pixaAddPix(pixa, pix2, L_COPY);
cmap = pixGetColormap(pix2);
pixcmapWriteStream(stderr, cmap);
fprintf(stderr, "Writing to: /tmp/lept/blend/blendcmap.pdf\n");
pixaConvertToPdf(pixa, 0, 1.0, L_FLATE_ENCODE, 0, "cmap-blendtest",
"/tmp/lept/blend/blendcmap.pdf");
pixDestroy(&pixs);
pixDestroy(&pixb);
pixDestroy(&pix1);
pixDestroy(&pix2);
pixaDestroy(&pixa);
return 0;
}
示例7: pixGenerateSelWithRuns
/*!
* pixGenerateSelWithRuns()
*
* Input: pix (1 bpp, typically small, to be used as a pattern)
* nhlines (number of hor lines along which elements are found)
* nvlines (number of vert lines along which elements are found)
* distance (min distance from boundary pixel; use 0 for default)
* minlength (min runlength to set hit or miss; use 0 for default)
* toppix (number of extra pixels of bg added above)
* botpix (number of extra pixels of bg added below)
* leftpix (number of extra pixels of bg added to left)
* rightpix (number of extra pixels of bg added to right)
* &pixe (<optional return> input pix expanded by extra pixels)
* Return: sel (hit-miss for input pattern), or null on error
*
* Notes:
* (1) The horizontal and vertical lines along which elements are
* selected are roughly equally spaced. The actual locations of
* the hits and misses are the centers of respective run-lengths.
* (2) No elements are selected that are less than 'distance' pixels away
* from a boundary pixel of the same color. This makes the
* match much more robust to edge noise. Valid inputs of
* 'distance' are 0, 1, 2, 3 and 4. If distance is either 0 or
* greater than 4, we reset it to the default value.
* (3) The 4 numbers for adding rectangles of pixels outside the fg
* can be use if the pattern is expected to be surrounded by bg
* (white) pixels. On the other hand, if the pattern may be near
* other fg (black) components on some sides, use 0 for those sides.
* (4) The pixels added to a side allow you to have miss elements there.
* There is a constraint between distance, minlength, and
* the added pixels for this to work. We illustrate using the
* default values. If you add 5 pixels to the top, and use a
* distance of 1, then you end up with a vertical run of at least
* 4 bg pixels along the top edge of the image. If you use a
* minimum runlength of 3, each vertical line will always find
* a miss near the center of its run. However, if you use a
* minimum runlength of 5, you will not get a miss on every vertical
* line. As another example, if you have 7 added pixels and a
* distance of 2, you can use a runlength up to 5 to guarantee
* that the miss element is recorded. We give a warning if the
* contraint does not guarantee a miss element outside the
* image proper.
* (5) The input pix, as extended by the extra pixels on selected sides,
* can optionally be returned. For debugging, call
* pixDisplayHitMissSel() to visualize the hit-miss sel superimposed
* on the generating bitmap.
*/
SEL *
pixGenerateSelWithRuns(PIX *pixs,
l_int32 nhlines,
l_int32 nvlines,
l_int32 distance,
l_int32 minlength,
l_int32 toppix,
l_int32 botpix,
l_int32 leftpix,
l_int32 rightpix,
PIX **ppixe)
{
l_int32 ws, hs, w, h, x, y, xval, yval, i, j, nh, nm;
l_float32 delh, delw;
NUMA *nah, *nam;
PIX *pixt1, *pixt2, *pixfg, *pixbg;
PTA *ptah, *ptam;
SEL *seld, *sel;
PROCNAME("pixGenerateSelWithRuns");
if (ppixe) *ppixe = NULL;
if (!pixs)
return (SEL *)ERROR_PTR("pixs not defined", procName, NULL);
if (pixGetDepth(pixs) != 1)
return (SEL *)ERROR_PTR("pixs not 1 bpp", procName, NULL);
if (nhlines < 1 && nvlines < 1)
return (SEL *)ERROR_PTR("nvlines and nhlines both < 1", procName, NULL);
if (distance <= 0)
distance = DEFAULT_DISTANCE_TO_BOUNDARY;
if (minlength <= 0)
minlength = DEFAULT_MIN_RUNLENGTH;
if (distance > MAX_DISTANCE_TO_BOUNDARY) {
L_WARNING("distance too large; setting to max value", procName);
distance = MAX_DISTANCE_TO_BOUNDARY;
}
/* Locate the foreground */
pixClipToForeground(pixs, &pixt1, NULL);
if (!pixt1)
return (SEL *)ERROR_PTR("pixt1 not made", procName, NULL);
ws = pixGetWidth(pixt1);
hs = pixGetHeight(pixt1);
w = ws;
h = hs;
/* Crop out a region including the foreground, and add pixels
* on sides depending on the side flags */
if (toppix || botpix || leftpix || rightpix) {
x = y = 0;
if (toppix) {
h += toppix;
//.........这里部分代码省略.........
示例8: ASSERT_HOST
/**
* Segment the page according to the current value of tessedit_pageseg_mode.
* pix_binary_ is used as the source image and should not be NULL.
* On return the blocks list owns all the constructed page layout.
*/
int Tesseract::SegmentPage(const STRING* input_file, BLOCK_LIST* blocks,
Tesseract* osd_tess, OSResults* osr) {
ASSERT_HOST(pix_binary_ != NULL);
int width = pixGetWidth(pix_binary_);
int height = pixGetHeight(pix_binary_);
// Get page segmentation mode.
PageSegMode pageseg_mode = static_cast<PageSegMode>(
static_cast<int>(tessedit_pageseg_mode));
// If a UNLV zone file can be found, use that instead of segmentation.
if (!PSM_COL_FIND_ENABLED(pageseg_mode) &&
input_file != NULL && input_file->length() > 0) {
STRING name = *input_file;
const char* lastdot = strrchr(name.string(), '.');
if (lastdot != NULL)
name[lastdot - name.string()] = '\0';
read_unlv_file(name, width, height, blocks);
}
if (blocks->empty()) {
// No UNLV file present. Work according to the PageSegMode.
// First make a single block covering the whole image.
BLOCK_IT block_it(blocks);
BLOCK* block = new BLOCK("", TRUE, 0, 0, 0, 0, width, height);
block->set_right_to_left(right_to_left());
block_it.add_to_end(block);
} else {
// UNLV file present. Use PSM_SINGLE_BLOCK.
pageseg_mode = PSM_SINGLE_BLOCK;
}
// The diacritic_blobs holds noise blobs that may be diacritics. They
// are separated out on areas of the image that seem noisy and short-circuit
// the layout process, going straight from the initial partition creation
// right through to after word segmentation, where they are added to the
// rej_cblobs list of the most appropriate word. From there classification
// will determine whether they are used.
BLOBNBOX_LIST diacritic_blobs;
int auto_page_seg_ret_val = 0;
TO_BLOCK_LIST to_blocks;
if (PSM_OSD_ENABLED(pageseg_mode) || PSM_BLOCK_FIND_ENABLED(pageseg_mode) ||
PSM_SPARSE(pageseg_mode)) {
auto_page_seg_ret_val = AutoPageSeg(
pageseg_mode, blocks, &to_blocks,
enable_noise_removal ? &diacritic_blobs : NULL, osd_tess, osr);
if (pageseg_mode == PSM_OSD_ONLY)
return auto_page_seg_ret_val;
// To create blobs from the image region bounds uncomment this line:
// to_blocks.clear(); // Uncomment to go back to the old mode.
} else {
deskew_ = FCOORD(1.0f, 0.0f);
reskew_ = FCOORD(1.0f, 0.0f);
if (pageseg_mode == PSM_CIRCLE_WORD) {
Pix* pixcleaned = RemoveEnclosingCircle(pix_binary_);
if (pixcleaned != NULL) {
pixDestroy(&pix_binary_);
pix_binary_ = pixcleaned;
}
}
}
if (auto_page_seg_ret_val < 0) {
return -1;
}
if (blocks->empty()) {
if (textord_debug_tabfind)
tprintf("Empty page\n");
return 0; // AutoPageSeg found an empty page.
}
bool splitting =
pageseg_devanagari_split_strategy != ShiroRekhaSplitter::NO_SPLIT;
bool cjk_mode = textord_use_cjk_fp_model;
textord_.TextordPage(pageseg_mode, reskew_, width, height, pix_binary_,
pix_thresholds_, pix_grey_, splitting || cjk_mode,
&diacritic_blobs, blocks, &to_blocks);
return auto_page_seg_ret_val;
}
示例9: SetBlobStrokeWidth
/**********************************************************************
* SetBlobStrokeWidth
*
* Set the horizontal and vertical stroke widths in the blob.
**********************************************************************/
void SetBlobStrokeWidth(Pix* pix, BLOBNBOX* blob) {
// Cut the blob rectangle into a Pix.
int pix_height = pixGetHeight(pix);
const TBOX& box = blob->bounding_box();
int width = box.width();
int height = box.height();
Box* blob_pix_box = boxCreate(box.left(), pix_height - box.top(),
width, height);
Pix* pix_blob = pixClipRectangle(pix, blob_pix_box, nullptr);
boxDestroy(&blob_pix_box);
Pix* dist_pix = pixDistanceFunction(pix_blob, 4, 8, L_BOUNDARY_BG);
pixDestroy(&pix_blob);
// Compute the stroke widths.
uint32_t* data = pixGetData(dist_pix);
int wpl = pixGetWpl(dist_pix);
// Horizontal width of stroke.
STATS h_stats(0, width + 1);
for (int y = 0; y < height; ++y) {
uint32_t* pixels = data + y*wpl;
int prev_pixel = 0;
int pixel = GET_DATA_BYTE(pixels, 0);
for (int x = 1; x < width; ++x) {
int next_pixel = GET_DATA_BYTE(pixels, x);
// We are looking for a pixel that is equal to its vertical neighbours,
// yet greater than its left neighbour.
if (prev_pixel < pixel &&
(y == 0 || pixel == GET_DATA_BYTE(pixels - wpl, x - 1)) &&
(y == height - 1 || pixel == GET_DATA_BYTE(pixels + wpl, x - 1))) {
if (pixel > next_pixel) {
// Single local max, so an odd width.
h_stats.add(pixel * 2 - 1, 1);
} else if (pixel == next_pixel && x + 1 < width &&
pixel > GET_DATA_BYTE(pixels, x + 1)) {
// Double local max, so an even width.
h_stats.add(pixel * 2, 1);
}
}
prev_pixel = pixel;
pixel = next_pixel;
}
}
// Vertical width of stroke.
STATS v_stats(0, height + 1);
for (int x = 0; x < width; ++x) {
int prev_pixel = 0;
int pixel = GET_DATA_BYTE(data, x);
for (int y = 1; y < height; ++y) {
uint32_t* pixels = data + y*wpl;
int next_pixel = GET_DATA_BYTE(pixels, x);
// We are looking for a pixel that is equal to its horizontal neighbours,
// yet greater than its upper neighbour.
if (prev_pixel < pixel &&
(x == 0 || pixel == GET_DATA_BYTE(pixels - wpl, x - 1)) &&
(x == width - 1 || pixel == GET_DATA_BYTE(pixels - wpl, x + 1))) {
if (pixel > next_pixel) {
// Single local max, so an odd width.
v_stats.add(pixel * 2 - 1, 1);
} else if (pixel == next_pixel && y + 1 < height &&
pixel > GET_DATA_BYTE(pixels + wpl, x)) {
// Double local max, so an even width.
v_stats.add(pixel * 2, 1);
}
}
prev_pixel = pixel;
pixel = next_pixel;
}
}
pixDestroy(&dist_pix);
// Store the horizontal and vertical width in the blob, keeping both
// widths if there is enough information, otherwse only the one with
// the most samples.
// If there are insufficient samples, store zero, rather than using
// 2*area/perimeter, as the numbers that gives do not match the numbers
// from the distance method.
if (h_stats.get_total() >= (width + height) / 4) {
blob->set_horz_stroke_width(h_stats.ile(0.5f));
if (v_stats.get_total() >= (width + height) / 4)
blob->set_vert_stroke_width(v_stats.ile(0.5f));
else
blob->set_vert_stroke_width(0.0f);
} else {
if (v_stats.get_total() >= (width + height) / 4 ||
v_stats.get_total() > h_stats.get_total()) {
blob->set_horz_stroke_width(0.0f);
blob->set_vert_stroke_width(v_stats.ile(0.5f));
} else {
blob->set_horz_stroke_width(h_stats.get_total() > 2 ? h_stats.ile(0.5f)
: 0.0f);
blob->set_vert_stroke_width(0.0f);
}
}
}
示例10: pixaGenerateFont
/*!
* pixaGenerateFont()
*
* Input: pix (of 95 characters in 3 rows)
* fontsize (4, 6, 8, ... , 20, in pts at 300 ppi)
* &bl1 (<return> baseline of row 1)
* &bl2 (<return> baseline of row 2)
* &bl3 (<return> baseline of row 3)
* Return: pixa of font bitmaps for 95 characters, or null on error
*
* Notes:
* (1) This does all the work. See pixaGenerateFontFromFile()
* for an overview.
* (2) The pix is for one of the 9 fonts. @fontsize is only
* used here for debugging.
*/
PIXA *
pixaGenerateFont(PIX *pixs,
l_int32 fontsize,
l_int32 *pbl0,
l_int32 *pbl1,
l_int32 *pbl2)
{
l_int32 i, j, nrows, nrowchars, nchars, h, yval;
l_int32 width, height;
l_int32 baseline[3];
l_int32 *tab = NULL;
BOX *box, *box1, *box2;
BOXA *boxar, *boxac, *boxacs;
PIX *pix1, *pix2, *pixr, *pixrc, *pixc;
PIXA *pixa;
l_int32 n, w, inrow, top;
l_int32 *ia;
NUMA *na;
PROCNAME("pixaGenerateFont");
if (!pbl0 || !pbl1 || !pbl2)
return (PIXA *)ERROR_PTR("&bl not all defined", procName, NULL);
*pbl0 = *pbl1 = *pbl2 = 0;
if (!pixs)
return (PIXA *)ERROR_PTR("pixs not defined", procName, NULL);
/* Locate the 3 rows of characters */
w = pixGetWidth(pixs);
na = pixCountPixelsByRow(pixs, NULL);
boxar = boxaCreate(0);
n = numaGetCount(na);
ia = numaGetIArray(na);
inrow = 0;
for (i = 0; i < n; i++) {
if (!inrow && ia[i] > 0) {
inrow = 1;
top = i;
} else if (inrow && ia[i] == 0) {
inrow = 0;
box = boxCreate(0, top, w, i - top);
boxaAddBox(boxar, box, L_INSERT);
}
}
FREE(ia);
numaDestroy(&na);
nrows = boxaGetCount(boxar);
#if DEBUG_FONT_GEN
L_INFO("For fontsize %s, have %d rows\n", procName, fontsize, nrows);
#endif /* DEBUG_FONT_GEN */
if (nrows != 3) {
L_INFO("nrows = %d; skipping fontsize %d\n", procName, nrows, fontsize);
return (PIXA *)ERROR_PTR("3 rows not generated", procName, NULL);
}
/* Grab the character images and baseline data */
#if DEBUG_BASELINE
lept_rmdir("baseline");
lept_mkdir("baseline");
#endif /* DEBUG_BASELINE */
tab = makePixelSumTab8();
pixa = pixaCreate(95);
for (i = 0; i < nrows; i++) {
box = boxaGetBox(boxar, i, L_CLONE);
pixr = pixClipRectangle(pixs, box, NULL); /* row of chars */
pixGetTextBaseline(pixr, tab, &yval);
baseline[i] = yval;
#if DEBUG_BASELINE
L_INFO("Baseline info: row %d, yval = %d, h = %d\n", procName,
i, yval, pixGetHeight(pixr));
pix1 = pixCopy(NULL, pixr);
pixRenderLine(pix1, 0, yval, pixGetWidth(pix1), yval, 1,
L_FLIP_PIXELS);
if (i == 0 )
pixWrite("/tmp/baseline/row0.png", pix1, IFF_PNG);
else if (i == 1)
pixWrite("/tmp/baseline/row1.png", pix1, IFF_PNG);
else
pixWrite("/tmp/baseline/row2.png", pix1, IFF_PNG);
pixDestroy(&pix1);
#endif /* DEBUG_BASELINE */
boxDestroy(&box);
//.........这里部分代码省略.........
示例11: bmfMakeAsciiTables
/*!
* bmfMakeAsciiTables
*
* Input: bmf
* Return: 0 if OK, 1 on error
*
* Notes:
* (1) This makes three tables, each of size 128, as follows:
* - fonttab is a table containing the index of the Pix
* that corresponds to each input ascii character;
* it maps (ascii-index) --> Pixa index
* - baselinetab is a table containing the baseline offset
* for the Pix that corresponds to each input ascii character;
* it maps (ascii-index) --> baseline offset
* - widthtab is a table containing the character width in
* pixels for the Pix that corresponds to that character;
* it maps (ascii-index) --> bitmap width
* (2) This also computes
* - lineheight (sum of maximum character extensions above and
* below the baseline)
* - kernwidth (spacing between characters within a word)
* - spacewidth (space between words)
* - vertlinesep (extra vertical spacing between textlines)
* (3) The baselines apply as follows:
* baseline1 (ascii 32 - 57), ascii 92
* baseline2 (ascii 58 - 91)
* baseline3 (ascii 93 - 126)
* (4) The only array in bmf that is not ascii-based is the
* array of bitmaps in the pixa, which starts at ascii 32.
*/
static l_int32
bmfMakeAsciiTables(L_BMF *bmf)
{
l_int32 i, maxh, height, charwidth, xwidth, kernwidth;
l_int32 *fonttab, *baselinetab, *widthtab;
PIX *pix;
PROCNAME("bmfMakeAsciiTables");
if (!bmf)
return ERROR_INT("bmf not defined", procName, 1);
/* First get the fonttab; we use this later for the char widths */
if ((fonttab = (l_int32 *)CALLOC(128, sizeof(l_int32))) == NULL)
return ERROR_INT("fonttab not made", procName, 1);
bmf->fonttab = fonttab;
for (i = 0; i < 128; i++)
fonttab[i] = UNDEF;
for (i = 32; i < 127; i++)
fonttab[i] = i - 32;
if ((baselinetab = (l_int32 *)CALLOC(128, sizeof(l_int32))) == NULL)
return ERROR_INT("baselinetab not made", procName, 1);
bmf->baselinetab = baselinetab;
for (i = 0; i < 128; i++)
baselinetab[i] = UNDEF;
for (i = 32; i <= 57; i++)
baselinetab[i] = bmf->baseline1;
for (i = 58; i <= 91; i++)
baselinetab[i] = bmf->baseline2;
baselinetab[92] = bmf->baseline1; /* the '\' char */
for (i = 93; i < 127; i++)
baselinetab[i] = bmf->baseline3;
/* Generate array of character widths; req's fonttab to exist */
if ((widthtab = (l_int32 *)CALLOC(128, sizeof(l_int32))) == NULL)
return ERROR_INT("widthtab not made", procName, 1);
bmf->widthtab = widthtab;
for (i = 0; i < 128; i++)
widthtab[i] = UNDEF;
for (i = 32; i < 127; i++) {
bmfGetWidth(bmf, i, &charwidth);
widthtab[i] = charwidth;
}
/* Get the line height of text characters, from the highest
* ascender to the lowest descender; req's fonttab to exist. */
pix = bmfGetPix(bmf, 32);
maxh = pixGetHeight(pix);
pixDestroy(&pix);
pix = bmfGetPix(bmf, 58);
height = pixGetHeight(pix);
pixDestroy(&pix);
maxh = L_MAX(maxh, height);
pix = bmfGetPix(bmf, 93);
height = pixGetHeight(pix);
pixDestroy(&pix);
maxh = L_MAX(maxh, height);
bmf->lineheight = maxh;
/* Get the kern width (distance between characters).
* We let it be the same for all characters in a given
* font size, and scale it linearly with the size;
* req's fonttab to be built first. */
bmfGetWidth(bmf, 120, &xwidth);
kernwidth = (l_int32)(0.08 * (l_float32)xwidth + 0.5);
bmf->kernwidth = L_MAX(1, kernwidth);
/* Save the space width (between words) */
bmfGetWidth(bmf, 32, &charwidth);
//.........这里部分代码省略.........
示例12: pixGetLocalSkewAngles
/*!
* pixGetLocalSkewAngles()
*
* Input: pixs
* nslices (the number of horizontal overlapping slices; must
* be larger than 1 and not exceed 20; use 0 for default)
* redsweep (sweep reduction factor: 1, 2, 4 or 8;
* use 0 for default value)
* redsearch (search reduction factor: 1, 2, 4 or 8, and
* not larger than redsweep; use 0 for default value)
* sweeprange (half the full range, assumed about 0; in degrees;
* use 0.0 for default value)
* sweepdelta (angle increment of sweep; in degrees;
* use 0.0 for default value)
* minbsdelta (min binary search increment angle; in degrees;
* use 0.0 for default value)
* &a (<optional return> slope of skew as fctn of y)
* &b (<optional return> intercept at y=0 of skew as fctn of y)
* Return: naskew, or null on error
*
* Notes:
* (1) The local skew is measured in a set of overlapping strips.
* We then do a least square linear fit parameters to get
* the slope and intercept parameters a and b in
* skew-angle = a * y + b (degrees)
* for the local skew as a function of raster line y.
* This is then used to make naskew, which can be interpreted
* as the computed skew angle (in degrees) at the left edge
* of each raster line.
* (2) naskew can then be used to find the baselines of text, because
* each text line has a baseline that should intersect
* the left edge of the image with the angle given by this
* array, evaluated at the raster line of intersection.
*/
NUMA *
pixGetLocalSkewAngles(PIX *pixs,
l_int32 nslices,
l_int32 redsweep,
l_int32 redsearch,
l_float32 sweeprange,
l_float32 sweepdelta,
l_float32 minbsdelta,
l_float32 *pa,
l_float32 *pb)
{
l_int32 w, h, hs, i, ystart, yend, ovlap, npts;
l_float32 angle, conf, ycenter, a, b;
BOX *box;
NUMA *naskew;
PIX *pix;
PTA *pta;
PROCNAME("pixGetLocalSkewAngles");
if (!pixs)
return (NUMA *)ERROR_PTR("pixs not defined", procName, NULL);
if (nslices < 2 || nslices > 20)
nslices = DEFAULT_SLICES;
if (redsweep < 1 || redsweep > 8)
redsweep = DEFAULT_SWEEP_REDUCTION;
if (redsearch < 1 || redsearch > redsweep)
redsearch = DEFAULT_BS_REDUCTION;
if (sweeprange == 0.0)
sweeprange = DEFAULT_SWEEP_RANGE;
if (sweepdelta == 0.0)
sweepdelta = DEFAULT_SWEEP_DELTA;
if (minbsdelta == 0.0)
minbsdelta = DEFAULT_MINBS_DELTA;
h = pixGetHeight(pixs);
w = pixGetWidth(pixs);
hs = h / nslices;
ovlap = (l_int32)(OVERLAP_FRACTION * hs);
pta = ptaCreate(nslices);
for (i = 0; i < nslices; i++) {
ystart = L_MAX(0, hs * i - ovlap);
yend = L_MIN(h - 1, hs * (i + 1) + ovlap);
ycenter = (ystart + yend) / 2;
box = boxCreate(0, ystart, w, yend - ystart + 1);
pix = pixClipRectangle(pixs, box, NULL);
pixFindSkewSweepAndSearch(pix, &angle, &conf, redsweep, redsearch,
sweeprange, sweepdelta, minbsdelta);
if (conf > MIN_ALLOWED_CONFIDENCE)
ptaAddPt(pta, ycenter, angle);
pixDestroy(&pix);
boxDestroy(&box);
}
/* ptaWriteStream(stderr, pta, 0); */
/* Do linear least squares fit */
if ((npts = ptaGetCount(pta)) < 2) {
ptaDestroy(&pta);
return (NUMA *)ERROR_PTR("can't fit skew", procName, NULL);
}
ptaGetLinearLSF(pta, &a, &b, NULL);
if (pa) *pa = a;
if (pb) *pb = b;
/* Make skew angle array as function of raster line */
naskew = numaCreate(h);
//.........这里部分代码省略.........
示例13: pixGetLocalSkewTransform
/*!
* pixGetLocalSkewTransform()
*
* Input: pixs
* nslices (the number of horizontal overlapping slices; must
* be larger than 1 and not exceed 20; use 0 for default)
* redsweep (sweep reduction factor: 1, 2, 4 or 8;
* use 0 for default value)
* redsearch (search reduction factor: 1, 2, 4 or 8, and
* not larger than redsweep; use 0 for default value)
* sweeprange (half the full range, assumed about 0; in degrees;
* use 0.0 for default value)
* sweepdelta (angle increment of sweep; in degrees;
* use 0.0 for default value)
* minbsdelta (min binary search increment angle; in degrees;
* use 0.0 for default value)
* &ptas (<return> 4 points in the source)
* &ptad (<return> the corresponding 4 pts in the dest)
* Return: 0 if OK, 1 on error
*
* Notes:
* (1) This generates two pairs of points in the src, each pair
* corresponding to a pair of points that would lie along
* the same raster line in a transformed (dewarped) image.
* (2) The sets of 4 src and 4 dest points returned by this function
* can then be used, in a projective or bilinear transform,
* to remove keystoning in the src.
*/
l_int32
pixGetLocalSkewTransform(PIX *pixs,
l_int32 nslices,
l_int32 redsweep,
l_int32 redsearch,
l_float32 sweeprange,
l_float32 sweepdelta,
l_float32 minbsdelta,
PTA **pptas,
PTA **pptad)
{
l_int32 w, h, i;
l_float32 deg2rad, angr, angd, dely;
NUMA *naskew;
PTA *ptas, *ptad;
PROCNAME("pixGetLocalSkewTransform");
if (!pptas || !pptad)
return ERROR_INT("&ptas and &ptad not defined", procName, 1);
*pptas = *pptad = NULL;
if (!pixs)
return ERROR_INT("pixs not defined", procName, 1);
if (nslices < 2 || nslices > 20)
nslices = DEFAULT_SLICES;
if (redsweep < 1 || redsweep > 8)
redsweep = DEFAULT_SWEEP_REDUCTION;
if (redsearch < 1 || redsearch > redsweep)
redsearch = DEFAULT_BS_REDUCTION;
if (sweeprange == 0.0)
sweeprange = DEFAULT_SWEEP_RANGE;
if (sweepdelta == 0.0)
sweepdelta = DEFAULT_SWEEP_DELTA;
if (minbsdelta == 0.0)
minbsdelta = DEFAULT_MINBS_DELTA;
naskew = pixGetLocalSkewAngles(pixs, nslices, redsweep, redsearch,
sweeprange, sweepdelta, minbsdelta,
NULL, NULL);
if (!naskew)
return ERROR_INT("naskew not made", procName, 1);
deg2rad = 3.14159265 / 180.;
w = pixGetWidth(pixs);
h = pixGetHeight(pixs);
ptas = ptaCreate(4);
ptad = ptaCreate(4);
*pptas = ptas;
*pptad = ptad;
/* Find i for skew line that intersects LHS at i and RHS at h / 20 */
for (i = 0; i < h; i++) {
numaGetFValue(naskew, i, &angd);
angr = angd * deg2rad;
dely = w * tan(angr);
if (i - dely > 0.05 * h)
break;
}
ptaAddPt(ptas, 0, i);
ptaAddPt(ptas, w - 1, i - dely);
ptaAddPt(ptad, 0, i);
ptaAddPt(ptad, w - 1, i);
/* Find i for skew line that intersects LHS at i and RHS at 19h / 20 */
for (i = h - 1; i > 0; i--) {
numaGetFValue(naskew, i, &angd);
angr = angd * deg2rad;
dely = w * tan(angr);
if (i - dely < 0.95 * h)
break;
}
ptaAddPt(ptas, 0, i);
//.........这里部分代码省略.........
示例14: pixFindBaselines
/*!
* pixFindBaselines()
*
* Input: pixs (1 bpp)
* &pta (<optional return> pairs of pts corresponding to
* approx. ends of each text line)
* debug (usually 0; set to 1 for debugging output)
* Return: na (of baseline y values), or null on error
*
* Notes:
* (1) Input binary image must have text lines already aligned
* horizontally. This can be done by either rotating the
* image with pixDeskew(), or, if a projective transform
* is required, by doing pixDeskewLocal() first.
* (2) Input null for &pta if you don't want this returned.
* The pta will come in pairs of points (left and right end
* of each baseline).
* (3) Caution: this will not work properly on text with multiple
* columns, where the lines are not aligned between columns.
* If there are multiple columns, they should be extracted
* separately before finding the baselines.
* (4) This function constructs different types of output
* for baselines; namely, a set of raster line values and
* a set of end points of each baseline.
* (5) This function was designed to handle short and long text lines
* without using dangerous thresholds on the peak heights. It does
* this by combining the differential signal with a morphological
* analysis of the locations of the text lines. One can also
* combine this data to normalize the peak heights, by weighting
* the differential signal in the region of each baseline
* by the inverse of the width of the text line found there.
* (6) There are various debug sections that can be turned on
* with the debug flag.
*/
NUMA *
pixFindBaselines(PIX *pixs,
PTA **ppta,
l_int32 debug)
{
l_int32 h, i, j, nbox, val1, val2, ndiff, bx, by, bw, bh;
l_int32 imaxloc, peakthresh, zerothresh, inpeak;
l_int32 mintosearch, max, maxloc, nloc, locval;
l_int32 *array;
l_float32 maxval;
BOXA *boxa1, *boxa2, *boxa3;
GPLOT *gplot;
NUMA *nasum, *nadiff, *naloc, *naval;
PIX *pixt1, *pixt2;
PTA *pta;
PROCNAME("pixFindBaselines");
if (!pixs)
return (NUMA *)ERROR_PTR("pixs not defined", procName, NULL);
pta = NULL;
if (ppta) {
pta = ptaCreate(0);
*ppta = pta;
}
lept_mkdir("/lept/baseline");
/* Close up the text characters, removing noise */
pixt1 = pixMorphSequence(pixs, "c25.1 + e3.1", 0);
/* Save the difference of adjacent row sums.
* The high positive-going peaks are the baselines */
if ((nasum = pixCountPixelsByRow(pixt1, NULL)) == NULL)
return (NUMA *)ERROR_PTR("nasum not made", procName, NULL);
h = pixGetHeight(pixs);
nadiff = numaCreate(h);
numaGetIValue(nasum, 0, &val2);
for (i = 0; i < h - 1; i++) {
val1 = val2;
numaGetIValue(nasum, i + 1, &val2);
numaAddNumber(nadiff, val1 - val2);
}
if (debug) /* show the difference signal */
gplotSimple1(nadiff, GPLOT_PNG, "/tmp/lept/baseline/diff", "Diff Sig");
/* Use the zeroes of the profile to locate each baseline. */
array = numaGetIArray(nadiff);
ndiff = numaGetCount(nadiff);
numaGetMax(nadiff, &maxval, &imaxloc);
/* Use this to begin locating a new peak: */
peakthresh = (l_int32)maxval / PEAK_THRESHOLD_RATIO;
/* Use this to begin a region between peaks: */
zerothresh = (l_int32)maxval / ZERO_THRESHOLD_RATIO;
naloc = numaCreate(0);
naval = numaCreate(0);
inpeak = FALSE;
for (i = 0; i < ndiff; i++) {
if (inpeak == FALSE) {
if (array[i] > peakthresh) { /* transition to in-peak */
inpeak = TRUE;
mintosearch = i + MIN_DIST_IN_PEAK; /* accept no zeros
* between i and mintosearch */
max = array[i];
maxloc = i;
//.........这里部分代码省略.........
示例15: main
main(int argc,
char **argv)
{
char *filein, *fileout;
l_int32 w, h;
l_float32 scale;
FILE *fp;
PIX *pix, *pixs, *pixd;
PIXCMAP *cmap;
static char mainName[] = "dithertest";
if (argc != 3)
exit(ERROR_INT(" Syntax: dithertest filein fileout", mainName, 1));
filein = argv[1];
fileout = argv[2];
if ((pix = pixRead(filein)) == NULL)
exit(ERROR_INT("pix not made", mainName, 1));
if (pixGetDepth(pix) != 8)
exit(ERROR_INT("pix not 8 bpp", mainName, 1));
pixs = pixGammaTRC(NULL, pix, GAMMA, 0, 255);
startTimer();
pixd = pixDitherToBinary(pixs);
fprintf(stderr, " time for binarized dither = %7.3f sec\n", stopTimer());
pixDisplayWrite(pixd, 1);
pixDestroy(&pixd);
/* Dither to 2 bpp, with colormap */
startTimer();
pixd = pixDitherTo2bpp(pixs, 1);
fprintf(stderr, " time for dither = %7.3f sec\n", stopTimer());
pixDisplayWrite(pixd, 1);
cmap = pixGetColormap(pixd);
pixcmapWriteStream(stderr, cmap);
pixDestroy(&pixd);
/* Dither to 2 bpp, without colormap */
startTimer();
pixd = pixDitherTo2bpp(pixs, 0);
fprintf(stderr, " time for dither = %7.3f sec\n", stopTimer());
pixDisplayWrite(pixd, 1);
pixDestroy(&pixd);
/* Dither to 2 bpp, without colormap; output in PostScript */
pixd = pixDitherTo2bpp(pixs, 0);
w = pixGetWidth(pixs);
h = pixGetHeight(pixs);
scale = L_MIN(FACTOR * 2550 / w, FACTOR * 3300 / h);
fp = lept_fopen(fileout, "wb+");
pixWriteStreamPS(fp, pixd, NULL, 300, scale);
lept_fclose(fp);
pixDestroy(&pixd);
/* Dither 2x upscale to 1 bpp */
startTimer();
pixd = pixScaleGray2xLIDither(pixs);
fprintf(stderr, " time for scale/dither = %7.3f sec\n", stopTimer());
pixDisplayWrite(pixd, 1);
pixDestroy(&pixd);
/* Dither 4x upscale to 1 bpp */
startTimer();
pixd = pixScaleGray4xLIDither(pixs);
fprintf(stderr, " time for scale/dither = %7.3f sec\n", stopTimer());
pixDisplayWrite(pixd, 1);
pixDestroy(&pixd);
pixDisplayMultiple("/tmp/junk_write_display*");
pixDestroy(&pix);
pixDestroy(&pixs);
return 0;
}