tesseract  4.00.00dev
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, const FEATURE_DESC_STRUCT *feature_desc)
 
void WriteProtos (FILE *File, uinT16 N, LIST ProtoList, BOOL8 WriteSigProtos, BOOL8 WriteInsigProtos)
 
int main (int argc, char *argv[])
 

Variables

CLUSTERCONFIG CNConfig
 

Macro Definition Documentation

◆ PROGRAM_FEATURE_TYPE

#define PROGRAM_FEATURE_TYPE   "cn"

Definition at line 40 of file cntraining.cpp.

Function Documentation

◆ DECLARE_STRING_PARAM_FLAG()

DECLARE_STRING_PARAM_FLAG ( )

◆ main() [1/2]

int main ( int  argc,
char **  argv 
)

This program reads in a text file consisting of feature samples from a training page in the following format:

   FontName UTF8-char-str xmin ymin xmax ymax page-number
    NumberOfFeatureTypes(N)
      FeatureTypeName1 NumberOfFeatures(M)
         Feature1
         ...
         FeatureM
      FeatureTypeName2 NumberOfFeatures(M)
         Feature1
         ...
         FeatureM
      ...
      FeatureTypeNameN NumberOfFeatures(M)
         Feature1
         ...
         FeatureM
   FontName CharName ...

The result of this program is a binary inttemp file used by the OCR engine.

Parameters
argcnumber of command line arguments
argvarray of command line arguments
Returns
none
Note
Exceptions: none
History: Fri Aug 18 08:56:17 1989, DSJ, Created.
History: Mon May 18 1998, Christy Russson, Revistion started.

Definition at line 391 of file tesseractmain.cpp.

391  {
392  const char* lang = "eng";
393  const char* image = NULL;
394  const char* outputbase = NULL;
395  const char* datapath = NULL;
396  bool list_langs = false;
397  bool print_parameters = false;
398  int arg_i = 1;
401  /* main() calls functions like ParseArgs which call exit().
402  * This results in memory leaks if vars_vec and vars_values are
403  * declared as auto variables (destructor is not called then). */
404  static GenericVector<STRING> vars_vec;
405  static GenericVector<STRING> vars_values;
406 
407 #ifdef NDEBUG
408  // Disable debugging and informational messages from Leptonica.
409  setMsgSeverity(L_SEVERITY_ERROR);
410 #endif
411 
412 #if defined(HAVE_TIFFIO_H) && defined(_WIN32)
413  /* Show libtiff warnings on console (not in GUI). */
414  TIFFSetWarningHandler(Win32WarningHandler);
415 #endif /* HAVE_TIFFIO_H && _WIN32 */
416 
417  ParseArgs(argc, argv, &lang, &image, &outputbase, &datapath, &list_langs,
418  &print_parameters, &vars_vec, &vars_values, &arg_i, &pagesegmode,
419  &enginemode);
420 
421  bool banner = false;
422  if (outputbase != NULL && strcmp(outputbase, "-") &&
423  strcmp(outputbase, "stdout")) {
424  banner = true;
425  }
426 
427  PERF_COUNT_START("Tesseract:main")
428 
429  // Call GlobalDawgCache here to create the global DawgCache object before
430  // the TessBaseAPI object. This fixes the order of destructor calls:
431  // first TessBaseAPI must be destructed, DawgCache must be the last object.
432  tesseract::Dict::GlobalDawgCache();
433 
434  // Avoid memory leak caused by auto variable when exit() is called.
435  static tesseract::TessBaseAPI api;
436 
437  api.SetOutputName(outputbase);
438 
439  int init_failed = api.Init(datapath, lang, enginemode, &(argv[arg_i]),
440  argc - arg_i, &vars_vec, &vars_values, false);
441  if (init_failed) {
442  fprintf(stderr, "Could not initialize tesseract.\n");
443  return EXIT_FAILURE;
444  }
445 
446  SetVariablesFromCLArgs(&api, argc, argv);
447 
448  if (list_langs) {
450  return EXIT_SUCCESS;
451  }
452 
453  if (print_parameters) {
454  FILE* fout = stdout;
455  fprintf(stdout, "Tesseract parameters:\n");
456  api.PrintVariables(fout);
457  api.End();
458  return EXIT_SUCCESS;
459  }
460 
461  FixPageSegMode(&api, pagesegmode);
462 
463  if (pagesegmode == tesseract::PSM_AUTO_ONLY) {
464  int ret_val = EXIT_SUCCESS;
465 
466  Pix* pixs = pixRead(image);
467  if (!pixs) {
468  fprintf(stderr, "Cannot open input file: %s\n", image);
469  return 2;
470  }
471 
472  api.SetImage(pixs);
473 
474  tesseract::Orientation orientation;
477  float deskew_angle;
478 
479  tesseract::PageIterator* it = api.AnalyseLayout();
480  if (it) {
481  it->Orientation(&orientation, &direction, &order, &deskew_angle);
482  tprintf(
483  "Orientation: %d\nWritingDirection: %d\nTextlineOrder: %d\n"
484  "Deskew angle: %.4f\n",
485  orientation, direction, order, deskew_angle);
486  } else {
487  ret_val = EXIT_FAILURE;
488  }
489 
490  delete it;
491 
492  pixDestroy(&pixs);
493  return ret_val;
494  }
495 
496  // set in_training_mode to true when using one of these configs:
497  // ambigs.train, box.train, box.train.stderr, linebox, rebox
498  bool b = false;
499  bool in_training_mode =
500  (api.GetBoolVariable("tessedit_ambigs_training", &b) && b) ||
501  (api.GetBoolVariable("tessedit_resegment_from_boxes", &b) && b) ||
502  (api.GetBoolVariable("tessedit_make_boxes_from_boxes", &b) && b);
503 
504  // Avoid memory leak caused by auto variable when exit() is called.
506 
507  if (in_training_mode) {
508  renderers.push_back(NULL);
509  } else {
510  PreloadRenderers(&api, &renderers, pagesegmode, outputbase);
511  }
512 
513  if (!renderers.empty()) {
514  if (banner) PrintBanner();
515  bool succeed = api.ProcessPages(image, NULL, 0, renderers[0]);
516  if (!succeed) {
517  fprintf(stderr, "Error during processing.\n");
518  return EXIT_FAILURE;
519  }
520  }
521 
523 
524  return EXIT_SUCCESS;
525 }
void PrintLangsList(tesseract::TessBaseAPI *api)
#define PERF_COUNT_START(FUNCT_NAME)
void PreloadRenderers(tesseract::TessBaseAPI *api, tesseract::PointerVector< tesseract::TessResultRenderer > *renderers, tesseract::PageSegMode pagesegmode, const char *outputbase)
struct TessBaseAPI TessBaseAPI
Definition: capi.h:83
void SetVariablesFromCLArgs(tesseract::TessBaseAPI *api, int argc, char **argv)
int push_back(T * object)
#define tprintf(...)
Definition: tprintf.h:31
int direction(EDGEPT *point)
Definition: vecfuncs.cpp:43
bool empty() const
Definition: genericvector.h:90
Automatic page segmentation, but no OSD, or OCR.
Definition: publictypes.h:155
void FixPageSegMode(tesseract::TessBaseAPI *api, tesseract::PageSegMode pagesegmode)
void PrintBanner()
#define PERF_COUNT_END
Fully automatic page segmentation, but no OSD.
Definition: publictypes.h:156
void Orientation(tesseract::Orientation *orientation, tesseract::WritingDirection *writing_direction, tesseract::TextlineOrder *textline_order, float *deskew_angle) const
void ParseArgs(const int argc, char **argv, const char **lang, const char **image, const char **outputbase, const char **datapath, bool *list_langs, bool *print_parameters, GenericVector< STRING > *vars_vec, GenericVector< STRING > *vars_values, int *arg_i, tesseract::PageSegMode *pagesegmode, tesseract::OcrEngineMode *enginemode)

◆ main() [2/2]

int main ( int  argc,
char *  argv[] 
)

This program reads in a text file consisting of feature samples from a training page in the following format:

   FontName CharName NumberOfFeatureTypes(N)
      FeatureTypeName1 NumberOfFeatures(M)
         Feature1
         ...
         FeatureM
      FeatureTypeName2 NumberOfFeatures(M)
         Feature1
         ...
         FeatureM
      ...
      FeatureTypeNameN NumberOfFeatures(M)
         Feature1
         ...
         FeatureM
   FontName CharName ...

It then appends these samples into a separate file for each character. The name of the file is

DirectoryName/FontName/CharName.FeatureTypeName

The DirectoryName can be specified via a command line argument. If not specified, it defaults to the current directory. The format of the resulting files is:

   NumberOfFeatures(M)
      Feature1
      ...
      FeatureM
   NumberOfFeatures(M)
   ...

The output files each have a header which describes the type of feature which the file contains. This header is in the format required by the clusterer. A command line argument can also be used to specify that only the first N samples of each class should be used.

Parameters
argcnumber of command line arguments
argvarray of command line arguments
Returns
none
Note
Globals: none
Exceptions: none
History: Fri Aug 18 08:56:17 1989, DSJ, Created.

Definition at line 133 of file cntraining.cpp.

133  {
134  // Set the global Config parameters before parsing the command line.
135  Config = CNConfig;
136 
137  const char *PageName;
138  FILE *TrainingPage;
139  LIST CharList = NIL_LIST;
140  CLUSTERER *Clusterer = nullptr;
141  LIST ProtoList = NIL_LIST;
142  LIST NormProtoList = NIL_LIST;
143  LIST pCharList;
144  LABELEDLIST CharSample;
145  FEATURE_DEFS_STRUCT FeatureDefs;
146  InitFeatureDefs(&FeatureDefs);
147 
148  ParseArguments(&argc, &argv);
149  int num_fonts = 0;
150  while ((PageName = GetNextFilename(argc, argv)) != nullptr) {
151  printf("Reading %s ...\n", PageName);
152  TrainingPage = Efopen(PageName, "rb");
153  ReadTrainingSamples(FeatureDefs, PROGRAM_FEATURE_TYPE, 100, nullptr,
154  TrainingPage, &CharList);
155  fclose(TrainingPage);
156  ++num_fonts;
157  }
158  printf("Clustering ...\n");
159  // To allow an individual font to form a separate cluster,
160  // reduce the min samples:
161  // Config.MinSamples = 0.5 / num_fonts;
162  pCharList = CharList;
163  // The norm protos will count the source protos, so we keep them here in
164  // freeable_protos, so they can be freed later.
165  GenericVector<LIST> freeable_protos;
166  iterate(pCharList) {
167  //Cluster
168  CharSample = (LABELEDLIST)first_node(pCharList);
169  Clusterer =
170  SetUpForClustering(FeatureDefs, CharSample, PROGRAM_FEATURE_TYPE);
171  if (Clusterer == nullptr) { // To avoid a SIGSEGV
172  fprintf(stderr, "Error: NULL clusterer!\n");
173  return 1;
174  }
175  float SavedMinSamples = Config.MinSamples;
176  // To disable the tendency to produce a single cluster for all fonts,
177  // make MagicSamples an impossible to achieve number:
178  // Config.MagicSamples = CharSample->SampleCount * 10;
179  Config.MagicSamples = CharSample->SampleCount;
180  while (Config.MinSamples > 0.001) {
181  ProtoList = ClusterSamples(Clusterer, &Config);
182  if (NumberOfProtos(ProtoList, 1, 0) > 0) {
183  break;
184  } else {
185  Config.MinSamples *= 0.95;
186  printf("0 significant protos for %s."
187  " Retrying clustering with MinSamples = %f%%\n",
188  CharSample->Label, Config.MinSamples);
189  }
190  }
191  Config.MinSamples = SavedMinSamples;
192  AddToNormProtosList(&NormProtoList, ProtoList, CharSample->Label);
193  freeable_protos.push_back(ProtoList);
194  FreeClusterer(Clusterer);
195  }
196  FreeTrainingSamples(CharList);
197  int desc_index = ShortNameToFeatureType(FeatureDefs, PROGRAM_FEATURE_TYPE);
198  WriteNormProtos(FLAGS_D.c_str(), NormProtoList,
199  FeatureDefs.FeatureDesc[desc_index]);
200  FreeNormProtoList(NormProtoList);
201  for (int i = 0; i < freeable_protos.size(); ++i) {
202  FreeProtoList(&freeable_protos[i]);
203  }
204  printf ("\n");
205  return 0;
206 } // main
void InitFeatureDefs(FEATURE_DEFS_STRUCT *featuredefs)
Definition: featdefs.cpp:121
void AddToNormProtosList(LIST *NormProtoList, LIST ProtoList, char *CharName)
#define PROGRAM_FEATURE_TYPE
Definition: cntraining.cpp:40
void FreeNormProtoList(LIST CharList)
int push_back(T object)
LIST ClusterSamples(CLUSTERER *Clusterer, CLUSTERCONFIG *Config)
Definition: cluster.cpp:512
FLOAT32 MinSamples
Definition: cluster.h:50
struct LABELEDLISTNODE * LABELEDLIST
void ParseArguments(int *argc, char ***argv)
#define NIL_LIST
Definition: oldlist.h:126
CLUSTERCONFIG Config
int size() const
Definition: genericvector.h:72
int MagicSamples
Definition: cluster.h:55
void WriteNormProtos(const char *Directory, LIST LabeledProtoList, const FEATURE_DESC_STRUCT *feature_desc)
Definition: cntraining.cpp:224
CLUSTERER * SetUpForClustering(const FEATURE_DEFS_STRUCT &FeatureDefs, LABELEDLIST char_sample, const char *program_feature_type)
void FreeProtoList(LIST *ProtoList)
Definition: cluster.cpp:573
const char * GetNextFilename(int argc, const char *const *argv)
const FEATURE_DESC_STRUCT * FeatureDesc[NUM_FEATURE_TYPES]
Definition: featdefs.h:50
#define first_node(l)
Definition: oldlist.h:139
int ShortNameToFeatureType(const FEATURE_DEFS_STRUCT &FeatureDefs, const char *ShortName)
Definition: featdefs.cpp:297
void FreeClusterer(CLUSTERER *Clusterer)
Definition: cluster.cpp:546
FILE * Efopen(const char *Name, const char *Mode)
Definition: efio.cpp:43
void ReadTrainingSamples(const FEATURE_DEFS_STRUCT &feature_defs, const char *feature_name, int max_samples, UNICHARSET *unicharset, FILE *file, LIST *training_samples)
int NumberOfProtos(LIST ProtoList, BOOL8 CountSigProtos, BOOL8 CountInsigProtos)
#define iterate(l)
Definition: oldlist.h:159
CLUSTERCONFIG CNConfig
Definition: cntraining.cpp:76
void FreeTrainingSamples(LIST CharList)

◆ WriteNormProtos()

void WriteNormProtos ( const char *  Directory,
LIST  LabeledProtoList,
const FEATURE_DESC_STRUCT feature_desc 
)

This routine writes the specified samples into files which are organized according to the font name and character name of the samples.

Parameters
Directorydirectory to place sample files into
LabeledProtoListList of labeled protos
feature_descDescription of the features
Returns
none
Note
Exceptions: none
History: Fri Aug 18 16:17:06 1989, DSJ, Created.

Definition at line 224 of file cntraining.cpp.

225  {
226  FILE *File;
227  STRING Filename;
228  LABELEDLIST LabeledProto;
229  int N;
230 
231  Filename = "";
232  if (Directory != nullptr && Directory[0] != '\0') {
233  Filename += Directory;
234  Filename += "/";
235  }
236  Filename += "normproto";
237  printf ("\nWriting %s ...", Filename.string());
238  File = Efopen (Filename.string(), "wb");
239  fprintf(File, "%0d\n", feature_desc->NumParams);
240  WriteParamDesc(File, feature_desc->NumParams, feature_desc->ParamDesc);
241  iterate(LabeledProtoList)
242  {
243  LabeledProto = (LABELEDLIST) first_node (LabeledProtoList);
244  N = NumberOfProtos(LabeledProto->List, true, false);
245  if (N < 1) {
246  printf ("\nError! Not enough protos for %s: %d protos"
247  " (%d significant protos"
248  ", %d insignificant protos)\n",
249  LabeledProto->Label, N,
250  NumberOfProtos(LabeledProto->List, 1, 0),
251  NumberOfProtos(LabeledProto->List, 0, 1));
252  exit(1);
253  }
254  fprintf(File, "\n%s %d\n", LabeledProto->Label, N);
255  WriteProtos(File, feature_desc->NumParams, LabeledProto->List, true, false);
256  }
257  fclose (File);
258 
259 } // WriteNormProtos
void WriteParamDesc(FILE *File, uinT16 N, const PARAM_DESC ParamDesc[])
Definition: clusttool.cpp:259
const PARAM_DESC * ParamDesc
Definition: ocrfeatures.h:59
const char * string() const
Definition: strngs.cpp:198
struct LABELEDLISTNODE * LABELEDLIST
void WriteProtos(FILE *File, uinT16 N, LIST ProtoList, BOOL8 WriteSigProtos, BOOL8 WriteInsigProtos)
Definition: cntraining.cpp:262
Definition: strngs.h:45
#define first_node(l)
Definition: oldlist.h:139
FILE * Efopen(const char *Name, const char *Mode)
Definition: efio.cpp:43
int NumberOfProtos(LIST ProtoList, BOOL8 CountSigProtos, BOOL8 CountInsigProtos)
#define iterate(l)
Definition: oldlist.h:159

◆ WriteProtos()

void WriteProtos ( FILE *  File,
uinT16  N,
LIST  ProtoList,
BOOL8  WriteSigProtos,
BOOL8  WriteInsigProtos 
)

Definition at line 262 of file cntraining.cpp.

268 {
269  PROTOTYPE *Proto;
270 
271  // write prototypes
272  iterate(ProtoList)
273  {
274  Proto = (PROTOTYPE *) first_node ( ProtoList );
275  if (( Proto->Significant && WriteSigProtos ) ||
276  ( ! Proto->Significant && WriteInsigProtos ) )
277  WritePrototype( File, N, Proto );
278  }
279 } // WriteProtos
void WritePrototype(FILE *File, uinT16 N, PROTOTYPE *Proto)
Definition: clusttool.cpp:288
#define first_node(l)
Definition: oldlist.h:139
unsigned Significant
Definition: cluster.h:68
#define iterate(l)
Definition: oldlist.h:159

Variable Documentation

◆ CNConfig

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

Definition at line 76 of file cntraining.cpp.