本文整理汇总了C++中TBLOB类的典型用法代码示例。如果您正苦于以下问题:C++ TBLOB类的具体用法?C++ TBLOB怎么用?C++ TBLOB使用的例子?那么恭喜您, 这里精选的类代码示例或许可以为您提供帮助。
在下文中一共展示了TBLOB类的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: render_segmentation
/**********************************************************************
* render_segmentation
*
* Create a list of line segments that represent the list of chunks
* using the correct segmentation that was supplied as input.
**********************************************************************/
void render_segmentation(ScrollView *window,
TBLOB *chunks,
SEARCH_STATE segmentation) {
TBLOB *blob;
C_COL color = Black;
int char_num = -1;
int chunks_left = 0;
TBOX bbox;
if (chunks) bbox = chunks->bounding_box();
for (blob = chunks; blob != NULL; blob = blob->next) {
bbox += blob->bounding_box();
if (chunks_left-- == 0) {
color = color_list[++char_num % NUM_COLORS];
if (char_num < segmentation[0])
chunks_left = segmentation[char_num + 1];
else
chunks_left = MAX_INT32;
}
render_outline(window, blob->outlines, color);
}
window->ZoomToRectangle(bbox.left(), bbox.top(),
bbox.right(), bbox.bottom());
}
示例2: count_blobs
/**********************************************************************
* 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;
}
示例3: plot
void TWERD::plot(ScrollView* window) {
ScrollView::Color color = WERD::NextColor(ScrollView::BLACK);
for (TBLOB* blob = blobs; blob != NULL; blob = blob->next) {
blob->plot(window, color, ScrollView::BROWN);
color = WERD::NextColor(color);
}
}
示例4: CountMisfitTops
// Returns the number of misfit blob tops in this word.
int Tesseract::CountMisfitTops(WERD_RES *word_res) {
int bad_blobs = 0;
TBLOB* blob = word_res->rebuild_word->blobs;
int blob_id = 0;
for (; blob != NULL; blob = blob->next, ++blob_id) {
UNICHAR_ID class_id = word_res->best_choice->unichar_id(blob_id);
if (unicharset.get_isalpha(class_id) || unicharset.get_isdigit(class_id)) {
int top = blob->bounding_box().top();
if (top >= INT_FEAT_RANGE)
top = INT_FEAT_RANGE - 1;
int min_bottom, max_bottom, min_top, max_top;
unicharset.get_top_bottom(class_id, &min_bottom, &max_bottom,
&min_top, &max_top);
if (max_top - min_top > kMaxCharTopRange)
continue;
bool bad = top < min_top - x_ht_acceptance_tolerance ||
top > max_top + x_ht_acceptance_tolerance;
if (bad)
++bad_blobs;
if (debug_x_ht_level >= 1) {
tprintf("Class %s is %s with top %d vs limits of %d->%d, +/-%d\n",
unicharset.id_to_unichar(class_id),
bad ? "Misfit" : "OK", top, min_top, max_top,
static_cast<int>(x_ht_acceptance_tolerance));
}
}
}
return bad_blobs;
}
示例5: chop_one_blob
/**
* @name chop_one_blob
*
* Start with the current one-blob word and its classification. Find
* the worst blobs and try to divide it up to improve the ratings.
* Used for testing chopper.
*/
bool Wordrec::chop_one_blob(TWERD *word,
BLOB_CHOICE_LIST_VECTOR *char_choices,
inT32 *blob_number,
SEAMS *seam_list,
int *right_chop_index) {
TBLOB *blob;
inT16 x = 0;
float rating_ceiling = MAX_FLOAT32;
BLOB_CHOICE_LIST *answer;
BLOB_CHOICE_IT answer_it;
SEAM *seam;
UNICHAR_ID unichar_id = 0;
int left_chop_index = 0;
do {
*blob_number = select_blob_to_split(*char_choices, rating_ceiling, false);
if (chop_debug)
cprintf("blob_number = %d\n", *blob_number);
if (*blob_number == -1)
return false;
seam = attempt_blob_chop(word, *blob_number, true, *seam_list);
if (seam != NULL)
break;
/* Must split null blobs */
answer = char_choices->get(*blob_number);
if (answer == NULL)
return false;
answer_it.set_to_list(answer);
rating_ceiling = answer_it.data()->rating(); // try a different blob
} while (true);
/* Split OK */
for (blob = word->blobs; x < *blob_number; x++) {
blob = blob->next;
}
if (chop_debug) {
tprintf("Chop made blob1:");
blob->bounding_box().print();
tprintf("and blob2:");
blob->next->bounding_box().print();
}
*seam_list = insert_seam(*seam_list, *blob_number, seam, blob, word->blobs);
answer = char_choices->get(*blob_number);
answer_it.set_to_list(answer);
unichar_id = answer_it.data()->unichar_id();
float rating = answer_it.data()->rating() / exp(1.0);
left_chop_index = atoi(unicharset.id_to_unichar(unichar_id));
delete char_choices->get(*blob_number);
// combine confidence w/ serial #
answer = fake_classify_blob(0, rating, -rating);
modify_blob_choice(answer, left_chop_index);
char_choices->insert(answer, *blob_number);
answer = fake_classify_blob(0, rating - 0.125f, -rating);
modify_blob_choice(answer, ++*right_chop_index);
char_choices->set(answer, *blob_number + 1);
return true;
}
示例6: bounding_box
TBOX TWERD::bounding_box() const {
TBOX result;
for (TBLOB* blob = blobs; blob != NULL; blob = blob->next) {
TBOX box = blob->bounding_box();
result += box;
}
return result;
}
示例7: count_blobs
/**********************************************************************
* record_blob_bounds
*
* Set up and initialize an array that holds the bounds of a set of
* blobs. Caller should delete[] the array.
**********************************************************************/
TBOX *Wordrec::record_blob_bounds(TBLOB *blobs) {
int nblobs = count_blobs(blobs);
TBOX *bboxes = new TBOX[nblobs];
inT16 x = 0;
for (TBLOB* blob = blobs; blob != NULL; blob = blob->next) {
bboxes[x] = blob->bounding_box();
x++;
}
return bboxes;
}
示例8: flip_hyphens
// Note: After running this function word_res->ratings
// might not contain the right BLOB_CHOICE corresponding to each character
// in word_res->best_choice.
void Tesseract::flip_hyphens(WERD_RES *word_res) {
WERD_CHOICE *best_choice = word_res->best_choice;
int i;
int prev_right = -9999;
int next_left;
TBOX out_box;
float aspect_ratio;
if (tessedit_lower_flip_hyphen <= 1)
return;
int num_blobs = word_res->rebuild_word->NumBlobs();
UNICHAR_ID unichar_dash = word_res->uch_set->unichar_to_id("-");
for (i = 0; i < best_choice->length() && i < num_blobs; ++i) {
TBLOB* blob = word_res->rebuild_word->blobs[i];
out_box = blob->bounding_box();
if (i + 1 == num_blobs)
next_left = 9999;
else
next_left = word_res->rebuild_word->blobs[i + 1]->bounding_box().left();
// Dont touch small or touching blobs - it is too dangerous.
if ((out_box.width() > 8 * word_res->denorm.x_scale()) &&
(out_box.left() > prev_right) && (out_box.right() < next_left)) {
aspect_ratio = out_box.width() / (float) out_box.height();
if (word_res->uch_set->eq(best_choice->unichar_id(i), ".")) {
if (aspect_ratio >= tessedit_upper_flip_hyphen &&
word_res->uch_set->contains_unichar_id(unichar_dash) &&
word_res->uch_set->get_enabled(unichar_dash)) {
/* Certain HYPHEN */
best_choice->set_unichar_id(unichar_dash, i);
if (word_res->reject_map[i].rejected())
word_res->reject_map[i].setrej_hyphen_accept();
}
if ((aspect_ratio > tessedit_lower_flip_hyphen) &&
word_res->reject_map[i].accepted())
//Suspected HYPHEN
word_res->reject_map[i].setrej_hyphen ();
}
else if (best_choice->unichar_id(i) == unichar_dash) {
if ((aspect_ratio >= tessedit_upper_flip_hyphen) &&
(word_res->reject_map[i].rejected()))
word_res->reject_map[i].setrej_hyphen_accept();
//Certain HYPHEN
if ((aspect_ratio <= tessedit_lower_flip_hyphen) &&
(word_res->reject_map[i].accepted()))
//Suspected HYPHEN
word_res->reject_map[i].setrej_hyphen();
}
}
prev_right = out_box.right();
}
}
示例9: bounding_box
// Baseline normalizes the blobs in-place, recording the normalization in the
// DENORMs in the blobs.
void TWERD::BLNormalize(const BLOCK* block, const ROW* row, Pix* pix,
bool inverse, float x_height, bool numeric_mode,
tesseract::OcrEngineMode hint,
const TBOX* norm_box,
DENORM* word_denorm) {
TBOX word_box = bounding_box();
if (norm_box != NULL) word_box = *norm_box;
float word_middle = (word_box.left() + word_box.right()) / 2.0f;
float input_y_offset = 0.0f;
float final_y_offset = static_cast<float>(kBlnBaselineOffset);
float scale = kBlnXHeight / x_height;
if (hint == tesseract::OEM_CUBE_ONLY || row == NULL) {
word_middle = word_box.left();
input_y_offset = word_box.bottom();
final_y_offset = 0.0f;
if (hint == tesseract::OEM_CUBE_ONLY)
scale = 1.0f;
} else {
input_y_offset = row->base_line(word_middle);
}
for (int b = 0; b < blobs.size(); ++b) {
TBLOB* blob = blobs[b];
TBOX blob_box = blob->bounding_box();
float mid_x = (blob_box.left() + blob_box.right()) / 2.0f;
float baseline = input_y_offset;
float blob_scale = scale;
if (numeric_mode) {
baseline = blob_box.bottom();
blob_scale = ClipToRange(kBlnXHeight * 4.0f / (3 * blob_box.height()),
scale, scale * 1.5f);
} else if (row != NULL && hint != tesseract::OEM_CUBE_ONLY) {
baseline = row->base_line(mid_x);
}
// The image will be 8-bit grey if the input was grey or color. Note that in
// a grey image 0 is black and 255 is white. If the input was binary, then
// the pix will be binary and 0 is white, with 1 being black.
// To tell the difference pixGetDepth() will return 8 or 1.
// The inverse flag will be true iff the word has been determined to be
// white on black, and is independent of whether the pix is 8 bit or 1 bit.
blob->Normalize(block, NULL, NULL, word_middle, baseline, blob_scale,
blob_scale, 0.0f, final_y_offset, inverse, pix);
}
if (word_denorm != NULL) {
word_denorm->SetupNormalization(block, NULL, NULL, word_middle,
input_y_offset, scale, scale,
0.0f, final_y_offset);
word_denorm->set_inverse(inverse);
word_denorm->set_pix(pix);
}
}
示例10: ExtractFeatures
// Extracts sets of 3-D features of length kStandardFeatureLength (=12.8), as
// (x,y) position and angle as measured counterclockwise from the vector
// <-1, 0>, from blob using two normalizations defined by bl_denorm and
// cn_denorm. See SetpuBLCNDenorms for definitions.
// If outline_cn_counts is not nullptr, on return it contains the cumulative
// number of cn features generated for each outline in the blob (in order).
// Thus after the first outline, there were (*outline_cn_counts)[0] features,
// after the second outline, there were (*outline_cn_counts)[1] features etc.
void Classify::ExtractFeatures(const TBLOB& blob,
bool nonlinear_norm,
GenericVector<INT_FEATURE_STRUCT>* bl_features,
GenericVector<INT_FEATURE_STRUCT>* cn_features,
INT_FX_RESULT_STRUCT* results,
GenericVector<int>* outline_cn_counts) {
DENORM bl_denorm, cn_denorm;
tesseract::Classify::SetupBLCNDenorms(blob, nonlinear_norm,
&bl_denorm, &cn_denorm, results);
if (outline_cn_counts != nullptr)
outline_cn_counts->truncate(0);
// Iterate the outlines.
for (TESSLINE* ol = blob.outlines; ol != nullptr; ol = ol->next) {
// Iterate the polygon.
EDGEPT* loop_pt = ol->FindBestStartPt();
EDGEPT* pt = loop_pt;
if (pt == nullptr) continue;
do {
if (pt->IsHidden()) continue;
// Find a run of equal src_outline.
EDGEPT* last_pt = pt;
do {
last_pt = last_pt->next;
} while (last_pt != loop_pt && !last_pt->IsHidden() &&
last_pt->src_outline == pt->src_outline);
last_pt = last_pt->prev;
// Until the adaptive classifier can be weaned off polygon segments,
// we have to force extraction from the polygon for the bl_features.
ExtractFeaturesFromRun(pt, last_pt, bl_denorm, kStandardFeatureLength,
true, bl_features);
ExtractFeaturesFromRun(pt, last_pt, cn_denorm, kStandardFeatureLength,
false, cn_features);
pt = last_pt;
} while ((pt = pt->next) != loop_pt);
if (outline_cn_counts != nullptr)
outline_cn_counts->push_back(cn_features->size());
}
results->NumBL = bl_features->size();
results->NumCN = cn_features->size();
results->YBottom = blob.bounding_box().bottom();
results->YTop = blob.bounding_box().top();
results->Width = blob.bounding_box().width();
}
示例11: ScrollView
// Displays the segmentation state of *this (if not the same as the last
// one displayed) and waits for a click in the window.
void WERD_CHOICE::DisplaySegmentation(TWERD* word) {
#ifndef GRAPHICS_DISABLED
// Number of different colors to draw with.
const int kNumColors = 6;
static ScrollView *segm_window = NULL;
// Check the state against the static prev_drawn_state.
static GenericVector<int> prev_drawn_state;
bool already_done = prev_drawn_state.size() == length_;
if (!already_done) prev_drawn_state.init_to_size(length_, 0);
for (int i = 0; i < length_; ++i) {
if (prev_drawn_state[i] != state_[i]) {
already_done = false;
}
prev_drawn_state[i] = state_[i];
}
if (already_done || word->blobs.empty()) return;
// Create the window if needed.
if (segm_window == NULL) {
segm_window = new ScrollView("Segmentation", 5, 10, 500, 256,
2000.0, 256.0, true);
} else {
segm_window->Clear();
}
TBOX bbox;
int blob_index = 0;
for (int c = 0; c < length_; ++c) {
ScrollView::Color color =
static_cast<ScrollView::Color>(c % kNumColors + 3);
for (int i = 0; i < state_[c]; ++i, ++blob_index) {
TBLOB* blob = word->blobs[blob_index];
bbox += blob->bounding_box();
blob->plot(segm_window, color, color);
}
}
segm_window->ZoomToRectangle(bbox.left(), bbox.top(),
bbox.right(), bbox.bottom());
segm_window->Update();
window_wait(segm_window);
#endif
}
示例12: TBOX
SEAM *Wordrec::chop_overlapping_blob(const GenericVector<TBOX>& boxes,
bool italic_blob, WERD_RES *word_res,
int *blob_number) {
TWERD *word = word_res->chopped_word;
for (*blob_number = 0; *blob_number < word->NumBlobs(); ++*blob_number) {
TBLOB *blob = word->blobs[*blob_number];
TPOINT topleft, botright;
topleft.x = blob->bounding_box().left();
topleft.y = blob->bounding_box().top();
botright.x = blob->bounding_box().right();
botright.y = blob->bounding_box().bottom();
TPOINT original_topleft, original_botright;
word_res->denorm.DenormTransform(NULL, topleft, &original_topleft);
word_res->denorm.DenormTransform(NULL, botright, &original_botright);
TBOX original_box = TBOX(original_topleft.x, original_botright.y,
original_botright.x, original_topleft.y);
bool almost_equal_box = false;
int num_overlap = 0;
for (int i = 0; i < boxes.size(); i++) {
if (original_box.overlap_fraction(boxes[i]) > 0.125)
num_overlap++;
if (original_box.almost_equal(boxes[i], 3))
almost_equal_box = true;
}
TPOINT location;
if (divisible_blob(blob, italic_blob, &location) ||
(!almost_equal_box && num_overlap > 1)) {
SEAM *seam = attempt_blob_chop(word, blob, *blob_number,
italic_blob, word_res->seam_array);
if (seam != NULL)
return seam;
}
}
*blob_number = -1;
return NULL;
}
示例13: SetupBLNormalize
// Normalize in-place and record the normalization in the DENORM.
void TWERD::SetupBLNormalize(const BLOCK* block, const ROW* row,
float x_height, bool numeric_mode,
DENORM* denorm) const {
int num_segments = 0;
DENORM_SEG* segs = NULL;
if (numeric_mode) {
segs = new DENORM_SEG[NumBlobs()];
for (TBLOB* blob = blobs; blob != NULL; blob = blob->next) {
TBOX blob_box = blob->bounding_box();
float factor = kBlnXHeight / x_height;
factor = ClipToRange(kBlnXHeight * 4.0f / (3 * blob_box.height()),
factor, factor * 1.5f);
segs[num_segments].xstart = blob_box.left();
segs[num_segments].ycoord = blob_box.bottom();
segs[num_segments++].scale_factor = factor;
}
}
denorm->SetupBLNormalize(block, row, x_height, bounding_box(),
num_segments, segs);
delete [] segs;
}
示例14: SetupBLCNDenorms
// Computes the DENORMS for bl(baseline) and cn(character) normalization
// during feature extraction. The input denorm describes the current state
// of the blob, which is usually a baseline-normalized word.
// The Transforms setup are as follows:
// Baseline Normalized (bl) Output:
// We center the grapheme by aligning the x-coordinate of its centroid with
// x=128 and leaving the already-baseline-normalized y as-is.
//
// Character Normalized (cn) Output:
// We align the grapheme's centroid at the origin and scale it
// asymmetrically in x and y so that the 2nd moments are a standard value
// (51.2) ie the result is vaguely square.
// If classify_nonlinear_norm is true:
// A non-linear normalization is setup that attempts to evenly distribute
// edges across x and y.
//
// Some of the fields of fx_info are also setup:
// Length: Total length of outline.
// Rx: Rounded y second moment. (Reversed by convention.)
// Ry: rounded x second moment.
// Xmean: Rounded x center of mass of the blob.
// Ymean: Rounded y center of mass of the blob.
void Classify::SetupBLCNDenorms(const TBLOB& blob, bool nonlinear_norm,
DENORM* bl_denorm, DENORM* cn_denorm,
INT_FX_RESULT_STRUCT* fx_info) {
// Compute 1st and 2nd moments of the original outline.
FCOORD center, second_moments;
int length = blob.ComputeMoments(¢er, &second_moments);
if (fx_info != nullptr) {
fx_info->Length = length;
fx_info->Rx = IntCastRounded(second_moments.y());
fx_info->Ry = IntCastRounded(second_moments.x());
fx_info->Xmean = IntCastRounded(center.x());
fx_info->Ymean = IntCastRounded(center.y());
}
// Setup the denorm for Baseline normalization.
bl_denorm->SetupNormalization(nullptr, nullptr, &blob.denorm(), center.x(), 128.0f,
1.0f, 1.0f, 128.0f, 128.0f);
// Setup the denorm for character normalization.
if (nonlinear_norm) {
GenericVector<GenericVector<int> > x_coords;
GenericVector<GenericVector<int> > y_coords;
TBOX box;
blob.GetPreciseBoundingBox(&box);
box.pad(1, 1);
blob.GetEdgeCoords(box, &x_coords, &y_coords);
cn_denorm->SetupNonLinear(&blob.denorm(), box, UINT8_MAX, UINT8_MAX,
0.0f, 0.0f, x_coords, y_coords);
} else {
cn_denorm->SetupNormalization(nullptr, nullptr, &blob.denorm(),
center.x(), center.y(),
51.2f / second_moments.x(),
51.2f / second_moments.y(),
128.0f, 128.0f);
}
}
示例15: TBLOB
BLOB_CHOICE* M_Utils::runBlobOCR(BLOBNBOX* blob, Tesseract* ocrengine) {
// * Normalize blob height to x-height (current OSD):
// SetupNormalization(NULL, NULL, &rotation, NULL, NULL, 0,
// box.rotational_x_middle(rotation),
// box.rotational_y_middle(rotation),
// kBlnXHeight / box.rotational_height(rotation),
// kBlnXHeight / box.rotational_height(rotation),
// 0, kBlnBaselineOffset);
BLOB_CHOICE_LIST ratings_lang;
C_BLOB* cblob = blob->cblob();
TBLOB* tblob = TBLOB::PolygonalCopy(cblob);
const TBOX& box = tblob->bounding_box();
// Normalize the blob. Set the origin to the place we want to be the
// bottom-middle, and scaling is to mpx, box_, NULL);
float scaling = static_cast<float>(kBlnXHeight) / box.height();
DENORM denorm;
float x_orig = (box.left() + box.right()) / 2.0f, y_orig = box.bottom();
denorm.SetupNormalization(NULL, NULL, NULL, NULL, NULL, 0,
x_orig, y_orig, scaling, scaling,
0.0f, static_cast<float>(kBlnBaselineOffset));
TBLOB* normed_blob = new TBLOB(*tblob);
normed_blob->Normalize(denorm);
ocrengine->AdaptiveClassifier(normed_blob, denorm, &ratings_lang, NULL);
delete normed_blob;
delete tblob;
// Get the best choice from ratings_lang and rating_equ. As the choice in the
// list has already been sorted by the certainty, we simply use the first
// choice.
BLOB_CHOICE *lang_choice = NULL;
if (ratings_lang.length() > 0) {
BLOB_CHOICE_IT choice_it(&ratings_lang);
lang_choice = choice_it.data();
}
return lang_choice;
}