tesseract
3.03
|
00001 // Copyright 2011 Google Inc. All Rights Reserved. 00002 // Author: rays@google.com (Ray Smith) 00003 00004 // Licensed under the Apache License, Version 2.0 (the "License"); 00005 // you may not use this file except in compliance with the License. 00006 // You may obtain a copy of the License at 00007 // http://www.apache.org/licenses/LICENSE-2.0 00008 // Unless required by applicable law or agreed to in writing, software 00009 // distributed under the License is distributed on an "AS IS" BASIS, 00010 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00011 // See the License for the specific language governing permissions and 00012 // limitations under the License. 00013 00014 // Filename: classifier_tester.cpp 00015 // Purpose: Tests a character classifier on data as formatted for training, 00016 // but doesn't have to be the same as the training data. 00017 // Author: Ray Smith 00018 00019 #include <stdio.h> 00020 #ifndef USE_STD_NAMESPACE 00021 #include "base/commandlineflags.h" 00022 #endif 00023 #include "baseapi.h" 00024 #include "commontraining.h" 00025 #include "cubeclassifier.h" 00026 #include "mastertrainer.h" 00027 #include "params.h" 00028 #include "strngs.h" 00029 #include "tessclassifier.h" 00030 00031 STRING_PARAM_FLAG(classifier, "", "Classifier to test"); 00032 STRING_PARAM_FLAG(lang, "eng", "Language to test"); 00033 STRING_PARAM_FLAG(tessdata_dir, "", "Directory of traineddata files"); 00034 DECLARE_INT_PARAM_FLAG(debug_level); 00035 DECLARE_STRING_PARAM_FLAG(T); 00036 00037 enum ClassifierName { 00038 CN_PRUNER, 00039 CN_FULL, 00040 CN_CUBE, 00041 CN_CUBETESS, 00042 CN_COUNT 00043 }; 00044 00045 const char* names[] = {"pruner", "full", "cube", "cubetess", NULL }; 00046 00047 static tesseract::ShapeClassifier* InitializeClassifier( 00048 const char* classifer_name, const UNICHARSET& unicharset, 00049 int argc, char **argv, 00050 tesseract::TessBaseAPI** api) { 00051 // Decode the classifier string. 00052 ClassifierName classifier = CN_COUNT; 00053 for (int c = 0; c < CN_COUNT; ++c) { 00054 if (strcmp(classifer_name, names[c]) == 0) { 00055 classifier = static_cast<ClassifierName>(c); 00056 break; 00057 } 00058 } 00059 if (classifier == CN_COUNT) { 00060 fprintf(stderr, "Invalid classifier name:%s\n", FLAGS_classifier.c_str()); 00061 return NULL; 00062 } 00063 00064 // We need to initialize tesseract to test. 00065 *api = new tesseract::TessBaseAPI; 00066 tesseract::OcrEngineMode engine_mode = tesseract::OEM_TESSERACT_ONLY; 00067 if (classifier == CN_CUBE || classifier == CN_CUBETESS) 00068 engine_mode = tesseract::OEM_TESSERACT_CUBE_COMBINED; 00069 tesseract::Tesseract* tesseract = NULL; 00070 tesseract::Classify* classify = NULL; 00071 if (classifier == CN_CUBE || classifier == CN_CUBETESS || 00072 classifier == CN_PRUNER || classifier == CN_FULL) { 00073 (*api)->SetVariable("cube_debug_level", "2"); 00074 if ((*api)->Init(FLAGS_tessdata_dir.c_str(), FLAGS_lang.c_str(), 00075 engine_mode) < 0) { 00076 fprintf(stderr, "Tesseract initialization failed!\n"); 00077 return NULL; 00078 } 00079 tesseract = const_cast<tesseract::Tesseract*>((*api)->tesseract()); 00080 classify = reinterpret_cast<tesseract::Classify*>(tesseract); 00081 if (classify->shape_table() == NULL) { 00082 fprintf(stderr, "Tesseract must contain a ShapeTable!\n"); 00083 return NULL; 00084 } 00085 } 00086 tesseract::ShapeClassifier* shape_classifier = NULL; 00087 00088 if (!FLAGS_T.empty()) { 00089 const char* config_name; 00090 while ((config_name = GetNextFilename(argc, argv)) != NULL) { 00091 tprintf("Reading config file %s ...\n", config_name); 00092 (*api)->ReadConfigFile(config_name); 00093 } 00094 } 00095 if (classifier == CN_PRUNER) { 00096 shape_classifier = new tesseract::TessClassifier(true, classify); 00097 } else if (classifier == CN_FULL) { 00098 shape_classifier = new tesseract::TessClassifier(false, classify); 00099 } else if (classifier == CN_CUBE) { 00100 shape_classifier = new tesseract::CubeClassifier(tesseract); 00101 } else if (classifier == CN_CUBETESS) { 00102 shape_classifier = new tesseract::CubeTessClassifier(tesseract); 00103 } else { 00104 fprintf(stderr, "%s tester not yet implemented\n", classifer_name); 00105 return NULL; 00106 } 00107 tprintf("Testing classifier %s:\n", classifer_name); 00108 return shape_classifier; 00109 } 00110 00111 // This program has complex setup requirements, so here is some help: 00112 // Two different modes, tr files and serialized mastertrainer. 00113 // From tr files: 00114 // classifier_tester -U unicharset -F font_properties -X xheights 00115 // -classifier x -lang lang [-output_trainer trainer] *.tr 00116 // From a serialized trainer: 00117 // classifier_tester -input_trainer trainer [-lang lang] -classifier x 00118 // 00119 // In the first case, the unicharset must be the unicharset from within 00120 // the classifier under test, and the font_properties and xheights files must 00121 // match the files used during training. 00122 // In the second case, the trainer file must have been prepared from 00123 // some previous run of shapeclustering, mftraining, or classifier_tester 00124 // using the same conditions as above, ie matching unicharset/font_properties. 00125 // 00126 // Available values of classifier (x above) are: 00127 // pruner : Tesseract class pruner only. 00128 // full : Tesseract full classifier. 00129 // cube : Cube classifier. (Not possible with an input trainer.) 00130 // cubetess : Tesseract class pruner with rescoring by Cube. (Not possible 00131 // with an input trainer.) 00132 int main(int argc, char **argv) { 00133 ParseArguments(&argc, &argv); 00134 STRING file_prefix; 00135 tesseract::MasterTrainer* trainer = tesseract::LoadTrainingData( 00136 argc, argv, false, NULL, &file_prefix); 00137 tesseract::TessBaseAPI* api; 00138 // Decode the classifier string. 00139 tesseract::ShapeClassifier* shape_classifier = InitializeClassifier( 00140 FLAGS_classifier.c_str(), trainer->unicharset(), argc, argv, &api); 00141 if (shape_classifier == NULL) { 00142 fprintf(stderr, "Classifier init failed!:%s\n", FLAGS_classifier.c_str()); 00143 return 1; 00144 } 00145 00146 // We want to test junk as well if it is available. 00147 // trainer->IncludeJunk(); 00148 // We want to test with replicated samples too. 00149 trainer->ReplicateAndRandomizeSamplesIfRequired(); 00150 00151 trainer->TestClassifierOnSamples(tesseract:: CT_UNICHAR_TOP1_ERR, 00152 MAX(3, FLAGS_debug_level), false, 00153 shape_classifier, NULL); 00154 delete shape_classifier; 00155 delete api; 00156 delete trainer; 00157 00158 return 0; 00159 } /* main */ 00160 00161 00162 00163 00164 00165