tesseract  3.04.00
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups 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 
102 // Actually do the recognition using the specified language mode. If none
103 // is specified, the default language model in the CubeRecoContext is used.
104 // Returns the sorted list of alternate answers
105 // The Word mode determines whether recognition is done as a word or a phrase
106 WordAltList *CubeObject::Recognize(LangModel *lang_mod, bool word_mode) {
107  if (char_samp_ == NULL) {
108  return NULL;
109  }
110 
111  // clear alt lists
112  Cleanup();
113 
114  // no specified language model, use the one in the reco context
115  if (lang_mod == NULL) {
116  lang_mod = cntxt_->LangMod();
117  }
118 
119  // normalize if necessary
120  if (cntxt_->SizeNormalization()) {
121  Normalize();
122  }
123 
124  // assume not de-slanted by default
125  deslanted_ = false;
126 
127  // create a beam search object
128  if (beam_obj_ == NULL) {
129  beam_obj_ = new BeamSearch(cntxt_, word_mode);
130  if (beam_obj_ == NULL) {
131  fprintf(stderr, "Cube ERROR (CubeObject::Recognize): could not construct "
132  "BeamSearch\n");
133  return NULL;
134  }
135  }
136 
137  // create a cube search object
138  if (srch_obj_ == NULL) {
139  srch_obj_ = new CubeSearchObject(cntxt_, char_samp_);
140  if (srch_obj_ == NULL) {
141  fprintf(stderr, "Cube ERROR (CubeObject::Recognize): could not construct "
142  "CubeSearchObject\n");
143  return NULL;
144  }
145  }
146 
147  // run a beam search against the tesslang model
148  alt_list_ = beam_obj_->Search(srch_obj_, lang_mod);
149 
150  // deslant (if supported by language) and re-reco if probability is low enough
151  if (cntxt_->HasItalics() == true &&
152  (alt_list_ == NULL || alt_list_->AltCount() < 1 ||
153  alt_list_->AltCost(0) > CubeUtils::Prob2Cost(kMinProbSkipDeslanted))) {
154 
155  if (deslanted_beam_obj_ == NULL) {
156  deslanted_beam_obj_ = new BeamSearch(cntxt_);
157  if (deslanted_beam_obj_ == NULL) {
158  fprintf(stderr, "Cube ERROR (CubeObject::Recognize): could not "
159  "construct deslanted BeamSearch\n");
160  return NULL;
161  }
162  }
163 
164  if (deslanted_srch_obj_ == NULL) {
165  deslanted_char_samp_ = char_samp_->Clone();
166  if (deslanted_char_samp_ == NULL) {
167  fprintf(stderr, "Cube ERROR (CubeObject::Recognize): could not "
168  "construct deslanted CharSamp\n");
169  return NULL;
170  }
171 
172  if (deslanted_char_samp_->Deslant() == false) {
173  return NULL;
174  }
175 
176  deslanted_srch_obj_ = new CubeSearchObject(cntxt_, deslanted_char_samp_);
177  if (deslanted_srch_obj_ == NULL) {
178  fprintf(stderr, "Cube ERROR (CubeObject::Recognize): could not "
179  "construct deslanted CubeSearchObject\n");
180  return NULL;
181  }
182  }
183 
184  // run a beam search against the tesslang model
185  deslanted_alt_list_ = deslanted_beam_obj_->Search(deslanted_srch_obj_,
186  lang_mod);
187  // should we use de-slanted altlist?
188  if (deslanted_alt_list_ != NULL && deslanted_alt_list_->AltCount() > 0) {
189  if (alt_list_ == NULL || alt_list_->AltCount() < 1 ||
190  deslanted_alt_list_->AltCost(0) < alt_list_->AltCost(0)) {
191  deslanted_ = true;
192  return deslanted_alt_list_;
193  }
194  }
195  }
196 
197  return alt_list_;
198 }
199 
200 // Recognize the member char sample as a word
202  return Recognize(lang_mod, true);
203 }
204 
205 // Recognize the member char sample as a word
207  return Recognize(lang_mod, false);
208 }
209 
210 // Computes the cost of a specific string. This is done by performing
211 // recognition of a language model that allows only the specified word
212 int CubeObject::WordCost(const char *str) {
213  WordListLangModel *lang_mod = new WordListLangModel(cntxt_);
214  if (lang_mod == NULL) {
215  return WORST_COST;
216  }
217 
218  if (lang_mod->AddString(str) == false) {
219  delete lang_mod;
220  return WORST_COST;
221  }
222 
223  // run a beam search against the single string wordlist model
224  WordAltList *alt_list = RecognizeWord(lang_mod);
225  delete lang_mod;
226 
227  int cost = WORST_COST;
228  if (alt_list != NULL) {
229  if (alt_list->AltCount() > 0) {
230  cost = alt_list->AltCost(0);
231  }
232  }
233 
234  return cost;
235 }
236 
237 // Recognizes a single character and returns the list of results.
239  if (char_samp_ == NULL) return NULL;
240  CharAltList* alt_list = NULL;
241  CharClassifier *char_classifier = cntxt_->Classifier();
242  ASSERT_HOST(char_classifier != NULL);
243  alt_list = char_classifier->Classify(char_samp_);
244  return alt_list;
245 }
246 
247 // Normalize the input word bitmap to have a minimum aspect ratio
249  // create a cube search object
250  CubeSearchObject *srch_obj = new CubeSearchObject(cntxt_, char_samp_);
251  if (srch_obj == NULL) {
252  return false;
253  }
254  // Perform over-segmentation
255  int seg_cnt = srch_obj->SegPtCnt();
256  // Only perform normalization if segment count is large enough
257  if (seg_cnt < kMinNormalizationSegmentCnt) {
258  delete srch_obj;
259  return true;
260  }
261  // compute the mean AR of the segments
262  double ar_mean = 0.0;
263  for (int seg_idx = 0; seg_idx <= seg_cnt; seg_idx++) {
264  CharSamp *seg_samp = srch_obj->CharSample(seg_idx - 1, seg_idx);
265  if (seg_samp != NULL && seg_samp->Width() > 0) {
266  ar_mean += (1.0 * seg_samp->Height() / seg_samp->Width());
267  }
268  }
269  ar_mean /= (seg_cnt + 1);
270  // perform normalization if segment AR is too high
271  if (ar_mean > kMinNormalizationAspectRatio) {
272  // scale down the image in the y-direction to attain AR
273  CharSamp *new_samp = char_samp_->Scale(char_samp_->Width(),
274  2.0 * char_samp_->Height() / ar_mean,
275  false);
276  if (new_samp != NULL) {
277  // free existing char samp if owned
278  if (own_char_samp_) {
279  delete char_samp_;
280  }
281  // update with new scaled charsamp and set ownership flag
282  char_samp_ = new_samp;
283  own_char_samp_ = true;
284  }
285  }
286  delete srch_obj;
287  return true;
288 }
289 }
int WordCost(const char *str)
LangModel * LangMod() const
static int Prob2Cost(double prob_val)
Definition: cube_utils.cpp:35
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)
#define WORST_COST
Definition: cube_const.h:30
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:92