00001
00019
00020
00021
00022 #include "mergenf.h"
00023 #include "general.h"
00024 #include "efio.h"
00025 #include "clusttool.h"
00026 #include "cluster.h"
00027 #include "oldlist.h"
00028 #include "protos.h"
00029 #include "minmax.h"
00030 #include "ocrfeatures.h"
00031 #include "debug.h"
00032 #include "const.h"
00033 #include "featdefs.h"
00034 #include "intproto.h"
00035
00036 #include <stdio.h>
00037 #include <string.h>
00038 #include <math.h>
00039
00040
00041
00042
00043
00044
00047
00048 make_float_var (AngleMatchScale, 1.0, MakeAngleMatchScale,
00049 7, 2, SetAngleMatchScale, "Angle Match Scale ...")
00050
00051 make_float_var (SimilarityMidpoint, 0.0075, MakeSimilarityMidpoint,
00052 7, 3, SetSimilarityMidpoint, "Similarity Midpoint ...")
00053
00054 make_float_var (SimilarityCurl, 2.0, MakeSimilarityCurl,
00055 7, 4, SetSimilarityCurl, "Similarity Curl ...")
00056
00057
00058 make_float_var (TangentBBoxPad, 0.5, MakeTangentBBoxPad,
00059 15, 3, SetTangentBBoxPad, "Tangent bounding box pad ...")
00060
00061 make_float_var (OrthogonalBBoxPad, 2.5, MakeOrthogonalBBoxPad,
00062 15, 4, SetOrthogonalBBoxPad, "Orthogonal bounding box pad ...")
00063
00064 make_float_var (AnglePad, 45.0, MakeAnglePad,
00065 15, 5, SetAnglePad, "Angle pad ...")
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00094 FLOAT32 CompareProtos (
00095 PROTO p1,
00096 PROTO p2)
00097 {
00098 FEATURE Feature;
00099 FLOAT32 WorstEvidence = WORST_EVIDENCE;
00100 FLOAT32 Evidence;
00101 FLOAT32 Angle, Length;
00102
00103
00104 Length = fabs (ProtoLength (p1) - ProtoLength (p2));
00105 if (Length > MAX_LENGTH_MISMATCH)
00106 return (0.0);
00107
00108
00109 Feature = NewFeature (&PicoFeatDesc);
00110 ParamOf (Feature, PicoFeatDir) = ProtoAngle (p1);
00111
00112
00113 Angle = ProtoAngle (p1) * 2.0 * PI;
00114
00115
00116 Length = ProtoLength (p1) / 2.0 - GetPicoFeatureLength () / 2.0;
00117 if (Length < 0) Length = 0;
00118
00119
00120 ParamOf (Feature, PicoFeatX) = ProtoX (p1) + cos (Angle) * Length;
00121 ParamOf (Feature, PicoFeatY) = ProtoY (p1) + sin (Angle) * Length;
00122 if (DummyFastMatch (Feature, p2))
00123 {
00124 Evidence = SubfeatureEvidence (Feature, p2);
00125 if (Evidence < WorstEvidence)
00126 WorstEvidence = Evidence;
00127 }
00128 else
00129 {
00130 FreeFeature (Feature);
00131 return (0.0);
00132 }
00133
00134
00135 ParamOf (Feature, PicoFeatX) = ProtoX (p1) - cos (Angle) * Length;
00136 ParamOf (Feature, PicoFeatY) = ProtoY (p1) - sin (Angle) * Length;
00137 if (DummyFastMatch (Feature, p2))
00138 {
00139 Evidence = SubfeatureEvidence (Feature, p2);
00140 if (Evidence < WorstEvidence)
00141 WorstEvidence = Evidence;
00142 }
00143 else
00144 {
00145 FreeFeature (Feature);
00146 return (0.0);
00147 }
00148
00149 FreeFeature (Feature);
00150 return (WorstEvidence);
00151
00152 }
00153
00154
00155
00167 void ComputeMergedProto (
00168 PROTO p1,
00169 PROTO p2,
00170 FLOAT32 w1,
00171 FLOAT32 w2,
00172 PROTO MergedProto)
00173 {
00174 FLOAT32 TotalWeight;
00175
00176 TotalWeight = w1 + w2;
00177 w1 /= TotalWeight;
00178 w2 /= TotalWeight;
00179
00180 ProtoX (MergedProto) = ProtoX (p1) * w1 + ProtoX (p2) * w2;
00181 ProtoY (MergedProto) = ProtoY (p1) * w1 + ProtoY (p2) * w2;
00182 ProtoLength (MergedProto) = ProtoLength (p1) * w1 + ProtoLength (p2) * w2;
00183 ProtoAngle (MergedProto) = ProtoAngle (p1) * w1 + ProtoAngle (p2) * w2;
00184 FillABC (MergedProto);
00185
00186 }
00187
00188
00189
00202 int FindClosestExistingProto (
00203 CLASS_TYPE Class,
00204 int NumMerged[],
00205 PROTOTYPE *Prototype)
00206 {
00207 PROTO_STRUCT NewProto;
00208 PROTO_STRUCT MergedProto;
00209 int Pid;
00210 PROTO Proto;
00211 int BestProto;
00212 FLOAT32 BestMatch;
00213 FLOAT32 Match, OldMatch, NewMatch;
00214
00215 MakeNewFromOld (&NewProto, Prototype);
00216
00217 BestProto = NO_PROTO;
00218 BestMatch = WORST_MATCH_ALLOWED;
00219 for (Pid = 0; Pid < NumProtosIn (Class); Pid++)
00220 {
00221 Proto = ProtoIn (Class, Pid);
00222 ComputeMergedProto (Proto, &NewProto,
00223 (FLOAT32) NumMerged[Pid], 1.0, &MergedProto);
00224 OldMatch = CompareProtos (Proto, &MergedProto);
00225 NewMatch = CompareProtos (&NewProto, &MergedProto);
00226 Match = MIN (OldMatch, NewMatch);
00227 if (Match > BestMatch)
00228 {
00229 BestProto = Pid;
00230 BestMatch = Match;
00231 }
00232 }
00233 return (BestProto);
00234
00235 }
00236
00237
00238
00247 void MakeNewFromOld (
00248 PROTO New,
00249 PROTOTYPE *Old)
00250 {
00251 ProtoX (New) = CenterX (Old->Mean);
00252 ProtoY (New) = CenterY (Old->Mean);
00253 ProtoLength (New) = LengthOf (Old->Mean);
00254 ProtoAngle (New) = OrientationOf (Old->Mean);
00255 FillABC (New);
00256
00257 }
00258
00259
00265 void InitSubfeatureVars ()
00266 {
00267 MakeAngleMatchScale ();
00268 MakeSimilarityCurl ();
00269 MakeSimilarityMidpoint ();
00270 }
00271
00272
00281 FLOAT32 SubfeatureEvidence (
00282 FEATURE Feature,
00283 PROTO Proto)
00284 {
00285 float Distance;
00286 float Dangle;
00287
00288 Dangle = ProtoAngle (Proto) - ParamOf(Feature, PicoFeatDir);
00289 if (Dangle < -0.5) Dangle += 1.0;
00290 if (Dangle > 0.5) Dangle -= 1.0;
00291 Dangle *= AngleMatchScale;
00292
00293 Distance = CoefficientA (Proto) * ParamOf(Feature, PicoFeatX) +
00294 CoefficientB (Proto) * ParamOf(Feature, PicoFeatY) +
00295 CoefficientC (Proto);
00296
00297 return (EvidenceOf (Distance * Distance + Dangle * Dangle));
00298 }
00299
00320 FLOAT32 EvidenceOf (
00321 register FLOAT32 Similarity)
00322 {
00323
00324 Similarity /= SimilarityMidpoint;
00325
00326 if (SimilarityCurl == 3)
00327 Similarity = Similarity * Similarity * Similarity;
00328 else if (SimilarityCurl == 2)
00329 Similarity = Similarity * Similarity;
00330 else
00331 Similarity = pow (Similarity, SimilarityCurl);
00332
00333 return (1.0 / (1.0 + Similarity));
00334 }
00335
00336
00342 void InitFastTrainerVars ()
00343 {
00344 MakeTangentBBoxPad ();
00345 MakeOrthogonalBBoxPad ();
00346 MakeAnglePad ();
00347
00348 }
00349
00350
00351
00363 BOOL8 DummyFastMatch (
00364 FEATURE Feature,
00365 PROTO Proto)
00366 {
00367 FRECT BoundingBox;
00368 FLOAT32 MaxAngleError;
00369 FLOAT32 AngleError;
00370
00371 MaxAngleError = AnglePad / 360.0;
00372 AngleError = fabs (ProtoAngle (Proto) - ParamOf (Feature, PicoFeatDir));
00373 if (AngleError > 0.5)
00374 AngleError = 1.0 - AngleError;
00375
00376 if (AngleError > MaxAngleError)
00377 return (FALSE);
00378
00379 ComputePaddedBoundingBox (Proto,
00380 TangentBBoxPad * GetPicoFeatureLength (),
00381 OrthogonalBBoxPad * GetPicoFeatureLength (),
00382 &BoundingBox);
00383
00384 return (PointInside (&BoundingBox,
00385 ParamOf (Feature, PicoFeatX),
00386 ParamOf (Feature, PicoFeatY)));
00387
00388 }
00389
00390
00391
00407 void ComputePaddedBoundingBox (
00408 PROTO Proto,
00409 FLOAT32 TangentPad,
00410 FLOAT32 OrthogonalPad,
00411 FRECT *BoundingBox)
00412 {
00413 FLOAT32 Pad, Length, Angle;
00414 FLOAT32 CosOfAngle, SinOfAngle;
00415
00416 Length = ProtoLength (Proto) / 2.0 + TangentPad;
00417 Angle = ProtoAngle (Proto) * 2.0 * PI;
00418 CosOfAngle = fabs (cos (Angle));
00419 SinOfAngle = fabs (sin (Angle));
00420
00421 Pad = MAX (CosOfAngle * Length, SinOfAngle * OrthogonalPad);
00422 BoundingBox->MinX = ProtoX (Proto) - Pad;
00423 BoundingBox->MaxX = ProtoX (Proto) + Pad;
00424
00425 Pad = MAX (SinOfAngle * Length, CosOfAngle * OrthogonalPad);
00426 BoundingBox->MinY = ProtoY (Proto) - Pad;
00427 BoundingBox->MaxY = ProtoY (Proto) + Pad;
00428
00429 }
00430
00431
00432
00443 BOOL8 PointInside (
00444 FRECT *Rectangle,
00445 FLOAT32 X,
00446 FLOAT32 Y)
00447 {
00448 if (X < Rectangle->MinX) return (FALSE);
00449 if (X > Rectangle->MaxX) return (FALSE);
00450 if (Y < Rectangle->MinY) return (FALSE);
00451 if (Y > Rectangle->MaxY) return (FALSE);
00452 return (TRUE);
00453
00454 }