classify/mfx.cpp

Go to the documentation of this file.
00001 
00020 /* =================
00021           Include Files and Type Defines
00022  ==================== */
00023 #include "mfdefs.h"
00024 #include "variables.h"
00025 #include "sigmenu.h"
00026 #include "mfoutline.h"
00027 #include "clusttool.h"           //NEEDED
00028 #include "const.h"
00029 #include "intfx.h"
00030 #include <math.h>
00031 
00032 /* default values for tunable knobs */
00033 /* old numbers corresponded to 10.0 degrees and 80.0 degrees */
00034 /* PREV DEFAULT 0.176326981 approx. 10.0 degrees */
00035 #define MIN_SLOPE               0.414213562
00036 /* PREV DEFAULT 5.671281820 approx. 80.0 degrees */
00037 #define MAX_SLOPE               2.414213562
00038 /* no noise filtering */
00039 #define NOISE_SEGMENT_LENGTH    (0.00)
00040 /* no feature splitting */
00041 #define MAX_FEATURE_LENGTH      (MAXFLOAT)
00042 
00043 /* =================
00044           Macros
00045  ==================== */
00046 /* miscellaneous macros */
00047 #define NormalizeAngle(A)       ( (((A)<0)?((A)+2*PI):(A)) / (2*PI) )
00048 
00049 /*----------------------------------------------------------------------------
00050           Private Function Prototypes
00051 -----------------------------------------------------------------------------*/
00052 void ComputeBulges(MFOUTLINE Start, MFOUTLINE End, MICROFEATURE MicroFeature);
00053 
00054 FLOAT32 ComputeOrientation(MFEDGEPT *Start, MFEDGEPT *End);
00055 
00056 MICROFEATURES ConvertToMicroFeatures(MFOUTLINE Outline,
00057                                      MICROFEATURES MicroFeatures);
00058 
00059 MICROFEATURE ExtractMicroFeature(MFOUTLINE Start, MFOUTLINE End);
00060 
00061 void SmearBulges(MICROFEATURES MicroFeatures, FLOAT32 XScale, FLOAT32 YScale);
00062 
00063 /*
00064 #if defined(__STDC__) || defined(__cplusplus)
00065 # define _ARGS(s) s
00066 #else
00067 # define _ARGS(s) ()
00068 #endif*/
00069 
00070 /* /users/danj/wiseowl/src/danj/microfeatures/mfx.c
00071 void ComputeBulges
00072   _ARGS((MFOUTLINE Start,
00073   MFOUTLINE End,
00074   MICROFEATURE MicroFeature));
00075 
00076 FLOAT32 ComputeOrientation
00077   _ARGS((MFEDGEPT *Start,
00078   MFEDGEPT *End));
00079 
00080 MICROFEATURES ConvertToMicroFeatures
00081   _ARGS((MFOUTLINE Outline,
00082   MICROFEATURES MicroFeatures));
00083 
00084 MICROFEATURE ExtractMicroFeature
00085   _ARGS((MFOUTLINE Start,
00086   MFOUTLINE End));
00087 
00088 void SmearBulges
00089   _ARGS((MICROFEATURES MicroFeatures,
00090   FLOAT32 XScale,
00091   FLOAT32 YScale));
00092 
00093 #undef _ARGS
00094 */
00095 
00096 /* =================
00097         Global Data Definitions and Declarations
00098  ==================== */
00099 /* tuning knobs that can be adjusted without recompilation */
00100 static FLOAT32 MinSlope;
00101 static FLOAT32 MaxSlope;
00102 static FLOAT32 NoiseSegmentLength;
00103 
00104 /* =================
00105             Public Code
00106  ==================== */
00107 /* =============================== */
00126 void InitMicroFxVars() { 
00127   VALUE dummy;
00128 
00129   float_variable (MinSlope, "MinSlope", MIN_SLOPE);
00130   float_variable (MaxSlope, "MaxSlope", MAX_SLOPE);
00131   float_variable (NoiseSegmentLength, "NoiseSegmentLength",
00132     NOISE_SEGMENT_LENGTH);
00133 }                                /* InitMicroFxVars */
00134 
00135 
00136 /* =============================== */
00150 CHAR_FEATURES BlobMicroFeatures(TBLOB *Blob, LINE_STATS *LineStats) { 
00151   MICROFEATURES MicroFeatures = NIL;
00152   FLOAT32 XScale, YScale;
00153   LIST Outlines;
00154   LIST RemainingOutlines;
00155   MFOUTLINE Outline;
00156   INT_FEATURE_ARRAY blfeatures;
00157   INT_FEATURE_ARRAY cnfeatures;
00158   INT_FX_RESULT_STRUCT results;
00159 
00160   if (Blob != NULL) {
00161     Outlines = ConvertBlob (Blob);
00162 //    NormalizeOutlines(Outlines, LineStats, &XScale, &YScale); 
00163     ExtractIntFeat(Blob, blfeatures, cnfeatures, &results);
00164     XScale = 0.2f / results.Ry;
00165     YScale = 0.2f / results.Rx;
00166 
00167     RemainingOutlines = Outlines;
00168     iterate(RemainingOutlines) { 
00169       Outline = (MFOUTLINE) first (RemainingOutlines);
00170       CharNormalizeOutline (Outline,
00171         results.Xmean, results.Ymean,
00172         XScale, YScale);
00173     }
00174 
00175     RemainingOutlines = Outlines;
00176     iterate(RemainingOutlines) {
00177       Outline = (MFOUTLINE) first (RemainingOutlines);
00178       FindDirectionChanges(Outline, MinSlope, MaxSlope);
00179       FilterEdgeNoise(Outline, NoiseSegmentLength);
00180       MarkDirectionChanges(Outline);
00181       SmearExtremities(Outline, XScale, YScale);
00182       MicroFeatures = ConvertToMicroFeatures (Outline, MicroFeatures);
00183     }
00184     SmearBulges(MicroFeatures, XScale, YScale);
00185     FreeOutlines(Outlines);
00186   }
00187   return ((CHAR_FEATURES) MicroFeatures);
00188 }                                /* BlobMicroFeatures */
00189 
00190 
00191 /* =================
00192               Private Macros
00193  ==================== */
00197 #define angle_of(x1,y1,x2,y2)                   \
00198 ((x2-x1) ?                                    \
00199    (atan2 (y2-y1, x2-x1)) :                     \
00200    ((y2<y1) ? (- PI / 2.0) : (PI / 2.0)))   \
00201 
00202 
00208 #define scale_angle(x)                             \
00209 (((x<0) ? (2.0 * PI + x) : (x)) * 0.5 / PI)  \
00210 
00211 /*---------------------------------------------------------------------------
00212             Private Code
00213 ---------------------------------------------------------------------------*/
00214 /* =============================== */
00240 void ComputeBulges(MFOUTLINE Start, MFOUTLINE End, MICROFEATURE MicroFeature) { 
00241   MATRIX_2D Matrix;
00242   MFEDGEPT *Origin;
00243   MFOUTLINE SegmentStart, SegmentEnd;
00244   FPOINT CurrentPoint, LastPoint;
00245   FLOAT32 BulgePosition;
00246 
00247   /* check for simple case */
00248   if (End == NextPointAfter (Start))
00249     FirstBulgeOf (MicroFeature) = SecondBulgeOf (MicroFeature) = 0;
00250   else {
00251     Origin = PointAt (Start);
00252 
00253     InitMatrix(&Matrix);
00254     RotateMatrix (&Matrix, OrientationOf (MicroFeature) * -2.0 * PI);
00255     TranslateMatrix (&Matrix, -XPositionOf (Origin), -YPositionOf (Origin));
00256 
00257     SegmentEnd = Start;
00258     FillPoint (CurrentPoint, 0, 0);
00259     BulgePosition = LengthOf (MicroFeature) / 3;
00260     CopyPoint(CurrentPoint, LastPoint);
00261     while (Xof (CurrentPoint) < BulgePosition) {
00262       SegmentStart = SegmentEnd;
00263       SegmentEnd = NextPointAfter (SegmentStart);
00264       CopyPoint(CurrentPoint, LastPoint);
00265       MapPoint (&Matrix, PositionOf (PointAt (SegmentEnd)), CurrentPoint);
00266     }
00267     FirstBulgeOf (MicroFeature) =
00268       XIntersectionOf(LastPoint, CurrentPoint, BulgePosition);
00269 
00270     BulgePosition *= 2;
00271 
00272     // Prevents from copying the points before computing the bulge if
00273     // CurrentPoint will not change. (Which would cause to output nan
00274     // for the SecondBulge.)
00275     if (Xof (CurrentPoint) < BulgePosition)
00276       CopyPoint(CurrentPoint, LastPoint);
00277     while (Xof (CurrentPoint) < BulgePosition) {
00278       SegmentStart = SegmentEnd;
00279       SegmentEnd = NextPointAfter (SegmentStart);
00280       CopyPoint(CurrentPoint, LastPoint);
00281       MapPoint (&Matrix, PositionOf (PointAt (SegmentEnd)), CurrentPoint);
00282     }
00283     SecondBulgeOf (MicroFeature) =
00284       XIntersectionOf(LastPoint, CurrentPoint, BulgePosition);
00285 
00286     FirstBulgeOf (MicroFeature) /= BULGENORMALIZER *
00287       LengthOf(MicroFeature);
00288     SecondBulgeOf (MicroFeature) /= BULGENORMALIZER *
00289       LengthOf(MicroFeature);
00290   }
00291 }                                /* ComputeBulges */
00292 
00293 
00294 /* =============================== */
00314 FLOAT32 ComputeOrientation(MFEDGEPT *Start, MFEDGEPT *End) { 
00315   FLOAT32 Orientation;
00316 
00317   Orientation = NormalizeAngle (AngleFrom (PositionOf (Start),
00318     PositionOf (End)));
00319 
00320   /* ensure that round-off errors do not put circular param out of range */
00321   if ((Orientation < 0) || (Orientation >= 1))
00322     Orientation = 0;
00323   return (Orientation);
00324 }                                /* ComputeOrientation */
00325 
00326 
00327 /* =============================== */
00337 MICROFEATURES ConvertToMicroFeatures(MFOUTLINE Outline,
00338                                      MICROFEATURES MicroFeatures) {
00339   MFOUTLINE Current;
00340   MFOUTLINE Last;
00341   MFOUTLINE First;
00342   MICROFEATURE NewFeature;
00343 
00344   if (DegenerateOutline (Outline))
00345     return (MicroFeatures);
00346 
00347   First = NextExtremity (Outline);
00348   Last = First;
00349   do {
00350     Current = NextExtremity (Last);
00351     NewFeature = ExtractMicroFeature (Last, Current);
00352     if (NewFeature != NULL)
00353       MicroFeatures = push (MicroFeatures, NewFeature);
00354     Last = Current;
00355   }
00356   while (Last != First);
00357 
00358   return (MicroFeatures);
00359 }                                /* ConvertToMicroFeatures */
00360 
00361 
00362 /* =============================== */
00380 MICROFEATURE ExtractMicroFeature(MFOUTLINE Start, MFOUTLINE End) { 
00381   MICROFEATURE NewFeature;
00382   MFEDGEPT *P1, *P2;
00383 
00384   P1 = PointAt (Start);
00385   P2 = PointAt (End);
00386 
00387   NewFeature = NewMicroFeature ();
00388   CenterX (NewFeature) = AverageOf (XPositionOf (P1), XPositionOf (P2));
00389   CenterY (NewFeature) = AverageOf (YPositionOf (P1), YPositionOf (P2));
00390   LengthOf (NewFeature) = DistanceBetween (PositionOf (P1), PositionOf (P2));
00391   OrientationOf (NewFeature) =
00392     NormalizedAngleFrom (&(PositionOf (P1)), &(PositionOf (P2)), 1.0);
00393   ComputeBulges(Start, End, NewFeature);
00394   return (NewFeature);
00395 }                                /* ExtractMicroFeature */
00396 
00397 
00398 /* =============================== */
00413 void SmearBulges(MICROFEATURES MicroFeatures, FLOAT32 XScale, FLOAT32 YScale) { 
00414   MICROFEATURE MicroFeature;
00415   FLOAT32 MinSmear;
00416   FLOAT32 MaxSmear;
00417   FLOAT32 Cos, Sin;
00418   FLOAT32 Scale;
00419 
00420   iterate(MicroFeatures) {
00421     MicroFeature = NextFeatureOf (MicroFeatures);
00422 
00423     Cos = fabs (cos (2.0 * PI * OrientationOf (MicroFeature)));
00424     Sin = fabs (sin (2.0 * PI * OrientationOf (MicroFeature)));
00425     Scale = YScale * Cos + XScale * Sin;
00426 
00427     MinSmear = -0.5 * Scale / (BULGENORMALIZER * LengthOf (MicroFeature));
00428     MaxSmear = 0.5 * Scale / (BULGENORMALIZER * LengthOf (MicroFeature));
00429 
00430     FirstBulgeOf (MicroFeature) += UniformRandomNumber (MinSmear, MaxSmear);
00431     SecondBulgeOf (MicroFeature) += UniformRandomNumber (MinSmear, MaxSmear);
00432   }
00433 }                                /* SmearBulges */

Generated on Wed Feb 28 19:49:10 2007 for Tesseract by  doxygen 1.5.1