|
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.