2007-03-08 04:03:40 +08:00
|
|
|
/******************************************************************************
|
2016-11-25 22:14:46 +08:00
|
|
|
** Filename: features.c
|
|
|
|
** Purpose: Generic definition of a feature.
|
|
|
|
** Author: Dan Johnson
|
|
|
|
** History: Mon May 21 10:49:04 1990, DSJ, Created.
|
2007-03-08 04:03:40 +08:00
|
|
|
**
|
2016-11-25 22:14:46 +08:00
|
|
|
** (c) Copyright Hewlett-Packard Company, 1988.
|
2007-03-08 04:03:40 +08:00
|
|
|
** 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.
|
|
|
|
******************************************************************************/
|
2014-09-13 04:41:19 +08:00
|
|
|
/*----------------------------------------------------------------------------
|
2007-03-08 04:03:40 +08:00
|
|
|
Include Files and Type Defines
|
2014-09-13 04:41:19 +08:00
|
|
|
----------------------------------------------------------------------------*/
|
2007-03-08 04:03:40 +08:00
|
|
|
#include "ocrfeatures.h"
|
|
|
|
#include "emalloc.h"
|
|
|
|
#include "callcpp.h"
|
|
|
|
#include "danerror.h"
|
|
|
|
#include "freelist.h"
|
|
|
|
#include "scanutils.h"
|
|
|
|
|
2009-07-11 10:17:36 +08:00
|
|
|
#include <assert.h>
|
|
|
|
#include <math.h>
|
|
|
|
|
2014-09-13 04:41:19 +08:00
|
|
|
/*----------------------------------------------------------------------------
|
2007-03-08 04:03:40 +08:00
|
|
|
Public Code
|
2014-09-13 04:41:19 +08:00
|
|
|
----------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
|
|
* Add a feature to a feature set. If the feature set is
|
|
|
|
* already full, FALSE is returned to indicate that the
|
|
|
|
* feature could not be added to the set; otherwise, TRUE is
|
|
|
|
* returned.
|
|
|
|
* @param FeatureSet set of features to add Feature to
|
|
|
|
* @param Feature feature to be added to FeatureSet
|
|
|
|
* @return TRUE if feature added to set, FALSE if set is already full.
|
|
|
|
* @note History: Tue May 22 17:22:23 1990, DSJ, Created.
|
2007-03-08 04:03:40 +08:00
|
|
|
*/
|
2014-09-13 04:41:19 +08:00
|
|
|
BOOL8 AddFeature(FEATURE_SET FeatureSet, FEATURE Feature) {
|
2009-03-11 03:03:06 +08:00
|
|
|
if (FeatureSet->NumFeatures >= FeatureSet->MaxNumFeatures) {
|
2007-03-08 04:03:40 +08:00
|
|
|
FreeFeature(Feature);
|
2009-07-11 10:17:36 +08:00
|
|
|
return FALSE;
|
2007-03-08 04:03:40 +08:00
|
|
|
}
|
|
|
|
|
2009-07-11 10:17:36 +08:00
|
|
|
FeatureSet->Features[FeatureSet->NumFeatures++] = Feature;
|
|
|
|
return TRUE;
|
2007-03-08 04:03:40 +08:00
|
|
|
} /* AddFeature */
|
|
|
|
|
2014-09-13 04:41:19 +08:00
|
|
|
/**
|
|
|
|
* Release the memory consumed by the specified feature.
|
|
|
|
* @param Feature feature to be deallocated.
|
|
|
|
* @return none
|
|
|
|
* @note History: Mon May 21 13:33:27 1990, DSJ, Created.
|
2007-03-08 04:03:40 +08:00
|
|
|
*/
|
2014-09-13 04:41:19 +08:00
|
|
|
void FreeFeature(FEATURE Feature) {
|
2007-03-08 04:03:40 +08:00
|
|
|
if (Feature) {
|
2009-07-11 10:17:36 +08:00
|
|
|
free_struct (Feature, sizeof (FEATURE_STRUCT)
|
2009-03-11 03:03:06 +08:00
|
|
|
+ sizeof (FLOAT32) * (Feature->Type->NumParams - 1),
|
2007-03-08 04:03:40 +08:00
|
|
|
"sizeof(FEATURE_STRUCT)+sizeof(FLOAT32)*(NumParamsIn(Feature)-1)");
|
|
|
|
}
|
|
|
|
|
|
|
|
} /* FreeFeature */
|
|
|
|
|
2014-09-13 04:41:19 +08:00
|
|
|
/**
|
|
|
|
* Release the memory consumed by the specified feature
|
|
|
|
* set. This routine also frees the memory consumed by the
|
|
|
|
* features contained in the set.
|
2016-11-25 22:14:46 +08:00
|
|
|
* @param FeatureSet set of features to be freed
|
2014-09-13 04:41:19 +08:00
|
|
|
* @return none
|
|
|
|
* @note History: Mon May 21 13:59:46 1990, DSJ, Created.
|
2007-03-08 04:03:40 +08:00
|
|
|
*/
|
2014-09-13 04:41:19 +08:00
|
|
|
void FreeFeatureSet(FEATURE_SET FeatureSet) {
|
2007-03-08 04:03:40 +08:00
|
|
|
int i;
|
|
|
|
|
|
|
|
if (FeatureSet) {
|
2009-03-11 03:03:06 +08:00
|
|
|
for (i = 0; i < FeatureSet->NumFeatures; i++)
|
2009-07-11 10:17:36 +08:00
|
|
|
FreeFeature(FeatureSet->Features[i]);
|
2007-03-08 04:03:40 +08:00
|
|
|
memfree(FeatureSet);
|
|
|
|
}
|
|
|
|
} /* FreeFeatureSet */
|
|
|
|
|
2014-09-13 04:41:19 +08:00
|
|
|
/**
|
|
|
|
* Allocate and return a new feature of the specified
|
|
|
|
* type.
|
2016-11-25 22:14:46 +08:00
|
|
|
* @param FeatureDesc description of feature to be created.
|
2014-09-13 04:41:19 +08:00
|
|
|
* @return New #FEATURE.
|
|
|
|
* @note History: Mon May 21 14:06:42 1990, DSJ, Created.
|
2007-03-08 04:03:40 +08:00
|
|
|
*/
|
2014-09-13 04:41:19 +08:00
|
|
|
FEATURE NewFeature(const FEATURE_DESC_STRUCT* FeatureDesc) {
|
2007-03-08 04:03:40 +08:00
|
|
|
FEATURE Feature;
|
|
|
|
|
2009-03-11 03:03:06 +08:00
|
|
|
Feature = (FEATURE) alloc_struct (sizeof (FEATURE_STRUCT) +
|
2007-03-08 04:03:40 +08:00
|
|
|
(FeatureDesc->NumParams - 1) *
|
|
|
|
sizeof (FLOAT32),
|
|
|
|
"sizeof(FEATURE_STRUCT)+sizeof(FLOAT32)*(NumParamsIn(Feature)-1)");
|
2009-03-11 03:03:06 +08:00
|
|
|
Feature->Type = FeatureDesc;
|
2007-03-08 04:03:40 +08:00
|
|
|
return (Feature);
|
|
|
|
|
|
|
|
} /* NewFeature */
|
|
|
|
|
2014-09-13 04:41:19 +08:00
|
|
|
/**
|
|
|
|
* Allocate and return a new feature set large enough to
|
|
|
|
* hold the specified number of features.
|
2016-11-25 22:14:46 +08:00
|
|
|
* @param NumFeatures maximum # of features to be put in feature set
|
2014-09-13 04:41:19 +08:00
|
|
|
* @return New #FEATURE_SET.
|
|
|
|
* @note History: Mon May 21 14:22:40 1990, DSJ, Created.
|
2007-03-08 04:03:40 +08:00
|
|
|
*/
|
2014-09-13 04:41:19 +08:00
|
|
|
FEATURE_SET NewFeatureSet(int NumFeatures) {
|
2007-03-08 04:03:40 +08:00
|
|
|
FEATURE_SET FeatureSet;
|
|
|
|
|
|
|
|
FeatureSet = (FEATURE_SET) Emalloc (sizeof (FEATURE_SET_STRUCT) +
|
|
|
|
(NumFeatures - 1) * sizeof (FEATURE));
|
2009-03-11 03:03:06 +08:00
|
|
|
FeatureSet->MaxNumFeatures = NumFeatures;
|
|
|
|
FeatureSet->NumFeatures = 0;
|
2007-03-08 04:03:40 +08:00
|
|
|
return (FeatureSet);
|
|
|
|
|
|
|
|
} /* NewFeatureSet */
|
|
|
|
|
2014-09-13 04:41:19 +08:00
|
|
|
/**
|
|
|
|
* Create a new feature of the specified type and read in
|
|
|
|
* the value of its parameters from File. The extra penalty
|
|
|
|
* for the feature is also computed by calling the appropriate
|
|
|
|
* function for the specified feature type. The correct text
|
|
|
|
* representation for a feature is a list of N floats where
|
|
|
|
* N is the number of parameters in the feature.
|
|
|
|
* @param File open text file to read feature from
|
|
|
|
* @param FeatureDesc specifies type of feature to read from File
|
|
|
|
* @return New #FEATURE read from File.
|
2016-11-25 22:14:46 +08:00
|
|
|
* @note Exceptions: #ILLEGAL_FEATURE_PARAM if text file doesn't match expected
|
|
|
|
* format
|
2014-09-13 04:41:19 +08:00
|
|
|
* @note History: Wed May 23 08:53:16 1990, DSJ, Created.
|
2007-03-08 04:03:40 +08:00
|
|
|
*/
|
2016-11-25 22:14:46 +08:00
|
|
|
FEATURE ReadFeature(FILE* File, const FEATURE_DESC_STRUCT* FeatureDesc) {
|
2007-03-08 04:03:40 +08:00
|
|
|
FEATURE Feature;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
Feature = NewFeature (FeatureDesc);
|
2009-03-11 03:03:06 +08:00
|
|
|
for (i = 0; i < Feature->Type->NumParams; i++) {
|
2014-04-29 07:10:48 +08:00
|
|
|
if (tfscanf(File, "%f", &(Feature->Params[i])) != 1)
|
2007-03-08 04:03:40 +08:00
|
|
|
DoError (ILLEGAL_FEATURE_PARAM, "Illegal feature parameter spec");
|
2012-03-03 01:31:24 +08:00
|
|
|
#ifndef _WIN32
|
2009-07-11 10:17:36 +08:00
|
|
|
assert (!isnan(Feature->Params[i]));
|
|
|
|
#endif
|
2007-03-08 04:03:40 +08:00
|
|
|
}
|
|
|
|
return (Feature);
|
|
|
|
} /* ReadFeature */
|
|
|
|
|
2014-09-13 04:41:19 +08:00
|
|
|
/**
|
|
|
|
* Create a new feature set of the specified type and read in
|
|
|
|
* the features from File. The correct text representation
|
|
|
|
* for a feature set is an integer which specifies the number (N)
|
|
|
|
* of features in a set followed by a list of N feature
|
|
|
|
* descriptions.
|
|
|
|
* @param File open text file to read new feature set from
|
|
|
|
* @param FeatureDesc specifies type of feature to read from File
|
|
|
|
* @return New feature set read from File.
|
|
|
|
* @note History: Wed May 23 09:17:31 1990, DSJ, Created.
|
2007-03-08 04:03:40 +08:00
|
|
|
*/
|
2016-11-25 22:14:46 +08:00
|
|
|
FEATURE_SET ReadFeatureSet(FILE* File, const FEATURE_DESC_STRUCT* FeatureDesc) {
|
2007-03-08 04:03:40 +08:00
|
|
|
FEATURE_SET FeatureSet;
|
|
|
|
int NumFeatures;
|
|
|
|
int i;
|
|
|
|
|
2014-04-24 07:12:53 +08:00
|
|
|
if (tfscanf(File, "%d", &NumFeatures) != 1 || NumFeatures < 0)
|
|
|
|
DoError(ILLEGAL_NUM_FEATURES, "Illegal number of features in set");
|
2007-03-08 04:03:40 +08:00
|
|
|
|
2014-04-24 07:12:53 +08:00
|
|
|
FeatureSet = NewFeatureSet(NumFeatures);
|
2007-03-08 04:03:40 +08:00
|
|
|
for (i = 0; i < NumFeatures; i++)
|
2014-04-24 07:12:53 +08:00
|
|
|
AddFeature(FeatureSet, ReadFeature (File, FeatureDesc));
|
2007-03-08 04:03:40 +08:00
|
|
|
|
|
|
|
return (FeatureSet);
|
|
|
|
} /* ReadFeatureSet */
|
|
|
|
|
2014-09-13 04:41:19 +08:00
|
|
|
/**
|
|
|
|
* Appends a textual representation of Feature to str.
|
|
|
|
* This representation is simply a list of the N parameters
|
|
|
|
* of the feature, terminated with a newline. It is assumed
|
|
|
|
* that the ExtraPenalty field can be reconstructed from the
|
|
|
|
* parameters of the feature. It is also assumed that the
|
|
|
|
* feature type information is specified or assumed elsewhere.
|
|
|
|
* @param Feature feature to write out to str
|
|
|
|
* @param str string to write Feature to
|
|
|
|
* @return none
|
|
|
|
* @note History: Wed May 23 09:28:18 1990, DSJ, Created.
|
2007-03-08 04:03:40 +08:00
|
|
|
*/
|
2015-05-13 06:22:34 +08:00
|
|
|
void WriteFeature(FEATURE Feature, STRING* str) {
|
|
|
|
for (int i = 0; i < Feature->Type->NumParams; i++) {
|
2013-09-23 23:15:06 +08:00
|
|
|
#ifndef WIN32
|
2012-02-02 10:57:42 +08:00
|
|
|
assert(!isnan(Feature->Params[i]));
|
2009-07-11 10:17:36 +08:00
|
|
|
#endif
|
2015-05-13 06:22:34 +08:00
|
|
|
str->add_str_double(" ", Feature->Params[i]);
|
2009-07-11 10:17:36 +08:00
|
|
|
}
|
2015-05-13 06:22:34 +08:00
|
|
|
*str += "\n";
|
2007-03-08 04:03:40 +08:00
|
|
|
} /* WriteFeature */
|
|
|
|
|
2014-09-13 04:41:19 +08:00
|
|
|
/**
|
|
|
|
* Write a textual representation of FeatureSet to File.
|
|
|
|
* This representation is an integer specifying the number of
|
|
|
|
* features in the set, followed by a newline, followed by
|
|
|
|
* text representations for each feature in the set.
|
|
|
|
* @param FeatureSet feature set to write to File
|
|
|
|
* @param str string to write Feature to
|
|
|
|
* @return none
|
|
|
|
* @note History: Wed May 23 10:06:03 1990, DSJ, Created.
|
2007-03-08 04:03:40 +08:00
|
|
|
*/
|
2015-05-13 06:22:34 +08:00
|
|
|
void WriteFeatureSet(FEATURE_SET FeatureSet, STRING* str) {
|
2007-03-08 04:03:40 +08:00
|
|
|
if (FeatureSet) {
|
2015-05-13 06:22:34 +08:00
|
|
|
str->add_str_int("", FeatureSet->NumFeatures);
|
|
|
|
*str += "\n";
|
|
|
|
for (int i = 0; i < FeatureSet->NumFeatures; i++) {
|
|
|
|
WriteFeature(FeatureSet->Features[i], str);
|
|
|
|
}
|
2007-03-08 04:03:40 +08:00
|
|
|
}
|
|
|
|
} /* WriteFeatureSet */
|
|
|
|
|
2014-09-13 04:41:19 +08:00
|
|
|
/**
|
|
|
|
* Write a textual representation of FeatureDesc to File
|
|
|
|
* in the old format (i.e. the format used by the clusterer).
|
|
|
|
*
|
|
|
|
* This format is:
|
|
|
|
* @verbatim
|
|
|
|
* Number of Params
|
|
|
|
* Description of Param 1
|
|
|
|
* ...
|
|
|
|
* @endverbatim
|
|
|
|
* @param File open text file to write FeatureDesc to
|
|
|
|
* @param FeatureDesc feature descriptor to write to File
|
|
|
|
* @return none
|
|
|
|
* @note History: Fri May 25 15:27:18 1990, DSJ, Created.
|
2007-03-08 04:03:40 +08:00
|
|
|
*/
|
2016-11-25 22:14:46 +08:00
|
|
|
void WriteOldParamDesc(FILE* File, const FEATURE_DESC_STRUCT* FeatureDesc) {
|
2007-03-08 04:03:40 +08:00
|
|
|
int i;
|
|
|
|
|
|
|
|
fprintf (File, "%d\n", FeatureDesc->NumParams);
|
|
|
|
for (i = 0; i < FeatureDesc->NumParams; i++) {
|
|
|
|
if (FeatureDesc->ParamDesc[i].Circular)
|
|
|
|
fprintf (File, "circular ");
|
|
|
|
else
|
|
|
|
fprintf (File, "linear ");
|
|
|
|
|
|
|
|
if (FeatureDesc->ParamDesc[i].NonEssential)
|
|
|
|
fprintf (File, "non-essential ");
|
|
|
|
else
|
|
|
|
fprintf (File, "essential ");
|
|
|
|
|
|
|
|
fprintf (File, "%f %f\n",
|
|
|
|
FeatureDesc->ParamDesc[i].Min, FeatureDesc->ParamDesc[i].Max);
|
|
|
|
}
|
|
|
|
} /* WriteOldParamDesc */
|