本文整理汇总了C++中TBOX::width方法的典型用法代码示例。如果您正苦于以下问题:C++ TBOX::width方法的具体用法?C++ TBOX::width怎么用?C++ TBOX::width使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类TBOX
的用法示例。
在下文中一共展示了TBOX::width方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: memalloc
/**********************************************************************
* blobs_widths
*
* Compute the widths of a list of blobs. Return an array of the widths
* and gaps.
**********************************************************************/
WIDTH_RECORD *blobs_widths(TBLOB *blobs) { /*blob to compute on */
WIDTH_RECORD *width_record;
TPOINT topleft; /*bounding box */
TPOINT botright;
int i = 0;
int blob_end;
int num_blobs = count_blobs (blobs);
/* Get memory */
width_record = (WIDTH_RECORD *) memalloc (sizeof (int) * num_blobs * 2);
width_record->num_chars = num_blobs;
TBOX bbox = blobs->bounding_box();
width_record->widths[i++] = bbox.width();
/* First width */
blob_end = bbox.right();
for (TBLOB* blob = blobs->next; blob != NULL; blob = blob->next) {
TBOX curbox = blob->bounding_box();
width_record->widths[i++] = curbox.left() - blob_end;
width_record->widths[i++] = curbox.width();
blob_end = curbox.right();
}
return width_record;
}
示例2: blob_noise_score
float blob_noise_score(PBLOB *blob) {
OUTLINE_IT outline_it;
TBOX box; //BB of outline
inT16 outline_count = 0;
inT16 max_dimension;
inT16 largest_outline_dimension = 0;
outline_it.set_to_list (blob->out_list ());
for (outline_it.mark_cycle_pt ();
!outline_it.cycled_list (); outline_it.forward ()) {
outline_count++;
box = outline_it.data ()->bounding_box ();
if (box.height () > box.width ())
max_dimension = box.height ();
else
max_dimension = box.width ();
if (largest_outline_dimension < max_dimension)
largest_outline_dimension = max_dimension;
}
if (fixsp_noise_score_fixing) {
if (outline_count > 5)
//penalise LOTS of blobs
largest_outline_dimension *= 2;
box = blob->bounding_box ();
if ((box.bottom () > bln_baseline_offset * 4) ||
(box.top () < bln_baseline_offset / 2))
//Lax blob is if high or low
largest_outline_dimension /= 2;
}
return largest_outline_dimension;
}
示例3: blob_noise_score
float Tesseract::blob_noise_score(TBLOB *blob) {
TBOX box; // BB of outline
inT16 outline_count = 0;
inT16 max_dimension;
inT16 largest_outline_dimension = 0;
for (TESSLINE* ol = blob->outlines; ol != NULL; ol= ol->next) {
outline_count++;
box = ol->bounding_box();
if (box.height() > box.width()) {
max_dimension = box.height();
} else {
max_dimension = box.width();
}
if (largest_outline_dimension < max_dimension)
largest_outline_dimension = max_dimension;
}
if (outline_count > 5) {
// penalise LOTS of blobs
largest_outline_dimension *= 2;
}
box = blob->bounding_box();
if (box.bottom() > kBlnBaselineOffset * 4 ||
box.top() < kBlnBaselineOffset / 2) {
// Lax blob is if high or low
largest_outline_dimension /= 2;
}
return largest_outline_dimension;
}
示例4: MarkAndDeleteNonTextBlobs
// Tests each blob in the list to see if it is certain non-text using 2
// conditions:
// 1. blob overlaps a cell with high value in noise_density_ (previously set
// by ComputeNoiseDensity).
// OR 2. The blob overlaps more than max_blob_overlaps in *this grid. This
// condition is disabled with max_blob_overlaps == -1.
// If it does, the blob is declared non-text, and is used to mark up the
// nontext_mask. Such blobs are fully deleted, and non-noise blobs have their
// neighbours reset, as they may now point to deleted data.
// WARNING: The blobs list blobs may be in the *this grid, but they are
// not removed. If any deleted blobs might be in *this, then this must be
// Clear()ed immediately after MarkAndDeleteNonTextBlobs is called.
// If the win is not NULL, deleted blobs are drawn on it in red, and kept
// blobs are drawn on it in ok_color.
void CCNonTextDetect::MarkAndDeleteNonTextBlobs(BLOBNBOX_LIST* blobs,
int max_blob_overlaps,
ScrollView* win,
ScrollView::Color ok_color,
Pix* nontext_mask) {
int imageheight = tright().y() - bleft().x();
BLOBNBOX_IT blob_it(blobs);
BLOBNBOX_LIST dead_blobs;
BLOBNBOX_IT dead_it(&dead_blobs);
for (blob_it.mark_cycle_pt(); !blob_it.cycled_list(); blob_it.forward()) {
BLOBNBOX* blob = blob_it.data();
TBOX box = blob->bounding_box();
if (!noise_density_->RectMostlyOverThreshold(box, max_noise_count_) &&
(max_blob_overlaps < 0 ||
!BlobOverlapsTooMuch(blob, max_blob_overlaps))) {
blob->ClearNeighbours();
#ifndef GRAPHICS_DISABLED
if (win != NULL)
blob->plot(win, ok_color, ok_color);
#endif // GRAPHICS_DISABLED
} else {
if (noise_density_->AnyZeroInRect(box)) {
// There is a danger that the bounding box may overlap real text, so
// we need to render the outline.
Pix* blob_pix = blob->cblob()->render_outline();
pixRasterop(nontext_mask, box.left(), imageheight - box.top(),
box.width(), box.height(), PIX_SRC | PIX_DST,
blob_pix, 0, 0);
pixDestroy(&blob_pix);
} else {
if (box.area() < gridsize() * gridsize()) {
// It is a really bad idea to make lots of small components in the
// photo mask, so try to join it to a bigger area by expanding the
// box in a way that does not touch any zero noise density cell.
box = AttemptBoxExpansion(box, *noise_density_, gridsize());
}
// All overlapped cells are non-zero, so just mark the rectangle.
pixRasterop(nontext_mask, box.left(), imageheight - box.top(),
box.width(), box.height(), PIX_SET, NULL, 0, 0);
}
#ifndef GRAPHICS_DISABLED
if (win != NULL)
blob->plot(win, ScrollView::RED, ScrollView::RED);
#endif // GRAPHICS_DISABLED
// It is safe to delete the cblob now, as it isn't used by the grid
// or BlobOverlapsTooMuch, and the BLOBNBOXes will go away with the
// dead_blobs list.
// TODO(rays) delete the delete when the BLOBNBOX destructor deletes
// the cblob.
delete blob->cblob();
dead_it.add_to_end(blob_it.extract());
}
}
}
示例5: DistanceOfBoxFromBox
// Compute the distance from the from_box to the to_box using curved
// projection space. Separation that involves a decrease in projection
// density (moving from the from_box to the to_box) is weighted more heavily
// than constant density, and an increase is weighted less.
// If horizontal_textline is true, then curved space is used vertically,
// as for a diacritic on the edge of a textline.
// The projection uses original image coords, so denorm is used to get
// back to the image coords from box/part space.
// How the calculation works: Think of a diacritic near a textline.
// Distance is measured from the far side of the from_box to the near side of
// the to_box. Shown is the horizontal textline case.
// |------^-----|
// | from | box |
// |------|-----|
// perpendicular |
// <------v-------->|--------------------|
// parallel | to box |
// |--------------------|
// Perpendicular distance uses "curved space" See VerticalDistance below.
// Parallel distance is linear.
// Result is perpendicular_gap + parallel_gap / kParaPerpDistRatio.
int TextlineProjection::DistanceOfBoxFromBox(const TBOX& from_box,
const TBOX& to_box,
bool horizontal_textline,
const DENORM* denorm,
bool debug) const {
// The parallel_gap is the horizontal gap between a horizontal textline and
// the box. Analogous for vertical.
int parallel_gap = 0;
// start_pt is the box end of the line to be modified for curved space.
TPOINT start_pt;
// end_pt is the partition end of the line to be modified for curved space.
TPOINT end_pt;
if (horizontal_textline) {
parallel_gap = from_box.x_gap(to_box) + from_box.width();
start_pt.x = (from_box.left() + from_box.right()) / 2;
end_pt.x = start_pt.x;
if (from_box.top() - to_box.top() >= to_box.bottom() - from_box.bottom()) {
start_pt.y = from_box.top();
end_pt.y = MIN(to_box.top(), start_pt.y);
} else {
start_pt.y = from_box.bottom();
end_pt.y = MAX(to_box.bottom(), start_pt.y);
}
} else {
parallel_gap = from_box.y_gap(to_box) + from_box.height();
if (from_box.right() - to_box.right() >= to_box.left() - from_box.left()) {
start_pt.x = from_box.right();
end_pt.x = MIN(to_box.right(), start_pt.x);
} else {
start_pt.x = from_box.left();
end_pt.x = MAX(to_box.left(), start_pt.x);
}
start_pt.y = (from_box.bottom() + from_box.top()) / 2;
end_pt.y = start_pt.y;
}
// The perpendicular gap is the max vertical distance gap out of:
// top of from_box to to_box top and bottom of from_box to to_box bottom.
// This value is then modified for curved projection space.
// Analogous for vertical.
int perpendicular_gap = 0;
// If start_pt == end_pt, then the from_box lies entirely within the to_box
// (in the perpendicular direction), so we don't need to calculate the
// perpendicular_gap.
if (start_pt.x != end_pt.x || start_pt.y != end_pt.y) {
if (denorm != NULL) {
// Denormalize the start and end.
denorm->DenormTransform(NULL, start_pt, &start_pt);
denorm->DenormTransform(NULL, end_pt, &end_pt);
}
if (abs(start_pt.y - end_pt.y) >= abs(start_pt.x - end_pt.x)) {
perpendicular_gap = VerticalDistance(debug, start_pt.x, start_pt.y,
end_pt.y);
} else {
perpendicular_gap = HorizontalDistance(debug, start_pt.x, end_pt.x,
start_pt.y);
}
}
// The parallel_gap weighs less than the perpendicular_gap.
return perpendicular_gap + parallel_gap / kParaPerpDistRatio;
}
示例6: SetupNonLinear
// Sets up the DENORM to execute a non-linear transformation based on
// preserving an even distribution of stroke edges. The transformation
// operates only within the given box.
// x_coords is a collection of the x-coords of vertical edges for each
// y-coord starting at box.bottom().
// y_coords is a collection of the y-coords of horizontal edges for each
// x-coord starting at box.left().
// Eg x_coords[0] is a collection of the x-coords of edges at y=bottom.
// Eg x_coords[1] is a collection of the x-coords of edges at y=bottom + 1.
// The second-level vectors must all be sorted in ascending order.
// See comments on the helper functions above for more details.
void DENORM::SetupNonLinear(
const DENORM* predecessor, const TBOX& box, float target_width,
float target_height, float final_xshift, float final_yshift,
const GenericVector<GenericVector<int> >& x_coords,
const GenericVector<GenericVector<int> >& y_coords) {
Clear();
predecessor_ = predecessor;
// x_map_ and y_map_ store a mapping from input x and y coordinate to output
// x and y coordinate, based on scaling to the supplied target_width and
// target_height.
x_map_ = new GenericVector<float>;
y_map_ = new GenericVector<float>;
// Set a 2-d image array to the run lengths at each pixel.
int width = box.width();
int height = box.height();
GENERIC_2D_ARRAY<int> minruns(width, height, 0);
ComputeRunlengthImage(box, x_coords, y_coords, &minruns);
// Edge density is the sum of the inverses of the run lengths. Compute
// edge density projection profiles.
ComputeEdgeDensityProfiles(box, minruns, x_map_, y_map_);
// Convert the edge density profiles to the coordinates by multiplying by
// the desired size and accumulating.
(*x_map_)[width] = target_width;
for (int x = width - 1; x >= 0; --x) {
(*x_map_)[x] = (*x_map_)[x + 1] - (*x_map_)[x] * target_width;
}
(*y_map_)[height] = target_height;
for (int y = height - 1; y >= 0; --y) {
(*y_map_)[y] = (*y_map_)[y + 1] - (*y_map_)[y] * target_height;
}
x_origin_ = box.left();
y_origin_ = box.bottom();
final_xshift_ = final_xshift;
final_yshift_ = final_yshift;
}
示例7: ComputeEdgeDensityProfiles
// Converts the run-length image (see above to the edge density profiles used
// for scaling, thus:
// ______________
// |7 1_1_1_1_1 7| = 5.28
// |1|5 5 1 5 5|1| = 3.8
// |1|2 2|1|2 2|1| = 5
// |1|2 2|1|2 2|1| = 5
// |1|2 2|1|2 2|1| = 5
// |1|2 2|1|2 2|1| = 5
// |1|5_5_1_5_5|1| = 3.8
// |7_1_1_1_1_1_7| = 5.28
// 6 4 4 8 4 4 6
// . . . . . . .
// 2 4 4 0 4 4 2
// 8 8
// Each profile is the sum of the reciprocals of the pixels in the image in
// the appropriate row or column, and these are then normalized to sum to 1.
// On output hx, hy contain an extra element, which will eventually be used
// to guarantee that the top/right edge of the box (and anything beyond) always
// gets mapped to the maximum target coordinate.
static void ComputeEdgeDensityProfiles(const TBOX& box,
const GENERIC_2D_ARRAY<int>& minruns,
GenericVector<float>* hx,
GenericVector<float>* hy) {
int width = box.width();
int height = box.height();
hx->init_to_size(width + 1, 0.0);
hy->init_to_size(height + 1, 0.0);
double total = 0.0;
for (int iy = 0; iy < height; ++iy) {
for (int ix = 0; ix < width; ++ix) {
int run = minruns(ix, iy);
if (run == 0) run = 1;
float density = 1.0f / run;
(*hx)[ix] += density;
(*hy)[iy] += density;
}
total += (*hy)[iy];
}
// Normalize each profile to sum to 1.
if (total > 0.0) {
for (int ix = 0; ix < width; ++ix) {
(*hx)[ix] /= total;
}
for (int iy = 0; iy < height; ++iy) {
(*hy)[iy] /= total;
}
}
// There is an extra element in each array, so initialize to 1.
(*hx)[width] = 1.0f;
(*hy)[height] = 1.0f;
}
示例8: VerticalTextlinePartner
// Return the partner of this TabVector if the vector qualifies as
// being a vertical text line, otherwise NULL.
TabVector* TabVector::VerticalTextlinePartner() {
if (!partners_.singleton())
return NULL;
TabVector_C_IT partner_it(&partners_);
TabVector* partner = partner_it.data();
BLOBNBOX_C_IT box_it1(&boxes_);
BLOBNBOX_C_IT box_it2(&partner->boxes_);
// Count how many boxes are also in the other list.
// At the same time, gather the mean width and median vertical gap.
if (textord_debug_tabfind > 1) {
Print("Testing for vertical text");
partner->Print(" partner");
}
int num_matched = 0;
int num_unmatched = 0;
int total_widths = 0;
int width = startpt().x() - partner->startpt().x();
if (width < 0)
width = -width;
STATS gaps(0, width * 2);
BLOBNBOX* prev_bbox = NULL;
box_it2.mark_cycle_pt();
for (box_it1.mark_cycle_pt(); !box_it1.cycled_list(); box_it1.forward()) {
BLOBNBOX* bbox = box_it1.data();
TBOX box = bbox->bounding_box();
if (prev_bbox != NULL) {
gaps.add(box.bottom() - prev_bbox->bounding_box().top(), 1);
}
while (!box_it2.cycled_list() && box_it2.data() != bbox &&
box_it2.data()->bounding_box().bottom() < box.bottom()) {
box_it2.forward();
}
if (!box_it2.cycled_list() && box_it2.data() == bbox &&
bbox->region_type() >= BRT_UNKNOWN &&
(prev_bbox == NULL || prev_bbox->region_type() >= BRT_UNKNOWN))
++num_matched;
else
++num_unmatched;
total_widths += box.width();
prev_bbox = bbox;
}
if (num_unmatched + num_matched == 0) return NULL;
double avg_width = total_widths * 1.0 / (num_unmatched + num_matched);
double max_gap = textord_tabvector_vertical_gap_fraction * avg_width;
int min_box_match = static_cast<int>((num_matched + num_unmatched) *
textord_tabvector_vertical_box_ratio);
bool is_vertical = (gaps.get_total() > 0 &&
num_matched >= min_box_match &&
gaps.median() <= max_gap);
if (textord_debug_tabfind > 1) {
tprintf("gaps=%d, matched=%d, unmatched=%d, min_match=%d "
"median gap=%.2f, width=%.2f max_gap=%.2f Vertical=%s\n",
gaps.get_total(), num_matched, num_unmatched, min_box_match,
gaps.median(), avg_width, max_gap, is_vertical?"Yes":"No");
}
return (is_vertical) ? partner : NULL;
}
示例9: GetEdgeCoords
// Adds edges to the given vectors.
// For all the edge steps in all the outlines, or polygonal approximation
// where there are no edge steps, collects the steps into x_coords/y_coords.
// x_coords is a collection of the x-coords of vertical edges for each
// y-coord starting at box.bottom().
// y_coords is a collection of the y-coords of horizontal edges for each
// x-coord starting at box.left().
// Eg x_coords[0] is a collection of the x-coords of edges at y=bottom.
// Eg x_coords[1] is a collection of the x-coords of edges at y=bottom + 1.
void TBLOB::GetEdgeCoords(const TBOX& box,
GenericVector<GenericVector<int> >* x_coords,
GenericVector<GenericVector<int> >* y_coords) const {
GenericVector<int> empty;
x_coords->init_to_size(box.height(), empty);
y_coords->init_to_size(box.width(), empty);
CollectEdges(box, nullptr, nullptr, x_coords, y_coords);
// Sort the output vectors.
for (int i = 0; i < x_coords->size(); ++i) (*x_coords)[i].sort();
for (int i = 0; i < y_coords->size(); ++i) (*y_coords)[i].sort();
}
示例10: make_tess_blob
/**********************************************************************
* make_rotated_tess_blob
*
* Make a single Tess style blob, applying the given rotation and
* renormalizing.
**********************************************************************/
TBLOB *make_rotated_tess_blob(const DENORM* denorm, PBLOB *blob,
BOOL8 flatten) {
if (denorm != NULL && denorm->block() != NULL &&
denorm->block()->classify_rotation().y() != 0.0) {
TBOX box = blob->bounding_box();
int src_width = box.width();
int src_height = box.height();
src_width = static_cast<int>(src_width / denorm->scale() + 0.5);
src_height = static_cast<int>(src_height / denorm->scale() + 0.5);
int x_middle = (box.left() + box.right()) / 2;
int y_middle = (box.top() + box.bottom()) / 2;
PBLOB* rotated_blob = PBLOB::deep_copy(blob);
rotated_blob->move(FCOORD(-x_middle, -y_middle));
rotated_blob->rotate(denorm->block()->classify_rotation());
ICOORD median_size = denorm->block()->median_size();
int tolerance = median_size.x() / 8;
// TODO(dsl/rays) find a better normalization solution. In the mean time
// make it work for CJK by normalizing for Cap height in the same way
// as is applied in compute_block_xheight when the row is presumed to
// be ALLCAPS, i.e. the x-height is the fixed fraction
// blob height * textord_merge_x / (textord_merge_x + textord_merge_asc)
if (NearlyEqual(src_width, static_cast<int>(median_size.x()), tolerance) &&
NearlyEqual(src_height, static_cast<int>(median_size.y()), tolerance)) {
float target_height = bln_x_height * (textord_merge_x + textord_merge_asc)
/ textord_merge_x;
rotated_blob->scale(target_height / box.width());
rotated_blob->move(FCOORD(0.0f,
bln_baseline_offset -
rotated_blob->bounding_box().bottom()));
}
TBLOB* result = make_tess_blob(rotated_blob, flatten);
delete rotated_blob;
return result;
} else {
return make_tess_blob(blob, flatten);
}
}
示例11: ComputeRunlengthImage
// Helper for SetupNonLinear computes an image of shortest run-lengths from
// the x/y edges provided.
// Based on "A nonlinear normalization method for handprinted Kanji character
// recognition -- line density equalization" by Hiromitsu Yamada et al.
// Eg below is an O in a 1-pixel margin-ed bounding box and the corresponding
// ______________ input x_coords and y_coords.
// | _________ | <empty>
// | | _ | | 1, 6
// | | | | | | 1, 3, 4, 6
// | | | | | | 1, 3, 4, 6
// | | | | | | 1, 3, 4, 6
// | | |_| | | 1, 3, 4, 6
// | |_________| | 1, 6
// |_____________| <empty>
// E 1 1 1 1 1 E
// m 7 7 2 7 7 m
// p 6 p
// t 7 t
// y y
// The output image contains the min of the x and y run-length (distance
// between edges) at each coordinate in the image thus:
// ______________
// |7 1_1_1_1_1 7|
// |1|5 5 1 5 5|1|
// |1|2 2|1|2 2|1|
// |1|2 2|1|2 2|1|
// |1|2 2|1|2 2|1|
// |1|2 2|1|2 2|1|
// |1|5_5_1_5_5|1|
// |7_1_1_1_1_1_7|
// Note that the input coords are all integer, so all partial pixels are dealt
// with elsewhere. Although it is nice for outlines to be properly connected
// and continuous, there is no requirement that they be as such, so they could
// have been derived from a flaky source, such as greyscale.
// This function works only within the provided box, and it is assumed that the
// input x_coords and y_coords have already been translated to have the bottom-
// left of box as the origin. Although an output, the minruns should have been
// pre-initialized to be the same size as box. Each element will contain the
// minimum of x and y run-length as shown above.
static void ComputeRunlengthImage(
const TBOX& box,
const GenericVector<GenericVector<int> >& x_coords,
const GenericVector<GenericVector<int> >& y_coords,
GENERIC_2D_ARRAY<int>* minruns) {
int width = box.width();
int height = box.height();
ASSERT_HOST(minruns->dim1() == width);
ASSERT_HOST(minruns->dim2() == height);
// Set a 2-d image array to the run lengths at each pixel.
for (int ix = 0; ix < width; ++ix) {
int y = 0;
for (int i = 0; i < y_coords[ix].size(); ++i) {
int y_edge = ClipToRange(y_coords[ix][i], 0, height);
int gap = y_edge - y;
// Every pixel between the last and current edge get set to the gap.
while (y < y_edge) {
(*minruns)(ix, y) = gap;
++y;
}
}
// Pretend there is a bounding box of edges all around the image.
int gap = height - y;
while (y < height) {
(*minruns)(ix, y) = gap;
++y;
}
}
// Now set the image pixels the the MIN of the x and y runlengths.
for (int iy = 0; iy < height; ++iy) {
int x = 0;
for (int i = 0; i < x_coords[iy].size(); ++i) {
int x_edge = ClipToRange(x_coords[iy][i], 0, width);
int gap = x_edge - x;
while (x < x_edge) {
if (gap < (*minruns)(x, iy))
(*minruns)(x, iy) = gap;
++x;
}
}
int gap = width - x;
while (x < width) {
if (gap < (*minruns)(x, iy))
(*minruns)(x, iy) = gap;
++x;
}
}
}
示例12: BoundsWithinBox
// 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;
}
示例13: suspect_fullstop
BOOL8 suspect_fullstop(WERD_RES *word, inT16 i) {
float aspect_ratio;
PBLOB_LIST *blobs = word->outword->blob_list ();
PBLOB_IT blob_it(blobs);
inT16 j;
TBOX box;
inT16 width;
inT16 height;
for (j = 0; j < i; j++)
blob_it.forward ();
box = blob_it.data ()->bounding_box ();
width = box.width ();
height = box.height ();
aspect_ratio = ((width > height) ? ((float) width) / height :
((float) height) / width);
return (aspect_ratio > tessed_fullstop_aspect_ratio);
}
示例14: LargeSpeckle
// Returns true if the blob is small enough to be a large speckle.
bool Classify::LargeSpeckle(const TBLOB &blob) {
double speckle_size = kBlnXHeight * speckle_large_max_size;
TBOX bbox = blob.bounding_box();
return bbox.width() < speckle_size && bbox.height() < speckle_size;
}
示例15: Fit
// (Re)Fit a line to the stored points. Returns false if the line
// is degenerate. Althougth the TabVector code mostly doesn't care about the
// direction of lines, XAtY would give silly results for a horizontal line.
// The class is mostly aimed at use for vertical lines representing
// horizontal tab stops.
bool TabVector::Fit(ICOORD vertical, bool force_parallel) {
needs_refit_ = false;
if (boxes_.empty()) {
// Don't refit something with no boxes, as that only happens
// in Evaluate, and we don't want to end up with a zero vector.
if (!force_parallel)
return false;
// If we are forcing parallel, then we just need to set the sort_key_.
ICOORD midpt = startpt_;
midpt += endpt_;
midpt /= 2;
sort_key_ = SortKey(vertical, midpt.x(), midpt.y());
return startpt_.y() != endpt_.y();
}
if (!force_parallel && !IsRagged()) {
// Use a fitted line as the vertical.
DetLineFit linepoints;
BLOBNBOX_C_IT it(&boxes_);
// Fit a line to all the boxes in the list.
for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
BLOBNBOX* bbox = it.data();
TBOX box = bbox->bounding_box();
int x1 = IsRightTab() ? box.right() : box.left();
ICOORD boxpt(x1, box.bottom());
linepoints.Add(boxpt);
if (it.at_last()) {
ICOORD top_pt(x1, box.top());
linepoints.Add(top_pt);
}
}
linepoints.Fit(&startpt_, &endpt_);
if (startpt_.y() != endpt_.y()) {
vertical = endpt_;
vertical -= startpt_;
}
}
int start_y = startpt_.y();
int end_y = endpt_.y();
sort_key_ = IsLeftTab() ? MAX_INT32 : -MAX_INT32;
BLOBNBOX_C_IT it(&boxes_);
// Choose a line parallel to the vertical such that all boxes are on the
// correct side of it.
mean_width_ = 0;
int width_count = 0;
for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
BLOBNBOX* bbox = it.data();
TBOX box = bbox->bounding_box();
mean_width_ += box.width();
++width_count;
int x1 = IsRightTab() ? box.right() : box.left();
// Test both the bottom and the top, as one will be more extreme, depending
// on the direction of skew.
int bottom_y = box.bottom();
int top_y = box.top();
int key = SortKey(vertical, x1, bottom_y);
if (IsLeftTab() == (key < sort_key_)) {
sort_key_ = key;
startpt_ = ICOORD(x1, bottom_y);
}
key = SortKey(vertical, x1, top_y);
if (IsLeftTab() == (key < sort_key_)) {
sort_key_ = key;
startpt_ = ICOORD(x1, top_y);
}
if (it.at_first())
start_y = bottom_y;
if (it.at_last())
end_y = top_y;
}
if (width_count > 0) {
mean_width_ = (mean_width_ + width_count - 1) / width_count;
}
endpt_ = startpt_ + vertical;
needs_evaluation_ = true;
if (start_y != end_y) {
// Set the ends of the vector to fully include the first and last blobs.
startpt_.set_x(XAtY(vertical, sort_key_, start_y));
startpt_.set_y(start_y);
endpt_.set_x(XAtY(vertical, sort_key_, end_y));
endpt_.set_y(end_y);
return true;
}
return false;
}