Tesseract  3.02
tesseract-ocr/cube/search_node.h
Go to the documentation of this file.
00001 /**********************************************************************
00002  * File:        search_node.h
00003  * Description: Declaration of the Beam Search Node Class
00004  * Author:    Ahmad Abdulkader
00005  * Created:   2008
00006  *
00007  * (C) Copyright 2008, Google Inc.
00008  ** Licensed under the Apache License, Version 2.0 (the "License");
00009  ** you may not use this file except in compliance with the License.
00010  ** You may obtain a copy of the License at
00011  ** http://www.apache.org/licenses/LICENSE-2.0
00012  ** Unless required by applicable law or agreed to in writing, software
00013  ** distributed under the License is distributed on an "AS IS" BASIS,
00014  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00015  ** See the License for the specific language governing permissions and
00016  ** limitations under the License.
00017  *
00018  **********************************************************************/
00019 
00020 // The SearchNode class abstracts the search lattice node in the lattice
00021 // generated by the BeamSearch class
00022 // The SearchNode class holds the lang_mod_edge associated with the lattice
00023 // node. It also holds a pointer to the parent SearchNode in the search path
00024 // In addition it holds the recognition and the language model costs of the
00025 // node and the path leading to this node
00026 
00027 #ifndef SEARCH_NODE_H
00028 #define SEARCH_NODE_H
00029 
00030 #include "lang_mod_edge.h"
00031 #include "cube_reco_context.h"
00032 
00033 namespace tesseract {
00034 
00035 class SearchNode {
00036  public:
00037   SearchNode(CubeRecoContext *cntxt, SearchNode *parent_node,
00038              int char_reco_cost, LangModEdge *edge, int col_idx);
00039 
00040   ~SearchNode();
00041 
00042   // Updates the parent of the current node if the specified path yields
00043   // a better path cost
00044   bool UpdateParent(SearchNode *new_parent, int new_reco_cost,
00045                     LangModEdge *new_edge);
00046   // returns the 32-bit string corresponding to the path leading to this node
00047   char_32 *PathString();
00048   // True if the two input nodes correspond to the same path
00049   static bool IdenticalPath(SearchNode *node1, SearchNode *node2);
00050 
00051   inline const char_32 *NodeString() { return str_; }
00052   inline void SetString(char_32 *str) { str_ = str; }
00053 
00054   // This node's character recognition cost.
00055   inline int CharRecoCost() { return char_reco_cost_; }
00056   // Total character recognition cost of the nodes in the best path,
00057   // excluding this node.
00058   inline int BestPathRecoCost() { return best_path_reco_cost_; }
00059   // Number of nodes in best path.
00060   inline int BestPathLength() { return best_path_len_; }
00061   // Mean mixed cost, i.e., mean character recognition cost +
00062   // current language model cost, all weighted by the RecoWgt parameter
00063   inline int BestCost() { return best_cost_; }
00064   // Mean character recognition cost of the nodes on the best path,
00065   // including this node.
00066   inline int BestRecoCost() { return mean_char_reco_cost_ ; }
00067 
00068   inline int ColIdx() { return col_idx_; }
00069   inline SearchNode *ParentNode() { return parent_node_; }
00070   inline LangModEdge *LangModelEdge() { return lang_mod_edge_;}
00071   inline int LangModCost() { return LangModCost(lang_mod_edge_, parent_node_); }
00072 
00073   // A comparer function that allows the SearchColumn class to sort the
00074   // nodes based on the path cost
00075   inline static int SearchNodeComparer(const void *node1, const void *node2) {
00076     return (*(reinterpret_cast<SearchNode * const *>(node1)))->best_cost_ -
00077         (*(reinterpret_cast<SearchNode * const *>(node2)))->best_cost_;
00078   }
00079 
00080  private:
00081   CubeRecoContext *cntxt_;
00082   // Character code
00083   const char_32 *str_;
00084   // Recognition cost of most recent character
00085   int char_reco_cost_;
00086   // Mean mixed cost,  i.e., mean character recognition cost +
00087   // current language model cost, all weighted by the RecoWgt parameter
00088   int best_cost_;
00089   // Mean character recognition cost of the nodes on the best path,
00090   // including this node.
00091   int mean_char_reco_cost_ ;
00092   // Total character recognition cost of the nodes in the best path,
00093   // excluding this node.
00094   int best_path_reco_cost_;
00095   // Number of nodes in best path.
00096   int best_path_len_;
00097   // Column index
00098   int col_idx_;
00099   // Parent Node
00100   SearchNode *parent_node_;
00101   // Language model edge
00102   LangModEdge *lang_mod_edge_;
00103   static int LangModCost(LangModEdge *lang_mod_edge, SearchNode *parent_node);
00104 };
00105 
00106 // Implments a SearchNode hash table used to detect if a Search Node exists
00107 // or not. This is needed to make sure that identical paths in the BeamSearch
00108 // converge
00109 class SearchNodeHashTable {
00110  public:
00111   SearchNodeHashTable() {
00112     memset(bin_size_array_, 0, sizeof(bin_size_array_));
00113   }
00114 
00115   ~SearchNodeHashTable() {
00116   }
00117 
00118   // inserts an entry in the hash table
00119   inline bool Insert(LangModEdge *lang_mod_edge, SearchNode *srch_node) {
00120     // compute hash based on the edge and its parent node edge
00121     unsigned int edge_hash = lang_mod_edge->Hash();
00122     unsigned int parent_hash = (srch_node->ParentNode() == NULL ?
00123         0 : srch_node->ParentNode()->LangModelEdge()->Hash());
00124     unsigned int hash_bin = (edge_hash + parent_hash) % kSearchNodeHashBins;
00125 
00126     // already maxed out, just fail
00127     if (bin_size_array_[hash_bin] >= kMaxSearchNodePerBin) {
00128       return false;
00129     }
00130 
00131     bin_array_[hash_bin][bin_size_array_[hash_bin]++] = srch_node;
00132 
00133     return true;
00134   }
00135 
00136   // Looks up an entry in the hash table
00137   inline SearchNode *Lookup(LangModEdge *lang_mod_edge,
00138                             SearchNode *parent_node) {
00139     // compute hash based on the edge and its parent node edge
00140     unsigned int edge_hash = lang_mod_edge->Hash();
00141     unsigned int parent_hash = (parent_node == NULL ?
00142         0 : parent_node->LangModelEdge()->Hash());
00143     unsigned int hash_bin = (edge_hash + parent_hash) % kSearchNodeHashBins;
00144 
00145     // lookup the entries in the hash bin
00146     for (int node_idx = 0; node_idx < bin_size_array_[hash_bin]; node_idx++) {
00147       if (lang_mod_edge->IsIdentical(
00148           bin_array_[hash_bin][node_idx]->LangModelEdge()) == true &&
00149           SearchNode::IdenticalPath(
00150           bin_array_[hash_bin][node_idx]->ParentNode(), parent_node) == true) {
00151         return bin_array_[hash_bin][node_idx];
00152       }
00153     }
00154 
00155     return NULL;
00156   }
00157 
00158  private:
00159   // Hash bin size parameters. These were determined emperically. These affect
00160   // the speed of the beam search but have no impact on accuracy
00161   static const int kSearchNodeHashBins = 4096;
00162   static const int kMaxSearchNodePerBin = 512;
00163   int bin_size_array_[kSearchNodeHashBins];
00164   SearchNode *bin_array_[kSearchNodeHashBins][kMaxSearchNodePerBin];
00165 };
00166 }
00167 
00168 #endif  // SEARCH_NODE_H