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 }