tesseract  3.04.00
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
cntraining.cpp File Reference
#include "oldlist.h"
#include "efio.h"
#include "emalloc.h"
#include "featdefs.h"
#include "tessopt.h"
#include "ocrfeatures.h"
#include "clusttool.h"
#include "cluster.h"
#include <string.h>
#include <stdio.h>
#include <math.h>
#include "unichar.h"
#include "commontraining.h"

Go to the source code of this file.

Macros

#define PROGRAM_FEATURE_TYPE   "cn"
 

Functions

 DECLARE_STRING_PARAM_FLAG (D)
 
int main (int argc, char **argv)
 
void WriteNormProtos (const char *Directory, LIST LabeledProtoList, CLUSTERER *Clusterer)
 
void WriteProtos (FILE *File, uinT16 N, LIST ProtoList, BOOL8 WriteSigProtos, BOOL8 WriteInsigProtos)
 
int main (int argc, char *argv[])
 

Variables

CLUSTERCONFIG CNConfig
 

Macro Definition Documentation

#define PROGRAM_FEATURE_TYPE   "cn"

Include Files and Type Defines

Definition at line 41 of file cntraining.cpp.

Function Documentation

DECLARE_STRING_PARAM_FLAG ( )
int main ( int  argc,
char **  argv 
)

Public Function Prototypes

Definition at line 41 of file tesseractmain.cpp.

41  {
42  if ((argc == 2 && strcmp(argv[1], "-v") == 0) ||
43  (argc == 2 && strcmp(argv[1], "--version") == 0)) {
44  char *versionStrP;
45 
46  fprintf(stderr, "tesseract %s\n", tesseract::TessBaseAPI::Version());
47 
48  versionStrP = getLeptonicaVersion();
49  fprintf(stderr, " %s\n", versionStrP);
50  lept_free(versionStrP);
51 
52  versionStrP = getImagelibVersions();
53  fprintf(stderr, " %s\n", versionStrP);
54  lept_free(versionStrP);
55 
56 #ifdef USE_OPENCL
57  cl_platform_id platform;
58  cl_uint num_platforms;
59  cl_device_id devices[2];
60  cl_uint num_devices;
61  char info[256];
62  int i;
63 
64  fprintf(stderr, " OpenCL info:\n");
65  clGetPlatformIDs(1, &platform, &num_platforms);
66  fprintf(stderr, " Found %d platforms.\n", num_platforms);
67  clGetPlatformInfo(platform, CL_PLATFORM_NAME, 256, info, 0);
68  fprintf(stderr, " Platform name: %s.\n", info);
69  clGetPlatformInfo(platform, CL_PLATFORM_VERSION, 256, info, 0);
70  fprintf(stderr, " Version: %s.\n", info);
71  clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, 2, devices, &num_devices);
72  fprintf(stderr, " Found %d devices.\n", num_devices);
73  for (i = 0; i < num_devices; ++i) {
74  clGetDeviceInfo(devices[i], CL_DEVICE_NAME, 256, info, 0);
75  fprintf(stderr, " Device %d name: %s.\n", i+1, info);
76  }
77 #endif
78  exit(0);
79  }
80 
81  // Make the order of args a bit more forgiving than it used to be.
82  const char* lang = "eng";
83  const char* image = NULL;
84  const char* outputbase = NULL;
85  const char* datapath = NULL;
86  bool noocr = false;
87  bool list_langs = false;
88  bool print_parameters = false;
89  GenericVector<STRING> vars_vec, vars_values;
90 
92  int arg = 1;
93  while (arg < argc && (outputbase == NULL || argv[arg][0] == '-')) {
94  if (strcmp(argv[arg], "-l") == 0 && arg + 1 < argc) {
95  lang = argv[arg + 1];
96  ++arg;
97  } else if (strcmp(argv[arg], "--tessdata-dir") == 0 && arg + 1 < argc) {
98  datapath = argv[arg + 1];
99  ++arg;
100  } else if (strcmp(argv[arg], "--user-words") == 0 && arg + 1 < argc) {
101  vars_vec.push_back("user_words_file");
102  vars_values.push_back(argv[arg + 1]);
103  ++arg;
104  } else if (strcmp(argv[arg], "--user-patterns") == 0 && arg + 1 < argc) {
105  vars_vec.push_back("user_patterns_file");
106  vars_values.push_back(argv[arg + 1]);
107  ++arg;
108  } else if (strcmp(argv[arg], "--list-langs") == 0) {
109  noocr = true;
110  list_langs = true;
111  } else if (strcmp(argv[arg], "-psm") == 0 && arg + 1 < argc) {
112  pagesegmode = static_cast<tesseract::PageSegMode>(atoi(argv[arg + 1]));
113  ++arg;
114  } else if (strcmp(argv[arg], "--print-parameters") == 0) {
115  noocr = true;
116  print_parameters = true;
117  } else if (strcmp(argv[arg], "-c") == 0 && arg + 1 < argc) {
118  // handled properly after api init
119  ++arg;
120  } else if (image == NULL) {
121  image = argv[arg];
122  } else if (outputbase == NULL) {
123  outputbase = argv[arg];
124  }
125  ++arg;
126  }
127 
128  if (argc == 2 && strcmp(argv[1], "--list-langs") == 0) {
129  list_langs = true;
130  noocr = true;
131  }
132 
133  if (outputbase == NULL && noocr == false) {
134  fprintf(stderr, "Usage:\n %s imagename|stdin outputbase|stdout "
135  "[options...] [configfile...]\n\n", argv[0]);
136 
137  fprintf(stderr, "OCR options:\n");
138  fprintf(stderr, " --tessdata-dir /path\tspecify the location of tessdata"
139  " path\n");
140  fprintf(stderr, " --user-words /path/to/file\tspecify the location of user"
141  " words file\n");
142  fprintf(stderr, " --user-patterns /path/to/file\tspecify the location of"
143  " user patterns file\n");
144  fprintf(stderr, " -l lang[+lang]\tspecify language(s) used for OCR\n");
145  fprintf(stderr, " -c configvar=value\tset value for control parameter.\n"
146  "\t\t\tMultiple -c arguments are allowed.\n");
147  fprintf(stderr, " -psm pagesegmode\tspecify page segmentation mode.\n");
148  fprintf(stderr, "These options must occur before any configfile.\n\n");
149  fprintf(stderr,
150  "pagesegmode values are:\n"
151  " 0 = Orientation and script detection (OSD) only.\n"
152  " 1 = Automatic page segmentation with OSD.\n"
153  " 2 = Automatic page segmentation, but no OSD, or OCR\n"
154  " 3 = Fully automatic page segmentation, but no OSD. (Default)\n"
155  " 4 = Assume a single column of text of variable sizes.\n"
156  " 5 = Assume a single uniform block of vertically aligned text.\n"
157  " 6 = Assume a single uniform block of text.\n"
158  " 7 = Treat the image as a single text line.\n"
159  " 8 = Treat the image as a single word.\n"
160  " 9 = Treat the image as a single word in a circle.\n"
161  " 10 = Treat the image as a single character.\n\n");
162  fprintf(stderr, "Single options:\n");
163  fprintf(stderr, " -v --version: version info\n");
164  fprintf(stderr, " --list-langs: list available languages for tesseract "
165  "engine. Can be used with --tessdata-dir.\n");
166  fprintf(stderr, " --print-parameters: print tesseract parameters to the "
167  "stdout.\n");
168  exit(1);
169  }
170 
171  if (outputbase != NULL && strcmp(outputbase, "-") &&
172  strcmp(outputbase, "stdout")) {
173  tprintf("Tesseract Open Source OCR Engine v%s with Leptonica\n",
175  }
176  PERF_COUNT_START("Tesseract:main")
178 
179  api.SetOutputName(outputbase);
180  int rc = api.Init(datapath, lang, tesseract::OEM_DEFAULT,
181  &(argv[arg]), argc - arg, &vars_vec, &vars_values, false);
182 
183  if (rc) {
184  fprintf(stderr, "Could not initialize tesseract.\n");
185  exit(1);
186  }
187 
188  char opt1[255], opt2[255];
189  for (arg = 0; arg < argc; arg++) {
190  if (strcmp(argv[arg], "-c") == 0 && arg + 1 < argc) {
191  strncpy(opt1, argv[arg + 1], 255);
192  char *p = strchr(opt1, '=');
193  if (!p) {
194  fprintf(stderr, "Missing = in configvar assignment\n");
195  exit(1);
196  }
197  *p = 0;
198  strncpy(opt2, strchr(argv[arg + 1], '=') + 1, 255);
199  opt2[254] = 0;
200  ++arg;
201 
202  if (!api.SetVariable(opt1, opt2)) {
203  fprintf(stderr, "Could not set option: %s=%s\n", opt1, opt2);
204  }
205  }
206  }
207 
208  if (list_langs) {
209  GenericVector<STRING> languages;
210  api.GetAvailableLanguagesAsVector(&languages);
211  fprintf(stderr, "List of available languages (%d):\n",
212  languages.size());
213  for (int index = 0; index < languages.size(); ++index) {
214  STRING& string = languages[index];
215  fprintf(stderr, "%s\n", string.string());
216  }
217  api.End();
218  exit(0);
219  }
220 
221  if (print_parameters) {
222  FILE* fout = stdout;
223  fprintf(stdout, "Tesseract parameters:\n");
224  api.PrintVariables(fout);
225  api.End();
226  exit(0);
227  }
228 
229  // We have 2 possible sources of pagesegmode: a config file and
230  // the command line. For backwards compatability reasons, the
231  // default in tesseract is tesseract::PSM_SINGLE_BLOCK, but the
232  // default for this program is tesseract::PSM_AUTO. We will let
233  // the config file take priority, so the command-line default
234  // can take priority over the tesseract default, so we use the
235  // value from the command line only if the retrieved mode
236  // is still tesseract::PSM_SINGLE_BLOCK, indicating no change
237  // in any config file. Therefore the only way to force
238  // tesseract::PSM_SINGLE_BLOCK is from the command line.
239  // It would be simpler if we could set the value before Init,
240  // but that doesn't work.
241  if (api.GetPageSegMode() == tesseract::PSM_SINGLE_BLOCK)
242  api.SetPageSegMode(pagesegmode);
243 
244  if (pagesegmode == tesseract::PSM_AUTO_ONLY ||
245  pagesegmode == tesseract::PSM_OSD_ONLY) {
246  int ret_val = 0;
247 
248  Pix* pixs = pixRead(image);
249  if (!pixs) {
250  fprintf(stderr, "Cannot open input file: %s\n", image);
251  exit(2);
252  }
253  api.SetImage(pixs);
254 
255  if (pagesegmode == tesseract::PSM_OSD_ONLY) {
256  OSResults osr;
257  if (api.DetectOS(&osr)) {
258  int orient = osr.best_result.orientation_id;
259  int script_id = osr.get_best_script(orient);
260  float orient_oco = osr.best_result.oconfidence;
261  float orient_sco = osr.best_result.sconfidence;
262  tprintf("Orientation: %d\nOrientation in degrees: %d\n" \
263  "Orientation confidence: %.2f\n" \
264  "Script: %d\nScript confidence: %.2f\n",
265  orient, OrientationIdToValue(orient), orient_oco,
266  script_id, orient_sco);
267  } else {
268  ret_val = 1;
269  }
270  } else {
271  tesseract::Orientation orientation;
274  float deskew_angle;
275  tesseract::PageIterator* it = api.AnalyseLayout();
276  if (it) {
277  it->Orientation(&orientation, &direction, &order, &deskew_angle);
278  tprintf("Orientation: %d\nWritingDirection: %d\nTextlineOrder: %d\n" \
279  "Deskew angle: %.4f\n",
280  orientation, direction, order, deskew_angle);
281  } else {
282  ret_val = 1;
283  }
284  delete it;
285  }
286  pixDestroy(&pixs);
287  exit(ret_val);
288  }
289 
290  bool b;
292  api.GetBoolVariable("tessedit_create_hocr", &b);
293  if (b) {
294  bool font_info;
295  api.GetBoolVariable("hocr_font_info", &font_info);
296  renderers.push_back(new tesseract::TessHOcrRenderer(outputbase, font_info));
297  }
298  api.GetBoolVariable("tessedit_create_pdf", &b);
299  if (b) {
300  renderers.push_back(new tesseract::TessPDFRenderer(outputbase,
301  api.GetDatapath()));
302  }
303  api.GetBoolVariable("tessedit_write_unlv", &b);
304  if (b) renderers.push_back(new tesseract::TessUnlvRenderer(outputbase));
305  api.GetBoolVariable("tessedit_create_boxfile", &b);
306  if (b) renderers.push_back(new tesseract::TessBoxTextRenderer(outputbase));
307  api.GetBoolVariable("tessedit_create_txt", &b);
308  if (b) renderers.push_back(new tesseract::TessTextRenderer(outputbase));
309  if (!renderers.empty()) {
310  // Since the PointerVector auto-deletes, null-out the renderers that are
311  // added to the root, and leave the root in the vector.
312  for (int r = 1; r < renderers.size(); ++r) {
313  renderers[0]->insert(renderers[r]);
314  renderers[r] = NULL;
315  }
316  if (!api.ProcessPages(image, NULL, 0, renderers[0])) {
317  fprintf(stderr, "Error during processing.\n");
318  exit(1);
319  }
320  }
321 
323  return 0; // Normal exit
324 }
Assume a single uniform block of text. (Default.)
Definition: publictypes.h:160
static const char * Version()
Definition: baseapi.cpp:142
int size() const
Definition: genericvector.h:72
Fully automatic page segmentation, but no OSD.
Definition: publictypes.h:156
int push_back(T object)
Orientation and script detection only.
Definition: publictypes.h:152
#define tprintf(...)
Definition: tprintf.h:31
int direction(EDGEPT *point)
Definition: vecfuncs.cpp:43
float sconfidence
Definition: osdetect.h:43
struct TessBaseAPI TessBaseAPI
Definition: capi.h:67
int orientation_id
Definition: osdetect.h:41
float oconfidence
Definition: osdetect.h:44
void insert(T *t, int index)
#define PERF_COUNT_END
const int OrientationIdToValue(const int &id)
Definition: osdetect.cpp:563
bool empty() const
Definition: genericvector.h:84
TESS_API int get_best_script(int orientation_id) const
Definition: osdetect.cpp:117
#define PERF_COUNT_START(FUNCT_NAME)
Automatic page segmentation, but no OSD, or OCR.
Definition: publictypes.h:155
void Orientation(tesseract::Orientation *orientation, tesseract::WritingDirection *writing_direction, tesseract::TextlineOrder *textline_order, float *deskew_angle) const
Definition: strngs.h:44
#define NULL
Definition: host.h:144
OSBestResult best_result
Definition: osdetect.h:79
int main ( int  argc,
char *  argv[] 
)

Public Code

Definition at line 89 of file cntraining.cpp.

142 {
143  // Set the global Config parameters before parsing the command line.
144  Config = CNConfig;
145 
146  const char *PageName;
147  FILE *TrainingPage;
148  LIST CharList = NIL_LIST;
149  CLUSTERER *Clusterer = NULL;
150  LIST ProtoList = NIL_LIST;
151  LIST NormProtoList = NIL_LIST;
152  LIST pCharList;
153  LABELEDLIST CharSample;
154  FEATURE_DEFS_STRUCT FeatureDefs;
155  InitFeatureDefs(&FeatureDefs);
156 
157  ParseArguments(&argc, &argv);
158  int num_fonts = 0;
159  while ((PageName = GetNextFilename(argc, argv)) != NULL) {
160  printf("Reading %s ...\n", PageName);
161  TrainingPage = Efopen(PageName, "rb");
163  100, NULL, TrainingPage, &CharList);
164  fclose(TrainingPage);
165  ++num_fonts;
166  }
167  printf("Clustering ...\n");
168  // To allow an individual font to form a separate cluster,
169  // reduce the min samples:
170  // Config.MinSamples = 0.5 / num_fonts;
171  pCharList = CharList;
172  iterate(pCharList) {
173  //Cluster
174  CharSample = (LABELEDLIST)first_node(pCharList);
175  Clusterer =
176  SetUpForClustering(FeatureDefs, CharSample, PROGRAM_FEATURE_TYPE);
177  float SavedMinSamples = Config.MinSamples;
178  // To disable the tendency to produce a single cluster for all fonts,
179  // make MagicSamples an impossible to achieve number:
180  // Config.MagicSamples = CharSample->SampleCount * 10;
181  Config.MagicSamples = CharSample->SampleCount;
182  while (Config.MinSamples > 0.001) {
183  ProtoList = ClusterSamples(Clusterer, &Config);
184  if (NumberOfProtos(ProtoList, 1, 0) > 0) {
185  break;
186  } else {
187  Config.MinSamples *= 0.95;
188  printf("0 significant protos for %s."
189  " Retrying clustering with MinSamples = %f%%\n",
190  CharSample->Label, Config.MinSamples);
191  }
192  }
193  Config.MinSamples = SavedMinSamples;
194  AddToNormProtosList(&NormProtoList, ProtoList, CharSample->Label);
195  }
196  FreeTrainingSamples(CharList);
197  if (Clusterer == NULL) { // To avoid a SIGSEGV
198  fprintf(stderr, "Error: NULL clusterer!\n");
199  return 1;
200  }
201  WriteNormProtos(FLAGS_D.c_str(), NormProtoList, Clusterer);
202  FreeNormProtoList(NormProtoList);
203  FreeProtoList(&ProtoList);
204  FreeClusterer(Clusterer);
205  printf ("\n");
206  return 0;
207 } // main
void WriteNormProtos(const char *Directory, LIST LabeledProtoList, CLUSTERER *Clusterer)
Definition: cntraining.cpp:215
#define first_node(l)
Definition: oldlist.h:139
CLUSTERER * SetUpForClustering(const FEATURE_DEFS_STRUCT &FeatureDefs, LABELEDLIST char_sample, const char *program_feature_type)
void InitFeatureDefs(FEATURE_DEFS_STRUCT *featuredefs)
Definition: featdefs.cpp:121
struct LABELEDLISTNODE * LABELEDLIST
void ParseArguments(int *argc, char ***argv)
#define iterate(l)
Definition: oldlist.h:159
CLUSTERCONFIG Config
void ReadTrainingSamples(const FEATURE_DEFS_STRUCT &feature_defs, const char *feature_name, int max_samples, UNICHARSET *unicharset, FILE *file, LIST *training_samples)
void FreeNormProtoList(LIST CharList)
void FreeTrainingSamples(LIST CharList)
int MagicSamples
Definition: cluster.h:55
#define PROGRAM_FEATURE_TYPE
Definition: cntraining.cpp:41
LIST ClusterSamples(CLUSTERER *Clusterer, CLUSTERCONFIG *Config)
Definition: cluster.cpp:508
FILE * Efopen(const char *Name, const char *Mode)
Definition: efio.cpp:32
void FreeProtoList(LIST *ProtoList)
Definition: cluster.cpp:564
void AddToNormProtosList(LIST *NormProtoList, LIST ProtoList, char *CharName)
FLOAT32 MinSamples
Definition: cluster.h:50
#define NIL_LIST
Definition: oldlist.h:126
void FreeClusterer(CLUSTERER *Clusterer)
Definition: cluster.cpp:536
CLUSTERCONFIG CNConfig
Definition: cntraining.cpp:79
#define NULL
Definition: host.h:144
int NumberOfProtos(LIST ProtoList, BOOL8 CountSigProtos, BOOL8 CountInsigProtos)
const char * GetNextFilename(int argc, const char *const *argv)
void WriteNormProtos ( const char *  Directory,
LIST  LabeledProtoList,
CLUSTERER Clusterer 
)

Private Function Prototypes


Private Code

Definition at line 215 of file cntraining.cpp.

232 {
233  FILE *File;
234  STRING Filename;
235  LABELEDLIST LabeledProto;
236  int N;
237 
238  Filename = "";
239  if (Directory != NULL && Directory[0] != '\0')
240  {
241  Filename += Directory;
242  Filename += "/";
243  }
244  Filename += "normproto";
245  printf ("\nWriting %s ...", Filename.string());
246  File = Efopen (Filename.string(), "wb");
247  fprintf(File,"%0d\n",Clusterer->SampleSize);
248  WriteParamDesc(File,Clusterer->SampleSize,Clusterer->ParamDesc);
249  iterate(LabeledProtoList)
250  {
251  LabeledProto = (LABELEDLIST) first_node (LabeledProtoList);
252  N = NumberOfProtos(LabeledProto->List, true, false);
253  if (N < 1) {
254  printf ("\nError! Not enough protos for %s: %d protos"
255  " (%d significant protos"
256  ", %d insignificant protos)\n",
257  LabeledProto->Label, N,
258  NumberOfProtos(LabeledProto->List, 1, 0),
259  NumberOfProtos(LabeledProto->List, 0, 1));
260  exit(1);
261  }
262  fprintf(File, "\n%s %d\n", LabeledProto->Label, N);
263  WriteProtos(File, Clusterer->SampleSize, LabeledProto->List, true, false);
264  }
265  fclose (File);
266 
267 } // WriteNormProtos
#define first_node(l)
Definition: oldlist.h:139
struct LABELEDLISTNODE * LABELEDLIST
#define iterate(l)
Definition: oldlist.h:159
void WriteProtos(FILE *File, uinT16 N, LIST ProtoList, BOOL8 WriteSigProtos, BOOL8 WriteInsigProtos)
Definition: cntraining.cpp:270
FILE * Efopen(const char *Name, const char *Mode)
Definition: efio.cpp:32
PARAM_DESC * ParamDesc
Definition: cluster.h:88
Definition: strngs.h:44
#define NULL
Definition: host.h:144
const char * string() const
Definition: strngs.cpp:193
inT16 SampleSize
Definition: cluster.h:87
int NumberOfProtos(LIST ProtoList, BOOL8 CountSigProtos, BOOL8 CountInsigProtos)
void WriteParamDesc(FILE *File, uinT16 N, PARAM_DESC ParamDesc[])
Definition: clusttool.cpp:318
void WriteProtos ( FILE *  File,
uinT16  N,
LIST  ProtoList,
BOOL8  WriteSigProtos,
BOOL8  WriteInsigProtos 
)

Definition at line 270 of file cntraining.cpp.

276 {
277  PROTOTYPE *Proto;
278 
279  // write prototypes
280  iterate(ProtoList)
281  {
282  Proto = (PROTOTYPE *) first_node ( ProtoList );
283  if (( Proto->Significant && WriteSigProtos ) ||
284  ( ! Proto->Significant && WriteInsigProtos ) )
285  WritePrototype( File, N, Proto );
286  }
287 } // WriteProtos
void WritePrototype(FILE *File, uinT16 N, PROTOTYPE *Proto)
Definition: clusttool.cpp:348
#define first_node(l)
Definition: oldlist.h:139
#define iterate(l)
Definition: oldlist.h:159
unsigned Significant
Definition: cluster.h:68

Variable Documentation

CLUSTERCONFIG CNConfig
Initial value:
=
{
elliptical, 0.025, 0.05, 0.8, 1e-3, 0
}

Global Data Definitions and Declarations

Definition at line 79 of file cntraining.cpp.