Tesseract  3.02
tesseract-ocr/classify/mfx.cpp
Go to the documentation of this file.
00001 /******************************************************************************
00002  **      Filename:       mfx.c
00003  **      Purpose:        Micro feature extraction routines
00004  **      Author:         Dan Johnson
00005  **      History:        7/21/89, DSJ, Created.
00006  **
00007  **      (c) Copyright Hewlett-Packard Company, 1988.
00008  ** Licensed under the Apache License, Version 2.0 (the "License");
00009  ** you may not use this file except in compliance with the License.
00010  ** You may obtain a copy of the License at
00011  ** http://www.apache.org/licenses/LICENSE-2.0
00012  ** Unless required by applicable law or agreed to in writing, software
00013  ** distributed under the License is distributed on an "AS IS" BASIS,
00014  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00015  ** See the License for the specific language governing permissions and
00016  ** limitations under the License.
00017  ******************************************************************************/
00021 #include "mfdefs.h"
00022 #include "mfoutline.h"
00023 #include "clusttool.h"           //NEEDED
00024 #include "const.h"
00025 #include "intfx.h"
00026 #include "normalis.h"
00027 #include "params.h"
00028 
00029 #include <math.h>
00030 
00035 /* old numbers corresponded to 10.0 degrees and 80.0 degrees */
00036 double_VAR(classify_min_slope, 0.414213562,
00037            "Slope below which lines are called horizontal");
00038 double_VAR(classify_max_slope, 2.414213562,
00039            "Slope above which lines are called vertical");
00040 
00044 /* miscellaneous macros */
00045 #define NormalizeAngle(A)       ( (((A)<0)?((A)+2*PI):(A)) / (2*PI) )
00046 
00047 /*----------------------------------------------------------------------------
00048           Private Function Prototypes
00049 -----------------------------------------------------------------------------*/
00050 FLOAT32 ComputeOrientation(MFEDGEPT *Start, MFEDGEPT *End);
00051 
00052 MICROFEATURES ConvertToMicroFeatures(MFOUTLINE Outline,
00053                                      MICROFEATURES MicroFeatures);
00054 
00055 MICROFEATURE ExtractMicroFeature(MFOUTLINE Start, MFOUTLINE End);
00056 
00061 /*---------------------------------------------------------------------------*/
00062 CHAR_FEATURES BlobMicroFeatures(TBLOB *Blob, const DENORM& denorm) {
00063 /*
00064  **      Parameters:
00065  **              Blob            blob to extract micro-features from
00066  **              denorm          control parameter to feature extractor
00067  **      Operation:
00068  **              This routine extracts micro-features from the specified
00069  **              blob and returns a list of the micro-features.  All
00070  **              micro-features are normalized according to the specified
00071  **              line statistics.
00072  **      Return: List of micro-features extracted from the blob.
00073  **      Exceptions: none
00074  **      History: 7/21/89, DSJ, Created.
00075  */
00076   MICROFEATURES MicroFeatures = NIL_LIST;
00077   FLOAT32 XScale, YScale;
00078   LIST Outlines;
00079   LIST RemainingOutlines;
00080   MFOUTLINE Outline;
00081   INT_FEATURE_ARRAY blfeatures;
00082   INT_FEATURE_ARRAY cnfeatures;
00083   INT_FX_RESULT_STRUCT results;
00084 
00085   if (Blob != NULL) {
00086     Outlines = ConvertBlob (Blob);
00087     if (!ExtractIntFeat(Blob, denorm, blfeatures, cnfeatures, &results))
00088       return NULL;
00089     XScale = 0.2f / results.Ry;
00090     YScale = 0.2f / results.Rx;
00091 
00092     RemainingOutlines = Outlines;
00093     iterate(RemainingOutlines) {
00094       Outline = (MFOUTLINE) first_node (RemainingOutlines);
00095       CharNormalizeOutline (Outline,
00096         results.Xmean, results.Ymean,
00097         XScale, YScale);
00098     }
00099 
00100     RemainingOutlines = Outlines;
00101     iterate(RemainingOutlines) {
00102       Outline = (MFOUTLINE) first_node (RemainingOutlines);
00103       FindDirectionChanges(Outline, classify_min_slope, classify_max_slope);
00104       MarkDirectionChanges(Outline);
00105       MicroFeatures = ConvertToMicroFeatures (Outline, MicroFeatures);
00106     }
00107     FreeOutlines(Outlines);
00108   }
00109   return ((CHAR_FEATURES) MicroFeatures);
00110 }                                /* BlobMicroFeatures */
00111 
00112 
00113 /*---------------------------------------------------------------------------
00114             Private Code
00115 ---------------------------------------------------------------------------*/
00116 
00117 /*---------------------------------------------------------------------------*/
00118 FLOAT32 ComputeOrientation(MFEDGEPT *Start, MFEDGEPT *End) {
00119 /*
00120  **      Parameters:
00121  **              Start           starting edge point of micro-feature
00122  **              End             ending edge point of micro-feature
00123  **      Globals: none
00124  **      Operation:
00125  **              This routine computes the orientation parameter of the
00126  **              specified micro-feature.  The orientation is the angle of
00127  **              the vector from Start to End.  It is normalized to a number
00128  **              between 0 and 1 where 0 corresponds to 0 degrees and 1
00129  **              corresponds to 360 degrees.  The actual range is [0,1), i.e.
00130  **              1 is excluded from the range (since it is actual the
00131  **              same orientation as 0).  This routine assumes that Start
00132  **              and End are not the same point.
00133  **      Return: Orientation parameter for the specified micro-feature.
00134  **      Exceptions: none
00135  **      History: 7/27/89, DSJ, Created.
00136  */
00137   FLOAT32 Orientation;
00138 
00139   Orientation = NormalizeAngle (AngleFrom (Start->Point, End->Point));
00140 
00141   /* ensure that round-off errors do not put circular param out of range */
00142   if ((Orientation < 0) || (Orientation >= 1))
00143     Orientation = 0;
00144   return (Orientation);
00145 }                                /* ComputeOrientation */
00146 
00147 
00148 /*---------------------------------------------------------------------------*/
00149 MICROFEATURES ConvertToMicroFeatures(MFOUTLINE Outline,
00150                                      MICROFEATURES MicroFeatures) {
00151 /*
00152  **      Parameters:
00153  **              Outline         outline to extract micro-features from
00154  **              MicroFeatures   list of micro-features to add to
00155  **      Globals: none
00156  **      Operation:
00157  **              This routine
00158  **      Return: List of micro-features with new features added to front.
00159  **      Exceptions: none
00160  **      History: 7/26/89, DSJ, Created.
00161  */
00162   MFOUTLINE Current;
00163   MFOUTLINE Last;
00164   MFOUTLINE First;
00165   MICROFEATURE NewFeature;
00166 
00167   if (DegenerateOutline (Outline))
00168     return (MicroFeatures);
00169 
00170   First = NextExtremity (Outline);
00171   Last = First;
00172   do {
00173     Current = NextExtremity (Last);
00174     if (!PointAt(Current)->Hidden) {
00175       NewFeature = ExtractMicroFeature (Last, Current);
00176       if (NewFeature != NULL)
00177         MicroFeatures = push (MicroFeatures, NewFeature);
00178     }
00179     Last = Current;
00180   }
00181   while (Last != First);
00182 
00183   return (MicroFeatures);
00184 }                                /* ConvertToMicroFeatures */
00185 
00186 
00187 /*---------------------------------------------------------------------------*/
00188 MICROFEATURE ExtractMicroFeature(MFOUTLINE Start, MFOUTLINE End) {
00189 /*
00190  **      Parameters:
00191  **              Start           starting point of micro-feature
00192  **              End             ending point of micro-feature
00193  **      Globals: none
00194  **      Operation:
00195  **              This routine computes the feature parameters which describe
00196  **              the micro-feature that starts and Start and ends at End.
00197  **              A new micro-feature is allocated, filled with the feature
00198  **              parameters, and returned.  The routine assumes that
00199  **              Start and End are not the same point.  If they are the
00200  **              same point, NULL is returned, a warning message is
00201  **              printed, and the current outline is dumped to stdout.
00202  **      Return: New micro-feature or NULL if the feature was rejected.
00203  **      Exceptions: none
00204  **      History: 7/26/89, DSJ, Created.
00205  **              11/17/89, DSJ, Added handling for Start and End same point.
00206  */
00207   MICROFEATURE NewFeature;
00208   MFEDGEPT *P1, *P2;
00209 
00210   P1 = PointAt(Start);
00211   P2 = PointAt(End);
00212 
00213   NewFeature = NewMicroFeature ();
00214   NewFeature[XPOSITION] = AverageOf(P1->Point.x, P2->Point.x);
00215   NewFeature[YPOSITION] = AverageOf(P1->Point.y, P2->Point.y);
00216   NewFeature[MFLENGTH] = DistanceBetween(P1->Point, P2->Point);
00217   NewFeature[ORIENTATION] = NormalizedAngleFrom(&P1->Point, &P2->Point, 1.0);
00218   NewFeature[FIRSTBULGE] = 0.0f;  // deprecated
00219   NewFeature[SECONDBULGE] = 0.0f;  // deprecated
00220 
00221   return NewFeature;
00222 }                                /* ExtractMicroFeature */