tesseract  3.05.02
cube_object.cpp
Go to the documentation of this file.
1 /**********************************************************************
2  * File: cube_object.cpp
3  * Description: Implementation of the Cube Object Class
4  * Author: Ahmad Abdulkader
5  * Created: 2007
6  *
7  * (C) Copyright 2008, 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 #include <math.h>
21 #include "cube_object.h"
22 #include "cube_utils.h"
23 #include "word_list_lang_model.h"
24 
25 namespace tesseract {
27  Init();
28  char_samp_ = char_samp;
29  cntxt_ = cntxt;
30 }
31 
33  int left, int top, int wid, int hgt) {
34  Init();
35  char_samp_ = CubeUtils::CharSampleFromPix(pix, left, top, wid, hgt);
36  own_char_samp_ = true;
37  cntxt_ = cntxt;
38 }
39 
40 // Data member initialization function
41 void CubeObject::Init() {
42  char_samp_ = NULL;
43  own_char_samp_ = false;
44  alt_list_ = NULL;
45  srch_obj_ = NULL;
46  deslanted_alt_list_ = NULL;
47  deslanted_srch_obj_ = NULL;
48  deslanted_ = false;
49  deslanted_char_samp_ = NULL;
50  beam_obj_ = NULL;
51  deslanted_beam_obj_ = NULL;
52  cntxt_ = NULL;
53 }
54 
55 // Cleanup function
56 void CubeObject::Cleanup() {
57  delete alt_list_;
58  alt_list_ = NULL;
59 
60  delete deslanted_alt_list_;
61  deslanted_alt_list_ = NULL;
62 }
63 
65  if (own_char_samp_ == true) {
66  delete char_samp_;
67  char_samp_ = NULL;
68  }
69 
70  delete srch_obj_;
71  srch_obj_ = NULL;
72 
73  delete deslanted_srch_obj_;
74  deslanted_srch_obj_ = NULL;
75 
76  delete beam_obj_;
77  beam_obj_ = NULL;
78 
79  delete deslanted_beam_obj_;
80  deslanted_beam_obj_ = NULL;
81 
82  delete deslanted_char_samp_;
83  deslanted_char_samp_ = NULL;
84 
85  Cleanup();
86 }
87 
94 WordAltList *CubeObject::Recognize(LangModel *lang_mod, bool word_mode) {
95  if (char_samp_ == NULL) {
96  return NULL;
97  }
98 
99  // clear alt lists
100  Cleanup();
101 
102  // no specified language model, use the one in the reco context
103  if (lang_mod == NULL) {
104  lang_mod = cntxt_->LangMod();
105  }
106 
107  // normalize if necessary
108  if (cntxt_->SizeNormalization()) {
109  Normalize();
110  }
111 
112  // assume not de-slanted by default
113  deslanted_ = false;
114 
115  // create a beam search object
116  if (beam_obj_ == NULL) {
117  beam_obj_ = new BeamSearch(cntxt_, word_mode);
118  }
119 
120  // create a cube search object
121  if (srch_obj_ == NULL) {
122  srch_obj_ = new CubeSearchObject(cntxt_, char_samp_);
123  }
124 
125  // run a beam search against the tesslang model
126  alt_list_ = beam_obj_->Search(srch_obj_, lang_mod);
127 
128  // deslant (if supported by language) and re-reco if probability is low enough
129  if (cntxt_->HasItalics() == true &&
130  (alt_list_ == NULL || alt_list_->AltCount() < 1 ||
131  alt_list_->AltCost(0) > CubeUtils::Prob2Cost(kMinProbSkipDeslanted))) {
132 
133  if (deslanted_beam_obj_ == NULL) {
134  deslanted_beam_obj_ = new BeamSearch(cntxt_);
135  }
136 
137  if (deslanted_srch_obj_ == NULL) {
138  deslanted_char_samp_ = char_samp_->Clone();
139  if (deslanted_char_samp_ == NULL) {
140  fprintf(stderr, "Cube ERROR (CubeObject::Recognize): could not "
141  "construct deslanted CharSamp\n");
142  return NULL;
143  }
144 
145  if (deslanted_char_samp_->Deslant() == false) {
146  return NULL;
147  }
148 
149  deslanted_srch_obj_ = new CubeSearchObject(cntxt_, deslanted_char_samp_);
150  }
151 
152  // run a beam search against the tesslang model
153  deslanted_alt_list_ = deslanted_beam_obj_->Search(deslanted_srch_obj_,
154  lang_mod);
155  // should we use de-slanted altlist?
156  if (deslanted_alt_list_ != NULL && deslanted_alt_list_->AltCount() > 0) {
157  if (alt_list_ == NULL || alt_list_->AltCount() < 1 ||
158  deslanted_alt_list_->AltCost(0) < alt_list_->AltCost(0)) {
159  deslanted_ = true;
160  return deslanted_alt_list_;
161  }
162  }
163  }
164 
165  return alt_list_;
166 }
167 
172  return Recognize(lang_mod, true);
173 }
174 
179  return Recognize(lang_mod, false);
180 }
181 
186 int CubeObject::WordCost(const char *str) {
187  WordListLangModel *lang_mod = new WordListLangModel(cntxt_);
188 
189  if (lang_mod->AddString(str) == false) {
190  delete lang_mod;
191  return WORST_COST;
192  }
193 
194  // run a beam search against the single string wordlist model
195  WordAltList *alt_list = RecognizeWord(lang_mod);
196  delete lang_mod;
197 
198  int cost = WORST_COST;
199  if (alt_list != NULL) {
200  if (alt_list->AltCount() > 0) {
201  cost = alt_list->AltCost(0);
202  }
203  }
204 
205  return cost;
206 }
207 
208 // Recognizes a single character and returns the list of results.
210  if (char_samp_ == NULL) return NULL;
211  CharAltList* alt_list = NULL;
212  CharClassifier *char_classifier = cntxt_->Classifier();
213  ASSERT_HOST(char_classifier != NULL);
214  alt_list = char_classifier->Classify(char_samp_);
215  return alt_list;
216 }
217 
218 // Normalize the input word bitmap to have a minimum aspect ratio
220  // create a cube search object
221  CubeSearchObject *srch_obj = new CubeSearchObject(cntxt_, char_samp_);
222  // Perform over-segmentation
223  int seg_cnt = srch_obj->SegPtCnt();
224  // Only perform normalization if segment count is large enough
225  if (seg_cnt < kMinNormalizationSegmentCnt) {
226  delete srch_obj;
227  return true;
228  }
229  // compute the mean AR of the segments
230  double ar_mean = 0.0;
231  for (int seg_idx = 0; seg_idx <= seg_cnt; seg_idx++) {
232  CharSamp *seg_samp = srch_obj->CharSample(seg_idx - 1, seg_idx);
233  if (seg_samp != NULL && seg_samp->Width() > 0) {
234  ar_mean += (1.0 * seg_samp->Height() / seg_samp->Width());
235  }
236  }
237  ar_mean /= (seg_cnt + 1);
238  // perform normalization if segment AR is too high
239  if (ar_mean > kMinNormalizationAspectRatio) {
240  // scale down the image in the y-direction to attain AR
241  CharSamp *new_samp = char_samp_->Scale(char_samp_->Width(),
242  2.0 * char_samp_->Height() / ar_mean,
243  false);
244  if (new_samp != NULL) {
245  // free existing char samp if owned
246  if (own_char_samp_) {
247  delete char_samp_;
248  }
249  // update with new scaled charsamp and set ownership flag
250  char_samp_ = new_samp;
251  own_char_samp_ = true;
252  }
253  }
254  delete srch_obj;
255  return true;
256 }
257 }
WordAltList * Search(SearchObject *srch_obj, LangModel *lang_mod=NULL)
Definition: beam_search.cpp:97
unsigned short Height() const
Definition: bmp_8.h:50
CharSamp * Clone() const
Definition: char_samp.cpp:542
virtual CharAltList * Classify(CharSamp *char_samp)=0
CharSamp * Scale(int wid, int hgt, bool isotropic=true)
Definition: char_samp.cpp:247
WordAltList * RecognizePhrase(LangModel *lang_mod=NULL)
int WordCost(const char *str)
unsigned short Width() const
Definition: bmp_8.h:48
CharClassifier * Classifier() const
bool Deslant()
Definition: bmp_8.cpp:752
LangModel * LangMod() const
static int Prob2Cost(double prob_val)
Definition: cube_utils.cpp:37
#define WORST_COST
Definition: cube_const.h:30
CharAltList * RecognizeChar()
CubeObject(CubeRecoContext *cntxt, CharSamp *char_samp)
Definition: cube_object.cpp:26
WordAltList * RecognizeWord(LangModel *lang_mod=NULL)
bool AddString(const char *char_ptr)
CharSamp * CharSample(int start_pt, int end_pt)
static CharSamp * CharSampleFromPix(Pix *pix, int left, int top, int wid, int hgt)
Definition: cube_utils.cpp:101
int AltCost(int alt_idx) const
Definition: altlist.h:41
int AltCount() const
Definition: altlist.h:39
#define ASSERT_HOST(x)
Definition: errcode.h:84