All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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  if (alt_list_ != NULL) {
58  delete alt_list_;
59  alt_list_ = NULL;
60  }
61 
62  if (deslanted_alt_list_ != NULL) {
63  delete deslanted_alt_list_;
64  deslanted_alt_list_ = NULL;
65  }
66 }
67 
69  if (char_samp_ != NULL && own_char_samp_ == true) {
70  delete char_samp_;
71  char_samp_ = NULL;
72  }
73 
74  if (srch_obj_ != NULL) {
75  delete srch_obj_;
76  srch_obj_ = NULL;
77  }
78 
79  if (deslanted_srch_obj_ != NULL) {
80  delete deslanted_srch_obj_;
81  deslanted_srch_obj_ = NULL;
82  }
83 
84  if (beam_obj_ != NULL) {
85  delete beam_obj_;
86  beam_obj_ = NULL;
87  }
88 
89  if (deslanted_beam_obj_ != NULL) {
90  delete deslanted_beam_obj_;
91  deslanted_beam_obj_ = NULL;
92  }
93 
94  if (deslanted_char_samp_ != NULL) {
95  delete deslanted_char_samp_;
96  deslanted_char_samp_ = NULL;
97  }
98 
99  Cleanup();
100 }
101 
108 WordAltList *CubeObject::Recognize(LangModel *lang_mod, bool word_mode) {
109  if (char_samp_ == NULL) {
110  return NULL;
111  }
112 
113  // clear alt lists
114  Cleanup();
115 
116  // no specified language model, use the one in the reco context
117  if (lang_mod == NULL) {
118  lang_mod = cntxt_->LangMod();
119  }
120 
121  // normalize if necessary
122  if (cntxt_->SizeNormalization()) {
123  Normalize();
124  }
125 
126  // assume not de-slanted by default
127  deslanted_ = false;
128 
129  // create a beam search object
130  if (beam_obj_ == NULL) {
131  beam_obj_ = new BeamSearch(cntxt_, word_mode);
132  if (beam_obj_ == NULL) {
133  fprintf(stderr, "Cube ERROR (CubeObject::Recognize): could not construct "
134  "BeamSearch\n");
135  return NULL;
136  }
137  }
138 
139  // create a cube search object
140  if (srch_obj_ == NULL) {
141  srch_obj_ = new CubeSearchObject(cntxt_, char_samp_);
142  if (srch_obj_ == NULL) {
143  fprintf(stderr, "Cube ERROR (CubeObject::Recognize): could not construct "
144  "CubeSearchObject\n");
145  return NULL;
146  }
147  }
148 
149  // run a beam search against the tesslang model
150  alt_list_ = beam_obj_->Search(srch_obj_, lang_mod);
151 
152  // deslant (if supported by language) and re-reco if probability is low enough
153  if (cntxt_->HasItalics() == true &&
154  (alt_list_ == NULL || alt_list_->AltCount() < 1 ||
155  alt_list_->AltCost(0) > CubeUtils::Prob2Cost(kMinProbSkipDeslanted))) {
156 
157  if (deslanted_beam_obj_ == NULL) {
158  deslanted_beam_obj_ = new BeamSearch(cntxt_);
159  if (deslanted_beam_obj_ == NULL) {
160  fprintf(stderr, "Cube ERROR (CubeObject::Recognize): could not "
161  "construct deslanted BeamSearch\n");
162  return NULL;
163  }
164  }
165 
166  if (deslanted_srch_obj_ == NULL) {
167  deslanted_char_samp_ = char_samp_->Clone();
168  if (deslanted_char_samp_ == NULL) {
169  fprintf(stderr, "Cube ERROR (CubeObject::Recognize): could not "
170  "construct deslanted CharSamp\n");
171  return NULL;
172  }
173 
174  if (deslanted_char_samp_->Deslant() == false) {
175  return NULL;
176  }
177 
178  deslanted_srch_obj_ = new CubeSearchObject(cntxt_, deslanted_char_samp_);
179  if (deslanted_srch_obj_ == NULL) {
180  fprintf(stderr, "Cube ERROR (CubeObject::Recognize): could not "
181  "construct deslanted CubeSearchObject\n");
182  return NULL;
183  }
184  }
185 
186  // run a beam search against the tesslang model
187  deslanted_alt_list_ = deslanted_beam_obj_->Search(deslanted_srch_obj_,
188  lang_mod);
189  // should we use de-slanted altlist?
190  if (deslanted_alt_list_ != NULL && deslanted_alt_list_->AltCount() > 0) {
191  if (alt_list_ == NULL || alt_list_->AltCount() < 1 ||
192  deslanted_alt_list_->AltCost(0) < alt_list_->AltCost(0)) {
193  deslanted_ = true;
194  return deslanted_alt_list_;
195  }
196  }
197  }
198 
199  return alt_list_;
200 }
201 
206  return Recognize(lang_mod, true);
207 }
208 
213  return Recognize(lang_mod, false);
214 }
215 
220 int CubeObject::WordCost(const char *str) {
221  WordListLangModel *lang_mod = new WordListLangModel(cntxt_);
222  if (lang_mod == NULL) {
223  return WORST_COST;
224  }
225 
226  if (lang_mod->AddString(str) == false) {
227  delete lang_mod;
228  return WORST_COST;
229  }
230 
231  // run a beam search against the single string wordlist model
232  WordAltList *alt_list = RecognizeWord(lang_mod);
233  delete lang_mod;
234 
235  int cost = WORST_COST;
236  if (alt_list != NULL) {
237  if (alt_list->AltCount() > 0) {
238  cost = alt_list->AltCost(0);
239  }
240  }
241 
242  return cost;
243 }
244 
245 // Recognizes a single character and returns the list of results.
247  if (char_samp_ == NULL) return NULL;
248  CharAltList* alt_list = NULL;
249  CharClassifier *char_classifier = cntxt_->Classifier();
250  ASSERT_HOST(char_classifier != NULL);
251  alt_list = char_classifier->Classify(char_samp_);
252  return alt_list;
253 }
254 
255 // Normalize the input word bitmap to have a minimum aspect ratio
257  // create a cube search object
258  CubeSearchObject *srch_obj = new CubeSearchObject(cntxt_, char_samp_);
259  if (srch_obj == NULL) {
260  return false;
261  }
262  // Perform over-segmentation
263  int seg_cnt = srch_obj->SegPtCnt();
264  // Only perform normalization if segment count is large enough
265  if (seg_cnt < kMinNormalizationSegmentCnt) {
266  delete srch_obj;
267  return true;
268  }
269  // compute the mean AR of the segments
270  double ar_mean = 0.0;
271  for (int seg_idx = 0; seg_idx <= seg_cnt; seg_idx++) {
272  CharSamp *seg_samp = srch_obj->CharSample(seg_idx - 1, seg_idx);
273  if (seg_samp != NULL && seg_samp->Width() > 0) {
274  ar_mean += (1.0 * seg_samp->Height() / seg_samp->Width());
275  }
276  }
277  ar_mean /= (seg_cnt + 1);
278  // perform normalization if segment AR is too high
279  if (ar_mean > kMinNormalizationAspectRatio) {
280  // scale down the image in the y-direction to attain AR
281  CharSamp *new_samp = char_samp_->Scale(char_samp_->Width(),
282  2.0 * char_samp_->Height() / ar_mean,
283  false);
284  if (new_samp != NULL) {
285  // free existing char samp if owned
286  if (own_char_samp_) {
287  delete char_samp_;
288  }
289  // update with new scaled charsamp and set ownership flag
290  char_samp_ = new_samp;
291  own_char_samp_ = true;
292  }
293  }
294  delete srch_obj;
295  return true;
296 }
297 }
int WordCost(const char *str)
#define WORST_COST
Definition: cube_const.h:30
LangModel * LangMod() const
static int Prob2Cost(double prob_val)
Definition: cube_utils.cpp:37
int AltCost(int alt_idx) const
Definition: altlist.h:41
unsigned short Width() const
Definition: bmp_8.h:48
WordAltList * RecognizeWord(LangModel *lang_mod=NULL)
#define ASSERT_HOST(x)
Definition: errcode.h:84
CubeObject(CubeRecoContext *cntxt, CharSamp *char_samp)
Definition: cube_object.cpp:26
CharSamp * CharSample(int start_pt, int end_pt)
CharSamp * Scale(int wid, int hgt, bool isotropic=true)
Definition: char_samp.cpp:251
virtual CharAltList * Classify(CharSamp *char_samp)=0
CharClassifier * Classifier() const
CharAltList * RecognizeChar()
WordAltList * RecognizePhrase(LangModel *lang_mod=NULL)
unsigned short Height() const
Definition: bmp_8.h:50
bool Deslant()
Definition: bmp_8.cpp:795
int AltCount() const
Definition: altlist.h:39
CharSamp * Clone() const
Definition: char_samp.cpp:565
#define NULL
Definition: host.h:144
bool AddString(const char *char_ptr)
WordAltList * Search(SearchObject *srch_obj, LangModel *lang_mod=NULL)
Definition: beam_search.cpp:98
static CharSamp * CharSampleFromPix(Pix *pix, int left, int top, int wid, int hgt)
Definition: cube_utils.cpp:104