tesseract 4.1.1
Loading...
Searching...
No Matches
wordrec.h
Go to the documentation of this file.
1
2// File: wordrec.h
3// Description: wordrec class.
4// Author: Samuel Charron
5//
6// (C) Copyright 2006, Google Inc.
7// Licensed under the Apache License, Version 2.0 (the "License");
8// you may not use this file except in compliance with the License.
9// You may obtain a copy of the License at
10// http://www.apache.org/licenses/LICENSE-2.0
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16//
18
19#ifndef TESSERACT_WORDREC_WORDREC_H_
20#define TESSERACT_WORDREC_WORDREC_H_
21
22#ifdef DISABLED_LEGACY_ENGINE
23
24#include <cstdint> // for int16_t, int32_t
25#include "classify.h" // for Classify
26#include "params.h" // for INT_VAR_H, IntParam, BOOL_VAR_H, BoolP...
27#include "ratngs.h" // for WERD_CHOICE
28
29namespace tesseract { class TessdataManager; }
30
31namespace tesseract {
32
33/* ccmain/tstruct.cpp */
34
35class Wordrec : public Classify {
36 public:
37 // config parameters
38
39 BOOL_VAR_H(wordrec_debug_blamer, false, "Print blamer debug messages");
40
41 BOOL_VAR_H(wordrec_run_blamer, false, "Try to set the blame for errors");
42
43 // methods
44 Wordrec();
45 virtual ~Wordrec() = default;
46
47 // tface.cpp
48 void program_editup(const char *textbase, TessdataManager *init_classifier,
49 TessdataManager *init_dict);
50 void program_editdown(int32_t elasped_time);
51 int end_recog();
52 int dict_word(const WERD_CHOICE &word);
53
54 // Member variables
56};
57
58} // namespace tesseract
59
60#else // DISABLED_LEGACY_ENGINE not defined
61
62#ifdef HAVE_CONFIG_H
63#include "config_auto.h"
64#endif
65
66#include <cstdint> // for int16_t, int32_t
67#include <memory>
68#include "associate.h"
69#include "callcpp.h" // for C_COL
70#include "chop.h" // for PointHeap, MAX_NUM_POINTS
71#include "classify.h" // for Classify
72#include "dict.h"
73#include "elst.h" // for ELIST_ITERATOR, ELISTIZEH, ELIST_LINK
74#include "findseam.h" // for SeamQueue, SeamPile
75#include "genericvector.h" // for GenericVector
76#include "language_model.h"
77#include "matrix.h"
78#include "oldlist.h" // for LIST
79#include "params.h" // for INT_VAR_H, IntParam, BOOL_VAR_H, BoolP...
80#include "points.h" // for ICOORD
81#include "ratngs.h" // for BLOB_CHOICE_LIST (ptr only), BLOB_CHOI...
82#include "seam.h" // for SEAM (ptr only), PRIORITY
83#include "stopper.h" // for DANGERR
84
85class EDGEPT_CLIST;
86class MATRIX;
87class STRING;
88class TBOX;
89class UNICHARSET;
90class WERD_RES;
91
92namespace tesseract { class LMPainPoints; }
93namespace tesseract { class TessdataManager; }
94namespace tesseract { struct BestChoiceBundle; }
95
96struct BlamerBundle;
97struct EDGEPT;
98struct MATRIX_COORD;
99struct SPLIT;
100struct TBLOB;
101struct TESSLINE;
102struct TWERD;
103
104namespace tesseract {
105
106// A class for storing which nodes are to be processed by the segmentation
107// search. There is a single SegSearchPending for each column in the ratings
108// matrix, and it indicates whether the segsearch should combine all
109// BLOB_CHOICES in the column, or just the given row with the parents
110// corresponding to *this SegSearchPending, and whether only updated parent
111// ViterbiStateEntries should be combined, or all, with the BLOB_CHOICEs.
113 public:
115 : classified_row_(-1),
116 revisit_whole_column_(false),
117 column_classified_(false) {}
118
119 // Marks the whole column as just classified. Used to start a search on
120 // a newly initialized ratings matrix.
122 column_classified_ = true;
123 }
124 // Marks the matrix entry at the given row as just classified.
125 // Used after classifying a new matrix cell.
126 // Additional to, not overriding a previous RevisitWholeColumn.
127 void SetBlobClassified(int row) {
128 classified_row_ = row;
129 }
130 // Marks the whole column as needing work, but not just classified.
131 // Used when the parent vse list is updated.
132 // Additional to, not overriding a previous SetBlobClassified.
134 revisit_whole_column_ = true;
135 }
136
137 // Clears *this to indicate no work to do.
138 void Clear() {
139 classified_row_ = -1;
140 revisit_whole_column_ = false;
141 column_classified_ = false;
142 }
143
144 // Returns true if there are updates to do in the column that *this
145 // represents.
146 bool WorkToDo() const {
147 return revisit_whole_column_ || column_classified_ || classified_row_ >= 0;
148 }
149 // Returns true if the given row was just classified.
150 bool IsRowJustClassified(int row) const {
151 return row == classified_row_ || column_classified_;
152 }
153 // Returns the single row to process if there is only one, otherwise -1.
154 int SingleRow() const {
155 return revisit_whole_column_ || column_classified_ ? -1 : classified_row_;
156 }
157
158 private:
159 // If non-negative, indicates the single row in the ratings matrix that has
160 // just been classified, and so should be combined with all the parents in the
161 // column that this SegSearchPending represents.
162 // Operates independently of revisit_whole_column.
163 int classified_row_;
164 // If revisit_whole_column is true, then all BLOB_CHOICEs in this column will
165 // be processed, but classified_row can indicate a row that is newly
166 // classified. Overridden if column_classified is true.
167 bool revisit_whole_column_;
168 // If column_classified is true, parent vses are processed with all rows
169 // regardless of whether they are just updated, overriding
170 // revisit_whole_column and classified_row.
171 bool column_classified_;
172};
173
174
175/* ccmain/tstruct.cpp *********************************************************/
177{
178 public:
179 FRAGMENT() { //constructor
180 }
181 FRAGMENT(EDGEPT *head_pt, //start
182 EDGEPT *tail_pt); //end
183
184 ICOORD head; //coords of start
185 ICOORD tail; //coords of end
186 EDGEPT *headpt; //start point
187 EDGEPT *tailpt; //end point
188};
190
191
192class Wordrec : public Classify {
193 public:
194 // config parameters *******************************************************
195 BOOL_VAR_H(merge_fragments_in_matrix, true,
196 "Merge the fragments in the ratings matrix and delete them "
197 "after merging");
198 BOOL_VAR_H(wordrec_enable_assoc, true, "Associator Enable");
199 BOOL_VAR_H(force_word_assoc, false,
200 "force associator to run regardless of what enable_assoc is."
201 "This is used for CJK where component grouping is necessary.");
202 INT_VAR_H(repair_unchopped_blobs, 1, "Fix blobs that aren't chopped");
203 double_VAR_H(tessedit_certainty_threshold, -2.25, "Good blob limit");
204 INT_VAR_H(chop_debug, 0, "Chop debug");
205 BOOL_VAR_H(chop_enable, 1, "Chop enable");
206 BOOL_VAR_H(chop_vertical_creep, 0, "Vertical creep");
207 INT_VAR_H(chop_split_length, 10000, "Split Length");
208 INT_VAR_H(chop_same_distance, 2, "Same distance");
209 INT_VAR_H(chop_min_outline_points, 6, "Min Number of Points on Outline");
210 INT_VAR_H(chop_seam_pile_size, 150, "Max number of seams in seam_pile");
211 BOOL_VAR_H(chop_new_seam_pile, 1, "Use new seam_pile");
212 INT_VAR_H(chop_inside_angle, -50, "Min Inside Angle Bend");
213 INT_VAR_H(chop_min_outline_area, 2000, "Min Outline Area");
214 double_VAR_H(chop_split_dist_knob, 0.5, "Split length adjustment");
215 double_VAR_H(chop_overlap_knob, 0.9, "Split overlap adjustment");
216 double_VAR_H(chop_center_knob, 0.15, "Split center adjustment");
217 INT_VAR_H(chop_centered_maxwidth, 90, "Width of (smaller) chopped blobs "
218 "above which we don't care that a chop is not near the center.");
219 double_VAR_H(chop_sharpness_knob, 0.06, "Split sharpness adjustment");
220 double_VAR_H(chop_width_change_knob, 5.0, "Width change adjustment");
221 double_VAR_H(chop_ok_split, 100.0, "OK split limit");
222 double_VAR_H(chop_good_split, 50.0, "Good split limit");
223 INT_VAR_H(chop_x_y_weight, 3, "X / Y length weight");
224 BOOL_VAR_H(assume_fixed_pitch_char_segment, false,
225 "include fixed-pitch heuristics in char segmentation");
226 INT_VAR_H(wordrec_debug_level, 0, "Debug level for wordrec");
227 INT_VAR_H(wordrec_max_join_chunks, 4,
228 "Max number of broken pieces to associate");
229 BOOL_VAR_H(wordrec_skip_no_truth_words, false,
230 "Only run OCR for words that had truth recorded in BlamerBundle");
231 BOOL_VAR_H(wordrec_debug_blamer, false, "Print blamer debug messages");
232 BOOL_VAR_H(wordrec_run_blamer, false, "Try to set the blame for errors");
233 INT_VAR_H(segsearch_debug_level, 0, "SegSearch debug level");
234 INT_VAR_H(segsearch_max_pain_points, 2000,
235 "Maximum number of pain points stored in the queue");
236 INT_VAR_H(segsearch_max_futile_classifications, 10,
237 "Maximum number of pain point classifications per word.");
238 double_VAR_H(segsearch_max_char_wh_ratio, 2.0,
239 "Maximum character width-to-height ratio");
240 BOOL_VAR_H(save_alt_choices, true,
241 "Save alternative paths found during chopping "
242 "and segmentation search");
243
244 // methods from wordrec/*.cpp ***********************************************
245 Wordrec();
246 ~Wordrec() override = default;
247
248 // Fills word->alt_choices with alternative paths found during
249 // chopping/segmentation search that are kept in best_choices.
250 void SaveAltChoices(const LIST &best_choices, WERD_RES *word);
251
252 // Fills character choice lattice in the given BlamerBundle
253 // using the given ratings matrix and best choice list.
254 void FillLattice(const MATRIX &ratings, const WERD_CHOICE_LIST &best_choices,
255 const UNICHARSET &unicharset, BlamerBundle *blamer_bundle);
256
257 // Calls fill_lattice_ member function
258 // (assumes that fill_lattice_ is not nullptr).
259 void CallFillLattice(const MATRIX &ratings,
260 const WERD_CHOICE_LIST &best_choices,
261 const UNICHARSET &unicharset,
262 BlamerBundle *blamer_bundle) {
263 (this->*fill_lattice_)(ratings, best_choices, unicharset, blamer_bundle);
264 }
265
266 // tface.cpp
267 void program_editup(const char *textbase, TessdataManager *init_classifier,
268 TessdataManager *init_dict);
269 void cc_recog(WERD_RES *word);
270 void program_editdown(int32_t elasped_time);
271 void set_pass1();
272 void set_pass2();
273 int end_recog();
274 BLOB_CHOICE_LIST *call_matcher(TBLOB* blob);
275 int dict_word(const WERD_CHOICE &word);
276 // wordclass.cpp
277 BLOB_CHOICE_LIST *classify_blob(TBLOB *blob,
278 const char *string,
279 C_COL color,
280 BlamerBundle *blamer_bundle);
281
282 // segsearch.cpp
283 // SegSearch works on the lower diagonal matrix of BLOB_CHOICE_LISTs.
284 // Each entry in the matrix represents the classification choice
285 // for a chunk, i.e. an entry in row 2, column 1 represents the list
286 // of ratings for the chunks 1 and 2 classified as a single blob.
287 // The entries on the diagonal of the matrix are classifier choice lists
288 // for a single chunk from the maximal segmentation.
289 //
290 // The ratings matrix given to SegSearch represents the segmentation
291 // graph / trellis for the current word. The nodes in the graph are the
292 // individual BLOB_CHOICEs in each of the BLOB_CHOICE_LISTs in the ratings
293 // matrix. The children of each node (nodes connected by outgoing links)
294 // are the entries in the column that is equal to node's row+1. The parents
295 // (nodes connected by the incoming links) are the entries in the row that
296 // is equal to the node's column-1. Here is an example ratings matrix:
297 //
298 // 0 1 2 3 4
299 // -------------------------
300 // 0| c,( |
301 // 1| d l,1 |
302 // 2| o |
303 // 3| c,( |
304 // 4| g,y l,1 |
305 // -------------------------
306 //
307 // In the example above node "o" has children (outgoing connection to nodes)
308 // "c","(","g","y" and parents (incoming connections from nodes) "l","1","d".
309 //
310 // The objective of the search is to find the least cost path, where the cost
311 // is determined by the language model components and the properties of the
312 // cut between the blobs on the path. SegSearch starts by populating the
313 // matrix with the all the entries that were classified by the chopper and
314 // finding the initial best path. Based on the classifier ratings, language
315 // model scores and the properties of each cut, a list of "pain points" is
316 // constructed - those are the points on the path where the choices do not
317 // look consistent with the neighboring choices, the cuts look particularly
318 // problematic, or the certainties of the blobs are low. The most troublesome
319 // "pain point" is picked from the list and the new entry in the ratings
320 // matrix corresponding to this "pain point" is filled in. Then the language
321 // model state is updated to reflect the new classification and the new
322 // "pain points" are added to the list and the next most troublesome
323 // "pain point" is determined. This continues until either the word choice
324 // composed from the best paths in the segmentation graph is "good enough"
325 // (e.g. above a certain certainty threshold, is an unambiguous dictionary
326 // word, etc) or there are no more "pain points" to explore.
327 //
328 // If associate_blobs is set to false no new classifications will be done
329 // to combine blobs. Segmentation search will run only one "iteration"
330 // on the classifications already recorded in chunks_record.ratings.
331 //
332 // Note: this function assumes that word_res, best_choice_bundle arguments
333 // are not nullptr.
334 void SegSearch(WERD_RES* word_res,
335 BestChoiceBundle* best_choice_bundle,
336 BlamerBundle* blamer_bundle);
337
338 // Setup and run just the initial segsearch on an established matrix,
339 // without doing any additional chopping or joining.
340 // (Internal factored version that can be used as part of the main SegSearch.)
341 void InitialSegSearch(WERD_RES* word_res, LMPainPoints* pain_points,
343 BestChoiceBundle* best_choice_bundle,
344 BlamerBundle* blamer_bundle);
345
346 // Runs SegSearch() function (above) without needing a best_choice_bundle
347 // or blamer_bundle. Used for testing.
348 void DoSegSearch(WERD_RES* word_res);
349
350 // chop.cpp
351 PRIORITY point_priority(EDGEPT *point);
352 void add_point_to_list(PointHeap* point_heap, EDGEPT *point);
353 // Returns true if the edgept supplied as input is an inside angle. This
354 // is determined by the angular change of the vectors from point to point.
355 bool is_inside_angle(EDGEPT *pt);
356 int angle_change(EDGEPT *point1, EDGEPT *point2, EDGEPT *point3);
357 EDGEPT *pick_close_point(EDGEPT *critical_point,
358 EDGEPT *vertical_point,
359 int *best_dist);
360 void prioritize_points(TESSLINE *outline, PointHeap* points);
361 void new_min_point(EDGEPT *local_min, PointHeap* points);
362 void new_max_point(EDGEPT *local_max, PointHeap* points);
363 void vertical_projection_point(EDGEPT *split_point, EDGEPT *target_point,
364 EDGEPT** best_point,
365 EDGEPT_CLIST *new_points);
366
367 // chopper.cpp
368 SEAM *attempt_blob_chop(TWERD *word, TBLOB *blob, int32_t blob_number,
369 bool italic_blob, const GenericVector<SEAM*>& seams);
370 SEAM *chop_numbered_blob(TWERD *word, int32_t blob_number,
371 bool italic_blob, const GenericVector<SEAM*>& seams);
372 SEAM *chop_overlapping_blob(const GenericVector<TBOX>& boxes,
373 bool italic_blob,
374 WERD_RES *word_res, int *blob_number);
375 SEAM *improve_one_blob(const GenericVector<BLOB_CHOICE*> &blob_choices,
376 DANGERR *fixpt,
377 bool split_next_to_fragment,
378 bool italic_blob,
379 WERD_RES *word,
380 int *blob_number);
381 SEAM *chop_one_blob(const GenericVector<TBOX> &boxes,
382 const GenericVector<BLOB_CHOICE*> &blob_choices,
383 WERD_RES *word_res,
384 int *blob_number);
385 void chop_word_main(WERD_RES *word);
386 void improve_by_chopping(float rating_cert_scale,
387 WERD_RES *word,
388 BestChoiceBundle *best_choice_bundle,
389 BlamerBundle *blamer_bundle,
390 LMPainPoints *pain_points,
392 int select_blob_to_split(const GenericVector<BLOB_CHOICE*> &blob_choices,
393 float rating_ceiling,
394 bool split_next_to_fragment);
395 int select_blob_to_split_from_fixpt(DANGERR *fixpt);
396
397 // findseam.cpp
398 void add_seam_to_queue(float new_priority, SEAM *new_seam, SeamQueue* seams);
399 void choose_best_seam(SeamQueue *seam_queue, const SPLIT *split,
400 PRIORITY priority, SEAM **seam_result, TBLOB *blob,
401 SeamPile *seam_pile);
402 void combine_seam(const SeamPile& seam_pile,
403 const SEAM* seam, SeamQueue* seam_queue);
404 SEAM *pick_good_seam(TBLOB *blob);
405 void try_point_pairs (EDGEPT * points[MAX_NUM_POINTS],
406 int16_t num_points,
407 SeamQueue* seam_queue,
408 SeamPile* seam_pile,
409 SEAM ** seam, TBLOB * blob);
410 void try_vertical_splits(EDGEPT * points[MAX_NUM_POINTS],
411 int16_t num_points,
412 EDGEPT_CLIST *new_points,
413 SeamQueue* seam_queue,
414 SeamPile* seam_pile,
415 SEAM ** seam, TBLOB * blob);
416
417 // gradechop.cpp
418 PRIORITY grade_split_length(SPLIT *split);
419 PRIORITY grade_sharpness(SPLIT *split);
420
421 // outlines.cpp
422 bool near_point(EDGEPT *point, EDGEPT *line_pt_0, EDGEPT *line_pt_1,
423 EDGEPT **near_pt);
424
425 // pieces.cpp
426 virtual BLOB_CHOICE_LIST *classify_piece(const GenericVector<SEAM*>& seams,
427 int16_t start,
428 int16_t end,
429 const char* description,
430 TWERD *word,
431 BlamerBundle *blamer_bundle);
432 // Try to merge fragments in the ratings matrix and put the result in
433 // the corresponding row and column
434 void merge_fragments(MATRIX *ratings,
435 int16_t num_blobs);
436 // Recursively go through the ratings matrix to find lists of fragments
437 // to be merged in the function merge_and_put_fragment_lists.
438 // current_frag is the position of the piece we are looking for.
439 // current_row is the row in the rating matrix we are currently at.
440 // start is the row we started initially, so that we can know where
441 // to append the results to the matrix. num_frag_parts is the total
442 // number of pieces we are looking for and num_blobs is the size of the
443 // ratings matrix.
444 void get_fragment_lists(int16_t current_frag,
445 int16_t current_row,
446 int16_t start,
447 int16_t num_frag_parts,
448 int16_t num_blobs,
449 MATRIX *ratings,
450 BLOB_CHOICE_LIST *choice_lists);
451 // Merge the fragment lists in choice_lists and append it to the
452 // ratings matrix
453 void merge_and_put_fragment_lists(int16_t row,
454 int16_t column,
455 int16_t num_frag_parts,
456 BLOB_CHOICE_LIST *choice_lists,
457 MATRIX *ratings);
458 // Filter the fragment list so that the filtered_choices only contain
459 // fragments that are in the correct position. choices is the list
460 // that we are going to filter. fragment_pos is the position in the
461 // fragment that we are looking for and num_frag_parts is the the
462 // total number of pieces. The result will be appended to
463 // filtered_choices.
464 void fill_filtered_fragment_list(BLOB_CHOICE_LIST *choices,
465 int fragment_pos,
466 int num_frag_parts,
467 BLOB_CHOICE_LIST *filtered_choices);
468
469 // Member variables.
470
471 std::unique_ptr<LanguageModel> language_model_;
473 // Stores the best choice for the previous word in the paragraph.
474 // This variable is modified by PAGE_RES_IT when iterating over
475 // words to OCR on the page.
477 // Sums of blame reasons computed by the blamer.
479 // Function used to fill char choice lattices.
480 void (Wordrec::*fill_lattice_)(const MATRIX &ratings,
481 const WERD_CHOICE_LIST &best_choices,
482 const UNICHARSET &unicharset,
483 BlamerBundle *blamer_bundle);
484
485 protected:
486 inline bool SegSearchDone(int num_futile_classifications) {
487 return (language_model_->AcceptableChoiceFound() ||
488 num_futile_classifications >=
489 segsearch_max_futile_classifications);
490 }
491
492 // Updates the language model state recorded for the child entries specified
493 // in pending[starting_col]. Enqueues the children of the updated entries
494 // into pending and proceeds to update (and remove from pending) all the
495 // remaining entries in pending[col] (col >= starting_col). Upon termination
496 // of this function all the pending[col] lists will be empty.
497 //
498 // The arguments:
499 //
500 // starting_col: index of the column in chunks_record->ratings from
501 // which the update should be started
502 //
503 // pending: list of entries listing chunks_record->ratings entries
504 // that should be updated
505 //
506 // pain_points: priority heap listing the pain points generated by
507 // the language model
508 //
509 // temp_pain_points: temporary storage for tentative pain points generated
510 // by the language model after a single call to LanguageModel::UpdateState()
511 // (the argument is passed in rather than created before each
512 // LanguageModel::UpdateState() call to avoid dynamic memory re-allocation)
513 //
514 // best_choice_bundle: a collection of variables that should be updated
515 // if a new best choice is found
516 //
517 void UpdateSegSearchNodes(
518 float rating_cert_scale,
519 int starting_col,
521 WERD_RES *word_res,
522 LMPainPoints *pain_points,
523 BestChoiceBundle *best_choice_bundle,
524 BlamerBundle *blamer_bundle);
525
526 // Process the given pain point: classify the corresponding blob, enqueue
527 // new pain points to join the newly classified blob with its neighbors.
528 void ProcessSegSearchPainPoint(float pain_point_priority,
529 const MATRIX_COORD &pain_point,
530 const char* pain_point_type,
532 WERD_RES *word_res,
533 LMPainPoints *pain_points,
534 BlamerBundle *blamer_bundle);
535 // Resets enough of the results so that the Viterbi search is re-run.
536 // Needed when the n-gram model is enabled, as the multi-length comparison
537 // implementation will re-value existing paths to worse values.
538 void ResetNGramSearch(WERD_RES* word_res,
539 BestChoiceBundle* best_choice_bundle,
541
542 // Add pain points for classifying blobs on the correct segmentation path
543 // (so that we can evaluate correct segmentation path and discover the reason
544 // for incorrect result).
545 void InitBlamerForSegSearch(WERD_RES *word_res,
546 LMPainPoints *pain_points,
547 BlamerBundle *blamer_bundle,
548 STRING *blamer_debug);
549};
550
551} // namespace tesseract
552
553#endif // DISABLED_LEGACY_ENGINE
554
555#endif // TESSERACT_WORDREC_WORDREC_H_
float PRIORITY
Definition: seam.h:36
#define ELISTIZEH(CLASSNAME)
Definition: elst.h:918
#define BOOL_VAR_H(name, val, comment)
Definition: params.h:297
#define INT_VAR_H(name, val, comment)
Definition: params.h:295
#define double_VAR_H(name, val, comment)
Definition: params.h:301
C_COL
Definition: callcpp.h:27
#define MAX_NUM_POINTS
Definition: chop.h:33
Definition: blobs.h:99
Definition: blobs.h:284
Definition: blobs.h:418
Definition: matrix.h:578
integer coordinate
Definition: points.h:32
Definition: rect.h:34
Definition: seam.h:38
Definition: split.h:37
Definition: strngs.h:45
Bundle together all the things pertaining to the best choice/state.
Definition: lm_state.h:222
void SetBlobClassified(int row)
Definition: wordrec.h:127
bool IsRowJustClassified(int row) const
Definition: wordrec.h:150
EDGEPT * headpt
Definition: wordrec.h:186
EDGEPT * tailpt
Definition: wordrec.h:187
FRAGMENT(EDGEPT *head_pt, EDGEPT *tail_pt)
int dict_word(const WERD_CHOICE &word)
Definition: tface.cpp:89
WERD_CHOICE * prev_word_best_choice_
Definition: wordrec.h:476
void CallFillLattice(const MATRIX &ratings, const WERD_CHOICE_LIST &best_choices, const UNICHARSET &unicharset, BlamerBundle *blamer_bundle)
Definition: wordrec.h:259
void program_editdown(int32_t elasped_time)
Definition: tface.cpp:75
void program_editup(const char *textbase, TessdataManager *init_classifier, TessdataManager *init_dict)
Definition: tface.cpp:40
void SaveAltChoices(const LIST &best_choices, WERD_RES *word)
void FillLattice(const MATRIX &ratings, const WERD_CHOICE_LIST &best_choices, const UNICHARSET &unicharset, BlamerBundle *blamer_bundle)
bool wordrec_run_blamer
Definition: wordrec.h:232
PRIORITY pass2_ok_split
Definition: wordrec.h:472
bool wordrec_debug_blamer
Definition: wordrec.h:231
bool SegSearchDone(int num_futile_classifications)
Definition: wordrec.h:486
~Wordrec() override=default
GenericVector< int > blame_reasons_
Definition: wordrec.h:478
std::unique_ptr< LanguageModel > language_model_
Definition: wordrec.h:471