tesseract
3.03
|
#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.
Defines | |
#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 |
#define PROGRAM_FEATURE_TYPE "cn" |
---------------------------------------------------------------------------- Include Files and Type Defines ----------------------------------------------------------------------------
Definition at line 41 of file cntraining.cpp.
int main | ( | int | argc, |
char ** | argv | ||
) |
---------------------------------------------------------------------------- Public Function Prototypes ----------------------------------------------------------------------------
Definition at line 45 of file tesseractmain.cpp.
{ if ((argc == 2 && strcmp(argv[1], "-v") == 0) || (argc == 2 && strcmp(argv[1], "--version") == 0)) { char *versionStrP; fprintf(stderr, "tesseract %s\n", tesseract::TessBaseAPI::Version()); versionStrP = getLeptonicaVersion(); fprintf(stderr, " %s\n", versionStrP); lept_free(versionStrP); versionStrP = getImagelibVersions(); fprintf(stderr, " %s\n", versionStrP); lept_free(versionStrP); #ifdef USE_OPENCL cl_platform_id platform; cl_uint num_platforms; cl_device_id devices[2]; cl_uint num_devices; char info[256]; int i; fprintf(stderr, " OpenCL info:\n"); clGetPlatformIDs(1, &platform, &num_platforms); fprintf(stderr, " Found %d platforms.\n", num_platforms); clGetPlatformInfo(platform, CL_PLATFORM_NAME, 256, info, 0); fprintf(stderr, " Platform name: %s.\n", info); clGetPlatformInfo(platform, CL_PLATFORM_VERSION, 256, info, 0); fprintf(stderr, " Version: %s.\n", info); clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, 2, devices, &num_devices); fprintf(stderr, " Found %d devices.\n", num_devices); for (i = 0; i < num_devices; ++i) { clGetDeviceInfo(devices[i], CL_DEVICE_NAME, 256, info, 0); fprintf(stderr, " Device %d name: %s.\n", i+1, info); } #endif exit(0); } // Make the order of args a bit more forgiving than it used to be. const char* lang = "eng"; const char* image = NULL; const char* output = NULL; const char* datapath = NULL; bool noocr = false; bool list_langs = false; bool print_parameters = false; tesseract::PageSegMode pagesegmode = tesseract::PSM_AUTO; int arg = 1; while (arg < argc && (output == NULL || argv[arg][0] == '-')) { if (strcmp(argv[arg], "-l") == 0 && arg + 1 < argc) { lang = argv[arg + 1]; ++arg; } else if (strcmp(argv[arg], "--tessdata-dir") == 0 && arg + 1 < argc) { datapath = argv[arg + 1]; ++arg; } else if (strcmp(argv[arg], "--list-langs") == 0) { noocr = true; list_langs = true; } else if (strcmp(argv[arg], "-psm") == 0 && arg + 1 < argc) { pagesegmode = static_cast<tesseract::PageSegMode>(atoi(argv[arg + 1])); ++arg; } else if (strcmp(argv[arg], "--print-parameters") == 0) { noocr = true; print_parameters = true; } else if (strcmp(argv[arg], "-c") == 0 && arg + 1 < argc) { // handled properly after api init ++arg; } else if (image == NULL) { image = argv[arg]; } else if (output == NULL) { output = argv[arg]; } ++arg; } if (argc == 2 && strcmp(argv[1], "--list-langs") == 0) { list_langs = true; noocr = true; } if (output == NULL && noocr == false) { fprintf(stderr, "Usage:\n %s imagename|stdin outputbase|stdout " "[options...] [configfile...]\n\n", argv[0]); fprintf(stderr, "OCR options:\n"); fprintf(stderr, " --tessdata-dir /path\tspecify location of tessdata" " path\n"); fprintf(stderr, " -l lang[+lang]\tspecify language(s) used for OCR\n"); fprintf(stderr, " -c configvar=value\tset value for control parameter.\n" "\t\t\tMultiple -c arguments are allowed.\n"); fprintf(stderr, " -psm pagesegmode\tspecify page segmentation mode.\n"); fprintf(stderr, "These options must occur before any configfile.\n\n"); fprintf(stderr, "pagesegmode values are:\n" " 0 = Orientation and script detection (OSD) only.\n" " 1 = Automatic page segmentation with OSD.\n" " 2 = Automatic page segmentation, but no OSD, or OCR\n" " 3 = Fully automatic page segmentation, but no OSD. (Default)\n" " 4 = Assume a single column of text of variable sizes.\n" " 5 = Assume a single uniform block of vertically aligned text.\n" " 6 = Assume a single uniform block of text.\n" " 7 = Treat the image as a single text line.\n" " 8 = Treat the image as a single word.\n" " 9 = Treat the image as a single word in a circle.\n" " 10 = Treat the image as a single character.\n\n"); fprintf(stderr, "Single options:\n"); fprintf(stderr, " -v --version: version info\n"); fprintf(stderr, " --list-langs: list available languages for tesseract " "engine. Can be used with --tessdata-dir.\n"); fprintf(stderr, " --print-parameters: print tesseract parameters to the " "stdout.\n"); exit(1); } if (output != NULL && strcmp(output, "-") && strcmp(output, "stdout")) { tprintf("Tesseract Open Source OCR Engine v%s with Leptonica\n", tesseract::TessBaseAPI::Version()); } PERF_COUNT_START("Tesseract:main") tesseract::TessBaseAPI api; api.SetOutputName(output); int rc = api.Init(datapath, lang, tesseract::OEM_DEFAULT, &(argv[arg]), argc - arg, NULL, NULL, false); if (rc) { fprintf(stderr, "Could not initialize tesseract.\n"); exit(1); } char opt1[255], opt2[255]; for (arg = 0; arg < argc; arg++) { if (strcmp(argv[arg], "-c") == 0 && arg + 1 < argc) { strncpy(opt1, argv[arg + 1], 255); *(strchr(opt1, '=')) = 0; strncpy(opt2, strchr(argv[arg + 1], '=') + 1, 255); opt2[254] = 0; ++arg; if (!api.SetVariable(opt1, opt2)) { fprintf(stderr, "Could not set option: %s=%s\n", opt1, opt2); } } } if (list_langs) { GenericVector<STRING> languages; api.GetAvailableLanguagesAsVector(&languages); fprintf(stderr, "List of available languages (%d):\n", languages.size()); for (int index = 0; index < languages.size(); ++index) { STRING& string = languages[index]; fprintf(stderr, "%s\n", string.string()); } api.End(); exit(0); } if (print_parameters) { FILE* fout = stdout; fprintf(stdout, "Tesseract parameters:\n"); api.PrintVariables(fout); api.End(); exit(0); } // We have 2 possible sources of pagesegmode: a config file and // the command line. For backwards compatability reasons, the // default in tesseract is tesseract::PSM_SINGLE_BLOCK, but the // default for this program is tesseract::PSM_AUTO. We will let // the config file take priority, so the command-line default // can take priority over the tesseract default, so we use the // value from the command line only if the retrieved mode // is still tesseract::PSM_SINGLE_BLOCK, indicating no change // in any config file. Therefore the only way to force // tesseract::PSM_SINGLE_BLOCK is from the command line. // It would be simpler if we could set the value before Init, // but that doesn't work. if (api.GetPageSegMode() == tesseract::PSM_SINGLE_BLOCK) api.SetPageSegMode(pagesegmode); bool stdInput = !strcmp(image, "stdin") || !strcmp(image, "-"); Pix* pixs = NULL; if (stdInput) { char byt; GenericVector<l_uint8> ch_data; std::istream file(std::cin.rdbuf()); #ifdef WIN32 if (_setmode(_fileno(stdin), _O_BINARY) == -1) tprintf("ERROR: cin to binary: %s", strerror(errno)); #endif // WIN32 while (file.get(byt)) { ch_data.push_back(byt); } std::cin.ignore(std::cin.rdbuf()->in_avail() + 1); pixs = pixReadMem(&ch_data[0], ch_data.size()); } if (pagesegmode == tesseract::PSM_AUTO_ONLY || pagesegmode == tesseract::PSM_OSD_ONLY) { int ret_val = 0; if (!pixs) pixs = pixRead(image); if (!pixs) { fprintf(stderr, "Cannot open input file: %s\n", image); exit(2); } api.SetImage(pixs); if (pagesegmode == tesseract::PSM_OSD_ONLY) { OSResults osr; if (api.DetectOS(&osr)) { int orient = osr.best_result.orientation_id; int script_id = osr.get_best_script(orient); float orient_oco = osr.best_result.oconfidence; float orient_sco = osr.best_result.sconfidence; tprintf("Orientation: %d\nOrientation in degrees: %d\n" \ "Orientation confidence: %.2f\n" \ "Script: %d\nScript confidence: %.2f\n", orient, OrientationIdToValue(orient), orient_oco, script_id, orient_sco); } else { ret_val = 1; } } else { tesseract::Orientation orientation; tesseract::WritingDirection direction; tesseract::TextlineOrder order; float deskew_angle; tesseract::PageIterator* it = api.AnalyseLayout(); if (it) { it->Orientation(&orientation, &direction, &order, &deskew_angle); tprintf("Orientation: %d\nWritingDirection: %d\nTextlineOrder: %d\n" \ "Deskew angle: %.4f\n", orientation, direction, order, deskew_angle); } else { ret_val = 1; } delete it; } pixDestroy(&pixs); exit(ret_val); } tesseract::TessResultRenderer* renderer = NULL; bool b; api.GetBoolVariable("tessedit_create_hocr", &b); if (b && renderer == NULL) renderer = new tesseract::TessHOcrRenderer(); api.GetBoolVariable("tessedit_create_pdf", &b); if (b && renderer == NULL) renderer = new tesseract::TessPDFRenderer(api.GetDatapath()); api.GetBoolVariable("tessedit_create_boxfile", &b); if (b && renderer == NULL) renderer = new tesseract::TessBoxTextRenderer(); if (renderer == NULL) renderer = new tesseract::TessTextRenderer(); if (pixs) { api.ProcessPage(pixs, 0, NULL, NULL, 0, renderer); pixDestroy(&pixs); } else { FILE* fin = fopen(image, "rb"); if (fin == NULL) { fprintf(stderr, "Cannot open input file: %s\n", image); exit(2); } fclose(fin); if (!api.ProcessPages(image, NULL, 0, renderer)) { fprintf(stderr, "Error during processing.\n"); exit(1); } } FILE* fout = stdout; if (strcmp(output, "-") && strcmp(output, "stdout")) { STRING outfile = STRING(output) + STRING(".") + STRING(renderer->file_extension()); fout = fopen(outfile.string(), "wb"); if (fout == NULL) { fprintf(stderr, "Cannot create output file %s\n", outfile.string()); exit(1); } } const char* data; inT32 data_len; if (renderer->GetOutput(&data, &data_len)) { fwrite(data, 1, data_len, fout); if (fout != stdout) fclose(fout); else clearerr(fout); } PERF_COUNT_END return 0; // Normal exit }
int main | ( | int | argc, |
char * | argv[] | ||
) |
---------------------------------------------------------------------------- Public Code ----------------------------------------------------------------------------
Definition at line 89 of file cntraining.cpp.
{ // Set the global Config parameters before parsing the command line. Config = CNConfig; const char *PageName; FILE *TrainingPage; LIST CharList = NIL_LIST; CLUSTERER *Clusterer = NULL; LIST ProtoList = NIL_LIST; LIST NormProtoList = NIL_LIST; LIST pCharList; LABELEDLIST CharSample; FEATURE_DEFS_STRUCT FeatureDefs; InitFeatureDefs(&FeatureDefs); ParseArguments(&argc, &argv); int num_fonts = 0; while ((PageName = GetNextFilename(argc, argv)) != NULL) { printf("Reading %s ...\n", PageName); TrainingPage = Efopen(PageName, "rb"); ReadTrainingSamples(FeatureDefs, PROGRAM_FEATURE_TYPE, 100, NULL, TrainingPage, &CharList); fclose(TrainingPage); ++num_fonts; } printf("Clustering ...\n"); // To allow an individual font to form a separate cluster, // reduce the min samples: // Config.MinSamples = 0.5 / num_fonts; pCharList = CharList; iterate(pCharList) { //Cluster CharSample = (LABELEDLIST)first_node(pCharList); Clusterer = SetUpForClustering(FeatureDefs, CharSample, PROGRAM_FEATURE_TYPE); float SavedMinSamples = Config.MinSamples; // To disable the tendency to produce a single cluster for all fonts, // make MagicSamples an impossible to achieve number: // Config.MagicSamples = CharSample->SampleCount * 10; Config.MagicSamples = CharSample->SampleCount; while (Config.MinSamples > 0.001) { ProtoList = ClusterSamples(Clusterer, &Config); if (NumberOfProtos(ProtoList, 1, 0) > 0) { break; } else { Config.MinSamples *= 0.95; printf("0 significant protos for %s." " Retrying clustering with MinSamples = %f%%\n", CharSample->Label, Config.MinSamples); } } Config.MinSamples = SavedMinSamples; AddToNormProtosList(&NormProtoList, ProtoList, CharSample->Label); } FreeTrainingSamples(CharList); if (Clusterer == NULL) { // To avoid a SIGSEGV fprintf(stderr, "Error: NULL clusterer!\n"); return 1; } WriteNormProtos(FLAGS_D.c_str(), NormProtoList, Clusterer); FreeNormProtoList(NormProtoList); FreeProtoList(&ProtoList); FreeClusterer(Clusterer); printf ("\n"); return 0; } // main
void WriteNormProtos | ( | const char * | Directory, |
LIST | LabeledProtoList, | ||
CLUSTERER * | Clusterer | ||
) |
---------------------------------------------------------------------------- Private Function Prototypes ----------------------------------------------------------------------------
---------------------------------------------------------------------------- Private Code ----------------------------------------------------------------------------
Definition at line 215 of file cntraining.cpp.
{ FILE *File; STRING Filename; LABELEDLIST LabeledProto; int N; Filename = ""; if (Directory != NULL && Directory[0] != '\0') { Filename += Directory; Filename += "/"; } Filename += "normproto"; printf ("\nWriting %s ...", Filename.string()); File = Efopen (Filename.string(), "wb"); fprintf(File,"%0d\n",Clusterer->SampleSize); WriteParamDesc(File,Clusterer->SampleSize,Clusterer->ParamDesc); iterate(LabeledProtoList) { LabeledProto = (LABELEDLIST) first_node (LabeledProtoList); N = NumberOfProtos(LabeledProto->List, true, false); if (N < 1) { printf ("\nError! Not enough protos for %s: %d protos" " (%d significant protos" ", %d insignificant protos)\n", LabeledProto->Label, N, NumberOfProtos(LabeledProto->List, 1, 0), NumberOfProtos(LabeledProto->List, 0, 1)); exit(1); } fprintf(File, "\n%s %d\n", LabeledProto->Label, N); WriteProtos(File, Clusterer->SampleSize, LabeledProto->List, true, false); } fclose (File); } // WriteNormProtos
void WriteProtos | ( | FILE * | File, |
uinT16 | N, | ||
LIST | ProtoList, | ||
BOOL8 | WriteSigProtos, | ||
BOOL8 | WriteInsigProtos | ||
) |
Definition at line 270 of file cntraining.cpp.
{ PROTOTYPE *Proto; // write prototypes iterate(ProtoList) { Proto = (PROTOTYPE *) first_node ( ProtoList ); if (( Proto->Significant && WriteSigProtos ) || ( ! Proto->Significant && WriteInsigProtos ) ) WritePrototype( File, N, Proto ); } } // WriteProtos
{ elliptical, 0.025, 0.05, 0.8, 1e-3, 0 }
---------------------------------------------------------------------------- Global Data Definitions and Declarations ----------------------------------------------------------------------------
Definition at line 79 of file cntraining.cpp.