tesseract  4.00.00dev
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 /*-------------------once in subfeat---------------------------------*/
37 double_VAR(training_angle_match_scale, 1.0, "Angle Match Scale ...");
38 
39 double_VAR(training_similarity_midpoint, 0.0075, "Similarity Midpoint ...");
40 
41 double_VAR(training_similarity_curl, 2.0, "Similarity Curl ...");
42 
43 /*-----------------------------once in fasttrain----------------------------------*/
44 double_VAR(training_tangent_bbox_pad, 0.5, "Tangent bounding box pad ...");
45 
46 double_VAR(training_orthogonal_bbox_pad, 2.5, "Orthogonal bounding box pad ...");
47 
48 double_VAR(training_angle_pad, 45.0, "Angle pad ...");
49 
67  FEATURE Feature;
68  FLOAT32 WorstEvidence = WORST_EVIDENCE;
69  FLOAT32 Evidence;
70  FLOAT32 Angle, Length;
71 
72  /* if p1 and p2 are not close in length, don't let them match */
73  Length = fabs (p1->Length - p2->Length);
74  if (Length > MAX_LENGTH_MISMATCH)
75  return (0.0);
76 
77  /* create a dummy pico-feature to be used for comparisons */
78  Feature = NewFeature (&PicoFeatDesc);
79  Feature->Params[PicoFeatDir] = p1->Angle;
80 
81  /* convert angle to radians */
82  Angle = p1->Angle * 2.0 * PI;
83 
84  /* find distance from center of p1 to 1/2 picofeat from end */
85  Length = p1->Length / 2.0 - GetPicoFeatureLength () / 2.0;
86  if (Length < 0) Length = 0;
87 
88  /* set the dummy pico-feature at one end of p1 and match it to p2 */
89  Feature->Params[PicoFeatX] = p1->X + cos (Angle) * Length;
90  Feature->Params[PicoFeatY] = p1->Y + sin (Angle) * Length;
91  if (DummyFastMatch (Feature, p2)) {
92  Evidence = SubfeatureEvidence (Feature, p2);
93  if (Evidence < WorstEvidence)
94  WorstEvidence = Evidence;
95  } else {
96  FreeFeature(Feature);
97  return 0.0;
98  }
99 
100  /* set the dummy pico-feature at the other end of p1 and match it to p2 */
101  Feature->Params[PicoFeatX] = p1->X - cos (Angle) * Length;
102  Feature->Params[PicoFeatY] = p1->Y - sin (Angle) * Length;
103  if (DummyFastMatch (Feature, p2)) {
104  Evidence = SubfeatureEvidence (Feature, p2);
105  if (Evidence < WorstEvidence)
106  WorstEvidence = Evidence;
107  } else {
108  FreeFeature(Feature);
109  return 0.0;
110  }
111 
112  FreeFeature (Feature);
113  return (WorstEvidence);
114 
115 } /* CompareProtos */
116 
133  PROTO p2,
134  FLOAT32 w1,
135  FLOAT32 w2,
136  PROTO MergedProto) {
137  FLOAT32 TotalWeight;
138 
139  TotalWeight = w1 + w2;
140  w1 /= TotalWeight;
141  w2 /= TotalWeight;
142 
143  MergedProto->X = p1->X * w1 + p2->X * w2;
144  MergedProto->Y = p1->Y * w1 + p2->Y * w2;
145  MergedProto->Length = p1->Length * w1 + p2->Length * w2;
146  MergedProto->Angle = p1->Angle * w1 + p2->Angle * w2;
147  FillABC(MergedProto);
148 } /* ComputeMergedProto */
149 
166 int FindClosestExistingProto(CLASS_TYPE Class, int NumMerged[],
167  PROTOTYPE *Prototype) {
168  PROTO_STRUCT NewProto;
169  PROTO_STRUCT MergedProto;
170  int Pid;
171  PROTO Proto;
172  int BestProto;
173  FLOAT32 BestMatch;
174  FLOAT32 Match, OldMatch, NewMatch;
175 
176  MakeNewFromOld (&NewProto, Prototype);
177 
178  BestProto = NO_PROTO;
179  BestMatch = WORST_MATCH_ALLOWED;
180  for (Pid = 0; Pid < Class->NumProtos; Pid++) {
181  Proto = ProtoIn(Class, Pid);
182  ComputeMergedProto(Proto, &NewProto,
183  (FLOAT32) NumMerged[Pid], 1.0, &MergedProto);
184  OldMatch = CompareProtos(Proto, &MergedProto);
185  NewMatch = CompareProtos(&NewProto, &MergedProto);
186  Match = MIN(OldMatch, NewMatch);
187  if (Match > BestMatch) {
188  BestProto = Pid;
189  BestMatch = Match;
190  }
191  }
192  return BestProto;
193 } /* FindClosestExistingProto */
194 
207 void MakeNewFromOld(PROTO New, PROTOTYPE *Old) {
208  New->X = CenterX(Old->Mean);
209  New->Y = CenterY(Old->Mean);
210  New->Length = LengthOf(Old->Mean);
211  New->Angle = OrientationOf(Old->Mean);
212  FillABC(New);
213 } /* MakeNewFromOld */
214 
215 /*-------------------once in subfeat---------------------------------*/
216 
223  float Distance;
224  float Dangle;
225 
226  Dangle = Proto->Angle - Feature->Params[PicoFeatDir];
227  if (Dangle < -0.5) Dangle += 1.0;
228  if (Dangle > 0.5) Dangle -= 1.0;
229  Dangle *= training_angle_match_scale;
230 
231  Distance = Proto->A * Feature->Params[PicoFeatX] +
232  Proto->B * Feature->Params[PicoFeatY] +
233  Proto->C;
234 
235  return (EvidenceOf (Distance * Distance + Dangle * Dangle));
236 }
237 
246 double EvidenceOf (double Similarity) {
247 
248  Similarity /= training_similarity_midpoint;
249 
250  if (training_similarity_curl == 3)
251  Similarity = Similarity * Similarity * Similarity;
252  else if (training_similarity_curl == 2)
253  Similarity = Similarity * Similarity;
254  else
255  Similarity = pow (Similarity, training_similarity_curl);
256 
257  return (1.0 / (1.0 + Similarity));
258 }
259 
276  FEATURE Feature,
277  PROTO Proto)
278 {
279  FRECT BoundingBox;
280  FLOAT32 MaxAngleError;
281  FLOAT32 AngleError;
282 
283  MaxAngleError = training_angle_pad / 360.0;
284  AngleError = fabs (Proto->Angle - Feature->Params[PicoFeatDir]);
285  if (AngleError > 0.5)
286  AngleError = 1.0 - AngleError;
287 
288  if (AngleError > MaxAngleError)
289  return (FALSE);
290 
294  &BoundingBox);
295 
296  return PointInside(&BoundingBox, Feature->Params[PicoFeatX],
297  Feature->Params[PicoFeatY]);
298 } /* DummyFastMatch */
299 
317 void ComputePaddedBoundingBox (PROTO Proto, FLOAT32 TangentPad,
318  FLOAT32 OrthogonalPad, FRECT *BoundingBox) {
319  FLOAT32 Pad, Length, Angle;
320  FLOAT32 CosOfAngle, SinOfAngle;
321 
322  Length = Proto->Length / 2.0 + TangentPad;
323  Angle = Proto->Angle * 2.0 * PI;
324  CosOfAngle = fabs(cos(Angle));
325  SinOfAngle = fabs(sin(Angle));
326 
327  Pad = MAX (CosOfAngle * Length, SinOfAngle * OrthogonalPad);
328  BoundingBox->MinX = Proto->X - Pad;
329  BoundingBox->MaxX = Proto->X + Pad;
330 
331  Pad = MAX(SinOfAngle * Length, CosOfAngle * OrthogonalPad);
332  BoundingBox->MinY = Proto->Y - Pad;
333  BoundingBox->MaxY = Proto->Y + Pad;
334 
335 } /* ComputePaddedBoundingBox */
336 
346 BOOL8 PointInside(FRECT *Rectangle, FLOAT32 X, FLOAT32 Y) {
347  if (X < Rectangle->MinX) return (FALSE);
348  if (X > Rectangle->MaxX) return (FALSE);
349  if (Y < Rectangle->MinY) return (FALSE);
350  if (Y > Rectangle->MaxY) return (FALSE);
351  return (TRUE);
352 
353 } /* PointInside */
FLOAT32 MinY
Definition: mergenf.h:47
#define LengthOf(M)
Definition: mergenf.h:55
#define OrientationOf(M)
Definition: mergenf.h:56
double training_similarity_curl
Definition: mergenf.cpp:41
#define TRUE
Definition: capi.h:45
FLOAT32 MaxX
Definition: mergenf.h:47
double training_tangent_bbox_pad
Definition: mergenf.cpp:44
FLOAT32 A
Definition: protos.h:44
double training_similarity_midpoint
Definition: mergenf.cpp:39
BOOL8 DummyFastMatch(FEATURE Feature, PROTO Proto)
Definition: mergenf.cpp:275
#define WORST_EVIDENCE
Definition: mergenf.h:33
void FillABC(PROTO Proto)
Definition: protos.cpp:197
inT16 NumProtos
Definition: protos.h:59
void ComputeMergedProto(PROTO p1, PROTO p2, FLOAT32 w1, FLOAT32 w2, PROTO MergedProto)
Definition: mergenf.cpp:132
BOOL8 PointInside(FRECT *Rectangle, FLOAT32 X, FLOAT32 Y)
Definition: mergenf.cpp:346
double training_orthogonal_bbox_pad
Definition: mergenf.cpp:46
FLOAT32 MinX
Definition: mergenf.h:47
double EvidenceOf(double Similarity)
Definition: mergenf.cpp:246
FLOAT32 SubfeatureEvidence(FEATURE Feature, PROTO Proto)
Definition: mergenf.cpp:222
void MakeNewFromOld(PROTO New, PROTOTYPE *Old)
Definition: mergenf.cpp:207
FLOAT32 MaxY
Definition: mergenf.h:47
FLOAT32 Length
Definition: protos.h:50
#define double_VAR(name, val, comment)
Definition: params.h:285
#define PI
Definition: const.h:19
unsigned char BOOL8
Definition: host.h:44
double training_angle_match_scale
Definition: mergenf.cpp:37
#define FALSE
Definition: capi.h:46
#define CenterY(M)
Definition: mergenf.h:54
FEATURE NewFeature(const FEATURE_DESC_STRUCT *FeatureDesc)
Definition: ocrfeatures.cpp:88
FLOAT32 * Mean
Definition: cluster.h:78
FLOAT32 Y
Definition: protos.h:48
FLOAT32 X
Definition: protos.h:47
void FreeFeature(FEATURE Feature)
Definition: ocrfeatures.cpp:59
#define MAX(x, y)
Definition: ndminx.h:24
void ComputePaddedBoundingBox(PROTO Proto, FLOAT32 TangentPad, FLOAT32 OrthogonalPad, FRECT *BoundingBox)
Definition: mergenf.cpp:317
FLOAT32 CompareProtos(PROTO p1, PROTO p2)
Definition: mergenf.cpp:66
float FLOAT32
Definition: host.h:42
Definition: mergenf.h:45
FLOAT32 Angle
Definition: protos.h:49
#define MAX_LENGTH_MISMATCH
Definition: mergenf.h:34
#define NO_PROTO
Definition: matchdefs.h:42
#define MIN(x, y)
Definition: ndminx.h:28
#define CenterX(M)
Definition: mergenf.h:53
double training_angle_pad
Definition: mergenf.cpp:48
FLOAT32 C
Definition: protos.h:46
FLOAT32 B
Definition: protos.h:45
FLOAT32 Params[1]
Definition: ocrfeatures.h:65
#define GetPicoFeatureLength()
Definition: picofeat.h:59
int FindClosestExistingProto(CLASS_TYPE Class, int NumMerged[], PROTOTYPE *Prototype)
Definition: mergenf.cpp:166
#define ProtoIn(Class, Pid)
Definition: protos.h:123
TESS_API const FEATURE_DESC_STRUCT PicoFeatDesc
#define WORST_MATCH_ALLOWED
Definition: mergenf.h:32