Tesseract 3.02

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
mergenf.cpp
Go to the documentation of this file.
1 /******************************************************************************
2 ** Filename: MergeNF.c
3 ** Purpose: Program for merging similar nano-feature protos
4 ** Author: Dan Johnson
5 ** History: Wed Nov 21 09:55:23 1990, DSJ, Created.
6 **
7 ** (c) Copyright Hewlett-Packard Company, 1988.
8 ** Licensed under the Apache License, Version 2.0 (the "License");
9 ** you may not use this file except in compliance with the License.
10 ** You may obtain a copy of the License at
11 ** http://www.apache.org/licenses/LICENSE-2.0
12 ** Unless required by applicable law or agreed to in writing, software
13 ** distributed under the License is distributed on an "AS IS" BASIS,
14 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 ** See the License for the specific language governing permissions and
16 ** limitations under the License.
17 ******************************************************************************/
18 #include "mergenf.h"
19 #include "host.h"
20 #include "efio.h"
21 #include "clusttool.h"
22 #include "cluster.h"
23 #include "oldlist.h"
24 #include "protos.h"
25 #include "ndminx.h"
26 #include "ocrfeatures.h"
27 #include "const.h"
28 #include "featdefs.h"
29 #include "intproto.h"
30 #include "params.h"
31
32 #include <stdio.h>
33 #include <string.h>
34 #include <math.h>
35
36
37 /*-------------------once in subfeat---------------------------------*/
38 double_VAR(training_angle_match_scale, 1.0, "Angle Match Scale ...");
39
40 double_VAR(training_similarity_midpoint, 0.0075, "Similarity Midpoint ...");
41
42 double_VAR(training_similarity_curl, 2.0, "Similarity Curl ...");
43
44 /*-----------------------------once in fasttrain----------------------------------*/
45 double_VAR(training_tangent_bbox_pad, 0.5, "Tangent bounding box pad ...");
46
47 double_VAR(training_orthogonal_bbox_pad, 2.5, "Orthogonal bounding box pad ...");
48
49 double_VAR(training_angle_pad, 45.0, "Angle pad ...");
50
67 FLOAT32 CompareProtos(PROTO p1, PROTO p2) {
68 FEATURE Feature;
69 FLOAT32 WorstEvidence = WORST_EVIDENCE;
70 FLOAT32 Evidence;
71 FLOAT32 Angle, Length;
72
73 /* if p1 and p2 are not close in length, don't let them match */
74 Length = fabs (p1->Length - p2->Length);
75 if (Length > MAX_LENGTH_MISMATCH)
76 return (0.0);
77
78 /* create a dummy pico-feature to be used for comparisons */
79 Feature = NewFeature (&PicoFeatDesc);
80 Feature->Params[PicoFeatDir] = p1->Angle;
81
82 /* convert angle to radians */
83 Angle = p1->Angle * 2.0 * PI;
84
85 /* find distance from center of p1 to 1/2 picofeat from end */
86 Length = p1->Length / 2.0 - GetPicoFeatureLength () / 2.0;
87 if (Length < 0) Length = 0;
88
89 /* set the dummy pico-feature at one end of p1 and match it to p2 */
90 Feature->Params[PicoFeatX] = p1->X + cos (Angle) * Length;
91 Feature->Params[PicoFeatY] = p1->Y + sin (Angle) * Length;
92 if (DummyFastMatch (Feature, p2)) {
93 Evidence = SubfeatureEvidence (Feature, p2);
94 if (Evidence < WorstEvidence)
95 WorstEvidence = Evidence;
96 } else {
97 FreeFeature(Feature);
98 return 0.0;
99 }
100
101 /* set the dummy pico-feature at the other end of p1 and match it to p2 */
102 Feature->Params[PicoFeatX] = p1->X - cos (Angle) * Length;
103 Feature->Params[PicoFeatY] = p1->Y - sin (Angle) * Length;
104 if (DummyFastMatch (Feature, p2)) {
105 Evidence = SubfeatureEvidence (Feature, p2);
106 if (Evidence < WorstEvidence)
107 WorstEvidence = Evidence;
108 } else {
109 FreeFeature(Feature);
110 return 0.0;
111 }
112
113 FreeFeature (Feature);
114 return (WorstEvidence);
115
116 } /* CompareProtos */
117
133 void ComputeMergedProto (PROTO p1,
134 PROTO p2,
135 FLOAT32 w1,
136 FLOAT32 w2,
137 PROTO MergedProto) {
138 FLOAT32 TotalWeight;
139
140 TotalWeight = w1 + w2;
141 w1 /= TotalWeight;
142 w2 /= TotalWeight;
143
144 MergedProto->X = p1->X * w1 + p2->X * w2;
145 MergedProto->Y = p1->Y * w1 + p2->Y * w2;
146 MergedProto->Length = p1->Length * w1 + p2->Length * w2;
147 MergedProto->Angle = p1->Angle * w1 + p2->Angle * w2;
148 FillABC(MergedProto);
149 } /* ComputeMergedProto */
150
167 int FindClosestExistingProto(CLASS_TYPE Class, int NumMerged[],
168 PROTOTYPE *Prototype) {
169 PROTO_STRUCT NewProto;
170 PROTO_STRUCT MergedProto;
171 int Pid;
172 PROTO Proto;
173 int BestProto;
174 FLOAT32 BestMatch;
175 FLOAT32 Match, OldMatch, NewMatch;
176
177 MakeNewFromOld (&NewProto, Prototype);
178
179 BestProto = NO_PROTO;
180 BestMatch = WORST_MATCH_ALLOWED;
181 for (Pid = 0; Pid < Class->NumProtos; Pid++) {
182 Proto = ProtoIn(Class, Pid);
183 ComputeMergedProto(Proto, &NewProto,
184 (FLOAT32) NumMerged[Pid], 1.0, &MergedProto);
185 OldMatch = CompareProtos(Proto, &MergedProto);
186 NewMatch = CompareProtos(&NewProto, &MergedProto);
187 Match = MIN(OldMatch, NewMatch);
188 if (Match > BestMatch) {
189 BestProto = Pid;
190 BestMatch = Match;
191 }
192 }
193 return BestProto;
194 } /* FindClosestExistingProto */
195
208 void MakeNewFromOld(PROTO New, PROTOTYPE *Old) {
209 New->X = CenterX(Old->Mean);
210 New->Y = CenterY(Old->Mean);
211 New->Length = LengthOf(Old->Mean);
212 New->Angle = OrientationOf(Old->Mean);
213 FillABC(New);
214 } /* MakeNewFromOld */
215
216 /*-------------------once in subfeat---------------------------------*/
217
223 FLOAT32 SubfeatureEvidence(FEATURE Feature, PROTO Proto) {
224 float Distance;
225 float Dangle;
226
227 Dangle = Proto->Angle - Feature->Params[PicoFeatDir];
228 if (Dangle < -0.5) Dangle += 1.0;
229 if (Dangle > 0.5) Dangle -= 1.0;
230 Dangle *= training_angle_match_scale;
231
232 Distance = Proto->A * Feature->Params[PicoFeatX] +
233 Proto->B * Feature->Params[PicoFeatY] +
234 Proto->C;
235
236 return (EvidenceOf (Distance * Distance + Dangle * Dangle));
237 }
238
247 double EvidenceOf (double Similarity) {
248
249 Similarity /= training_similarity_midpoint;
250
251 if (training_similarity_curl == 3)
252 Similarity = Similarity * Similarity * Similarity;
253 else if (training_similarity_curl == 2)
254 Similarity = Similarity * Similarity;
255 else
256 Similarity = pow (Similarity, training_similarity_curl);
257
258 return (1.0 / (1.0 + Similarity));
259 }
260
276 BOOL8 DummyFastMatch (
277 FEATURE Feature,
278 PROTO Proto)
279 {
280 FRECT BoundingBox;
281 FLOAT32 MaxAngleError;
282 FLOAT32 AngleError;
283
284 MaxAngleError = training_angle_pad / 360.0;
285 AngleError = fabs (Proto->Angle - Feature->Params[PicoFeatDir]);
286 if (AngleError > 0.5)
287 AngleError = 1.0 - AngleError;
288
289 if (AngleError > MaxAngleError)
290 return (FALSE);
291
292 ComputePaddedBoundingBox (Proto,
293 training_tangent_bbox_pad * GetPicoFeatureLength (),
294 training_orthogonal_bbox_pad * GetPicoFeatureLength (),
295 &BoundingBox);
296
297 return PointInside(&BoundingBox, Feature->Params[PicoFeatX],
298 Feature->Params[PicoFeatY]);
299 } /* DummyFastMatch */
300
318 void ComputePaddedBoundingBox (PROTO Proto, FLOAT32 TangentPad,
319 FLOAT32 OrthogonalPad, FRECT *BoundingBox) {
320 FLOAT32 Pad, Length, Angle;
321 FLOAT32 CosOfAngle, SinOfAngle;
322
323 Length = Proto->Length / 2.0 + TangentPad;
324 Angle = Proto->Angle * 2.0 * PI;
325 CosOfAngle = fabs(cos(Angle));
326 SinOfAngle = fabs(sin(Angle));
327
328 Pad = MAX (CosOfAngle * Length, SinOfAngle * OrthogonalPad);
329 BoundingBox->MinX = Proto->X - Pad;
330 BoundingBox->MaxX = Proto->X + Pad;
331
332 Pad = MAX(SinOfAngle * Length, CosOfAngle * OrthogonalPad);
333 BoundingBox->MinY = Proto->Y - Pad;
334 BoundingBox->MaxY = Proto->Y + Pad;
335
336 } /* ComputePaddedBoundingBox */
337
347 BOOL8 PointInside(FRECT *Rectangle, FLOAT32 X, FLOAT32 Y) {
348 if (X < Rectangle->MinX) return (FALSE);
349 if (X > Rectangle->MaxX) return (FALSE);
350 if (Y < Rectangle->MinY) return (FALSE);
351 if (Y > Rectangle->MaxY) return (FALSE);
352 return (TRUE);
353
354 } /* PointInside */