tesseract  4.0.0-1-g2a2b
intmatcher.cpp
Go to the documentation of this file.
1 /******************************************************************************
2  ** Filename: intmatcher.cpp
3  ** Purpose: Generic high level classification routines.
4  ** Author: Robert Moss
5  ** (c) Copyright Hewlett-Packard Company, 1988.
6  ** Licensed under the Apache License, Version 2.0 (the "License");
7  ** you may not use this file except in compliance with the License.
8  ** You may obtain a copy of the License at
9  ** http://www.apache.org/licenses/LICENSE-2.0
10  ** Unless required by applicable law or agreed to in writing, software
11  ** distributed under the License is distributed on an "AS IS" BASIS,
12  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  ** See the License for the specific language governing permissions and
14  ** limitations under the License.
15  ******************************************************************************/
16 
17 // Include automatically generated configuration file if running autoconf.
18 #ifdef HAVE_CONFIG_H
19 #include "config_auto.h"
20 #endif
21 
22 /*----------------------------------------------------------------------------
23  Include Files and Type Defines
24 ----------------------------------------------------------------------------*/
25 #include "intmatcher.h"
26 
27 #include "fontinfo.h"
28 #include "intproto.h"
29 #include "callcpp.h"
30 #include "scrollview.h"
31 #include "float2int.h"
32 #include "globals.h"
33 #include "helpers.h"
34 #include "classify.h"
35 #include "shapetable.h"
36 #include <cmath>
37 
40 
41 /*----------------------------------------------------------------------------
42  Global Data Definitions and Declarations
43 ----------------------------------------------------------------------------*/
44 // Parameters of the sigmoid used to convert similarity to evidence in the
45 // similarity_evidence_table_ that is used to convert distance metric to an
46 // 8 bit evidence value in the secondary matcher. (See IntMatcher::Init).
48 const float IntegerMatcher::kSimilarityCenter = 0.0075;
49 
50 #define offset_table_entries \
51  255, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, \
52  0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, \
53  0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, \
54  0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, \
55  0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, \
56  0, 1, 0, 2, 0, 1, 0, 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, \
57  0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, \
58  0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, \
59  0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, \
60  0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, \
61  0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
62 
63 #define INTMATCHER_OFFSET_TABLE_SIZE 256
64 
65 #define next_table_entries \
66  0, 0, 0, 0x2, 0, 0x4, 0x4, 0x6, 0, 0x8, 0x8, 0x0a, 0x08, 0x0c, 0x0c, 0x0e, \
67  0, 0x10, 0x10, 0x12, 0x10, 0x14, 0x14, 0x16, 0x10, 0x18, 0x18, 0x1a, \
68  0x18, 0x1c, 0x1c, 0x1e, 0, 0x20, 0x20, 0x22, 0x20, 0x24, 0x24, 0x26, \
69  0x20, 0x28, 0x28, 0x2a, 0x28, 0x2c, 0x2c, 0x2e, 0x20, 0x30, 0x30, 0x32, \
70  0x30, 0x34, 0x34, 0x36, 0x30, 0x38, 0x38, 0x3a, 0x38, 0x3c, 0x3c, 0x3e, \
71  0, 0x40, 0x40, 0x42, 0x40, 0x44, 0x44, 0x46, 0x40, 0x48, 0x48, 0x4a, \
72  0x48, 0x4c, 0x4c, 0x4e, 0x40, 0x50, 0x50, 0x52, 0x50, 0x54, 0x54, 0x56, \
73  0x50, 0x58, 0x58, 0x5a, 0x58, 0x5c, 0x5c, 0x5e, 0x40, 0x60, 0x60, 0x62, \
74  0x60, 0x64, 0x64, 0x66, 0x60, 0x68, 0x68, 0x6a, 0x68, 0x6c, 0x6c, 0x6e, \
75  0x60, 0x70, 0x70, 0x72, 0x70, 0x74, 0x74, 0x76, 0x70, 0x78, 0x78, 0x7a, \
76  0x78, 0x7c, 0x7c, 0x7e, 0, 0x80, 0x80, 0x82, 0x80, 0x84, 0x84, 0x86, \
77  0x80, 0x88, 0x88, 0x8a, 0x88, 0x8c, 0x8c, 0x8e, 0x80, 0x90, 0x90, 0x92, \
78  0x90, 0x94, 0x94, 0x96, 0x90, 0x98, 0x98, 0x9a, 0x98, 0x9c, 0x9c, 0x9e, \
79  0x80, 0xa0, 0xa0, 0xa2, 0xa0, 0xa4, 0xa4, 0xa6, 0xa0, 0xa8, 0xa8, 0xaa, \
80  0xa8, 0xac, 0xac, 0xae, 0xa0, 0xb0, 0xb0, 0xb2, 0xb0, 0xb4, 0xb4, 0xb6, \
81  0xb0, 0xb8, 0xb8, 0xba, 0xb8, 0xbc, 0xbc, 0xbe, 0x80, 0xc0, 0xc0, 0xc2, \
82  0xc0, 0xc4, 0xc4, 0xc6, 0xc0, 0xc8, 0xc8, 0xca, 0xc8, 0xcc, 0xcc, 0xce, \
83  0xc0, 0xd0, 0xd0, 0xd2, 0xd0, 0xd4, 0xd4, 0xd6, 0xd0, 0xd8, 0xd8, 0xda, \
84  0xd8, 0xdc, 0xdc, 0xde, 0xc0, 0xe0, 0xe0, 0xe2, 0xe0, 0xe4, 0xe4, 0xe6, \
85  0xe0, 0xe8, 0xe8, 0xea, 0xe8, 0xec, 0xec, 0xee, 0xe0, 0xf0, 0xf0, 0xf2, \
86  0xf0, 0xf4, 0xf4, 0xf6, 0xf0, 0xf8, 0xf8, 0xfa, 0xf8, 0xfc, 0xfc, 0xfe
87 
88 // See http://b/19318793 (#6) for a complete discussion. Merging arrays
89 // offset_table and next_table helps improve performance of PIE code.
90 static const uint8_t data_table[512] = {offset_table_entries, next_table_entries};
91 
92 static const uint8_t* const offset_table = &data_table[0];
93 static const uint8_t* const next_table =
94  &data_table[INTMATCHER_OFFSET_TABLE_SIZE];
95 
96 namespace tesseract {
97 
98 // Encapsulation of the intermediate data and computations made by the class
99 // pruner. The class pruner implements a simple linear classifier on binary
100 // features by heavily quantizing the feature space, and applying
101 // NUM_BITS_PER_CLASS (2)-bit weights to the features. Lack of resolution in
102 // weights is compensated by a non-constant bias that is dependent on the
103 // number of features present.
104 class ClassPruner {
105  public:
106  ClassPruner(int max_classes) {
107  // The unrolled loop in ComputeScores means that the array sizes need to
108  // be rounded up so that the array is big enough to accommodate the extra
109  // entries accessed by the unrolling. Each pruner word is of sized
110  // BITS_PER_WERD and each entry is NUM_BITS_PER_CLASS, so there are
111  // BITS_PER_WERD / NUM_BITS_PER_CLASS entries.
112  // See ComputeScores.
113  max_classes_ = max_classes;
114  rounded_classes_ = RoundUp(
116  class_count_ = new int[rounded_classes_];
117  norm_count_ = new int[rounded_classes_];
118  sort_key_ = new int[rounded_classes_ + 1];
119  sort_index_ = new int[rounded_classes_ + 1];
120  for (int i = 0; i < rounded_classes_; i++) {
121  class_count_[i] = 0;
122  }
123  pruning_threshold_ = 0;
124  num_features_ = 0;
125  num_classes_ = 0;
126  }
127 
129  delete []class_count_;
130  delete []norm_count_;
131  delete []sort_key_;
132  delete []sort_index_;
133  }
134 
137  void ComputeScores(const INT_TEMPLATES_STRUCT* int_templates,
138  int num_features, const INT_FEATURE_STRUCT* features) {
139  num_features_ = num_features;
140  int num_pruners = int_templates->NumClassPruners;
141  for (int f = 0; f < num_features; ++f) {
142  const INT_FEATURE_STRUCT* feature = &features[f];
143  // Quantize the feature to NUM_CP_BUCKETS*NUM_CP_BUCKETS*NUM_CP_BUCKETS.
144  int x = feature->X * NUM_CP_BUCKETS >> 8;
145  int y = feature->Y * NUM_CP_BUCKETS >> 8;
146  int theta = feature->Theta * NUM_CP_BUCKETS >> 8;
147  int class_id = 0;
148  // Each CLASS_PRUNER_STRUCT only covers CLASSES_PER_CP(32) classes, so
149  // we need a collection of them, indexed by pruner_set.
150  for (int pruner_set = 0; pruner_set < num_pruners; ++pruner_set) {
151  // Look up quantized feature in a 3-D array, an array of weights for
152  // each class.
153  const uint32_t* pruner_word_ptr =
154  int_templates->ClassPruners[pruner_set]->p[x][y][theta];
155  for (int word = 0; word < WERDS_PER_CP_VECTOR; ++word) {
156  uint32_t pruner_word = *pruner_word_ptr++;
157  // This inner loop is unrolled to speed up the ClassPruner.
158  // Currently gcc would not unroll it unless it is set to O3
159  // level of optimization or -funroll-loops is specified.
160  /*
161  uint32_t class_mask = (1 << NUM_BITS_PER_CLASS) - 1;
162  for (int bit = 0; bit < BITS_PER_WERD/NUM_BITS_PER_CLASS; bit++) {
163  class_count_[class_id++] += pruner_word & class_mask;
164  pruner_word >>= NUM_BITS_PER_CLASS;
165  }
166  */
167  class_count_[class_id++] += pruner_word & CLASS_PRUNER_CLASS_MASK;
168  pruner_word >>= NUM_BITS_PER_CLASS;
169  class_count_[class_id++] += pruner_word & CLASS_PRUNER_CLASS_MASK;
170  pruner_word >>= NUM_BITS_PER_CLASS;
171  class_count_[class_id++] += pruner_word & CLASS_PRUNER_CLASS_MASK;
172  pruner_word >>= NUM_BITS_PER_CLASS;
173  class_count_[class_id++] += pruner_word & CLASS_PRUNER_CLASS_MASK;
174  pruner_word >>= NUM_BITS_PER_CLASS;
175  class_count_[class_id++] += pruner_word & CLASS_PRUNER_CLASS_MASK;
176  pruner_word >>= NUM_BITS_PER_CLASS;
177  class_count_[class_id++] += pruner_word & CLASS_PRUNER_CLASS_MASK;
178  pruner_word >>= NUM_BITS_PER_CLASS;
179  class_count_[class_id++] += pruner_word & CLASS_PRUNER_CLASS_MASK;
180  pruner_word >>= NUM_BITS_PER_CLASS;
181  class_count_[class_id++] += pruner_word & CLASS_PRUNER_CLASS_MASK;
182  pruner_word >>= NUM_BITS_PER_CLASS;
183  class_count_[class_id++] += pruner_word & CLASS_PRUNER_CLASS_MASK;
184  pruner_word >>= NUM_BITS_PER_CLASS;
185  class_count_[class_id++] += pruner_word & CLASS_PRUNER_CLASS_MASK;
186  pruner_word >>= NUM_BITS_PER_CLASS;
187  class_count_[class_id++] += pruner_word & CLASS_PRUNER_CLASS_MASK;
188  pruner_word >>= NUM_BITS_PER_CLASS;
189  class_count_[class_id++] += pruner_word & CLASS_PRUNER_CLASS_MASK;
190  pruner_word >>= NUM_BITS_PER_CLASS;
191  class_count_[class_id++] += pruner_word & CLASS_PRUNER_CLASS_MASK;
192  pruner_word >>= NUM_BITS_PER_CLASS;
193  class_count_[class_id++] += pruner_word & CLASS_PRUNER_CLASS_MASK;
194  pruner_word >>= NUM_BITS_PER_CLASS;
195  class_count_[class_id++] += pruner_word & CLASS_PRUNER_CLASS_MASK;
196  pruner_word >>= NUM_BITS_PER_CLASS;
197  class_count_[class_id++] += pruner_word & CLASS_PRUNER_CLASS_MASK;
198  }
199  }
200  }
201  }
202 
208  void AdjustForExpectedNumFeatures(const uint16_t* expected_num_features,
209  int cutoff_strength) {
210  for (int class_id = 0; class_id < max_classes_; ++class_id) {
211  if (num_features_ < expected_num_features[class_id]) {
212  int deficit = expected_num_features[class_id] - num_features_;
213  class_count_[class_id] -= class_count_[class_id] * deficit /
214  (num_features_ * cutoff_strength + deficit);
215  }
216  }
217  }
218 
221  void DisableDisabledClasses(const UNICHARSET& unicharset) {
222  for (int class_id = 0; class_id < max_classes_; ++class_id) {
223  if (!unicharset.get_enabled(class_id))
224  class_count_[class_id] = 0; // This char is disabled!
225  }
226  }
227 
229  void DisableFragments(const UNICHARSET& unicharset) {
230  for (int class_id = 0; class_id < max_classes_; ++class_id) {
231  // Do not include character fragments in the class pruner
232  // results if disable_character_fragments is true.
233  if (unicharset.get_fragment(class_id)) {
234  class_count_[class_id] = 0;
235  }
236  }
237  }
238 
243  void NormalizeForXheight(int norm_multiplier,
244  const uint8_t* normalization_factors) {
245  for (int class_id = 0; class_id < max_classes_; class_id++) {
246  norm_count_[class_id] = class_count_[class_id] -
247  ((norm_multiplier * normalization_factors[class_id]) >> 8);
248  }
249  }
250 
253  for (int class_id = 0; class_id < max_classes_; class_id++) {
254  norm_count_[class_id] = class_count_[class_id];
255  }
256  }
257 
261  void PruneAndSort(int pruning_factor, int keep_this,
262  bool max_of_non_fragments, const UNICHARSET& unicharset) {
263  int max_count = 0;
264  for (int c = 0; c < max_classes_; ++c) {
265  if (norm_count_[c] > max_count &&
266  // This additional check is added in order to ensure that
267  // the classifier will return at least one non-fragmented
268  // character match.
269  // TODO(daria): verify that this helps accuracy and does not
270  // hurt performance.
271  (!max_of_non_fragments || !unicharset.get_fragment(c))) {
272  max_count = norm_count_[c];
273  }
274  }
275  // Prune Classes.
276  pruning_threshold_ = (max_count * pruning_factor) >> 8;
277  // Select Classes.
278  if (pruning_threshold_ < 1)
279  pruning_threshold_ = 1;
280  num_classes_ = 0;
281  for (int class_id = 0; class_id < max_classes_; class_id++) {
282  if (norm_count_[class_id] >= pruning_threshold_ ||
283  class_id == keep_this) {
284  ++num_classes_;
285  sort_index_[num_classes_] = class_id;
286  sort_key_[num_classes_] = norm_count_[class_id];
287  }
288  }
289 
290  // Sort Classes using Heapsort Algorithm.
291  if (num_classes_ > 1)
292  HeapSort(num_classes_, sort_key_, sort_index_);
293  }
294 
297  void DebugMatch(const Classify& classify,
298  const INT_TEMPLATES_STRUCT* int_templates,
299  const INT_FEATURE_STRUCT* features) const {
300  int num_pruners = int_templates->NumClassPruners;
301  int max_num_classes = int_templates->NumClasses;
302  for (int f = 0; f < num_features_; ++f) {
303  const INT_FEATURE_STRUCT* feature = &features[f];
304  tprintf("F=%3d(%d,%d,%d),", f, feature->X, feature->Y, feature->Theta);
305  // Quantize the feature to NUM_CP_BUCKETS*NUM_CP_BUCKETS*NUM_CP_BUCKETS.
306  int x = feature->X * NUM_CP_BUCKETS >> 8;
307  int y = feature->Y * NUM_CP_BUCKETS >> 8;
308  int theta = feature->Theta * NUM_CP_BUCKETS >> 8;
309  int class_id = 0;
310  for (int pruner_set = 0; pruner_set < num_pruners; ++pruner_set) {
311  // Look up quantized feature in a 3-D array, an array of weights for
312  // each class.
313  const uint32_t* pruner_word_ptr =
314  int_templates->ClassPruners[pruner_set]->p[x][y][theta];
315  for (int word = 0; word < WERDS_PER_CP_VECTOR; ++word) {
316  uint32_t pruner_word = *pruner_word_ptr++;
317  for (int word_class = 0; word_class < 16 &&
318  class_id < max_num_classes; ++word_class, ++class_id) {
319  if (norm_count_[class_id] >= pruning_threshold_) {
320  tprintf(" %s=%d,",
321  classify.ClassIDToDebugStr(int_templates,
322  class_id, 0).string(),
323  pruner_word & CLASS_PRUNER_CLASS_MASK);
324  }
325  pruner_word >>= NUM_BITS_PER_CLASS;
326  }
327  }
328  tprintf("\n");
329  }
330  }
331  }
332 
334  void SummarizeResult(const Classify& classify,
335  const INT_TEMPLATES_STRUCT* int_templates,
336  const uint16_t* expected_num_features,
337  int norm_multiplier,
338  const uint8_t* normalization_factors) const {
339  tprintf("CP:%d classes, %d features:\n", num_classes_, num_features_);
340  for (int i = 0; i < num_classes_; ++i) {
341  int class_id = sort_index_[num_classes_ - i];
342  STRING class_string = classify.ClassIDToDebugStr(int_templates,
343  class_id, 0);
344  tprintf("%s:Initial=%d, E=%d, Xht-adj=%d, N=%d, Rat=%.2f\n",
345  class_string.string(),
346  class_count_[class_id],
347  expected_num_features[class_id],
348  (norm_multiplier * normalization_factors[class_id]) >> 8,
349  sort_key_[num_classes_ - i],
350  100.0 - 100.0 * sort_key_[num_classes_ - i] /
351  (CLASS_PRUNER_CLASS_MASK * num_features_));
352  }
353  }
354 
358  CP_RESULT_STRUCT empty;
359  results->init_to_size(num_classes_, empty);
360  for (int c = 0; c < num_classes_; ++c) {
361  (*results)[c].Class = sort_index_[num_classes_ - c];
362  (*results)[c].Rating = 1.0 - sort_key_[num_classes_ - c] /
363  (static_cast<float>(CLASS_PRUNER_CLASS_MASK) * num_features_);
364  }
365  return num_classes_;
366  }
367 
368  private:
370  int *class_count_;
374  int *norm_count_;
376  int *sort_key_;
378  int *sort_index_;
380  int max_classes_;
382  int rounded_classes_;
384  int pruning_threshold_;
386  int num_features_;
388  int num_classes_;
389 };
390 
391 /*----------------------------------------------------------------------------
392  Public Code
393 ----------------------------------------------------------------------------*/
410  int num_features, int keep_this,
411  const INT_FEATURE_STRUCT* features,
412  const uint8_t* normalization_factors,
413  const uint16_t* expected_num_features,
415  ClassPruner pruner(int_templates->NumClasses);
416  // Compute initial match scores for all classes.
417  pruner.ComputeScores(int_templates, num_features, features);
418  // Adjust match scores for number of expected features.
419  pruner.AdjustForExpectedNumFeatures(expected_num_features,
421  // Apply disabled classes in unicharset - only works without a shape_table.
422  if (shape_table_ == nullptr)
424  // If fragments are disabled, remove them, also only without a shape table.
425  if (disable_character_fragments && shape_table_ == nullptr)
427 
428  // If we have good x-heights, apply the given normalization factors.
429  if (normalization_factors != nullptr) {
431  normalization_factors);
432  } else {
433  pruner.NoNormalization();
434  }
435  // Do the actual pruning and sort the short-list.
437  shape_table_ == nullptr, unicharset);
438 
439  if (classify_debug_level > 2) {
440  pruner.DebugMatch(*this, int_templates, features);
441  }
442  if (classify_debug_level > 1) {
443  pruner.SummarizeResult(*this, int_templates, expected_num_features,
445  normalization_factors);
446  }
447  // Convert to the expected output format.
448  return pruner.SetupResults(results);
449 }
450 
451 } // namespace tesseract
452 
470 void IntegerMatcher::Match(INT_CLASS ClassTemplate,
471  BIT_VECTOR ProtoMask,
472  BIT_VECTOR ConfigMask,
473  int16_t NumFeatures,
474  const INT_FEATURE_STRUCT* Features,
475  UnicharRating* Result,
476  int AdaptFeatureThreshold,
477  int Debug,
478  bool SeparateDebugWindows) {
479  ScratchEvidence *tables = new ScratchEvidence();
480  int Feature;
481 
482  if (MatchDebuggingOn (Debug))
483  cprintf ("Integer Matcher -------------------------------------------\n");
484 
485  tables->Clear(ClassTemplate);
486  Result->feature_misses = 0;
487 
488  for (Feature = 0; Feature < NumFeatures; Feature++) {
489  int csum = UpdateTablesForFeature(ClassTemplate, ProtoMask, ConfigMask,
490  Feature, &Features[Feature],
491  tables, Debug);
492  // Count features that were missed over all configs.
493  if (csum == 0)
494  ++Result->feature_misses;
495  }
496 
497 #ifndef GRAPHICS_DISABLED
498  if (PrintProtoMatchesOn(Debug) || PrintMatchSummaryOn(Debug)) {
499  DebugFeatureProtoError(ClassTemplate, ProtoMask, ConfigMask, *tables,
500  NumFeatures, Debug);
501  }
502 
503  if (DisplayProtoMatchesOn(Debug)) {
504  DisplayProtoDebugInfo(ClassTemplate, ProtoMask, ConfigMask,
505  *tables, SeparateDebugWindows);
506  }
507 
508  if (DisplayFeatureMatchesOn(Debug)) {
509  DisplayFeatureDebugInfo(ClassTemplate, ProtoMask, ConfigMask, NumFeatures,
510  Features, AdaptFeatureThreshold, Debug,
511  SeparateDebugWindows);
512  }
513 #endif
514 
515  tables->UpdateSumOfProtoEvidences(ClassTemplate, ConfigMask, NumFeatures);
516  tables->NormalizeSums(ClassTemplate, NumFeatures, NumFeatures);
517 
518  FindBestMatch(ClassTemplate, *tables, Result);
519 
520 #ifndef GRAPHICS_DISABLED
521  if (PrintMatchSummaryOn(Debug))
522  Result->Print();
523 
524  if (MatchDebuggingOn(Debug))
525  cprintf("Match Complete --------------------------------------------\n");
526 #endif
527 
528  delete tables;
529 }
530 
550  INT_CLASS ClassTemplate,
551  BIT_VECTOR ProtoMask,
552  BIT_VECTOR ConfigMask,
553  uint16_t BlobLength,
554  int16_t NumFeatures,
555  INT_FEATURE_ARRAY Features,
556  PROTO_ID *ProtoArray,
557  int AdaptProtoThreshold,
558  int Debug) {
559  ScratchEvidence *tables = new ScratchEvidence();
560  int NumGoodProtos = 0;
561 
562  /* DEBUG opening heading */
563  if (MatchDebuggingOn (Debug))
564  cprintf
565  ("Find Good Protos -------------------------------------------\n");
566 
567  tables->Clear(ClassTemplate);
568 
569  for (int Feature = 0; Feature < NumFeatures; Feature++)
570  UpdateTablesForFeature(
571  ClassTemplate, ProtoMask, ConfigMask, Feature, &(Features[Feature]),
572  tables, Debug);
573 
574 #ifndef GRAPHICS_DISABLED
575  if (PrintProtoMatchesOn (Debug) || PrintMatchSummaryOn (Debug))
576  DebugFeatureProtoError(ClassTemplate, ProtoMask, ConfigMask, *tables,
577  NumFeatures, Debug);
578 #endif
579 
580  /* Average Proto Evidences & Find Good Protos */
581  for (int proto = 0; proto < ClassTemplate->NumProtos; proto++) {
582  /* Compute Average for Actual Proto */
583  int Temp = 0;
584  for (int i = 0; i < ClassTemplate->ProtoLengths[proto]; i++)
585  Temp += tables->proto_evidence_[proto][i];
586 
587  Temp /= ClassTemplate->ProtoLengths[proto];
588 
589  /* Find Good Protos */
590  if (Temp >= AdaptProtoThreshold) {
591  *ProtoArray = proto;
592  ProtoArray++;
593  NumGoodProtos++;
594  }
595  }
596 
597  if (MatchDebuggingOn (Debug))
598  cprintf ("Match Complete --------------------------------------------\n");
599  delete tables;
600 
601  return NumGoodProtos;
602 }
603 
619  INT_CLASS ClassTemplate,
620  BIT_VECTOR ProtoMask,
621  BIT_VECTOR ConfigMask,
622  uint16_t BlobLength,
623  int16_t NumFeatures,
624  INT_FEATURE_ARRAY Features,
625  FEATURE_ID *FeatureArray,
626  int AdaptFeatureThreshold,
627  int Debug) {
628  ScratchEvidence *tables = new ScratchEvidence();
629  int NumBadFeatures = 0;
630 
631  /* DEBUG opening heading */
632  if (MatchDebuggingOn(Debug))
633  cprintf("Find Bad Features -------------------------------------------\n");
634 
635  tables->Clear(ClassTemplate);
636 
637  for (int Feature = 0; Feature < NumFeatures; Feature++) {
638  UpdateTablesForFeature(
639  ClassTemplate, ProtoMask, ConfigMask, Feature, &Features[Feature],
640  tables, Debug);
641 
642  /* Find Best Evidence for Current Feature */
643  int best = 0;
644  for (int i = 0; i < ClassTemplate->NumConfigs; i++)
645  if (tables->feature_evidence_[i] > best)
646  best = tables->feature_evidence_[i];
647 
648  /* Find Bad Features */
649  if (best < AdaptFeatureThreshold) {
650  *FeatureArray = Feature;
651  FeatureArray++;
652  NumBadFeatures++;
653  }
654  }
655 
656 #ifndef GRAPHICS_DISABLED
657  if (PrintProtoMatchesOn(Debug) || PrintMatchSummaryOn(Debug))
658  DebugFeatureProtoError(ClassTemplate, ProtoMask, ConfigMask, *tables,
659  NumFeatures, Debug);
660 #endif
661 
662  if (MatchDebuggingOn(Debug))
663  cprintf("Match Complete --------------------------------------------\n");
664 
665  delete tables;
666  return NumBadFeatures;
667 }
668 
669 
671  : classify_debug_level_(classify_debug_level)
672 {
673  /* Initialize table for evidence to similarity lookup */
674  for (int i = 0; i < SE_TABLE_SIZE; i++) {
675  uint32_t IntSimilarity = i << (27 - SE_TABLE_BITS);
676  double Similarity = ((double) IntSimilarity) / 65536.0 / 65536.0;
677  double evidence = Similarity / kSimilarityCenter;
678  evidence = 255.0 / (evidence * evidence + 1.0);
679 
680  if (kSEExponentialMultiplier > 0.0) {
681  double scale = 1.0 - exp(-kSEExponentialMultiplier) *
682  exp(kSEExponentialMultiplier * ((double) i / SE_TABLE_SIZE));
683  evidence *= ClipToRange(scale, 0.0, 1.0);
684  }
685 
686  similarity_evidence_table_[i] = (uint8_t) (evidence + 0.5);
687  }
688 
689  /* Initialize evidence computation variables */
690  evidence_table_mask_ =
691  ((1 << kEvidenceTableBits) - 1) << (9 - kEvidenceTableBits);
692  mult_trunc_shift_bits_ = (14 - kIntEvidenceTruncBits);
693  table_trunc_shift_bits_ = (27 - SE_TABLE_BITS - (mult_trunc_shift_bits_ << 1));
694  evidence_mult_mask_ = ((1 << kIntEvidenceTruncBits) - 1);
695 }
696 
697 /*----------------------------------------------------------------------------
698  Private Code
699 ----------------------------------------------------------------------------*/
700 void ScratchEvidence::Clear(const INT_CLASS class_template) {
701  memset(sum_feature_evidence_, 0,
702  class_template->NumConfigs * sizeof(sum_feature_evidence_[0]));
703  memset(proto_evidence_, 0,
704  class_template->NumProtos * sizeof(proto_evidence_[0]));
705 }
706 
708  memset(feature_evidence_, 0,
709  class_template->NumConfigs * sizeof(feature_evidence_[0]));
710 }
711 
716 static void IMDebugConfiguration(int FeatureNum, uint16_t ActualProtoNum,
717  uint8_t Evidence, BIT_VECTOR ConfigMask,
718  uint32_t ConfigWord) {
719  cprintf ("F = %3d, P = %3d, E = %3d, Configs = ",
720  FeatureNum, (int) ActualProtoNum, (int) Evidence);
721  while (ConfigWord) {
722  if (ConfigWord & 1)
723  cprintf ("1");
724  else
725  cprintf ("0");
726  ConfigWord >>= 1;
727  }
728  cprintf ("\n");
729 }
730 
735 static void IMDebugConfigurationSum(int FeatureNum, uint8_t *FeatureEvidence,
736  int32_t ConfigCount) {
737  cprintf("F=%3d, C=", FeatureNum);
738  for (int ConfigNum = 0; ConfigNum < ConfigCount; ConfigNum++) {
739  cprintf("%4d", FeatureEvidence[ConfigNum]);
740  }
741  cprintf("\n");
742 }
743 
755 int IntegerMatcher::UpdateTablesForFeature(
756  INT_CLASS ClassTemplate,
757  BIT_VECTOR ProtoMask,
758  BIT_VECTOR ConfigMask,
759  int FeatureNum,
760  const INT_FEATURE_STRUCT* Feature,
761  ScratchEvidence *tables,
762  int Debug) {
763  uint32_t ConfigWord;
764  uint32_t ProtoWord;
765  uint32_t ProtoNum;
766  uint32_t ActualProtoNum;
767  uint8_t proto_byte;
768  int32_t proto_word_offset;
769  int32_t proto_offset;
770  uint8_t config_byte;
771  int32_t config_offset;
772  PROTO_SET ProtoSet;
773  uint32_t *ProtoPrunerPtr;
774  INT_PROTO Proto;
775  int ProtoSetIndex;
776  uint8_t Evidence;
777  uint32_t XFeatureAddress;
778  uint32_t YFeatureAddress;
779  uint32_t ThetaFeatureAddress;
780  uint8_t* UINT8Pointer;
781  int ProtoIndex;
782  uint8_t Temp;
783  int* IntPointer;
784  int ConfigNum;
785  int32_t M3;
786  int32_t A3;
787  uint32_t A4;
788 
789  tables->ClearFeatureEvidence(ClassTemplate);
790 
791  /* Precompute Feature Address offset for Proto Pruning */
792  XFeatureAddress = ((Feature->X >> 2) << 1);
793  YFeatureAddress = (NUM_PP_BUCKETS << 1) + ((Feature->Y >> 2) << 1);
794  ThetaFeatureAddress = (NUM_PP_BUCKETS << 2) + ((Feature->Theta >> 2) << 1);
795 
796  for (ProtoSetIndex = 0, ActualProtoNum = 0;
797  ProtoSetIndex < ClassTemplate->NumProtoSets; ProtoSetIndex++) {
798  ProtoSet = ClassTemplate->ProtoSets[ProtoSetIndex];
799  ProtoPrunerPtr = (uint32_t *) ((*ProtoSet).ProtoPruner);
800  for (ProtoNum = 0; ProtoNum < PROTOS_PER_PROTO_SET;
801  ProtoNum += (PROTOS_PER_PROTO_SET >> 1), ActualProtoNum +=
802  (PROTOS_PER_PROTO_SET >> 1), ProtoMask++, ProtoPrunerPtr++) {
803  /* Prune Protos of current Proto Set */
804  ProtoWord = *(ProtoPrunerPtr + XFeatureAddress);
805  ProtoWord &= *(ProtoPrunerPtr + YFeatureAddress);
806  ProtoWord &= *(ProtoPrunerPtr + ThetaFeatureAddress);
807  ProtoWord &= *ProtoMask;
808 
809  if (ProtoWord != 0) {
810  proto_byte = ProtoWord & 0xff;
811  ProtoWord >>= 8;
812  proto_word_offset = 0;
813  while (ProtoWord != 0 || proto_byte != 0) {
814  while (proto_byte == 0) {
815  proto_byte = ProtoWord & 0xff;
816  ProtoWord >>= 8;
817  proto_word_offset += 8;
818  }
819  proto_offset = offset_table[proto_byte] + proto_word_offset;
820  proto_byte = next_table[proto_byte];
821  Proto = &(ProtoSet->Protos[ProtoNum + proto_offset]);
822  ConfigWord = Proto->Configs[0];
823  A3 = (((Proto->A * (Feature->X - 128)) << 1)
824  - (Proto->B * (Feature->Y - 128)) + (Proto->C << 9));
825  M3 =
826  (((int8_t) (Feature->Theta - Proto->Angle)) * kIntThetaFudge) << 1;
827 
828  if (A3 < 0)
829  A3 = ~A3;
830  if (M3 < 0)
831  M3 = ~M3;
832  A3 >>= mult_trunc_shift_bits_;
833  M3 >>= mult_trunc_shift_bits_;
834  if (static_cast<uint32_t>(A3) > evidence_mult_mask_)
835  A3 = evidence_mult_mask_;
836  if (static_cast<uint32_t>(M3) > evidence_mult_mask_)
837  M3 = evidence_mult_mask_;
838 
839  A4 = (A3 * A3) + (M3 * M3);
840  A4 >>= table_trunc_shift_bits_;
841  if (A4 > evidence_table_mask_)
842  Evidence = 0;
843  else
844  Evidence = similarity_evidence_table_[A4];
845 
846  if (PrintFeatureMatchesOn (Debug))
847  IMDebugConfiguration (FeatureNum,
848  ActualProtoNum + proto_offset,
849  Evidence, ConfigMask, ConfigWord);
850 
851  ConfigWord &= *ConfigMask;
852 
853  UINT8Pointer = tables->feature_evidence_ - 8;
854  config_byte = 0;
855  while (ConfigWord != 0 || config_byte != 0) {
856  while (config_byte == 0) {
857  config_byte = ConfigWord & 0xff;
858  ConfigWord >>= 8;
859  UINT8Pointer += 8;
860  }
861  config_offset = offset_table[config_byte];
862  config_byte = next_table[config_byte];
863  if (Evidence > UINT8Pointer[config_offset])
864  UINT8Pointer[config_offset] = Evidence;
865  }
866 
867  UINT8Pointer =
868  &(tables->proto_evidence_[ActualProtoNum + proto_offset][0]);
869  for (ProtoIndex =
870  ClassTemplate->ProtoLengths[ActualProtoNum + proto_offset];
871  ProtoIndex > 0; ProtoIndex--, UINT8Pointer++) {
872  if (Evidence > *UINT8Pointer) {
873  Temp = *UINT8Pointer;
874  *UINT8Pointer = Evidence;
875  Evidence = Temp;
876  }
877  else if (Evidence == 0)
878  break;
879  }
880  }
881  }
882  }
883  }
884 
885  if (PrintFeatureMatchesOn(Debug)) {
886  IMDebugConfigurationSum(FeatureNum, tables->feature_evidence_,
887  ClassTemplate->NumConfigs);
888  }
889 
890  IntPointer = tables->sum_feature_evidence_;
891  UINT8Pointer = tables->feature_evidence_;
892  int SumOverConfigs = 0;
893  for (ConfigNum = ClassTemplate->NumConfigs; ConfigNum > 0; ConfigNum--) {
894  int evidence = *UINT8Pointer++;
895  SumOverConfigs += evidence;
896  *IntPointer++ += evidence;
897  }
898  return SumOverConfigs;
899 }
900 
905 #ifndef GRAPHICS_DISABLED
906 void IntegerMatcher::DebugFeatureProtoError(
907  INT_CLASS ClassTemplate,
908  BIT_VECTOR ProtoMask,
909  BIT_VECTOR ConfigMask,
910  const ScratchEvidence& tables,
911  int16_t NumFeatures,
912  int Debug) {
913  float ProtoConfigs[MAX_NUM_CONFIGS];
914  int ConfigNum;
915  uint32_t ConfigWord;
916  int ProtoSetIndex;
917  uint16_t ProtoNum;
918  uint8_t ProtoWordNum;
919  PROTO_SET ProtoSet;
920  uint16_t ActualProtoNum;
921 
922  if (PrintMatchSummaryOn(Debug)) {
923  cprintf("Configuration Mask:\n");
924  for (ConfigNum = 0; ConfigNum < ClassTemplate->NumConfigs; ConfigNum++)
925  cprintf("%1d", (((*ConfigMask) >> ConfigNum) & 1));
926  cprintf("\n");
927 
928  cprintf("Feature Error for Configurations:\n");
929  for (ConfigNum = 0; ConfigNum < ClassTemplate->NumConfigs; ConfigNum++) {
930  cprintf(
931  " %5.1f",
932  100.0 * (1.0 - (float)tables.sum_feature_evidence_[ConfigNum]
933  / NumFeatures / 256.0));
934  }
935  cprintf("\n\n\n");
936  }
937 
938  if (PrintMatchSummaryOn (Debug)) {
939  cprintf ("Proto Mask:\n");
940  for (ProtoSetIndex = 0; ProtoSetIndex < ClassTemplate->NumProtoSets;
941  ProtoSetIndex++) {
942  ActualProtoNum = (ProtoSetIndex * PROTOS_PER_PROTO_SET);
943  for (ProtoWordNum = 0; ProtoWordNum < 2;
944  ProtoWordNum++, ProtoMask++) {
945  ActualProtoNum = (ProtoSetIndex * PROTOS_PER_PROTO_SET);
946  for (ProtoNum = 0;
947  ((ProtoNum < (PROTOS_PER_PROTO_SET >> 1))
948  && (ActualProtoNum < ClassTemplate->NumProtos));
949  ProtoNum++, ActualProtoNum++)
950  cprintf ("%1d", (((*ProtoMask) >> ProtoNum) & 1));
951  cprintf ("\n");
952  }
953  }
954  cprintf ("\n");
955  }
956 
957  for (int i = 0; i < ClassTemplate->NumConfigs; i++)
958  ProtoConfigs[i] = 0;
959 
960  if (PrintProtoMatchesOn (Debug)) {
961  cprintf ("Proto Evidence:\n");
962  for (ProtoSetIndex = 0; ProtoSetIndex < ClassTemplate->NumProtoSets;
963  ProtoSetIndex++) {
964  ProtoSet = ClassTemplate->ProtoSets[ProtoSetIndex];
965  ActualProtoNum = (ProtoSetIndex * PROTOS_PER_PROTO_SET);
966  for (ProtoNum = 0;
967  ((ProtoNum < PROTOS_PER_PROTO_SET) &&
968  (ActualProtoNum < ClassTemplate->NumProtos));
969  ProtoNum++, ActualProtoNum++) {
970  cprintf ("P %3d =", ActualProtoNum);
971  int temp = 0;
972  for (int j = 0; j < ClassTemplate->ProtoLengths[ActualProtoNum]; j++) {
973  uint8_t data = tables.proto_evidence_[ActualProtoNum][j];
974  cprintf(" %d", data);
975  temp += data;
976  }
977 
978  cprintf(" = %6.4f%%\n",
979  temp / 256.0 / ClassTemplate->ProtoLengths[ActualProtoNum]);
980 
981  ConfigWord = ProtoSet->Protos[ProtoNum].Configs[0];
982  ConfigNum = 0;
983  while (ConfigWord) {
984  cprintf ("%5d", ConfigWord & 1 ? temp : 0);
985  if (ConfigWord & 1)
986  ProtoConfigs[ConfigNum] += temp;
987  ConfigNum++;
988  ConfigWord >>= 1;
989  }
990  cprintf("\n");
991  }
992  }
993  }
994 
995  if (PrintMatchSummaryOn (Debug)) {
996  cprintf ("Proto Error for Configurations:\n");
997  for (ConfigNum = 0; ConfigNum < ClassTemplate->NumConfigs; ConfigNum++)
998  cprintf (" %5.1f",
999  100.0 * (1.0 -
1000  ProtoConfigs[ConfigNum] /
1001  ClassTemplate->ConfigLengths[ConfigNum] / 256.0));
1002  cprintf ("\n\n");
1003  }
1004 
1005  if (PrintProtoMatchesOn (Debug)) {
1006  cprintf ("Proto Sum for Configurations:\n");
1007  for (ConfigNum = 0; ConfigNum < ClassTemplate->NumConfigs; ConfigNum++)
1008  cprintf (" %4.1f", ProtoConfigs[ConfigNum] / 256.0);
1009  cprintf ("\n\n");
1010 
1011  cprintf ("Proto Length for Configurations:\n");
1012  for (ConfigNum = 0; ConfigNum < ClassTemplate->NumConfigs; ConfigNum++)
1013  cprintf (" %4.1f",
1014  (float) ClassTemplate->ConfigLengths[ConfigNum]);
1015  cprintf ("\n\n");
1016  }
1017 
1018 }
1019 
1020 void IntegerMatcher::DisplayProtoDebugInfo(
1021  INT_CLASS ClassTemplate,
1022  BIT_VECTOR ProtoMask,
1023  BIT_VECTOR ConfigMask,
1024  const ScratchEvidence& tables,
1025  bool SeparateDebugWindows) {
1026  uint16_t ProtoNum;
1027  uint16_t ActualProtoNum;
1028  PROTO_SET ProtoSet;
1029  int ProtoSetIndex;
1030 
1032  if (SeparateDebugWindows) {
1035  }
1036 
1037 
1038  for (ProtoSetIndex = 0; ProtoSetIndex < ClassTemplate->NumProtoSets;
1039  ProtoSetIndex++) {
1040  ProtoSet = ClassTemplate->ProtoSets[ProtoSetIndex];
1041  ActualProtoNum = ProtoSetIndex * PROTOS_PER_PROTO_SET;
1042  for (ProtoNum = 0;
1043  ((ProtoNum < PROTOS_PER_PROTO_SET) &&
1044  (ActualProtoNum < ClassTemplate->NumProtos));
1045  ProtoNum++, ActualProtoNum++) {
1046  /* Compute Average for Actual Proto */
1047  int temp = 0;
1048  for (int i = 0; i < ClassTemplate->ProtoLengths[ActualProtoNum]; i++)
1049  temp += tables.proto_evidence_[ActualProtoNum][i];
1050 
1051  temp /= ClassTemplate->ProtoLengths[ActualProtoNum];
1052 
1053  if ((ProtoSet->Protos[ProtoNum]).Configs[0] & (*ConfigMask)) {
1054  DisplayIntProto(ClassTemplate, ActualProtoNum, temp / 255.0);
1055  }
1056  }
1057  }
1058 }
1059 
1060 
1061 void IntegerMatcher::DisplayFeatureDebugInfo(
1062  INT_CLASS ClassTemplate,
1063  BIT_VECTOR ProtoMask,
1064  BIT_VECTOR ConfigMask,
1065  int16_t NumFeatures,
1066  const INT_FEATURE_STRUCT* Features,
1067  int AdaptFeatureThreshold,
1068  int Debug,
1069  bool SeparateDebugWindows) {
1070  ScratchEvidence *tables = new ScratchEvidence();
1071 
1072  tables->Clear(ClassTemplate);
1073 
1075  if (SeparateDebugWindows) {
1078  }
1079 
1080  for (int Feature = 0; Feature < NumFeatures; Feature++) {
1081  UpdateTablesForFeature(
1082  ClassTemplate, ProtoMask, ConfigMask, Feature, &Features[Feature],
1083  tables, 0);
1084 
1085  /* Find Best Evidence for Current Feature */
1086  int best = 0;
1087  for (int i = 0; i < ClassTemplate->NumConfigs; i++)
1088  if (tables->feature_evidence_[i] > best)
1089  best = tables->feature_evidence_[i];
1090 
1091  /* Update display for current feature */
1092  if (ClipMatchEvidenceOn(Debug)) {
1093  if (best < AdaptFeatureThreshold)
1094  DisplayIntFeature(&Features[Feature], 0.0);
1095  else
1096  DisplayIntFeature(&Features[Feature], 1.0);
1097  } else {
1098  DisplayIntFeature(&Features[Feature], best / 255.0);
1099  }
1100  }
1101 
1102  delete tables;
1103 }
1104 #endif
1105 
1110  INT_CLASS ClassTemplate, BIT_VECTOR ConfigMask, int16_t NumFeatures) {
1111 
1112  int *IntPointer;
1113  uint32_t ConfigWord;
1114  int ProtoSetIndex;
1115  uint16_t ProtoNum;
1116  PROTO_SET ProtoSet;
1117  int NumProtos;
1118  uint16_t ActualProtoNum;
1119 
1120  NumProtos = ClassTemplate->NumProtos;
1121 
1122  for (ProtoSetIndex = 0; ProtoSetIndex < ClassTemplate->NumProtoSets;
1123  ProtoSetIndex++) {
1124  ProtoSet = ClassTemplate->ProtoSets[ProtoSetIndex];
1125  ActualProtoNum = (ProtoSetIndex * PROTOS_PER_PROTO_SET);
1126  for (ProtoNum = 0;
1127  ((ProtoNum < PROTOS_PER_PROTO_SET) && (ActualProtoNum < NumProtos));
1128  ProtoNum++, ActualProtoNum++) {
1129  int temp = 0;
1130  for (int i = 0; i < ClassTemplate->ProtoLengths[ActualProtoNum]; i++)
1131  temp += proto_evidence_[ActualProtoNum] [i];
1132 
1133  ConfigWord = ProtoSet->Protos[ProtoNum].Configs[0];
1134  ConfigWord &= *ConfigMask;
1135  IntPointer = sum_feature_evidence_;
1136  while (ConfigWord) {
1137  if (ConfigWord & 1)
1138  *IntPointer += temp;
1139  IntPointer++;
1140  ConfigWord >>= 1;
1141  }
1142  }
1143  }
1144 }
1145 
1151  INT_CLASS ClassTemplate, int16_t NumFeatures, int32_t used_features) {
1152 
1153  for (int i = 0; i < ClassTemplate->NumConfigs; i++) {
1155  (NumFeatures + ClassTemplate->ConfigLengths[i]);
1156  }
1157 }
1158 
1164 int IntegerMatcher::FindBestMatch(
1165  INT_CLASS class_template,
1166  const ScratchEvidence &tables,
1167  UnicharRating* result) {
1168  int best_match = 0;
1169  result->config = 0;
1170  result->fonts.truncate(0);
1171  result->fonts.reserve(class_template->NumConfigs);
1172 
1173  /* Find best match */
1174  for (int c = 0; c < class_template->NumConfigs; ++c) {
1175  int rating = tables.sum_feature_evidence_[c];
1176  if (*classify_debug_level_ > 2)
1177  tprintf("Config %d, rating=%d\n", c, rating);
1178  if (rating > best_match) {
1179  result->config = c;
1180  best_match = rating;
1181  }
1182  result->fonts.push_back(ScoredFont(c, rating));
1183  }
1184 
1185  // Compute confidence on a Probability scale.
1186  result->rating = best_match / 65536.0f;
1187 
1188  return best_match;
1189 }
1190 
1195 float IntegerMatcher::ApplyCNCorrection(float rating, int blob_length,
1196  int normalization_factor,
1197  int matcher_multiplier) {
1198  return (rating * blob_length +
1199  matcher_multiplier * normalization_factor / 256.0) /
1200  (blob_length + matcher_multiplier);
1201 }
1202 
1212 void
1213 HeapSort (int n, int ra[], int rb[]) {
1214  int i, rra, rrb;
1215  int l, j, ir;
1216 
1217  l = (n >> 1) + 1;
1218  ir = n;
1219  for (;;) {
1220  if (l > 1) {
1221  rra = ra[--l];
1222  rrb = rb[l];
1223  }
1224  else {
1225  rra = ra[ir];
1226  rrb = rb[ir];
1227  ra[ir] = ra[1];
1228  rb[ir] = rb[1];
1229  if (--ir == 1) {
1230  ra[1] = rra;
1231  rb[1] = rrb;
1232  return;
1233  }
1234  }
1235  i = l;
1236  j = l << 1;
1237  while (j <= ir) {
1238  if (j < ir && ra[j] < ra[j + 1])
1239  ++j;
1240  if (rra < ra[j]) {
1241  ra[i] = ra[j];
1242  rb[i] = rb[j];
1243  j += (i = j);
1244  }
1245  else
1246  j = ir + 1;
1247  }
1248  ra[i] = rra;
1249  rb[i] = rrb;
1250  }
1251 }
void NormalizeSums(INT_CLASS ClassTemplate, int16_t NumFeatures, int32_t used_features)
#define DisplayProtoMatchesOn(D)
Definition: intproto.h:196
static const float kSEExponentialMultiplier
Definition: intmatcher.h:92
int SetupResults(GenericVector< CP_RESULT_STRUCT > *results) const
Definition: intmatcher.cpp:357
void NormalizeForXheight(int norm_multiplier, const uint8_t *normalization_factors)
Definition: intmatcher.cpp:243
static const int kIntEvidenceTruncBits
Definition: intmatcher.h:90
void cprintf(const char *format,...)
Definition: callcpp.cpp:33
void IMDebugConfigurationSum(INT_FEATURE FeatureNum, uint8_t *FeatureEvidence, int32_t ConfigCount)
uint8_t FEATURE_ID
Definition: matchdefs.h:48
uint32_t Configs[WERDS_PER_CONFIG_VEC]
Definition: intproto.h:86
void DisplayIntFeature(const INT_FEATURE_STRUCT *Feature, float Evidence)
Definition: intproto.cpp:599
#define SE_TABLE_SIZE
Definition: intmatcher.h:67
const char * string() const
Definition: strngs.cpp:196
int FindGoodProtos(INT_CLASS ClassTemplate, BIT_VECTOR ProtoMask, BIT_VECTOR ConfigMask, uint16_t BlobLength, int16_t NumFeatures, INT_FEATURE_ARRAY Features, PROTO_ID *ProtoArray, int AdaptProtoThreshold, int Debug)
Definition: intmatcher.cpp:549
static const float kSimilarityCenter
Definition: intmatcher.h:94
static const int kEvidenceTableBits
Definition: intmatcher.h:88
CLASS_PRUNER_STRUCT * ClassPruners[MAX_NUM_CLASS_PRUNERS]
Definition: intproto.h:122
void UpdateSumOfProtoEvidences(INT_CLASS ClassTemplate, BIT_VECTOR ConfigMask, int16_t NumFeatures)
#define MatchDebuggingOn(D)
Definition: intproto.h:193
#define NUM_BITS_PER_CLASS
Definition: intproto.h:55
void ComputeScores(const INT_TEMPLATES_STRUCT *int_templates, int num_features, const INT_FEATURE_STRUCT *features)
Definition: intmatcher.cpp:137
uint32_t * BIT_VECTOR
Definition: bitvec.h:28
void InitProtoDisplayWindowIfReqd()
Definition: intproto.cpp:1769
#define CLASS_PRUNER_CLASS_MASK
Definition: intproto.h:56
uint32_t p[NUM_CP_BUCKETS][NUM_CP_BUCKETS][NUM_CP_BUCKETS][WERDS_PER_CP_VECTOR]
Definition: intproto.h:78
uint8_t NumProtoSets
Definition: intproto.h:107
int PruneClasses(const INT_TEMPLATES_STRUCT *int_templates, int num_features, int keep_this, const INT_FEATURE_STRUCT *features, const uint8_t *normalization_factors, const uint16_t *expected_num_features, GenericVector< CP_RESULT_STRUCT > *results)
Definition: intmatcher.cpp:409
void Match(INT_CLASS ClassTemplate, BIT_VECTOR ProtoMask, BIT_VECTOR ConfigMask, int16_t NumFeatures, const INT_FEATURE_STRUCT *Features, tesseract::UnicharRating *Result, int AdaptFeatureThreshold, int Debug, bool SeparateDebugWindows)
Definition: intmatcher.cpp:470
uint8_t * ProtoLengths
Definition: intproto.h:110
void DisableDisabledClasses(const UNICHARSET &unicharset)
Definition: intmatcher.cpp:221
void DisableFragments(const UNICHARSET &unicharset)
Definition: intmatcher.cpp:229
int classify_class_pruner_multiplier
Definition: classify.h:506
PROTO_SET ProtoSets[MAX_NUM_PROTO_SETS]
Definition: intproto.h:109
uint8_t NumConfigs
Definition: intproto.h:108
void Clear(const INT_CLASS class_template)
Definition: intmatcher.cpp:700
#define MAX_NUM_CONFIGS
Definition: intproto.h:47
int classify_class_pruner_threshold
Definition: classify.h:504
#define BITS_PER_WERD
Definition: intproto.h:45
#define DisplayFeatureMatchesOn(D)
Definition: intproto.h:195
void ClearFeatureEvidence(const INT_CLASS class_template)
Definition: intmatcher.cpp:707
float ApplyCNCorrection(float rating, int blob_length, int normalization_factor, int matcher_multiplier)
UNICHARSET unicharset
Definition: ccutil.h:68
void PruneAndSort(int pruning_factor, int keep_this, bool max_of_non_fragments, const UNICHARSET &unicharset)
Definition: intmatcher.cpp:261
INT_PROTO_STRUCT Protos[PROTOS_PER_PROTO_SET]
Definition: intproto.h:97
void init_to_size(int size, const T &t)
int RoundUp(int n, int block_size)
Definition: helpers.h:105
#define PrintFeatureMatchesOn(D)
Definition: intproto.h:197
void IMDebugConfiguration(INT_FEATURE FeatureNum, uint16_t ActualProtoNum, uint8_t Evidence, BIT_VECTOR ConfigMask, uint32_t ConfigWord)
uint16_t ConfigLengths[MAX_NUM_CONFIGS]
Definition: intproto.h:111
IntegerMatcher(tesseract::IntParam *classify_debug_level)
Definition: intmatcher.cpp:670
STRING ClassIDToDebugStr(const INT_TEMPLATES_STRUCT *templates, int class_id, int config_id) const
#define PrintMatchSummaryOn(D)
Definition: intproto.h:194
bool get_enabled(UNICHAR_ID unichar_id) const
Definition: unicharset.h:873
ShapeTable * shape_table_
Definition: classify.h:553
#define SE_TABLE_BITS
Definition: intmatcher.h:66
DLLSYM void tprintf(const char *format,...)
Definition: tprintf.cpp:37
#define PROTOS_PER_PROTO_SET
Definition: intproto.h:49
#define NUM_CP_BUCKETS
Definition: intproto.h:53
uint8_t feature_evidence_[MAX_NUM_CONFIGS]
Definition: intmatcher.h:70
INT_FEATURE_STRUCT INT_FEATURE_ARRAY[MAX_NUM_INT_FEATURES]
Definition: intproto.h:150
int16_t PROTO_ID
Definition: matchdefs.h:42
bool disable_character_fragments
Definition: classify.h:491
const CHAR_FRAGMENT * get_fragment(UNICHAR_ID unichar_id) const
Definition: unicharset.h:729
Definition: strngs.h:45
static const int kIntThetaFudge
Definition: intmatcher.h:86
void InitFeatureDisplayWindowIfReqd()
Definition: intproto.cpp:1780
#define ClipMatchEvidenceOn(D)
Definition: intproto.h:199
#define WERDS_PER_CP_VECTOR
Definition: intproto.h:62
int FindBadFeatures(INT_CLASS ClassTemplate, BIT_VECTOR ProtoMask, BIT_VECTOR ConfigMask, uint16_t BlobLength, int16_t NumFeatures, INT_FEATURE_ARRAY Features, FEATURE_ID *FeatureArray, int AdaptFeatureThreshold, int Debug)
Definition: intmatcher.cpp:618
void DisplayIntProto(INT_CLASS Class, PROTO_ID ProtoId, float Evidence)
Definition: intproto.cpp:618
uint16_t NumProtos
Definition: intproto.h:106
void InitIntMatchWindowIfReqd()
Definition: intproto.cpp:1748
#define PrintProtoMatchesOn(D)
Definition: intproto.h:198
void DebugMatch(const Classify &classify, const INT_TEMPLATES_STRUCT *int_templates, const INT_FEATURE_STRUCT *features) const
Definition: intmatcher.cpp:297
#define next_table_entries
Definition: intmatcher.cpp:65
#define NUM_PP_BUCKETS
Definition: intproto.h:52
T ClipToRange(const T &x, const T &lower_bound, const T &upper_bound)
Definition: helpers.h:111
void SummarizeResult(const Classify &classify, const INT_TEMPLATES_STRUCT *int_templates, const uint16_t *expected_num_features, int norm_multiplier, const uint8_t *normalization_factors) const
Definition: intmatcher.cpp:334
void AdjustForExpectedNumFeatures(const uint16_t *expected_num_features, int cutoff_strength)
Definition: intmatcher.cpp:208
uint8_t Angle
Definition: intproto.h:85
int classify_cp_cutoff_strength
Definition: classify.h:508
#define INTMATCHER_OFFSET_TABLE_SIZE
Definition: intmatcher.cpp:63
int sum_feature_evidence_[MAX_NUM_CONFIGS]
Definition: intmatcher.h:71
uint8_t proto_evidence_[MAX_NUM_PROTOS][MAX_PROTO_INDEX]
Definition: intmatcher.h:72
ClassPruner(int max_classes)
Definition: intmatcher.cpp:106
void HeapSort(int n, int ra[], int rb[])
#define offset_table_entries
Definition: intmatcher.cpp:50
GenericVector< ScoredFont > fonts
Definition: shapetable.h:88