Tesseract 3.02

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- Class List
- Class Hierarchy
- Class Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Public Member Functions | Friends
QSPLINE Class Reference

`#include <quspline.h>`

List of all members.

## Public Member Functions
| QSPLINE ()
| QSPLINE (const QSPLINE &src)
| QSPLINE (inT32 count, inT32 *xstarts, double *coeffs)
| ~QSPLINE ()
| QSPLINE (int xstarts[], int segcount, int xcoords[], int ycoords[], int blobcount, int degree)
double | step (double x1, double x2)
double | y (double x) const
void | move (ICOORD vec)
BOOL8 | overlap (QSPLINE *spline2, double fraction)
void | extrapolate (double gradient, int left, int right)
void | plot (ScrollView *window, ScrollView::Color colour) const
QSPLINE & | operator= (const QSPLINE &source)

## Friends
void | make_first_baseline (TBOX *, int, int *, int *, QSPLINE *, QSPLINE *, float)
void | make_holed_baseline (TBOX *, int, QSPLINE *, QSPLINE *, float)
void | tweak_row_baseline (ROW *, double, double)

## Detailed Description

Definition at line 30 of file quspline.h.

## Constructor & Destructor Documentation

QSPLINE::QSPLINE | ( |  | ) |
| inline

Definition at line 42 of file quspline.h.

{ //empty constructor
segments = 0;
xcoords = NULL; //everything empty
quadratics = NULL;
}

QSPLINE::QSPLINE | ( | const QSPLINE & | src | ) |

Definition at line 136 of file quspline.cpp.

{
segments = 0;
xcoords = NULL;
quadratics = NULL;
*this = src;
}

QSPLINE::QSPLINE | ( | inT32 | count,
|  | inT32 * | xstarts,
|  | double * | coeffs
| ) |  |

Definition at line 38 of file quspline.cpp.

{
inT32 index; //segment index
//get memory
xcoords = (inT32 *) alloc_mem ((count + 1) * sizeof (inT32));
quadratics = (QUAD_COEFFS *) alloc_mem (count * sizeof (QUAD_COEFFS));
segments = count;
for (index = 0; index < segments; index++) {
//copy them
xcoords[index] = xstarts[index];
quadratics[index] = QUAD_COEFFS (coeffs[index * 3],
coeffs[index * 3 + 1],
coeffs[index * 3 + 2]);
}
//right edge
xcoords[index] = xstarts[index];
}

QSPLINE::~QSPLINE | ( |  | ) |

Definition at line 151 of file quspline.cpp.

{
if (xcoords != NULL) {
free_mem(xcoords);
xcoords = NULL;
}
if (quadratics != NULL) {
free_mem(quadratics);
quadratics = NULL;
}
}

QSPLINE::QSPLINE | ( | int | xstarts[],
|  | int | segcount,
|  | int | xcoords[],
|  | int | ycoords[],
|  | int | blobcount,
|  | int | degree
| ) |  |

Definition at line 67 of file quspline.cpp.

{
register int pointindex; /*no along text line */
register int segment; /*segment no */
inT32 *ptcounts; //no in each segment
QLSQ qlsq; /*accumulator */
segments = segcount;
xcoords = (inT32 *) alloc_mem ((segcount + 1) * sizeof (inT32));
ptcounts = (inT32 *) alloc_mem ((segcount + 1) * sizeof (inT32));
quadratics = (QUAD_COEFFS *) alloc_mem (segcount * sizeof (QUAD_COEFFS));
memmove (xcoords, xstarts, (segcount + 1) * sizeof (inT32));
ptcounts[0] = 0; /*none in any yet */
for (segment = 0, pointindex = 0; pointindex < pointcount; pointindex++) {
while (segment < segcount && xpts[pointindex] >= xstarts[segment]) {
segment++; /*try next segment */
/*cumulative counts */
ptcounts[segment] = ptcounts[segment - 1];
}
ptcounts[segment]++; /*no in previous partition */
}
while (segment < segcount) {
segment++;
/*zero the rest */
ptcounts[segment] = ptcounts[segment - 1];
}
for (segment = 0; segment < segcount; segment++) {
qlsq.clear ();
/*first blob */
pointindex = ptcounts[segment];
if (pointindex > 0
&& xpts[pointindex] != xpts[pointindex - 1]
&& xpts[pointindex] != xstarts[segment])
qlsq.add (xstarts[segment],
ypts[pointindex - 1]
+ (ypts[pointindex] - ypts[pointindex - 1])
* (xstarts[segment] - xpts[pointindex - 1])
/ (xpts[pointindex] - xpts[pointindex - 1]));
for (; pointindex < ptcounts[segment + 1]; pointindex++) {
qlsq.add (xpts[pointindex], ypts[pointindex]);
}
if (pointindex > 0 && pointindex < pointcount
&& xpts[pointindex] != xstarts[segment + 1])
qlsq.add (xstarts[segment + 1],
ypts[pointindex - 1]
+ (ypts[pointindex] - ypts[pointindex - 1])
* (xstarts[segment + 1] - xpts[pointindex - 1])
/ (xpts[pointindex] - xpts[pointindex - 1]));
qlsq.fit (degree);
quadratics[segment].a = qlsq.get_a ();
quadratics[segment].b = qlsq.get_b ();
quadratics[segment].c = qlsq.get_c ();
}
free_mem(ptcounts);
}

## Member Function Documentation

void QSPLINE::extrapolate | ( | double | gradient,
|  | int | left,
|  | int | right
| ) |  |

Definition at line 306 of file quspline.cpp.

{
register int segment; /*current segment of spline */
int dest_segment; //dest index
int *xstarts; //new boundaries
QUAD_COEFFS *quads; //new ones
int increment; //in size
increment = xmin < xcoords[0] ? 1 : 0;
if (xmax > xcoords[segments])
increment++;
if (increment == 0)
return;
xstarts = (int *) alloc_mem ((segments + 1 + increment) * sizeof (int));
quads =
(QUAD_COEFFS *) alloc_mem ((segments + increment) * sizeof (QUAD_COEFFS));
if (xmin < xcoords[0]) {
xstarts[0] = xmin;
quads[0].a = 0;
quads[0].b = gradient;
quads[0].c = y (xcoords[0]) - quads[0].b * xcoords[0];
dest_segment = 1;
}
else
dest_segment = 0;
for (segment = 0; segment < segments; segment++) {
xstarts[dest_segment] = xcoords[segment];
quads[dest_segment] = quadratics[segment];
dest_segment++;
}
xstarts[dest_segment] = xcoords[segment];
if (xmax > xcoords[segments]) {
quads[dest_segment].a = 0;
quads[dest_segment].b = gradient;
quads[dest_segment].c = y (xcoords[segments])
- quads[dest_segment].b * xcoords[segments];
dest_segment++;
xstarts[dest_segment] = xmax + 1;
}
segments = dest_segment;
free_mem(xcoords);
free_mem(quadratics);
xcoords = (inT32 *) xstarts;
quadratics = quads;
}

void QSPLINE::move | ( | ICOORD | vec | ) |

Definition at line 259 of file quspline.cpp.

{
inT32 segment; //index of segment
inT16 x_shift = vec.x ();
for (segment = 0; segment < segments; segment++) {
xcoords[segment] += x_shift;
quadratics[segment].move (vec);
}
xcoords[segment] += x_shift;
}

QSPLINE & QSPLINE::operator= | ( | const QSPLINE & | source | ) |

Definition at line 170 of file quspline.cpp.

{
if (xcoords != NULL)
free_mem(xcoords);
if (quadratics != NULL)
free_mem(quadratics);
segments = source.segments;
xcoords = (inT32 *) alloc_mem ((segments + 1) * sizeof (inT32));
quadratics = (QUAD_COEFFS *) alloc_mem (segments * sizeof (QUAD_COEFFS));
memmove (xcoords, source.xcoords, (segments + 1) * sizeof (inT32));
memmove (quadratics, source.quadratics, segments * sizeof (QUAD_COEFFS));
return *this;
}

BOOL8 QSPLINE::overlap | ( | QSPLINE * | spline2,
|  | double | fraction
| ) |  |

Definition at line 280 of file quspline.cpp.

{
int leftlimit; /*common left limit */
int rightlimit; /*common right limit */
leftlimit = xcoords[1];
rightlimit = xcoords[segments - 1];
/*or too non-overlap */
if (spline2->segments < 3 || spline2->xcoords[1] > leftlimit + fraction * (rightlimit - leftlimit)
|| spline2->xcoords[spline2->segments - 1] < rightlimit
- fraction * (rightlimit - leftlimit))
return FALSE;
else
return TRUE;
}

void QSPLINE::plot | ( | ScrollView * | window,
|  | ScrollView::Color | colour
| ) |  | const

Definition at line 363 of file quspline.cpp.

{
inT32 segment; //index of segment
inT16 step; //index of poly piece
double increment; //x increment
double x; //x coord
window->Pen(colour);
for (segment = 0; segment < segments; segment++) {
increment =
(double) (xcoords[segment + 1] -
xcoords[segment]) / QSPLINE_PRECISION;
x = xcoords[segment];
for (step = 0; step <= QSPLINE_PRECISION; step++) {
if (segment == 0 && step == 0)
window->SetCursor(x, quadratics[segment].y (x));
else
window->DrawTo(x, quadratics[segment].y (x));
x += increment;
}
}
}

double QSPLINE::step | ( | double | x1,
|  | double | x2
| ) |  |

Definition at line 192 of file quspline.cpp.

{
int index1, index2; //indices of coords
double total; /*total steps */
index1 = spline_index (x1);
index2 = spline_index (x2);
total = 0;
while (index1 < index2) {
total +=
(double) quadratics[index1 + 1].y ((float) xcoords[index1 + 1]);
total -= (double) quadratics[index1].y ((float) xcoords[index1 + 1]);
index1++; /*next segment */
}
return total; /*total steps */
}

double QSPLINE::y | ( | double | x | ) | const

Definition at line 217 of file quspline.cpp.

{
inT32 index; //segment index
index = spline_index (x);
return quadratics[index].y (x);//in correct segment
}

## Friends And Related Function Documentation

void make_first_baseline | ( | TBOX * | ,
|  | int | ,
|  | int * | ,
|  | int * | ,
|  | QSPLINE * | ,
|  | QSPLINE * | ,
|  | float |
| ) |  |
| friend

void make_holed_baseline | ( | TBOX * | ,
|  | int | ,
|  | QSPLINE * | ,
|  | QSPLINE * | ,
|  | float |
| ) |  |
| friend

void tweak_row_baseline | ( | ROW * | ,
|  | double | ,
|  | double |
| ) |  |
| friend

Definition at line 680 of file tordmain.cpp.

{
TBOX blob_box; //bounding box
C_BLOB *blob; //current blob
WERD *word; //current word
inT32 blob_count; //no of blobs
inT32 src_index; //source segment
inT32 dest_index; //destination segment
inT32 *xstarts; //spline segments
double *coeffs; //spline coeffs
float ydiff; //baseline error
float x_centre; //centre of blob
//words of row
WERD_IT word_it = row->word_list ();
C_BLOB_IT blob_it; //blob iterator
blob_count = 0;
for (word_it.mark_cycle_pt (); !word_it.cycled_list (); word_it.forward ()) {
word = word_it.data (); //current word
//get total blobs
blob_count += word->cblob_list ()->length ();
}
if (blob_count == 0)
return;
xstarts =
(inT32 *) alloc_mem ((blob_count + row->baseline.segments + 1) *
sizeof (inT32));
coeffs =
(double *) alloc_mem ((blob_count + row->baseline.segments) * 3 *
sizeof (double));
src_index = 0;
dest_index = 0;
xstarts[0] = row->baseline.xcoords[0];
for (word_it.mark_cycle_pt (); !word_it.cycled_list (); word_it.forward ()) {
word = word_it.data (); //current word
//blobs in word
blob_it.set_to_list (word->cblob_list ());
for (blob_it.mark_cycle_pt (); !blob_it.cycled_list ();
blob_it.forward ()) {
blob = blob_it.data ();
blob_box = blob->bounding_box ();
x_centre = (blob_box.left () + blob_box.right ()) / 2.0;
ydiff = blob_box.bottom () - row->base_line (x_centre);
if (ydiff < 0)
ydiff = -ydiff / row->x_height ();
else
ydiff = ydiff / row->x_height ();
if (ydiff < blshift_maxshift
&& blob_box.height () / row->x_height () > blshift_xfraction) {
if (xstarts[dest_index] >= x_centre)
xstarts[dest_index] = blob_box.left ();
coeffs[dest_index * 3] = 0;
coeffs[dest_index * 3 + 1] = 0;
coeffs[dest_index * 3 + 2] = blob_box.bottom ();
//shift it
dest_index++;
xstarts[dest_index] = blob_box.right () + 1;
}
else {
if (xstarts[dest_index] <= x_centre) {
while (row->baseline.xcoords[src_index + 1] <= x_centre
&& src_index < row->baseline.segments - 1) {
if (row->baseline.xcoords[src_index + 1] >
xstarts[dest_index]) {
coeffs[dest_index * 3] =
row->baseline.quadratics[src_index].a;
coeffs[dest_index * 3 + 1] =
row->baseline.quadratics[src_index].b;
coeffs[dest_index * 3 + 2] =
row->baseline.quadratics[src_index].c;
dest_index++;
xstarts[dest_index] =
row->baseline.xcoords[src_index + 1];
}
src_index++;
}
coeffs[dest_index * 3] =
row->baseline.quadratics[src_index].a;
coeffs[dest_index * 3 + 1] =
row->baseline.quadratics[src_index].b;
coeffs[dest_index * 3 + 2] =
row->baseline.quadratics[src_index].c;
dest_index++;
xstarts[dest_index] = row->baseline.xcoords[src_index + 1];
}
}
}
}
while (src_index < row->baseline.segments
&& row->baseline.xcoords[src_index + 1] <= xstarts[dest_index])
src_index++;
while (src_index < row->baseline.segments) {
coeffs[dest_index * 3] = row->baseline.quadratics[src_index].a;
coeffs[dest_index * 3 + 1] = row->baseline.quadratics[src_index].b;
coeffs[dest_index * 3 + 2] = row->baseline.quadratics[src_index].c;
dest_index++;
src_index++;
xstarts[dest_index] = row->baseline.xcoords[src_index];
}
//turn to spline
row->baseline = QSPLINE (dest_index, xstarts, coeffs);
free_mem(xstarts);
free_mem(coeffs);
}

The documentation for this class was generated from the following files:

- /mnt/data/src/tesseract-ocr/ccstruct/quspline.h
- /mnt/data/src/tesseract-ocr/ccstruct/quspline.cpp