mirror of
https://github.com/tesseract-ocr/tesseract.git
synced 2024-11-27 12:49:35 +08:00
ParamUtils::ReportParamsUsageStatistics() work extracted from master; rough first draft, as in: not compile-tested, not backported to using PrintFontsTable() instead of fmt::format et al.
This commit is contained in:
parent
9d71da7854
commit
c38b33b9fe
@ -161,6 +161,17 @@ public:
|
||||
*/
|
||||
void PrintVariables(FILE *fp) const;
|
||||
|
||||
/*
|
||||
* Report parameters' usage statistics, i.e. report which params have been
|
||||
* set, modified and read/checked until now during this run-time's lifetime.
|
||||
*
|
||||
* Use this method for run-time 'discovery' about which tesseract parameters
|
||||
* are actually *used* during your particular usage of the library, ergo
|
||||
* answering the question:
|
||||
* "Which of all those parameters are actually *relevant* to my use case today?"
|
||||
*/
|
||||
void ReportParamsUsageStatistics() const;
|
||||
|
||||
/**
|
||||
* Get value of named variable as a string, if it exists.
|
||||
*/
|
||||
|
@ -292,8 +292,8 @@ bool TessBaseAPI::SetDebugVariable(const char *name, const char *value) {
|
||||
}
|
||||
|
||||
bool TessBaseAPI::GetIntVariable(const char *name, int *value) const {
|
||||
auto *p = ParamUtils::FindParam<IntParam>(name, GlobalParams()->int_params,
|
||||
tesseract_->params()->int_params);
|
||||
auto *p = ParamUtils::FindParam<IntParam>(name, GlobalParams()->int_params(),
|
||||
tesseract_->params()->int_params());
|
||||
if (p == nullptr) {
|
||||
return false;
|
||||
}
|
||||
@ -302,8 +302,8 @@ bool TessBaseAPI::GetIntVariable(const char *name, int *value) const {
|
||||
}
|
||||
|
||||
bool TessBaseAPI::GetBoolVariable(const char *name, bool *value) const {
|
||||
auto *p = ParamUtils::FindParam<BoolParam>(name, GlobalParams()->bool_params,
|
||||
tesseract_->params()->bool_params);
|
||||
auto *p = ParamUtils::FindParam<BoolParam>(name, GlobalParams()->bool_params(),
|
||||
tesseract_->params()->bool_params());
|
||||
if (p == nullptr) {
|
||||
return false;
|
||||
}
|
||||
@ -312,14 +312,14 @@ bool TessBaseAPI::GetBoolVariable(const char *name, bool *value) const {
|
||||
}
|
||||
|
||||
const char *TessBaseAPI::GetStringVariable(const char *name) const {
|
||||
auto *p = ParamUtils::FindParam<StringParam>(name, GlobalParams()->string_params,
|
||||
tesseract_->params()->string_params);
|
||||
auto *p = ParamUtils::FindParam<StringParam>(name, GlobalParams()->string_params(),
|
||||
tesseract_->params()->string_params());
|
||||
return (p != nullptr) ? p->c_str() : nullptr;
|
||||
}
|
||||
|
||||
bool TessBaseAPI::GetDoubleVariable(const char *name, double *value) const {
|
||||
auto *p = ParamUtils::FindParam<DoubleParam>(name, GlobalParams()->double_params,
|
||||
tesseract_->params()->double_params);
|
||||
auto *p = ParamUtils::FindParam<DoubleParam>(name, GlobalParams()->double_params(),
|
||||
tesseract_->params()->double_params());
|
||||
if (p == nullptr) {
|
||||
return false;
|
||||
}
|
||||
@ -357,6 +357,19 @@ void TessBaseAPI::PrintVariables(FILE *fp) const {
|
||||
ParamUtils::PrintParams(fp, tesseract_->params());
|
||||
}
|
||||
|
||||
// Report parameters' usage statistics, i.e. report which params have been
|
||||
// set, modified and read/checked until now during this run-time's lifetime.
|
||||
//
|
||||
// Use this method for run-time 'discovery' about which tesseract parameters
|
||||
// are actually *used* during your particular usage of the library, ergo
|
||||
// answering the question:
|
||||
// "Which of all those parameters are actually *relevant* to my use case today?"
|
||||
void TessBaseAPI::ReportParamsUsageStatistics() const {
|
||||
tesseract::ParamsVectors *vec = tesseract_->params();
|
||||
|
||||
ParamUtils::ReportParamsUsageStatistics(vec);
|
||||
}
|
||||
|
||||
/**
|
||||
* The datapath must be the name of the data directory or
|
||||
* some other file in which the data directory resides (for instance argv[0].)
|
||||
|
@ -212,16 +212,16 @@ SVMenuNode *ParamsEditor::BuildListOfAllLeaves(tesseract::Tesseract *tess) {
|
||||
int num_iterations = (tess->params() == nullptr) ? 1 : 2;
|
||||
for (int v = 0; v < num_iterations; ++v) {
|
||||
tesseract::ParamsVectors *vec = (v == 0) ? GlobalParams() : tess->params();
|
||||
for (auto ¶m : vec->int_params) {
|
||||
for (auto ¶m : vec->int_params()) {
|
||||
vc_it.add_after_then_move(new ParamContent(param));
|
||||
}
|
||||
for (auto ¶m : vec->bool_params) {
|
||||
for (auto ¶m : vec->bool_params()) {
|
||||
vc_it.add_after_then_move(new ParamContent(param));
|
||||
}
|
||||
for (auto ¶m : vec->string_params) {
|
||||
for (auto ¶m : vec->string_params()) {
|
||||
vc_it.add_after_then_move(new ParamContent(param));
|
||||
}
|
||||
for (auto ¶m : vec->double_params) {
|
||||
for (auto ¶m : vec->double_params()) {
|
||||
vc_it.add_after_then_move(new ParamContent(param));
|
||||
}
|
||||
}
|
||||
|
@ -18,11 +18,14 @@
|
||||
|
||||
#include "params.h"
|
||||
|
||||
#include "helpers.h" // for chomp_string
|
||||
#include "helpers.h" // for chomp_string, mupdf imports, etc.: see also the header collision comment in there (MSVC-specific).
|
||||
#include "host.h" // tesseract/export.h, windows.h for MAX_PATH
|
||||
#include "serialis.h" // for TFile
|
||||
#include "tprintf.h"
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <climits> // for INT_MIN, INT_MAX
|
||||
#include <cmath> // for NAN, std::isnan
|
||||
#include <cstdio>
|
||||
@ -31,10 +34,12 @@
|
||||
#include <locale> // for std::locale::classic
|
||||
#include <sstream> // for std::stringstream
|
||||
|
||||
|
||||
namespace tesseract {
|
||||
|
||||
TESS_API
|
||||
tesseract::ParamsVectors *GlobalParams() {
|
||||
static tesseract::ParamsVectors global_params = tesseract::ParamsVectors();
|
||||
static tesseract::ParamsVectors global_params; // static auto-inits at startup
|
||||
return &global_params;
|
||||
}
|
||||
|
||||
@ -42,7 +47,7 @@ bool ParamUtils::ReadParamsFile(const char *file, SetParamConstraint constraint,
|
||||
ParamsVectors *member_params) {
|
||||
TFile fp;
|
||||
if (!fp.Open(file, nullptr)) {
|
||||
tprintf("read_params_file: Can't open %s\n", file);
|
||||
tprintf("ERROR: read_params_file: Can't open file {}\n", file);
|
||||
return true;
|
||||
}
|
||||
return ReadParamsFromFp(constraint, &fp, member_params);
|
||||
@ -71,18 +76,157 @@ bool ParamUtils::ReadParamsFromFp(SetParamConstraint constraint, TFile *fp,
|
||||
|
||||
if (!foundit) {
|
||||
anyerr = true; // had an error
|
||||
tprintf("Warning: Parameter not found: %s\n", line);
|
||||
tprintf("WARNING: Parameter not found: {}\n", line);
|
||||
}
|
||||
}
|
||||
}
|
||||
return anyerr;
|
||||
}
|
||||
|
||||
void ParamUtils::ReportParamsUsageStatistics(const ParamsVectors *member_params)
|
||||
{
|
||||
std::string report_path = vars_report_file;
|
||||
FILE* f = nullptr;
|
||||
|
||||
if (report_path == "stdout" || report_path == "-" || report_path == "1")
|
||||
f = stdout;
|
||||
else if (report_path == "stdeerr" || report_path == "+" || report_path == "2")
|
||||
f = stderr;
|
||||
else if (!report_path.empty())
|
||||
{
|
||||
#if defined(HAVE_MUPDF)
|
||||
fz_context* ctx = fz_get_global_context();
|
||||
fz_mkdir_for_file(ctx, report_path.c_str());
|
||||
f = fz_fopen_utf8(ctx, report_path.c_str(), "w");
|
||||
#else
|
||||
f = fopen(report_path.c_str(), "w");
|
||||
#endif
|
||||
if (!f)
|
||||
{
|
||||
tprintf("ERROR: Cannot produce paramater usage report file: {}\n", report_path);
|
||||
}
|
||||
}
|
||||
|
||||
if (!f)
|
||||
return;
|
||||
|
||||
fprintf(f, "\n\nTesseract Parameter Usage Statistics: which params have been relevant?\n"
|
||||
"----------------------------------------------------------------------\n\n");
|
||||
|
||||
// first collect all parameter names:
|
||||
|
||||
typedef enum {
|
||||
INT_PARAM = 0,
|
||||
BOOL_PARAM,
|
||||
DOUBLE_PARAM,
|
||||
STRING_PARAM,
|
||||
} param_type_t;
|
||||
|
||||
typedef struct param_info {
|
||||
const char* name;
|
||||
bool global;
|
||||
param_type_t type;
|
||||
const Param* ref;
|
||||
} param_info_t;
|
||||
|
||||
std::vector<param_info_t> param_names;
|
||||
|
||||
if (member_params != nullptr) {
|
||||
for (auto p : member_params->int_params_c()) {
|
||||
param_names.push_back({ p->name_str(), false, INT_PARAM, p });
|
||||
}
|
||||
for (auto p : member_params->bool_params_c()) {
|
||||
param_names.push_back({ p->name_str(), false, BOOL_PARAM, p });
|
||||
}
|
||||
for (auto p : member_params->string_params_c()) {
|
||||
param_names.push_back({ p->name_str(), false, STRING_PARAM, p });
|
||||
}
|
||||
for (auto p : member_params->double_params_c()) {
|
||||
param_names.push_back({ p->name_str(), false, DOUBLE_PARAM, p });
|
||||
}
|
||||
}
|
||||
|
||||
const ParamsVectors* globals = GlobalParams();
|
||||
|
||||
for (auto p : globals->int_params_c()) {
|
||||
param_names.push_back({ p->name_str(), true, INT_PARAM, p });
|
||||
}
|
||||
for (auto p : globals->bool_params_c()) {
|
||||
param_names.push_back({ p->name_str(), true, BOOL_PARAM, p });
|
||||
}
|
||||
for (auto p : globals->string_params_c()) {
|
||||
param_names.push_back({ p->name_str(), true, STRING_PARAM, p });
|
||||
}
|
||||
for (auto p : globals->double_params_c()) {
|
||||
param_names.push_back({ p->name_str(), true, DOUBLE_PARAM, p });
|
||||
}
|
||||
|
||||
sort(param_names.begin(), param_names.end(), [](param_info_t& a, param_info_t& b)
|
||||
{
|
||||
int rv = strcmp(b.name, a.name);
|
||||
if (rv == 0)
|
||||
{
|
||||
rv = (int) b.global - (int) a.global;
|
||||
}
|
||||
#if !defined(NDEBUG)
|
||||
if (rv == 0)
|
||||
{
|
||||
fprintf(stderr, "Apparently you have double-defined Tesseract Variable: '%s'! Fix that in the source code!\n", a.name);
|
||||
ASSEERT0(!"Apparently you have double-defined a Tesseract Variable.");
|
||||
}
|
||||
#endif
|
||||
return rv >= 0;
|
||||
});
|
||||
|
||||
static const char* type_map[] = { "[Integer]", "[Boolean]", "[Float]", "[String]" };
|
||||
static const char* categories[] = { "(Global)", "(Local)" };
|
||||
static const char* write_access[] = { ".", "w", "W" };
|
||||
static const char* read_access[] = { ".", "r", "R" };
|
||||
|
||||
auto acc = [](int access) {
|
||||
if (access > 2)
|
||||
access = 2;
|
||||
return access;
|
||||
};
|
||||
|
||||
for (auto item : param_names) {
|
||||
const Param* p = item.ref;
|
||||
auto stats = p->access_counts();
|
||||
if (stats.reading > 0)
|
||||
{
|
||||
fmt::print(f, "* {:.<60} {:8} {}{} {:9} = {}\n", p->name_str(), categories[item.global], write_access[acc(stats.writing)], read_access[acc(stats.reading)], type_map[item.type], p->formatted_value_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (report_all_variables)
|
||||
{
|
||||
fprintf(f, "\n\nUnused parameters:\n\n");
|
||||
|
||||
for (auto item : param_names) {
|
||||
const Param* p = item.ref;
|
||||
auto stats = p->access_counts();
|
||||
if (stats.reading <= 0)
|
||||
{
|
||||
fmt::print(f, "* {:.<60} {:8} {}{} {:9} = {}\n", p->name_str(), categories[item.global], write_access[acc(stats.writing)], read_access[acc(stats.reading)], type_map[item.type], p->formatted_value_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (f != stdout)
|
||||
{
|
||||
fclose(f);
|
||||
}
|
||||
else
|
||||
{
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
bool ParamUtils::SetParam(const char *name, const char *value, SetParamConstraint constraint,
|
||||
ParamsVectors *member_params) {
|
||||
// Look for the parameter among string parameters.
|
||||
auto *sp =
|
||||
FindParam<StringParam>(name, GlobalParams()->string_params, member_params->string_params);
|
||||
FindParam<StringParam>(name, GlobalParams()->string_params(), member_params->string_params());
|
||||
if (sp != nullptr && sp->constraint_ok(constraint)) {
|
||||
sp->set_value(value);
|
||||
}
|
||||
@ -91,7 +235,7 @@ bool ParamUtils::SetParam(const char *name, const char *value, SetParamConstrain
|
||||
}
|
||||
|
||||
// Look for the parameter among int parameters.
|
||||
auto *ip = FindParam<IntParam>(name, GlobalParams()->int_params, member_params->int_params);
|
||||
auto *ip = FindParam<IntParam>(name, GlobalParams()->int_params(), member_params->int_params());
|
||||
if (ip && ip->constraint_ok(constraint)) {
|
||||
int intval = INT_MIN;
|
||||
std::stringstream stream(value);
|
||||
@ -103,7 +247,7 @@ bool ParamUtils::SetParam(const char *name, const char *value, SetParamConstrain
|
||||
}
|
||||
|
||||
// Look for the parameter among bool parameters.
|
||||
auto *bp = FindParam<BoolParam>(name, GlobalParams()->bool_params, member_params->bool_params);
|
||||
auto *bp = FindParam<BoolParam>(name, GlobalParams()->bool_params(), member_params->bool_params());
|
||||
if (bp != nullptr && bp->constraint_ok(constraint)) {
|
||||
if (*value == 'T' || *value == 't' || *value == 'Y' || *value == 'y' || *value == '1') {
|
||||
bp->set_value(true);
|
||||
@ -114,7 +258,7 @@ bool ParamUtils::SetParam(const char *name, const char *value, SetParamConstrain
|
||||
|
||||
// Look for the parameter among double parameters.
|
||||
auto *dp =
|
||||
FindParam<DoubleParam>(name, GlobalParams()->double_params, member_params->double_params);
|
||||
FindParam<DoubleParam>(name, GlobalParams()->double_params(), member_params->double_params());
|
||||
if (dp != nullptr && dp->constraint_ok(constraint)) {
|
||||
double doubleval = NAN;
|
||||
std::stringstream stream(value);
|
||||
@ -131,26 +275,26 @@ bool ParamUtils::GetParamAsString(const char *name, const ParamsVectors *member_
|
||||
std::string *value) {
|
||||
// Look for the parameter among string parameters.
|
||||
auto *sp =
|
||||
FindParam<StringParam>(name, GlobalParams()->string_params, member_params->string_params);
|
||||
FindParam<StringParam>(name, GlobalParams()->string_params_c(), member_params->string_params_c());
|
||||
if (sp) {
|
||||
*value = sp->c_str();
|
||||
return true;
|
||||
}
|
||||
// Look for the parameter among int parameters.
|
||||
auto *ip = FindParam<IntParam>(name, GlobalParams()->int_params, member_params->int_params);
|
||||
auto *ip = FindParam<IntParam>(name, GlobalParams()->int_params_c(), member_params->int_params_c());
|
||||
if (ip) {
|
||||
*value = std::to_string(int32_t(*ip));
|
||||
return true;
|
||||
}
|
||||
// Look for the parameter among bool parameters.
|
||||
auto *bp = FindParam<BoolParam>(name, GlobalParams()->bool_params, member_params->bool_params);
|
||||
auto *bp = FindParam<BoolParam>(name, GlobalParams()->bool_params_c(), member_params->bool_params_c());
|
||||
if (bp != nullptr) {
|
||||
*value = bool(*bp) ? "1" : "0";
|
||||
return true;
|
||||
}
|
||||
// Look for the parameter among double parameters.
|
||||
auto *dp =
|
||||
FindParam<DoubleParam>(name, GlobalParams()->double_params, member_params->double_params);
|
||||
FindParam<DoubleParam>(name, GlobalParams()->double_params_c(), member_params->double_params_c());
|
||||
if (dp != nullptr) {
|
||||
std::ostringstream stream;
|
||||
stream.imbue(std::locale::classic());
|
||||
@ -163,27 +307,55 @@ bool ParamUtils::GetParamAsString(const char *name, const ParamsVectors *member_
|
||||
|
||||
void ParamUtils::PrintParams(FILE *fp, const ParamsVectors *member_params) {
|
||||
int num_iterations = (member_params == nullptr) ? 1 : 2;
|
||||
// When printing to stdout info text is included.
|
||||
// Info text is omitted when printing to a file (would result in an invalid config file).
|
||||
if (!fp)
|
||||
fp = stdout;
|
||||
bool print_info = (fp == stdout || fp == stderr);
|
||||
std::ostringstream stream;
|
||||
stream.imbue(std::locale::classic());
|
||||
for (int v = 0; v < num_iterations; ++v) {
|
||||
const ParamsVectors *vec = (v == 0) ? GlobalParams() : member_params;
|
||||
for (auto int_param : vec->int_params) {
|
||||
stream << int_param->name_str() << '\t' << (int32_t)(*int_param) << '\t'
|
||||
<< int_param->info_str() << '\n';
|
||||
for (auto int_param : vec->int_params_c()) {
|
||||
if (print_info) {
|
||||
stream << int_param->name_str() << '\t' << (int32_t)(*int_param) << '\t'
|
||||
<< int_param->info_str() << '\n';
|
||||
} else {
|
||||
stream << int_param->name_str() << '\t' << (int32_t)(*int_param) << '\n';
|
||||
}
|
||||
}
|
||||
for (auto bool_param : vec->bool_params) {
|
||||
stream << bool_param->name_str() << '\t' << bool(*bool_param) << '\t'
|
||||
<< bool_param->info_str() << '\n';
|
||||
for (auto bool_param : vec->bool_params_c()) {
|
||||
if (print_info) {
|
||||
stream << bool_param->name_str() << '\t' << bool(*bool_param) << '\t'
|
||||
<< bool_param->info_str() << '\n';
|
||||
} else {
|
||||
stream << bool_param->name_str() << '\t' << bool(*bool_param) << '\n';
|
||||
}
|
||||
}
|
||||
for (auto string_param : vec->string_params) {
|
||||
stream << string_param->name_str() << '\t' << string_param->c_str() << '\t'
|
||||
<< string_param->info_str() << '\n';
|
||||
for (auto string_param : vec->string_params_c()) {
|
||||
if (print_info) {
|
||||
stream << string_param->name_str() << '\t' << string_param->c_str() << '\t'
|
||||
<< string_param->info_str() << '\n';
|
||||
} else {
|
||||
stream << string_param->name_str() << '\t' << string_param->c_str() << '\n';
|
||||
}
|
||||
}
|
||||
for (auto double_param : vec->double_params) {
|
||||
stream << double_param->name_str() << '\t' << (double)(*double_param) << '\t'
|
||||
<< double_param->info_str() << '\n';
|
||||
for (auto double_param : vec->double_params_c()) {
|
||||
if (print_info) {
|
||||
stream << double_param->name_str() << '\t' << (double)(*double_param) << '\t'
|
||||
<< double_param->info_str() << '\n';
|
||||
} else {
|
||||
stream << double_param->name_str() << '\t' << (double)(*double_param) << '\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_MUPDF
|
||||
if (print_info)
|
||||
{
|
||||
tprintf("{}", stream.str().c_str());
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
fprintf(fp, "%s", stream.str().c_str());
|
||||
}
|
||||
|
||||
@ -192,16 +364,16 @@ void ParamUtils::ResetToDefaults(ParamsVectors *member_params) {
|
||||
int num_iterations = (member_params == nullptr) ? 1 : 2;
|
||||
for (int v = 0; v < num_iterations; ++v) {
|
||||
ParamsVectors *vec = (v == 0) ? GlobalParams() : member_params;
|
||||
for (auto ¶m : vec->int_params) {
|
||||
for (auto ¶m : vec->int_params()) {
|
||||
param->ResetToDefault();
|
||||
}
|
||||
for (auto ¶m : vec->bool_params) {
|
||||
for (auto ¶m : vec->bool_params()) {
|
||||
param->ResetToDefault();
|
||||
}
|
||||
for (auto ¶m : vec->string_params) {
|
||||
for (auto ¶m : vec->string_params()) {
|
||||
param->ResetToDefault();
|
||||
}
|
||||
for (auto ¶m : vec->double_params) {
|
||||
for (auto ¶m : vec->double_params()) {
|
||||
param->ResetToDefault();
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,8 @@
|
||||
* File: params.h
|
||||
* Description: Class definitions of the *_VAR classes for tunable constants.
|
||||
* Author: Ray Smith
|
||||
*
|
||||
* UTF8 detect helper statement: «bloody MSVC»
|
||||
*
|
||||
* (C) Copyright 1991, Hewlett-Packard Ltd.
|
||||
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -43,11 +45,43 @@ enum SetParamConstraint {
|
||||
SET_PARAM_CONSTRAINT_NON_INIT_ONLY,
|
||||
};
|
||||
|
||||
struct ParamsVectors {
|
||||
std::vector<IntParam *> int_params;
|
||||
std::vector<BoolParam *> bool_params;
|
||||
std::vector<StringParam *> string_params;
|
||||
std::vector<DoubleParam *> double_params;
|
||||
class ParamsVectors {
|
||||
std::vector<IntParam *> _int_params;
|
||||
std::vector<BoolParam *> _bool_params;
|
||||
std::vector<StringParam *> _string_params;
|
||||
std::vector<DoubleParam *> _double_params;
|
||||
|
||||
public:
|
||||
ParamsVectors() {
|
||||
}
|
||||
~ParamsVectors() {
|
||||
}
|
||||
|
||||
std::vector<IntParam *> &int_params() {
|
||||
return _int_params;
|
||||
}
|
||||
std::vector<BoolParam *> &bool_params() {
|
||||
return _bool_params;
|
||||
}
|
||||
std::vector<StringParam *> &string_params() {
|
||||
return _string_params;
|
||||
}
|
||||
std::vector<DoubleParam *> &double_params() {
|
||||
return _double_params;
|
||||
}
|
||||
|
||||
const std::vector<IntParam *> &int_params_c() const {
|
||||
return _int_params;
|
||||
}
|
||||
const std::vector<BoolParam *> &bool_params_c() const {
|
||||
return _bool_params;
|
||||
}
|
||||
const std::vector<StringParam *> &string_params_c() const {
|
||||
return _string_params;
|
||||
}
|
||||
const std::vector<DoubleParam *> &double_params_c() const {
|
||||
return _double_params;
|
||||
}
|
||||
};
|
||||
|
||||
// Utility functions for working with Tesseract parameters.
|
||||
@ -69,6 +103,25 @@ public:
|
||||
static bool SetParam(const char *name, const char *value, SetParamConstraint constraint,
|
||||
ParamsVectors *member_params);
|
||||
|
||||
// accept both - and _ in key names, e.g. user-specified 'debug-all' would match 'debug_all'
|
||||
// in the database.
|
||||
static inline bool CompareKeys(const char *db_key, const char *user_key)
|
||||
{
|
||||
// if (0 == strcmp(db_key, user_key))
|
||||
// return true;
|
||||
|
||||
for (; *db_key && *user_key; db_key++, user_key++)
|
||||
{
|
||||
if (*db_key != *user_key)
|
||||
{
|
||||
if (*db_key == '_' && *user_key == '-')
|
||||
continue;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Returns the pointer to the parameter with the given name (of the
|
||||
// appropriate type) if it was found in the vector obtained from
|
||||
// GlobalParams() or in the given member_params.
|
||||
@ -76,16 +129,16 @@ public:
|
||||
static T *FindParam(const char *name, const std::vector<T *> &global_vec,
|
||||
const std::vector<T *> &member_vec) {
|
||||
for (auto *param : global_vec) {
|
||||
if (strcmp(param->name_str(), name) == 0) {
|
||||
if (CompareKeys(param->name_str(), name)) {
|
||||
return param;
|
||||
}
|
||||
}
|
||||
for (auto *param : member_vec) {
|
||||
if (strcmp(param->name_str(), name) == 0) {
|
||||
if (CompareKeys(param->name_str(), name)) {
|
||||
return param;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
// Removes the given pointer to the param from the given vector.
|
||||
template <class T>
|
||||
@ -105,6 +158,15 @@ public:
|
||||
// Print parameters to the given file.
|
||||
static void PrintParams(FILE *fp, const ParamsVectors *member_params);
|
||||
|
||||
// Report parameters' usage statistics, i.e. report which params have been
|
||||
// set, modified and read/checked until now during this run-time's lifetime.
|
||||
//
|
||||
// Use this method for run-time 'discovery' about which tesseract parameters
|
||||
// are actually *used* during your particular usage of the library, ergo
|
||||
// answering the question:
|
||||
// "Which of all those parameters are actually *relevant* to my use case today?"
|
||||
static void ReportParamsUsageStatistics(const ParamsVectors *member_params);
|
||||
|
||||
// Resets all parameters back to default values;
|
||||
static void ResetToDefaults(ParamsVectors *member_params);
|
||||
};
|
||||
@ -133,16 +195,29 @@ public:
|
||||
(constraint == SET_PARAM_CONSTRAINT_NON_INIT_ONLY && !this->is_init()));
|
||||
}
|
||||
|
||||
typedef struct access_counts {
|
||||
int reading;
|
||||
int writing;
|
||||
} access_counts_t;
|
||||
|
||||
access_counts_t access_counts() const {
|
||||
return access_counts_;
|
||||
}
|
||||
|
||||
virtual std::string formatted_value_str() const = 0;
|
||||
|
||||
protected:
|
||||
Param(const char *name, const char *comment, bool init)
|
||||
: name_(name), info_(comment), init_(init) {
|
||||
debug_ = (strstr(name, "debug") != nullptr) || (strstr(name, "display"));
|
||||
access_counts_ = {0,0};
|
||||
}
|
||||
|
||||
const char *name_; // name of this parameter
|
||||
const char *info_; // for menus
|
||||
bool init_; // needs to be set before init
|
||||
bool debug_;
|
||||
mutable access_counts_t access_counts_;
|
||||
};
|
||||
|
||||
class IntParam : public Param {
|
||||
@ -151,40 +226,51 @@ public:
|
||||
: Param(name, comment, init) {
|
||||
value_ = value;
|
||||
default_ = value;
|
||||
params_vec_ = &(vec->int_params);
|
||||
vec->int_params.push_back(this);
|
||||
access_counts_.writing++;
|
||||
params_vec_ = vec;
|
||||
vec->int_params().push_back(this);
|
||||
}
|
||||
~IntParam() {
|
||||
ParamUtils::RemoveParam<IntParam>(this, params_vec_);
|
||||
ParamUtils::RemoveParam<IntParam>(this, ¶ms_vec_->int_params());
|
||||
}
|
||||
operator int32_t() const {
|
||||
return value_;
|
||||
access_counts_.reading++;
|
||||
return value_;
|
||||
}
|
||||
void operator=(int32_t value) {
|
||||
value_ = value;
|
||||
access_counts_.writing++;
|
||||
value_ = value;
|
||||
}
|
||||
void set_value(int32_t value) {
|
||||
value_ = value;
|
||||
access_counts_.writing++;
|
||||
value_ = value;
|
||||
}
|
||||
void ResetToDefault() {
|
||||
value_ = default_;
|
||||
access_counts_.writing++;
|
||||
value_ = default_;
|
||||
}
|
||||
void ResetFrom(const ParamsVectors *vec) {
|
||||
for (auto *param : vec->int_params) {
|
||||
for (auto *param : vec->int_params_c()) {
|
||||
if (strcmp(param->name_str(), name_) == 0) {
|
||||
// printf("overriding param %s=%d by =%d\n", name_, value_,
|
||||
// param);
|
||||
value_ = *param;
|
||||
// tprintf("overriding param {}={} by ={}\n", name_, value_,
|
||||
// *param);
|
||||
access_counts_.writing++;
|
||||
value_ = *param;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual std::string formatted_value_str() const override {
|
||||
return std::to_string(value_);
|
||||
}
|
||||
|
||||
private:
|
||||
int32_t value_;
|
||||
int32_t default_;
|
||||
// Pointer to the vector that contains this param (not owned by this class).
|
||||
std::vector<IntParam *> *params_vec_;
|
||||
|
||||
// Pointer to the vector that contains this param (not owned by this class). Used by the destructor.
|
||||
ParamsVectors *params_vec_;
|
||||
};
|
||||
|
||||
class BoolParam : public Param {
|
||||
@ -193,40 +279,51 @@ public:
|
||||
: Param(name, comment, init) {
|
||||
value_ = value;
|
||||
default_ = value;
|
||||
params_vec_ = &(vec->bool_params);
|
||||
vec->bool_params.push_back(this);
|
||||
access_counts_.writing++;
|
||||
params_vec_ = vec;
|
||||
vec->bool_params().push_back(this);
|
||||
}
|
||||
~BoolParam() {
|
||||
ParamUtils::RemoveParam<BoolParam>(this, params_vec_);
|
||||
ParamUtils::RemoveParam<BoolParam>(this, ¶ms_vec_->bool_params());
|
||||
}
|
||||
operator bool() const {
|
||||
return value_;
|
||||
access_counts_.reading++;
|
||||
return value_;
|
||||
}
|
||||
void operator=(bool value) {
|
||||
value_ = value;
|
||||
access_counts_.writing++;
|
||||
value_ = value;
|
||||
}
|
||||
void set_value(bool value) {
|
||||
value_ = value;
|
||||
access_counts_.writing++;
|
||||
value_ = value;
|
||||
}
|
||||
void ResetToDefault() {
|
||||
value_ = default_;
|
||||
access_counts_.writing++;
|
||||
value_ = default_;
|
||||
}
|
||||
void ResetFrom(const ParamsVectors *vec) {
|
||||
for (auto *param : vec->bool_params) {
|
||||
for (auto *param : vec->bool_params_c()) {
|
||||
if (strcmp(param->name_str(), name_) == 0) {
|
||||
// printf("overriding param %s=%s by =%s\n", name_, value_ ? "true" :
|
||||
// tprintf("overriding param {}={} by ={}\n", name_, value_ ? "true" :
|
||||
// "false", *param ? "true" : "false");
|
||||
value_ = *param;
|
||||
access_counts_.writing++;
|
||||
value_ = *param;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual std::string formatted_value_str() const override {
|
||||
return std::to_string(value_);
|
||||
}
|
||||
|
||||
private:
|
||||
bool value_;
|
||||
bool default_;
|
||||
|
||||
// Pointer to the vector that contains this param (not owned by this class).
|
||||
std::vector<BoolParam *> *params_vec_;
|
||||
ParamsVectors *params_vec_;
|
||||
};
|
||||
|
||||
class StringParam : public Param {
|
||||
@ -236,52 +333,74 @@ public:
|
||||
: Param(name, comment, init) {
|
||||
value_ = value;
|
||||
default_ = value;
|
||||
params_vec_ = &(vec->string_params);
|
||||
vec->string_params.push_back(this);
|
||||
access_counts_.writing++;
|
||||
params_vec_ = vec;
|
||||
vec->string_params().push_back(this);
|
||||
}
|
||||
~StringParam() {
|
||||
ParamUtils::RemoveParam<StringParam>(this, params_vec_);
|
||||
ParamUtils::RemoveParam<StringParam>(this, ¶ms_vec_->string_params());
|
||||
}
|
||||
operator std::string &() {
|
||||
return value_;
|
||||
access_counts_.reading++;
|
||||
return value_;
|
||||
}
|
||||
const char *c_str() const {
|
||||
return value_.c_str();
|
||||
access_counts_.reading++;
|
||||
return value_.c_str();
|
||||
}
|
||||
bool contains(char c) const {
|
||||
return value_.find(c) != std::string::npos;
|
||||
access_counts_.reading++;
|
||||
return value_.find(c) != std::string::npos;
|
||||
}
|
||||
bool empty() const {
|
||||
return value_.empty();
|
||||
access_counts_.reading++;
|
||||
return value_.empty();
|
||||
}
|
||||
bool operator==(const std::string &other) const {
|
||||
return value_ == other;
|
||||
access_counts_.reading++;
|
||||
return value_ == other;
|
||||
}
|
||||
void operator=(const std::string &value) {
|
||||
value_ = value;
|
||||
access_counts_.writing++;
|
||||
value_ = value;
|
||||
}
|
||||
void set_value(const std::string &value) {
|
||||
value_ = value;
|
||||
access_counts_.writing++;
|
||||
value_ = value;
|
||||
}
|
||||
const std::string &value() {
|
||||
access_counts_.reading++;
|
||||
return value_;
|
||||
}
|
||||
void ResetToDefault() {
|
||||
value_ = default_;
|
||||
access_counts_.writing++;
|
||||
value_ = default_;
|
||||
}
|
||||
void ResetFrom(const ParamsVectors *vec) {
|
||||
for (auto *param : vec->string_params) {
|
||||
for (auto *param : vec->string_params_c()) {
|
||||
if (strcmp(param->name_str(), name_) == 0) {
|
||||
// printf("overriding param %s=%s by =%s\n", name_, value_,
|
||||
// tprintf("overriding param {}={} by ={}\n", name_, value_,
|
||||
// param->c_str());
|
||||
value_ = *param;
|
||||
access_counts_.writing++;
|
||||
value_ = *param;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual std::string formatted_value_str() const override {
|
||||
std::string rv = (const char *)u8"«";
|
||||
rv += value_;
|
||||
rv += (const char *)u8"»";
|
||||
return rv;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string value_;
|
||||
std::string default_;
|
||||
|
||||
// Pointer to the vector that contains this param (not owned by this class).
|
||||
std::vector<StringParam *> *params_vec_;
|
||||
ParamsVectors *params_vec_;
|
||||
};
|
||||
|
||||
class DoubleParam : public Param {
|
||||
@ -290,40 +409,57 @@ public:
|
||||
: Param(name, comment, init) {
|
||||
value_ = value;
|
||||
default_ = value;
|
||||
params_vec_ = &(vec->double_params);
|
||||
vec->double_params.push_back(this);
|
||||
access_counts_.writing++;
|
||||
params_vec_ = vec;
|
||||
vec->double_params().push_back(this);
|
||||
}
|
||||
~DoubleParam() {
|
||||
ParamUtils::RemoveParam<DoubleParam>(this, params_vec_);
|
||||
ParamUtils::RemoveParam<DoubleParam>(this, ¶ms_vec_->double_params());
|
||||
}
|
||||
operator double() const {
|
||||
return value_;
|
||||
access_counts_.reading++;
|
||||
return value_;
|
||||
}
|
||||
void operator=(double value) {
|
||||
value_ = value;
|
||||
access_counts_.writing++;
|
||||
value_ = value;
|
||||
}
|
||||
void set_value(double value) {
|
||||
value_ = value;
|
||||
access_counts_.writing++;
|
||||
value_ = value;
|
||||
}
|
||||
void ResetToDefault() {
|
||||
value_ = default_;
|
||||
access_counts_.writing++;
|
||||
value_ = default_;
|
||||
}
|
||||
void ResetFrom(const ParamsVectors *vec) {
|
||||
for (auto *param : vec->double_params) {
|
||||
for (auto *param : vec->double_params_c()) {
|
||||
if (strcmp(param->name_str(), name_) == 0) {
|
||||
// printf("overriding param %s=%f by =%f\n", name_, value_,
|
||||
// tprintf("overriding param {}={} by ={}\n", name_, value_,
|
||||
// *param);
|
||||
value_ = *param;
|
||||
access_counts_.writing++;
|
||||
value_ = *param;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual std::string formatted_value_str() const override {
|
||||
#if 0
|
||||
return std::to_string(value_); // always outputs %.6f format style values
|
||||
#else
|
||||
char sbuf[40];
|
||||
snprintf(sbuf, sizeof(sbuf), "%1.f", value_);
|
||||
return sbuf;
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
double value_;
|
||||
double default_;
|
||||
|
||||
// Pointer to the vector that contains this param (not owned by this class).
|
||||
std::vector<DoubleParam *> *params_vec_;
|
||||
ParamsVectors *params_vec_;
|
||||
};
|
||||
|
||||
// Global parameter lists.
|
||||
@ -338,6 +474,7 @@ private:
|
||||
TESS_API
|
||||
ParamsVectors *GlobalParams();
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* Note on defining parameters.
|
||||
*
|
||||
@ -382,6 +519,12 @@ ParamsVectors *GlobalParams();
|
||||
|
||||
#define double_INIT_MEMBER(name, val, comment, vec) name(val, #name, comment, true, vec)
|
||||
|
||||
// ------------------------------------
|
||||
|
||||
extern BOOL_VAR_H(debug_all);
|
||||
extern STRING_VAR_H(vars_report_file);
|
||||
extern BOOL_VAR_H(report_all_variables);
|
||||
|
||||
} // namespace tesseract
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user