2007-03-08 04:03:40 +08:00
|
|
|
/******************************************************************************
|
2016-11-08 02:46:33 +08:00
|
|
|
** Filename: picofeat.c
|
|
|
|
** Purpose: Definition of pico-features.
|
|
|
|
** Author: Dan Johnson
|
|
|
|
** History: 9/4/90, DSJ, Created.
|
2007-03-08 04:03:40 +08:00
|
|
|
**
|
2016-11-08 02:46:33 +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 "picofeat.h"
|
2010-11-24 02:34:14 +08:00
|
|
|
|
|
|
|
#include "classify.h"
|
|
|
|
#include "efio.h"
|
|
|
|
#include "featdefs.h"
|
2007-03-08 04:03:40 +08:00
|
|
|
#include "fpoint.h"
|
2010-11-24 02:34:14 +08:00
|
|
|
#include "mfoutline.h"
|
|
|
|
#include "ocrfeatures.h"
|
|
|
|
#include "params.h"
|
2012-02-02 10:57:42 +08:00
|
|
|
#include "trainingsample.h"
|
2007-03-08 04:03:40 +08:00
|
|
|
|
|
|
|
#include <math.h>
|
2010-11-24 02:34:14 +08:00
|
|
|
#include <stdio.h>
|
2007-03-08 04:03:40 +08:00
|
|
|
|
2009-07-11 10:17:36 +08:00
|
|
|
/*---------------------------------------------------------------------------
|
|
|
|
Variables
|
|
|
|
----------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
double_VAR(classify_pico_feature_length, 0.05, "Pico Feature Length");
|
2007-03-08 04:03:40 +08:00
|
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
|
|
Private Function Prototypes
|
|
|
|
----------------------------------------------------------------------------*/
|
|
|
|
void ConvertSegmentToPicoFeat(FPOINT *Start,
|
|
|
|
FPOINT *End,
|
|
|
|
FEATURE_SET FeatureSet);
|
|
|
|
|
2007-05-16 09:30:20 +08:00
|
|
|
void ConvertToPicoFeatures2(MFOUTLINE Outline, FEATURE_SET FeatureSet);
|
2007-03-08 04:03:40 +08:00
|
|
|
|
2007-05-16 09:30:20 +08:00
|
|
|
void NormalizePicoX(FEATURE_SET FeatureSet);
|
2007-03-08 04:03:40 +08:00
|
|
|
|
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
|
|
|
----------------------------------------------------------------------------*/
|
2007-03-08 04:03:40 +08:00
|
|
|
/*---------------------------------------------------------------------------*/
|
2010-11-24 02:34:14 +08:00
|
|
|
namespace tesseract {
|
2014-09-13 04:41:19 +08:00
|
|
|
/**
|
|
|
|
* Operation: Dummy for now.
|
|
|
|
*
|
|
|
|
* Globals:
|
|
|
|
* - classify_norm_method normalization method currently specified
|
|
|
|
* @param Blob blob to extract pico-features from
|
|
|
|
* @return Pico-features for Blob.
|
|
|
|
* @note Exceptions: none
|
|
|
|
* @note History: 9/4/90, DSJ, Created.
|
2007-03-08 04:03:40 +08:00
|
|
|
*/
|
2014-09-13 04:41:19 +08:00
|
|
|
FEATURE_SET Classify::ExtractPicoFeatures(TBLOB *Blob) {
|
2007-03-08 04:03:40 +08:00
|
|
|
LIST Outlines;
|
|
|
|
LIST RemainingOutlines;
|
|
|
|
MFOUTLINE Outline;
|
|
|
|
FEATURE_SET FeatureSet;
|
|
|
|
FLOAT32 XScale, YScale;
|
|
|
|
|
2010-11-24 02:34:14 +08:00
|
|
|
FeatureSet = NewFeatureSet(MAX_PICO_FEATURES);
|
|
|
|
Outlines = ConvertBlob(Blob);
|
|
|
|
NormalizeOutlines(Outlines, &XScale, &YScale);
|
2007-03-08 04:03:40 +08:00
|
|
|
RemainingOutlines = Outlines;
|
2007-05-16 09:30:20 +08:00
|
|
|
iterate(RemainingOutlines) {
|
|
|
|
Outline = (MFOUTLINE) first_node (RemainingOutlines);
|
|
|
|
ConvertToPicoFeatures2(Outline, FeatureSet);
|
2007-03-08 04:03:40 +08:00
|
|
|
}
|
2009-07-11 10:17:36 +08:00
|
|
|
if (classify_norm_method == baseline)
|
2007-05-16 09:30:20 +08:00
|
|
|
NormalizePicoX(FeatureSet);
|
|
|
|
FreeOutlines(Outlines);
|
2007-03-08 04:03:40 +08:00
|
|
|
return (FeatureSet);
|
|
|
|
|
|
|
|
} /* ExtractPicoFeatures */
|
2010-11-24 02:34:14 +08:00
|
|
|
} // namespace tesseract
|
2007-03-08 04:03:40 +08:00
|
|
|
|
2014-09-13 04:41:19 +08:00
|
|
|
/*----------------------------------------------------------------------------
|
2007-03-08 04:03:40 +08:00
|
|
|
Private Code
|
2014-09-13 04:41:19 +08:00
|
|
|
----------------------------------------------------------------------------*/
|
2007-03-08 04:03:40 +08:00
|
|
|
/*---------------------------------------------------------------------------*/
|
2014-09-13 04:41:19 +08:00
|
|
|
/**
|
|
|
|
* This routine converts an entire segment of an outline
|
|
|
|
* into a set of pico features which are added to
|
|
|
|
* FeatureSet. The length of the segment is rounded to the
|
|
|
|
* nearest whole number of pico-features. The pico-features
|
|
|
|
* are spaced evenly over the entire segment.
|
|
|
|
* Globals:
|
2016-11-08 02:46:33 +08:00
|
|
|
* - classify_pico_feature_length length of a single pico-feature
|
2014-09-13 04:41:19 +08:00
|
|
|
* @param Start starting point of pico-feature
|
|
|
|
* @param End ending point of pico-feature
|
|
|
|
* @param FeatureSet set to add pico-feature to
|
|
|
|
* @return none (results are placed in FeatureSet)
|
|
|
|
* @note Exceptions: none
|
|
|
|
* @note History: Tue Apr 30 15:44:34 1991, DSJ, Created.
|
|
|
|
*/
|
2007-03-08 04:03:40 +08:00
|
|
|
void ConvertSegmentToPicoFeat(FPOINT *Start,
|
|
|
|
FPOINT *End,
|
|
|
|
FEATURE_SET FeatureSet) {
|
|
|
|
FEATURE Feature;
|
|
|
|
FLOAT32 Angle;
|
|
|
|
FLOAT32 Length;
|
|
|
|
int NumFeatures;
|
|
|
|
FPOINT Center;
|
|
|
|
FPOINT Delta;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
Angle = NormalizedAngleFrom (Start, End, 1.0);
|
|
|
|
Length = DistanceBetween (*Start, *End);
|
2009-07-11 10:17:36 +08:00
|
|
|
NumFeatures = (int) floor (Length / classify_pico_feature_length + 0.5);
|
2007-03-08 04:03:40 +08:00
|
|
|
if (NumFeatures < 1)
|
|
|
|
NumFeatures = 1;
|
|
|
|
|
|
|
|
/* compute vector for one pico feature */
|
2009-03-11 03:03:06 +08:00
|
|
|
Delta.x = XDelta (*Start, *End) / NumFeatures;
|
|
|
|
Delta.y = YDelta (*Start, *End) / NumFeatures;
|
2007-03-08 04:03:40 +08:00
|
|
|
|
|
|
|
/* compute position of first pico feature */
|
2009-03-11 03:03:06 +08:00
|
|
|
Center.x = Start->x + Delta.x / 2.0;
|
|
|
|
Center.y = Start->y + Delta.y / 2.0;
|
2007-03-08 04:03:40 +08:00
|
|
|
|
|
|
|
/* compute each pico feature in segment and add to feature set */
|
|
|
|
for (i = 0; i < NumFeatures; i++) {
|
|
|
|
Feature = NewFeature (&PicoFeatDesc);
|
2009-03-11 03:03:06 +08:00
|
|
|
Feature->Params[PicoFeatDir] = Angle;
|
|
|
|
Feature->Params[PicoFeatX] = Center.x;
|
|
|
|
Feature->Params[PicoFeatY] = Center.y;
|
2007-05-16 09:30:20 +08:00
|
|
|
AddFeature(FeatureSet, Feature);
|
2007-03-08 04:03:40 +08:00
|
|
|
|
2009-03-11 03:03:06 +08:00
|
|
|
Center.x += Delta.x;
|
|
|
|
Center.y += Delta.y;
|
2007-03-08 04:03:40 +08:00
|
|
|
}
|
|
|
|
} /* ConvertSegmentToPicoFeat */
|
|
|
|
|
|
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
2014-09-13 04:41:19 +08:00
|
|
|
/**
|
2015-09-15 04:12:06 +08:00
|
|
|
* This routine steps through the specified outline and cuts it
|
2014-09-13 04:41:19 +08:00
|
|
|
* up into pieces of equal length. These pieces become the
|
|
|
|
* desired pico-features. Each segment in the outline
|
|
|
|
* is converted into an integral number of pico-features.
|
|
|
|
*
|
|
|
|
* Globals:
|
|
|
|
* - classify_pico_feature_length length of features to be extracted
|
|
|
|
* @param Outline outline to extract micro-features from
|
|
|
|
* @param FeatureSet set of features to add pico-features to
|
|
|
|
* @return none (results are returned in FeatureSet)
|
|
|
|
* @note Exceptions: none
|
|
|
|
* @note History: 4/30/91, DSJ, Adapted from ConvertToPicoFeatures().
|
2007-03-08 04:03:40 +08:00
|
|
|
*/
|
2014-09-13 04:41:19 +08:00
|
|
|
void ConvertToPicoFeatures2(MFOUTLINE Outline, FEATURE_SET FeatureSet) {
|
2007-03-08 04:03:40 +08:00
|
|
|
MFOUTLINE Next;
|
|
|
|
MFOUTLINE First;
|
|
|
|
MFOUTLINE Current;
|
|
|
|
|
2009-07-11 10:17:36 +08:00
|
|
|
if (DegenerateOutline(Outline))
|
2007-03-08 04:03:40 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
First = Outline;
|
|
|
|
Current = First;
|
2009-07-11 10:17:36 +08:00
|
|
|
Next = NextPointAfter(Current);
|
2007-03-08 04:03:40 +08:00
|
|
|
do {
|
|
|
|
/* note that an edge is hidden if the ending point of the edge is
|
|
|
|
marked as hidden. This situation happens because the order of
|
|
|
|
the outlines is reversed when they are converted from the old
|
|
|
|
format. In the old format, a hidden edge is marked by the
|
|
|
|
starting point for that edge. */
|
2009-07-11 10:17:36 +08:00
|
|
|
if (!(PointAt(Next)->Hidden))
|
|
|
|
ConvertSegmentToPicoFeat (&(PointAt(Current)->Point),
|
|
|
|
&(PointAt(Next)->Point), FeatureSet);
|
2007-03-08 04:03:40 +08:00
|
|
|
|
|
|
|
Current = Next;
|
2009-07-11 10:17:36 +08:00
|
|
|
Next = NextPointAfter(Current);
|
2007-03-08 04:03:40 +08:00
|
|
|
}
|
|
|
|
while (Current != First);
|
|
|
|
|
|
|
|
} /* ConvertToPicoFeatures2 */
|
|
|
|
|
|
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
2014-09-13 04:41:19 +08:00
|
|
|
/**
|
|
|
|
* This routine computes the average x position over all
|
|
|
|
* of the pico-features in FeatureSet and then renormalizes
|
|
|
|
* the pico-features to force this average to be the x origin
|
|
|
|
* (i.e. x=0).
|
|
|
|
* @param FeatureSet pico-features to be normalized
|
|
|
|
* @return none (FeatureSet is changed)
|
|
|
|
* @note Globals: none
|
|
|
|
* @note Exceptions: none
|
|
|
|
* @note History: Tue Sep 4 16:50:08 1990, DSJ, Created.
|
2007-03-08 04:03:40 +08:00
|
|
|
*/
|
2014-09-13 04:41:19 +08:00
|
|
|
void NormalizePicoX(FEATURE_SET FeatureSet) {
|
2007-03-08 04:03:40 +08:00
|
|
|
int i;
|
|
|
|
FEATURE Feature;
|
|
|
|
FLOAT32 Origin = 0.0;
|
|
|
|
|
2009-03-11 03:03:06 +08:00
|
|
|
for (i = 0; i < FeatureSet->NumFeatures; i++) {
|
|
|
|
Feature = FeatureSet->Features[i];
|
|
|
|
Origin += Feature->Params[PicoFeatX];
|
2007-03-08 04:03:40 +08:00
|
|
|
}
|
2009-03-11 03:03:06 +08:00
|
|
|
Origin /= FeatureSet->NumFeatures;
|
2007-03-08 04:03:40 +08:00
|
|
|
|
2009-03-11 03:03:06 +08:00
|
|
|
for (i = 0; i < FeatureSet->NumFeatures; i++) {
|
|
|
|
Feature = FeatureSet->Features[i];
|
|
|
|
Feature->Params[PicoFeatX] -= Origin;
|
2007-03-08 04:03:40 +08:00
|
|
|
}
|
|
|
|
} /* NormalizePicoX */
|
2012-02-02 10:57:42 +08:00
|
|
|
|
2015-05-13 06:22:34 +08:00
|
|
|
namespace tesseract {
|
2012-02-02 10:57:42 +08:00
|
|
|
/*---------------------------------------------------------------------------*/
|
2014-09-13 04:41:19 +08:00
|
|
|
/**
|
|
|
|
* @param blob blob to extract features from
|
|
|
|
* @param fx_info
|
|
|
|
* @return Integer character-normalized features for blob.
|
|
|
|
* @note Exceptions: none
|
|
|
|
* @note History: 8/8/2011, rays, Created.
|
|
|
|
*/
|
2015-05-13 06:22:34 +08:00
|
|
|
FEATURE_SET Classify::ExtractIntCNFeatures(
|
|
|
|
const TBLOB& blob, const INT_FX_RESULT_STRUCT& fx_info) {
|
2013-11-09 04:30:56 +08:00
|
|
|
INT_FX_RESULT_STRUCT local_fx_info(fx_info);
|
|
|
|
GenericVector<INT_FEATURE_STRUCT> bl_features;
|
2015-05-13 06:22:34 +08:00
|
|
|
tesseract::TrainingSample* sample = tesseract::BlobToTrainingSample(
|
|
|
|
blob, false, &local_fx_info, &bl_features);
|
2016-12-13 00:21:24 +08:00
|
|
|
if (sample == nullptr) return nullptr;
|
2012-02-02 10:57:42 +08:00
|
|
|
|
|
|
|
int num_features = sample->num_features();
|
|
|
|
const INT_FEATURE_STRUCT* features = sample->features();
|
|
|
|
FEATURE_SET feature_set = NewFeatureSet(num_features);
|
|
|
|
for (int f = 0; f < num_features; ++f) {
|
|
|
|
FEATURE feature = NewFeature(&IntFeatDesc);
|
|
|
|
|
|
|
|
feature->Params[IntX] = features[f].X;
|
|
|
|
feature->Params[IntY] = features[f].Y;
|
|
|
|
feature->Params[IntDir] = features[f].Theta;
|
|
|
|
AddFeature(feature_set, feature);
|
|
|
|
}
|
|
|
|
delete sample;
|
|
|
|
|
|
|
|
return feature_set;
|
|
|
|
} /* ExtractIntCNFeatures */
|
|
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
2014-09-13 04:41:19 +08:00
|
|
|
/**
|
|
|
|
* @param blob blob to extract features from
|
|
|
|
* @param fx_info
|
|
|
|
* @return Geometric (top/bottom/width) features for blob.
|
|
|
|
* @note Exceptions: none
|
|
|
|
* @note History: 8/8/2011, rays, Created.
|
|
|
|
*/
|
2015-05-13 06:22:34 +08:00
|
|
|
FEATURE_SET Classify::ExtractIntGeoFeatures(
|
|
|
|
const TBLOB& blob, const INT_FX_RESULT_STRUCT& fx_info) {
|
2013-11-09 04:30:56 +08:00
|
|
|
INT_FX_RESULT_STRUCT local_fx_info(fx_info);
|
|
|
|
GenericVector<INT_FEATURE_STRUCT> bl_features;
|
2015-05-13 06:22:34 +08:00
|
|
|
tesseract::TrainingSample* sample = tesseract::BlobToTrainingSample(
|
|
|
|
blob, false, &local_fx_info, &bl_features);
|
2016-12-13 00:21:24 +08:00
|
|
|
if (sample == nullptr) return nullptr;
|
2012-02-02 10:57:42 +08:00
|
|
|
|
|
|
|
FEATURE_SET feature_set = NewFeatureSet(1);
|
|
|
|
FEATURE feature = NewFeature(&IntFeatDesc);
|
|
|
|
|
|
|
|
feature->Params[GeoBottom] = sample->geo_feature(GeoBottom);
|
|
|
|
feature->Params[GeoTop] = sample->geo_feature(GeoTop);
|
|
|
|
feature->Params[GeoWidth] = sample->geo_feature(GeoWidth);
|
|
|
|
AddFeature(feature_set, feature);
|
|
|
|
delete sample;
|
|
|
|
|
|
|
|
return feature_set;
|
|
|
|
} /* ExtractIntGeoFeatures */
|
2015-05-13 06:22:34 +08:00
|
|
|
|
|
|
|
} // namespace tesseract.
|