2010-11-24 02:34:14 +08:00
|
|
|
/**********************************************************************
|
|
|
|
* File: params.cpp
|
|
|
|
* Description: Initialization and setting of Tesseract parameters.
|
|
|
|
* Author: Ray Smith
|
|
|
|
*
|
|
|
|
* (C) Copyright 1991, Hewlett-Packard Ltd.
|
|
|
|
** Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
** you may not use this file except in compliance with the License.
|
|
|
|
** You may obtain a copy of the License at
|
|
|
|
** http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
** Unless required by applicable law or agreed to in writing, software
|
|
|
|
** distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
** See the License for the specific language governing permissions and
|
|
|
|
** limitations under the License.
|
|
|
|
*
|
|
|
|
**********************************************************************/
|
|
|
|
|
2019-04-17 04:01:16 +08:00
|
|
|
#include <climits> // for INT_MIN, INT_MAX
|
|
|
|
#include <cmath> // for NAN, std::isnan
|
2018-09-19 00:51:11 +08:00
|
|
|
#include <cstdio>
|
2018-06-22 02:32:51 +08:00
|
|
|
#include <cstring>
|
2018-09-19 00:51:11 +08:00
|
|
|
#include <cstdlib>
|
2019-04-17 04:01:16 +08:00
|
|
|
#include <locale> // for std::locale::classic
|
|
|
|
#include <sstream> // for std::stringstream
|
2018-06-22 02:32:51 +08:00
|
|
|
|
|
|
|
#include "genericvector.h"
|
2019-04-22 04:20:13 +08:00
|
|
|
#include "host.h" // platform.h, windows.h for MAX_PATH
|
2018-06-22 02:32:51 +08:00
|
|
|
#include "tprintf.h"
|
|
|
|
#include "params.h"
|
2010-11-24 02:34:14 +08:00
|
|
|
|
|
|
|
#define PLUS '+' //flag states
|
|
|
|
#define MINUS '-'
|
|
|
|
#define EQUAL '='
|
|
|
|
|
|
|
|
tesseract::ParamsVectors *GlobalParams() {
|
2016-11-08 02:46:33 +08:00
|
|
|
static tesseract::ParamsVectors global_params = tesseract::ParamsVectors();
|
2016-10-25 02:13:08 +08:00
|
|
|
return &global_params;
|
2010-11-24 02:34:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
namespace tesseract {
|
|
|
|
|
2012-02-02 11:14:43 +08:00
|
|
|
bool ParamUtils::ReadParamsFile(const char *file,
|
|
|
|
SetParamConstraint constraint,
|
2010-11-24 02:34:14 +08:00
|
|
|
ParamsVectors *member_params) {
|
Use POSIX data types and macros (#878)
* api: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* ccmain: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* ccstruct: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* classify: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* cutil: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* dict: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* textord: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* training: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* wordrec: Replace Tesseract data types by POSIX data types
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* ccutil: Replace Tesseract data types by POSIX data types
Now all Tesseract data types which are no longer needed can be removed
from ccutil/host.h.
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* ccmain: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* ccstruct: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* classify: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* dict: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* lstm: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* textord: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* wordrec: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* ccutil: Replace Tesseract's MIN_*INT, MAX_*INT* by POSIX *INT*_MIN, *INT*_MAX
Remove the macros which are now unused from ccutil/host.h.
Remove also the obsolete history comments.
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* Fix build error caused by ambiguous ClipToRange
Error message vom Appveyor CI:
C:\projects\tesseract\ccstruct\coutln.cpp(818): error C2672: 'ClipToRange': no matching overloaded function found [C:\projects\tesseract\build\libtesseract.vcxproj]
C:\projects\tesseract\ccstruct\coutln.cpp(818): error C2782: 'T ClipToRange(const T &,const T &,const T &)': template parameter 'T' is ambiguous [C:\projects\tesseract\build\libtesseract.vcxproj]
c:\projects\tesseract\ccutil\helpers.h(122): note: see declaration of 'ClipToRange'
C:\projects\tesseract\ccstruct\coutln.cpp(818): note: could be 'char'
C:\projects\tesseract\ccstruct\coutln.cpp(818): note: or 'int'
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* unittest: Replace Tesseract's MAX_INT8 by POSIX INT8_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
* arch: Replace Tesseract's MAX_INT8 by POSIX INT8_MAX
Signed-off-by: Stefan Weil <sw@weilnetz.de>
2018-03-14 04:36:30 +08:00
|
|
|
int16_t nameoffset; // offset for real name
|
2010-11-24 02:34:14 +08:00
|
|
|
|
|
|
|
if (*file == PLUS) {
|
|
|
|
nameoffset = 1;
|
|
|
|
} else if (*file == MINUS) {
|
|
|
|
nameoffset = 1;
|
|
|
|
} else {
|
|
|
|
nameoffset = 0;
|
|
|
|
}
|
|
|
|
|
2017-04-28 06:48:23 +08:00
|
|
|
TFile fp;
|
|
|
|
if (!fp.Open(file + nameoffset, nullptr)) {
|
2010-11-24 02:34:14 +08:00
|
|
|
tprintf("read_params_file: Can't open %s\n", file + nameoffset);
|
|
|
|
return true;
|
|
|
|
}
|
2017-04-28 06:48:23 +08:00
|
|
|
return ReadParamsFromFp(constraint, &fp, member_params);
|
2010-11-24 02:34:14 +08:00
|
|
|
}
|
|
|
|
|
2017-04-28 06:48:23 +08:00
|
|
|
bool ParamUtils::ReadParamsFromFp(SetParamConstraint constraint, TFile *fp,
|
2010-11-24 02:34:14 +08:00
|
|
|
ParamsVectors *member_params) {
|
|
|
|
char line[MAX_PATH]; // input line
|
|
|
|
bool anyerr = false; // true if any error
|
|
|
|
bool foundit; // found parameter
|
|
|
|
char *valptr; // value field
|
|
|
|
|
2017-04-28 06:48:23 +08:00
|
|
|
while (fp->FGets(line, MAX_PATH) != nullptr) {
|
2017-03-01 19:41:17 +08:00
|
|
|
if (line[0] != '\r' && line[0] != '\n' && line[0] != '#') {
|
2014-06-03 14:57:52 +08:00
|
|
|
chomp_string(line); // remove newline
|
2010-11-24 02:34:14 +08:00
|
|
|
for (valptr = line; *valptr && *valptr != ' ' && *valptr != '\t';
|
|
|
|
valptr++);
|
|
|
|
if (*valptr) { // found blank
|
|
|
|
*valptr = '\0'; // make name a string
|
|
|
|
do
|
|
|
|
valptr++; // find end of blanks
|
|
|
|
while (*valptr == ' ' || *valptr == '\t');
|
|
|
|
}
|
2012-02-02 11:14:43 +08:00
|
|
|
foundit = SetParam(line, valptr, constraint, member_params);
|
2010-11-24 02:34:14 +08:00
|
|
|
|
|
|
|
if (!foundit) {
|
|
|
|
anyerr = true; // had an error
|
2018-09-20 14:37:06 +08:00
|
|
|
tprintf("Warning: Parameter not found: %s\n", line);
|
2010-11-24 02:34:14 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return anyerr;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ParamUtils::SetParam(const char *name, const char* value,
|
2012-02-02 11:14:43 +08:00
|
|
|
SetParamConstraint constraint,
|
|
|
|
ParamsVectors *member_params) {
|
2010-11-24 02:34:14 +08:00
|
|
|
// Look for the parameter among string parameters.
|
2019-03-26 14:55:08 +08:00
|
|
|
auto *sp = FindParam<StringParam>(name, GlobalParams()->string_params,
|
2010-11-24 02:34:14 +08:00
|
|
|
member_params->string_params);
|
2016-12-13 00:20:28 +08:00
|
|
|
if (sp != nullptr && sp->constraint_ok(constraint)) sp->set_value(value);
|
|
|
|
if (*value == '\0') return (sp != nullptr);
|
2010-11-24 02:34:14 +08:00
|
|
|
|
|
|
|
// Look for the parameter among int parameters.
|
2019-03-26 14:55:08 +08:00
|
|
|
auto *ip = FindParam<IntParam>(name, GlobalParams()->int_params,
|
2010-11-24 02:34:14 +08:00
|
|
|
member_params->int_params);
|
2019-04-17 04:01:16 +08:00
|
|
|
if (ip && ip->constraint_ok(constraint)) {
|
|
|
|
int intval = INT_MIN;
|
|
|
|
std::stringstream stream(value);
|
|
|
|
stream.imbue(std::locale::classic());
|
|
|
|
stream >> intval;
|
|
|
|
if (intval != INT_MIN) {
|
|
|
|
ip->set_value(intval);
|
|
|
|
}
|
|
|
|
}
|
2010-11-24 02:34:14 +08:00
|
|
|
|
|
|
|
// Look for the parameter among bool parameters.
|
2019-03-26 14:55:08 +08:00
|
|
|
auto *bp = FindParam<BoolParam>(name, GlobalParams()->bool_params,
|
2010-11-24 02:34:14 +08:00
|
|
|
member_params->bool_params);
|
2016-12-13 00:20:28 +08:00
|
|
|
if (bp != nullptr && bp->constraint_ok(constraint)) {
|
2010-11-24 02:34:14 +08:00
|
|
|
if (*value == 'T' || *value == 't' ||
|
|
|
|
*value == 'Y' || *value == 'y' || *value == '1') {
|
|
|
|
bp->set_value(true);
|
|
|
|
} else if (*value == 'F' || *value == 'f' ||
|
|
|
|
*value == 'N' || *value == 'n' || *value == '0') {
|
|
|
|
bp->set_value(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Look for the parameter among double parameters.
|
2019-03-26 14:55:08 +08:00
|
|
|
auto *dp = FindParam<DoubleParam>(name, GlobalParams()->double_params,
|
2010-11-24 02:34:14 +08:00
|
|
|
member_params->double_params);
|
2016-12-13 00:20:28 +08:00
|
|
|
if (dp != nullptr && dp->constraint_ok(constraint)) {
|
2019-04-17 04:01:16 +08:00
|
|
|
double doubleval = NAN;
|
|
|
|
std::stringstream stream(value);
|
|
|
|
stream.imbue(std::locale::classic());
|
|
|
|
stream >> doubleval;
|
|
|
|
if (!std::isnan(doubleval)) {
|
2010-11-24 02:34:14 +08:00
|
|
|
dp->set_value(doubleval);
|
2019-04-17 04:01:16 +08:00
|
|
|
}
|
2010-11-24 02:34:14 +08:00
|
|
|
}
|
|
|
|
return (sp || ip || bp || dp);
|
|
|
|
}
|
|
|
|
|
2010-11-30 08:53:31 +08:00
|
|
|
bool ParamUtils::GetParamAsString(const char *name,
|
|
|
|
const ParamsVectors* member_params,
|
|
|
|
STRING *value) {
|
|
|
|
// Look for the parameter among string parameters.
|
2019-03-26 14:55:08 +08:00
|
|
|
auto *sp = FindParam<StringParam>(name, GlobalParams()->string_params,
|
2010-11-30 08:53:31 +08:00
|
|
|
member_params->string_params);
|
|
|
|
if (sp) {
|
|
|
|
*value = sp->string();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
// Look for the parameter among int parameters.
|
2019-03-26 14:55:08 +08:00
|
|
|
auto *ip = FindParam<IntParam>(name, GlobalParams()->int_params,
|
2010-11-30 08:53:31 +08:00
|
|
|
member_params->int_params);
|
|
|
|
if (ip) {
|
|
|
|
char buf[128];
|
2018-03-14 02:01:40 +08:00
|
|
|
snprintf(buf, sizeof(buf), "%d", int32_t(*ip));
|
2010-11-30 08:53:31 +08:00
|
|
|
*value = buf;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
// Look for the parameter among bool parameters.
|
2019-03-26 14:55:08 +08:00
|
|
|
auto *bp = FindParam<BoolParam>(name, GlobalParams()->bool_params,
|
2010-11-30 08:53:31 +08:00
|
|
|
member_params->bool_params);
|
2016-12-13 00:20:28 +08:00
|
|
|
if (bp != nullptr) {
|
2019-03-30 20:45:50 +08:00
|
|
|
*value = bool(*bp) ? "1": "0";
|
2010-11-30 08:53:31 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
// Look for the parameter among double parameters.
|
2019-03-26 14:55:08 +08:00
|
|
|
auto *dp = FindParam<DoubleParam>(name, GlobalParams()->double_params,
|
2010-11-30 08:53:31 +08:00
|
|
|
member_params->double_params);
|
2016-12-13 00:20:28 +08:00
|
|
|
if (dp != nullptr) {
|
2010-11-30 08:53:31 +08:00
|
|
|
char buf[128];
|
|
|
|
snprintf(buf, sizeof(buf), "%g", double(*dp));
|
|
|
|
*value = buf;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-11-24 02:34:14 +08:00
|
|
|
void ParamUtils::PrintParams(FILE *fp, const ParamsVectors *member_params) {
|
|
|
|
int v, i;
|
2016-12-13 00:20:28 +08:00
|
|
|
int num_iterations = (member_params == nullptr) ? 1 : 2;
|
2010-11-24 02:34:14 +08:00
|
|
|
for (v = 0; v < num_iterations; ++v) {
|
|
|
|
const ParamsVectors *vec = (v == 0) ? GlobalParams() : member_params;
|
|
|
|
for (i = 0; i < vec->int_params.size(); ++i) {
|
2014-08-11 03:08:20 +08:00
|
|
|
fprintf(fp, "%s\t%d\t%s\n", vec->int_params[i]->name_str(),
|
2018-03-14 02:01:40 +08:00
|
|
|
(int32_t)(*vec->int_params[i]), vec->int_params[i]->info_str());
|
2010-11-24 02:34:14 +08:00
|
|
|
}
|
|
|
|
for (i = 0; i < vec->bool_params.size(); ++i) {
|
2014-08-11 03:08:20 +08:00
|
|
|
fprintf(fp, "%s\t%d\t%s\n", vec->bool_params[i]->name_str(),
|
2019-03-30 20:45:50 +08:00
|
|
|
bool(*vec->bool_params[i]), vec->bool_params[i]->info_str());
|
2010-11-24 02:34:14 +08:00
|
|
|
}
|
|
|
|
for (int i = 0; i < vec->string_params.size(); ++i) {
|
2014-08-11 03:08:20 +08:00
|
|
|
fprintf(fp, "%s\t%s\t%s\n", vec->string_params[i]->name_str(),
|
|
|
|
vec->string_params[i]->string(), vec->string_params[i]->info_str());
|
2010-11-24 02:34:14 +08:00
|
|
|
}
|
|
|
|
for (int i = 0; i < vec->double_params.size(); ++i) {
|
2014-08-11 03:08:20 +08:00
|
|
|
fprintf(fp, "%s\t%g\t%s\n", vec->double_params[i]->name_str(),
|
|
|
|
(double)(*vec->double_params[i]), vec->double_params[i]->info_str());
|
2010-11-24 02:34:14 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-23 23:26:50 +08:00
|
|
|
// Resets all parameters back to default values;
|
|
|
|
void ParamUtils::ResetToDefaults(ParamsVectors* member_params) {
|
|
|
|
int v, i;
|
2016-12-13 00:20:28 +08:00
|
|
|
int num_iterations = (member_params == nullptr) ? 1 : 2;
|
2013-09-23 23:26:50 +08:00
|
|
|
for (v = 0; v < num_iterations; ++v) {
|
|
|
|
ParamsVectors *vec = (v == 0) ? GlobalParams() : member_params;
|
|
|
|
for (i = 0; i < vec->int_params.size(); ++i) {
|
|
|
|
vec->int_params[i]->ResetToDefault();
|
|
|
|
}
|
|
|
|
for (i = 0; i < vec->bool_params.size(); ++i) {
|
|
|
|
vec->bool_params[i]->ResetToDefault();
|
|
|
|
}
|
|
|
|
for (int i = 0; i < vec->string_params.size(); ++i) {
|
|
|
|
vec->string_params[i]->ResetToDefault();
|
|
|
|
}
|
|
|
|
for (int i = 0; i < vec->double_params.size(); ++i) {
|
|
|
|
vec->double_params[i]->ResetToDefault();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-24 02:34:14 +08:00
|
|
|
} // namespace tesseract
|