00001 
00020 
00021 
00022 
00023 #include "mfdefs.h"
00024 #include "variables.h"
00025 #include "sigmenu.h"
00026 #include "mfoutline.h"
00027 #include "clusttool.h"           
00028 #include "const.h"
00029 #include "intfx.h"
00030 #include <math.h>
00031 
00032 
00033 
00034 
00035 #define MIN_SLOPE               0.414213562
00036 
00037 #define MAX_SLOPE               2.414213562
00038 
00039 #define NOISE_SEGMENT_LENGTH    (0.00)
00040 
00041 #define MAX_FEATURE_LENGTH      (MAXFLOAT)
00042 
00043 
00044 
00045 
00046 
00047 #define NormalizeAngle(A)       ( (((A)<0)?((A)+2*PI):(A)) / (2*PI) )
00048 
00049 
00050 
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 
00065 
00066 
00067 
00068 
00069 
00070 
00071 
00072 
00073 
00074 
00075 
00076 
00077 
00078 
00079 
00080 
00081 
00082 
00083 
00084 
00085 
00086 
00087 
00088 
00089 
00090 
00091 
00092 
00093 
00094 
00095 
00096 
00097 
00098 
00099 
00100 static FLOAT32 MinSlope;
00101 static FLOAT32 MaxSlope;
00102 static FLOAT32 NoiseSegmentLength;
00103 
00104 
00105 
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 }                                
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 
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 }                                
00189 
00190 
00191 
00192 
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 
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   
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     
00273     
00274     
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 }                                
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   
00321   if ((Orientation < 0) || (Orientation >= 1))
00322     Orientation = 0;
00323   return (Orientation);
00324 }                                
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 }                                
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 }                                
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 }