/src/tesseract/src/lstm/recodebeam.h
Line | Count | Source |
1 | | /////////////////////////////////////////////////////////////////////// |
2 | | // File: recodebeam.h |
3 | | // Description: Beam search to decode from the re-encoded CJK as a sequence of |
4 | | // smaller numbers in place of a single large code. |
5 | | // Author: Ray Smith |
6 | | // |
7 | | // (C) Copyright 2015, Google Inc. |
8 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
9 | | // you may not use this file except in compliance with the License. |
10 | | // You may obtain a copy of the License at |
11 | | // http://www.apache.org/licenses/LICENSE-2.0 |
12 | | // Unless required by applicable law or agreed to in writing, software |
13 | | // distributed under the License is distributed on an "AS IS" BASIS, |
14 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
15 | | // See the License for the specific language governing permissions and |
16 | | // limitations under the License. |
17 | | // |
18 | | /////////////////////////////////////////////////////////////////////// |
19 | | |
20 | | #ifndef THIRD_PARTY_TESSERACT_LSTM_RECODEBEAM_H_ |
21 | | #define THIRD_PARTY_TESSERACT_LSTM_RECODEBEAM_H_ |
22 | | |
23 | | #include "dawg.h" |
24 | | #include "dict.h" |
25 | | #include "genericheap.h" |
26 | | #include "genericvector.h" |
27 | | #include "kdpair.h" |
28 | | #include "networkio.h" |
29 | | #include "ratngs.h" |
30 | | #include "unicharcompress.h" |
31 | | |
32 | | #include <unordered_set> // for std::unordered_set |
33 | | #include <vector> // for std::vector |
34 | | |
35 | | namespace tesseract { |
36 | | |
37 | | // Enum describing what can follow the current node. |
38 | | // Consider the following softmax outputs: |
39 | | // Timestep 0 1 2 3 4 5 6 7 8 |
40 | | // X-score 0.01 0.55 0.98 0.42 0.01 0.01 0.40 0.95 0.01 |
41 | | // Y-score 0.00 0.01 0.01 0.01 0.01 0.97 0.59 0.04 0.01 |
42 | | // Null-score 0.99 0.44 0.01 0.57 0.98 0.02 0.01 0.01 0.98 |
43 | | // Then the correct CTC decoding (in which adjacent equal classes are folded, |
44 | | // and then all nulls are dropped) is clearly XYX, but simple decoding (taking |
45 | | // the max at each timestep) leads to: |
46 | | // Null@0.99 X@0.55 X@0.98 Null@0.57 Null@0.98 Y@0.97 Y@0.59 X@0.95 Null@0.98, |
47 | | // which folds to the correct XYX. The conversion to Tesseract rating and |
48 | | // certainty uses the sum of the log probs (log of the product of probabilities) |
49 | | // for the Rating and the minimum log prob for the certainty, but that yields a |
50 | | // minimum certainty of log(0.55), which is poor for such an obvious case. |
51 | | // CTC says that the probability of the result is the SUM of the products of the |
52 | | // probabilities over ALL PATHS that decode to the same result, which includes: |
53 | | // NXXNNYYXN, NNXNNYYN, NXXXNYYXN, NNXXNYXXN, and others including XXXXXYYXX. |
54 | | // That is intractable, so some compromise between simple and ideal is needed. |
55 | | // Observing that evenly split timesteps rarely happen next to each other, we |
56 | | // allow scores at a transition between classes to be added for decoding thus: |
57 | | // N@0.99 (N+X)@0.99 X@0.98 (N+X)@0.99 N@0.98 Y@0.97 (X+Y+N)@1.00 X@0.95 N@0.98. |
58 | | // This works because NNX and NXX both decode to X, so in the middle we can use |
59 | | // N+X. Note that the classes either side of a sum must stand alone, i.e. use a |
60 | | // single score, to force all paths to pass through them and decode to the same |
61 | | // result. Also in the special case of a transition from X to Y, with only one |
62 | | // timestep between, it is possible to add X+Y+N, since XXY, XYY, and XNY all |
63 | | // decode to XY. |
64 | | // An important condition is that we cannot combine X and Null between two |
65 | | // stand-alone Xs, since that can decode as XNX->XX or XXX->X, so the scores for |
66 | | // X and Null have to go in separate paths. Combining scores in this way |
67 | | // provides a much better minimum certainty of log(0.95). |
68 | | // In the implementation of the beam search, we have to place the possibilities |
69 | | // X, X+N and X+Y+N in the beam under appropriate conditions of the previous |
70 | | // node, and constrain what can follow, to enforce the rules explained above. |
71 | | // We therefore have 3 different types of node determined by what can follow: |
72 | | enum NodeContinuation { |
73 | | NC_ANYTHING, // This node used just its own score, so anything can follow. |
74 | | NC_ONLY_DUP, // The current node combined another score with the score for |
75 | | // itself, without a stand-alone duplicate before, so must be |
76 | | // followed by a stand-alone duplicate. |
77 | | NC_NO_DUP, // The current node combined another score with the score for |
78 | | // itself, after a stand-alone, so can only be followed by |
79 | | // something other than a duplicate of the current node. |
80 | | NC_COUNT |
81 | | }; |
82 | | |
83 | | // Enum describing the top-n status of a code. |
84 | | enum TopNState { |
85 | | TN_TOP2, // Winner or 2nd. |
86 | | TN_TOPN, // Runner up in top-n, but not 1st or 2nd. |
87 | | TN_ALSO_RAN, // Not in the top-n. |
88 | | TN_COUNT |
89 | | }; |
90 | | |
91 | | // Lattice element for Re-encode beam search. |
92 | | struct RecodeNode { |
93 | | RecodeNode() |
94 | 1.56M | : code(-1) |
95 | 1.56M | , unichar_id(INVALID_UNICHAR_ID) |
96 | 1.56M | , permuter(TOP_CHOICE_PERM) |
97 | 1.56M | , start_of_dawg(false) |
98 | 1.56M | , start_of_word(false) |
99 | 1.56M | , end_of_word(false) |
100 | 1.56M | , duplicate(false) |
101 | 1.56M | , certainty(0.0f) |
102 | 1.56M | , score(0.0f) |
103 | 1.56M | , prev(nullptr) |
104 | 1.56M | , dawgs(nullptr) |
105 | 1.56M | , code_hash(0) {} |
106 | | RecodeNode(int c, int uni_id, PermuterType perm, bool dawg_start, bool word_start, bool end, |
107 | | bool dup, float cert, float s, const RecodeNode *p, DawgPositionVector *d, |
108 | | uint64_t hash) |
109 | 28.5M | : code(c) |
110 | 28.5M | , unichar_id(uni_id) |
111 | 28.5M | , permuter(perm) |
112 | 28.5M | , start_of_dawg(dawg_start) |
113 | 28.5M | , start_of_word(word_start) |
114 | 28.5M | , end_of_word(end) |
115 | 28.5M | , duplicate(dup) |
116 | 28.5M | , certainty(cert) |
117 | 28.5M | , score(s) |
118 | 28.5M | , prev(p) |
119 | 28.5M | , dawgs(d) |
120 | 28.5M | , code_hash(hash) {} |
121 | | // NOTE: If we could use C++11, then this would be a move constructor. |
122 | | // Instead we have copy constructor that does a move!! This is because we |
123 | | // don't want to copy the whole DawgPositionVector each time, and true |
124 | | // copying isn't necessary for this struct. It does get moved around a lot |
125 | | // though inside the heap and during heap push, hence the move semantics. |
126 | 98.0M | RecodeNode(const RecodeNode &src) : dawgs(nullptr) { |
127 | 98.0M | *this = src; |
128 | 98.0M | ASSERT_HOST(src.dawgs == nullptr); |
129 | 98.0M | } |
130 | 177M | RecodeNode &operator=(const RecodeNode &src) { |
131 | 177M | if (this != &src) { |
132 | 177M | delete dawgs; |
133 | 177M | code = src.code; |
134 | 177M | unichar_id = src.unichar_id; |
135 | 177M | permuter = src.permuter; |
136 | 177M | start_of_dawg = src.start_of_dawg; |
137 | 177M | start_of_word = src.start_of_word; |
138 | 177M | end_of_word = src.end_of_word; |
139 | 177M | duplicate = src.duplicate; |
140 | 177M | certainty = src.certainty; |
141 | 177M | score = src.score; |
142 | 177M | prev = src.prev; |
143 | 177M | dawgs = src.dawgs; |
144 | 177M | code_hash = src.code_hash; |
145 | 177M | const_cast<RecodeNode &>(src).dawgs = nullptr; |
146 | 177M | } |
147 | 177M | return *this; |
148 | 177M | } |
149 | 128M | ~RecodeNode() { |
150 | 128M | delete dawgs; |
151 | 128M | } |
152 | | // Prints details of the node. |
153 | | void Print(int null_char, const UNICHARSET &unicharset, int depth) const; |
154 | | |
155 | | // The re-encoded code here = index to network output. |
156 | | int code; |
157 | | // The decoded unichar_id is only valid for the final code of a sequence. |
158 | | int unichar_id; |
159 | | // The type of permuter active at this point. Intervals between start_of_word |
160 | | // and end_of_word make valid words of type given by permuter where |
161 | | // end_of_word is true. These aren't necessarily delimited by spaces. |
162 | | PermuterType permuter; |
163 | | // True if this is the initial dawg state. May be attached to a space or, |
164 | | // in a non-space-delimited lang, the end of the previous word. |
165 | | bool start_of_dawg; |
166 | | // True if this is the first node in a dictionary word. |
167 | | bool start_of_word; |
168 | | // True if this represents a valid candidate end of word position. Does not |
169 | | // necessarily mark the end of a word, since a word can be extended beyond a |
170 | | // candidate end by a continuation, eg 'the' continues to 'these'. |
171 | | bool end_of_word; |
172 | | // True if this->code is a duplicate of prev->code. Some training modes |
173 | | // allow the network to output duplicate characters and crush them with CTC, |
174 | | // but that would mess up the dictionary search, so we just smash them |
175 | | // together on the fly using the duplicate flag. |
176 | | bool duplicate; |
177 | | // Certainty (log prob) of (just) this position. |
178 | | float certainty; |
179 | | // Total certainty of the path to this position. |
180 | | float score; |
181 | | // The previous node in this chain. Borrowed pointer. |
182 | | const RecodeNode *prev; |
183 | | // The currently active dawgs at this position. Owned pointer. |
184 | | DawgPositionVector *dawgs; |
185 | | // A hash of all codes in the prefix and this->code as well. Used for |
186 | | // duplicate path removal. |
187 | | uint64_t code_hash; |
188 | | }; |
189 | | |
190 | | using RecodePair = KDPairInc<double, RecodeNode>; |
191 | | using RecodeHeap = GenericHeap<RecodePair>; |
192 | | |
193 | | // Class that holds the entire beam search for recognition of a text line. |
194 | | class TESS_API RecodeBeamSearch { |
195 | | public: |
196 | | // Borrows the pointer, which is expected to survive until *this is deleted. |
197 | | RecodeBeamSearch(const UnicharCompress &recoder, int null_char, bool simple_text, Dict *dict); |
198 | | ~RecodeBeamSearch(); |
199 | | |
200 | | // Decodes the set of network outputs, storing the lattice internally. |
201 | | // If charset is not null, it enables detailed debugging of the beam search. |
202 | | void Decode(const NetworkIO &output, double dict_ratio, double cert_offset, |
203 | | double worst_dict_cert, const UNICHARSET *charset, int lstm_choice_mode = 0); |
204 | | void Decode(const GENERIC_2D_ARRAY<float> &output, double dict_ratio, double cert_offset, |
205 | | double worst_dict_cert, const UNICHARSET *charset); |
206 | | |
207 | | void DecodeSecondaryBeams(const NetworkIO &output, double dict_ratio, double cert_offset, |
208 | | double worst_dict_cert, const UNICHARSET *charset); |
209 | | |
210 | | // Returns the best path as labels/scores/xcoords similar to simple CTC. |
211 | | void ExtractBestPathAsLabels(std::vector<int> *labels, std::vector<int> *xcoords) const; |
212 | | // Returns the best path as unichar-ids/certs/ratings/xcoords skipping |
213 | | // duplicates, nulls and intermediate parts. |
214 | | void ExtractBestPathAsUnicharIds(bool debug, const UNICHARSET *unicharset, |
215 | | std::vector<int> *unichar_ids, std::vector<float> *certs, |
216 | | std::vector<float> *ratings, std::vector<int> *xcoords) const; |
217 | | |
218 | | // Returns the best path as a set of WERD_RES. |
219 | | void ExtractBestPathAsWords(const TBOX &line_box, float scale_factor, bool debug, |
220 | | const UNICHARSET *unicharset, PointerVector<WERD_RES> *words); |
221 | | |
222 | | // Generates debug output of the content of the beams after a Decode. |
223 | | void DebugBeams(const UNICHARSET &unicharset) const; |
224 | | |
225 | | // Extract the best characters from the current decode iteration and block |
226 | | // those symbols for the next iteration. In contrast to Tesseract's standard |
227 | | // method to chose the best overall node chain, this methods looks at a short |
228 | | // node chain segmented by the character boundaries and chooses the best |
229 | | // option independent of the remaining node chain. |
230 | | void extractSymbolChoices(const UNICHARSET *unicharset); |
231 | | |
232 | | // Generates debug output of the content of the beams after a Decode. |
233 | | void PrintBeam2(bool uids, const UNICHARSET *charset, bool secondary) const; |
234 | | // Segments the timestep bundle by the character_boundaries. |
235 | | void segmentTimestepsByCharacters(); |
236 | | std::vector<std::vector<std::pair<const char *, float>>> |
237 | | // Unions the segmented timestep character bundles to one big bundle. |
238 | | combineSegmentedTimesteps( |
239 | | std::vector<std::vector<std::vector<std::pair<const char *, float>>>> *segmentedTimesteps); |
240 | | // Stores the alternative characters of every timestep together with their |
241 | | // probability. |
242 | | std::vector<std::vector<std::pair<const char *, float>>> timesteps; |
243 | | std::vector<std::vector<std::vector<std::pair<const char *, float>>>> segmentedTimesteps; |
244 | | // Stores the character choices found in the ctc algorithm |
245 | | std::vector<std::vector<std::pair<const char *, float>>> ctc_choices; |
246 | | // Stores all unicharids which are excluded for future iterations |
247 | | std::vector<std::unordered_set<int>> excludedUnichars; |
248 | | // Stores the character boundaries regarding timesteps. |
249 | | std::vector<int> character_boundaries_; |
250 | | // Clipping value for certainty inside Tesseract. Reflects the minimum value |
251 | | // of certainty that will be returned by ExtractBestPathAsUnicharIds. |
252 | | // Supposedly on a uniform scale that can be compared across languages and |
253 | | // engines. |
254 | | static constexpr float kMinCertainty = -20.0f; |
255 | | // Number of different code lengths for which we have a separate beam. |
256 | | static const int kNumLengths = RecodedCharID::kMaxCodeLen + 1; |
257 | | // Total number of beams: dawg/nodawg * number of NodeContinuation * number |
258 | | // of different lengths. |
259 | | static const int kNumBeams = 2 * NC_COUNT * kNumLengths; |
260 | | // Returns the relevant factor in the beams_ index. |
261 | 19.2M | static int LengthFromBeamsIndex(int index) { |
262 | 19.2M | return index % kNumLengths; |
263 | 19.2M | } |
264 | 104M | static NodeContinuation ContinuationFromBeamsIndex(int index) { |
265 | 104M | return static_cast<NodeContinuation>((index / kNumLengths) % NC_COUNT); |
266 | 104M | } |
267 | 19.2M | static bool IsDawgFromBeamsIndex(int index) { |
268 | 19.2M | return index / (kNumLengths * NC_COUNT) > 0; |
269 | 19.2M | } |
270 | | // Computes a beams_ index from the given factors. |
271 | 50.4M | static int BeamIndex(bool is_dawg, NodeContinuation cont, int length) { |
272 | 50.4M | return (is_dawg * NC_COUNT + cont) * kNumLengths + length; |
273 | 50.4M | } |
274 | | |
275 | | private: |
276 | | // Struct for the Re-encode beam search. This struct holds the data for |
277 | | // a single time-step position of the output. Use a vector<RecodeBeam> |
278 | | // to hold all the timesteps and prevent reallocation of the individual heaps. |
279 | | struct RecodeBeam { |
280 | | // Resets to the initial state without deleting all the memory. |
281 | 1.55M | void Clear() { |
282 | 93.5M | for (auto &beam : beams_) { |
283 | 93.5M | beam.clear(); |
284 | 93.5M | } |
285 | 1.55M | RecodeNode empty; |
286 | 4.67M | for (auto &best_initial_dawg : best_initial_dawgs_) { |
287 | 4.67M | best_initial_dawg = empty; |
288 | 4.67M | } |
289 | 1.55M | } |
290 | | |
291 | | // A separate beam for each combination of code length, |
292 | | // NodeContinuation, and dictionary flag. Separating out all these types |
293 | | // allows the beam to be quite narrow, and yet still have a low chance of |
294 | | // losing the best path. |
295 | | // We have to keep all these beams separate, since the highest scoring paths |
296 | | // come from the paths that are most likely to dead-end at any time, like |
297 | | // dawg paths, NC_ONLY_DUP etc. |
298 | | // Each heap is stored with the WORST result at the top, so we can quickly |
299 | | // get the top-n values. |
300 | | RecodeHeap beams_[kNumBeams]; |
301 | | // While the language model is only a single word dictionary, we can use |
302 | | // word starts as a choke point in the beam, and keep only a single dict |
303 | | // start node at each step (for each NodeContinuation type), so we find the |
304 | | // best one here and push it on the heap, if it qualifies, after processing |
305 | | // all of the step. |
306 | | RecodeNode best_initial_dawgs_[NC_COUNT]; |
307 | | }; |
308 | | using TopPair = KDPairInc<float, int>; |
309 | | |
310 | | // Generates debug output of the content of a single beam position. |
311 | | void DebugBeamPos(const UNICHARSET &unicharset, const RecodeHeap &heap) const; |
312 | | |
313 | | // Returns the given best_nodes as unichar-ids/certs/ratings/xcoords skipping |
314 | | // duplicates, nulls and intermediate parts. |
315 | | static void ExtractPathAsUnicharIds(const std::vector<const RecodeNode *> &best_nodes, |
316 | | std::vector<int> *unichar_ids, std::vector<float> *certs, |
317 | | std::vector<float> *ratings, std::vector<int> *xcoords, |
318 | | std::vector<int> *character_boundaries = nullptr); |
319 | | |
320 | | // Sets up a word with the ratings matrix and fake blobs with boxes in the |
321 | | // right places. |
322 | | WERD_RES *InitializeWord(bool leading_space, const TBOX &line_box, int word_start, int word_end, |
323 | | float space_certainty, const UNICHARSET *unicharset, |
324 | | float scale_factor); |
325 | | |
326 | | // Fills top_n_flags_ with bools that are true iff the corresponding output |
327 | | // is one of the top_n. |
328 | | void ComputeTopN(const float *outputs, int num_outputs, int top_n); |
329 | | |
330 | | void ComputeSecTopN(std::unordered_set<int> *exList, const float *outputs, int num_outputs, |
331 | | int top_n); |
332 | | |
333 | | // Adds the computation for the current time-step to the beam. Call at each |
334 | | // time-step in sequence from left to right. outputs is the activation vector |
335 | | // for the current timestep. |
336 | | void DecodeStep(const float *outputs, int t, double dict_ratio, double cert_offset, |
337 | | double worst_dict_cert, const UNICHARSET *charset, bool debug = false); |
338 | | |
339 | | void DecodeSecondaryStep(const float *outputs, int t, double dict_ratio, double cert_offset, |
340 | | double worst_dict_cert, const UNICHARSET *charset, bool debug = false); |
341 | | |
342 | | // Saves the most certain choices for the current time-step. |
343 | | void SaveMostCertainChoices(const float *outputs, int num_outputs, const UNICHARSET *charset); |
344 | | |
345 | | // Calculates more accurate character boundaries which can be used to |
346 | | // provide more accurate alternative symbol choices. |
347 | | static void calculateCharBoundaries(std::vector<int> *starts, std::vector<int> *ends, |
348 | | std::vector<int> *character_boundaries_, int maxWidth); |
349 | | |
350 | | // Adds to the appropriate beams the legal (according to recoder) |
351 | | // continuations of context prev, which is from the given index to beams_, |
352 | | // using the given network outputs to provide scores to the choices. Uses only |
353 | | // those choices for which top_n_flags[code] == top_n_flag. |
354 | | void ContinueContext(const RecodeNode *prev, int index, const float *outputs, |
355 | | TopNState top_n_flag, const UNICHARSET *unicharset, double dict_ratio, |
356 | | double cert_offset, double worst_dict_cert, RecodeBeam *step); |
357 | | // Continues for a new unichar, using dawg or non-dawg as per flag. |
358 | | void ContinueUnichar(int code, int unichar_id, float cert, float worst_dict_cert, |
359 | | float dict_ratio, bool use_dawgs, NodeContinuation cont, |
360 | | const RecodeNode *prev, RecodeBeam *step); |
361 | | // Adds a RecodeNode composed of the args to the correct heap in step if |
362 | | // unichar_id is a valid dictionary continuation of whatever is in prev. |
363 | | void ContinueDawg(int code, int unichar_id, float cert, NodeContinuation cont, |
364 | | const RecodeNode *prev, RecodeBeam *step); |
365 | | // Sets the correct best_initial_dawgs_ with a RecodeNode composed of the args |
366 | | // if better than what is already there. |
367 | | void PushInitialDawgIfBetter(int code, int unichar_id, PermuterType permuter, bool start, |
368 | | bool end, float cert, NodeContinuation cont, const RecodeNode *prev, |
369 | | RecodeBeam *step); |
370 | | // Adds a RecodeNode composed of the args to the correct heap in step for |
371 | | // partial unichar or duplicate if there is room or if better than the |
372 | | // current worst element if already full. |
373 | | void PushDupOrNoDawgIfBetter(int length, bool dup, int code, int unichar_id, float cert, |
374 | | float worst_dict_cert, float dict_ratio, bool use_dawgs, |
375 | | NodeContinuation cont, const RecodeNode *prev, RecodeBeam *step); |
376 | | // Adds a RecodeNode composed of the args to the correct heap in step if there |
377 | | // is room or if better than the current worst element if already full. |
378 | | void PushHeapIfBetter(int max_size, int code, int unichar_id, PermuterType permuter, |
379 | | bool dawg_start, bool word_start, bool end, bool dup, float cert, |
380 | | const RecodeNode *prev, DawgPositionVector *d, RecodeHeap *heap); |
381 | | // Adds a RecodeNode to heap if there is room |
382 | | // or if better than the current worst element if already full. |
383 | | void PushHeapIfBetter(int max_size, RecodeNode *node, RecodeHeap *heap); |
384 | | // Searches the heap for an entry matching new_node, and updates the entry |
385 | | // with reshuffle if needed. Returns true if there was a match. |
386 | | bool UpdateHeapIfMatched(RecodeNode *new_node, RecodeHeap *heap); |
387 | | // Computes and returns the code-hash for the given code and prev. |
388 | | uint64_t ComputeCodeHash(int code, bool dup, const RecodeNode *prev) const; |
389 | | // Backtracks to extract the best path through the lattice that was built |
390 | | // during Decode. On return the best_nodes vector essentially contains the set |
391 | | // of code, score pairs that make the optimal path with the constraint that |
392 | | // the recoder can decode the code sequence back to a sequence of unichar-ids. |
393 | | void ExtractBestPaths(std::vector<const RecodeNode *> *best_nodes, |
394 | | std::vector<const RecodeNode *> *second_nodes) const; |
395 | | // Helper backtracks through the lattice from the given node, storing the |
396 | | // path and reversing it. |
397 | | void ExtractPath(const RecodeNode *node, std::vector<const RecodeNode *> *path) const; |
398 | | void ExtractPath(const RecodeNode *node, std::vector<const RecodeNode *> *path, |
399 | | int limiter) const; |
400 | | // Helper prints debug information on the given lattice path. |
401 | | void DebugPath(const UNICHARSET *unicharset, const std::vector<const RecodeNode *> &path) const; |
402 | | // Helper prints debug information on the given unichar path. |
403 | | void DebugUnicharPath(const UNICHARSET *unicharset, const std::vector<const RecodeNode *> &path, |
404 | | const std::vector<int> &unichar_ids, const std::vector<float> &certs, |
405 | | const std::vector<float> &ratings, const std::vector<int> &xcoords) const; |
406 | | |
407 | | static const int kBeamWidths[RecodedCharID::kMaxCodeLen + 1]; |
408 | | |
409 | | // The encoder/decoder that we will be using. |
410 | | const UnicharCompress &recoder_; |
411 | | // The beam for each timestep in the output. |
412 | | std::vector<RecodeBeam *> beam_; |
413 | | // Secondary Beam for Results with less Probability |
414 | | std::vector<RecodeBeam *> secondary_beam_; |
415 | | // The number of timesteps valid in beam_; |
416 | | int beam_size_; |
417 | | // A flag to indicate which outputs are the top-n choices. Current timestep |
418 | | // only. |
419 | | std::vector<TopNState> top_n_flags_; |
420 | | // A record of the highest and second scoring codes. |
421 | | int top_code_; |
422 | | int second_code_; |
423 | | // Heap used to compute the top_n_flags_. |
424 | | GenericHeap<TopPair> top_heap_; |
425 | | // Borrowed pointer to the dictionary to use in the search. |
426 | | Dict *dict_; |
427 | | // True if the language is space-delimited, which is true for most languages |
428 | | // except chi*, jpn, tha. |
429 | | bool space_delimited_; |
430 | | // True if the input is simple text, ie adjacent equal chars are not to be |
431 | | // eliminated. |
432 | | bool is_simple_text_; |
433 | | // The encoded (class label) of the null/reject character. |
434 | | int null_char_; |
435 | | }; |
436 | | |
437 | | } // namespace tesseract. |
438 | | |
439 | | #endif // THIRD_PARTY_TESSERACT_LSTM_RECODEBEAM_H_ |