tesseract  5.0.0-alpha-619-ge9db
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 **
6  ** (c) Copyright Hewlett-Packard Company, 1988.
7  ** Licensed under the Apache License, Version 2.0 (the "License");
8  ** you may not use this file except in compliance with the License.
9  ** You may obtain a copy of the License at
10  ** http://www.apache.org/licenses/LICENSE-2.0
11  ** Unless required by applicable law or agreed to in writing, software
12  ** distributed under the License is distributed on an "AS IS" BASIS,
13  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  ** See the License for the specific language governing permissions and
15  ** limitations under the License.
16 ******************************************************************************/
17 
18 #define _USE_MATH_DEFINES // for M_PI
19 #include <algorithm>
20 #include <cfloat> // for FLT_MAX
21 #include <cmath> // for M_PI
22 #include <cstdio>
23 #include <cstring>
24 
25 #include "mergenf.h"
26 #include "clusttool.h"
27 #include "cluster.h"
28 #include "oldlist.h"
29 #include "protos.h"
30 #include "ocrfeatures.h"
31 #include "featdefs.h"
32 #include "intproto.h"
33 #include "params.h"
34 
35 /*-------------------once in subfeat---------------------------------*/
36 static double_VAR(training_angle_match_scale, 1.0, "Angle Match Scale ...");
37 
38 static double_VAR(training_similarity_midpoint, 0.0075, "Similarity Midpoint ...");
39 
40 static double_VAR(training_similarity_curl, 2.0, "Similarity Curl ...");
41 
42 /*-----------------------------once in fasttrain----------------------------------*/
43 static double_VAR(training_tangent_bbox_pad, 0.5, "Tangent bounding box pad ...");
44 
45 static double_VAR(training_orthogonal_bbox_pad, 2.5, "Orthogonal bounding box pad ...");
46 
47 static double_VAR(training_angle_pad, 45.0, "Angle pad ...");
48 
63 float CompareProtos(PROTO p1, PROTO p2) {
64  FEATURE Feature;
65  float WorstEvidence = WORST_EVIDENCE;
66  float Evidence;
67  float Angle, Length;
68 
69  /* if p1 and p2 are not close in length, don't let them match */
70  Length = fabs (p1->Length - p2->Length);
71  if (Length > MAX_LENGTH_MISMATCH)
72  return (0.0);
73 
74  /* create a dummy pico-feature to be used for comparisons */
75  Feature = NewFeature (&PicoFeatDesc);
76  Feature->Params[PicoFeatDir] = p1->Angle;
77 
78  /* convert angle to radians */
79  Angle = p1->Angle * 2.0 * M_PI;
80 
81  /* find distance from center of p1 to 1/2 picofeat from end */
82  Length = p1->Length / 2.0 - GetPicoFeatureLength () / 2.0;
83  if (Length < 0) Length = 0;
84 
85  /* set the dummy pico-feature at one end of p1 and match it to p2 */
86  Feature->Params[PicoFeatX] = p1->X + cos (Angle) * Length;
87  Feature->Params[PicoFeatY] = p1->Y + sin (Angle) * Length;
88  if (DummyFastMatch (Feature, p2)) {
89  Evidence = SubfeatureEvidence (Feature, p2);
90  if (Evidence < WorstEvidence)
91  WorstEvidence = Evidence;
92  } else {
93  FreeFeature(Feature);
94  return 0.0;
95  }
96 
97  /* set the dummy pico-feature at the other end of p1 and match it to p2 */
98  Feature->Params[PicoFeatX] = p1->X - cos (Angle) * Length;
99  Feature->Params[PicoFeatY] = p1->Y - sin (Angle) * Length;
100  if (DummyFastMatch (Feature, p2)) {
101  Evidence = SubfeatureEvidence (Feature, p2);
102  if (Evidence < WorstEvidence)
103  WorstEvidence = Evidence;
104  } else {
105  FreeFeature(Feature);
106  return 0.0;
107  }
108 
109  FreeFeature (Feature);
110  return (WorstEvidence);
111 
112 } /* CompareProtos */
113 
124  PROTO p2,
125  float w1,
126  float w2,
127  PROTO MergedProto) {
128  float TotalWeight;
129 
130  TotalWeight = w1 + w2;
131  w1 /= TotalWeight;
132  w2 /= TotalWeight;
133 
134  MergedProto->X = p1->X * w1 + p2->X * w2;
135  MergedProto->Y = p1->Y * w1 + p2->Y * w2;
136  MergedProto->Length = p1->Length * w1 + p2->Length * w2;
137  MergedProto->Angle = p1->Angle * w1 + p2->Angle * w2;
138  FillABC(MergedProto);
139 } /* ComputeMergedProto */
140 
155 int FindClosestExistingProto(CLASS_TYPE Class, int NumMerged[],
156  PROTOTYPE *Prototype) {
157  PROTO_STRUCT NewProto;
158  PROTO_STRUCT MergedProto;
159  int Pid;
160  PROTO Proto;
161  int BestProto;
162  float BestMatch;
163  float Match, OldMatch, NewMatch;
164 
165  MakeNewFromOld (&NewProto, Prototype);
166 
167  BestProto = NO_PROTO;
168  BestMatch = WORST_MATCH_ALLOWED;
169  for (Pid = 0; Pid < Class->NumProtos; Pid++) {
170  Proto = ProtoIn(Class, Pid);
171  ComputeMergedProto(Proto, &NewProto,
172  static_cast<float>(NumMerged[Pid]), 1.0, &MergedProto);
173  OldMatch = CompareProtos(Proto, &MergedProto);
174  NewMatch = CompareProtos(&NewProto, &MergedProto);
175  Match = std::min(OldMatch, NewMatch);
176  if (Match > BestMatch) {
177  BestProto = Pid;
178  BestMatch = Match;
179  }
180  }
181  return BestProto;
182 } /* FindClosestExistingProto */
183 
193 void MakeNewFromOld(PROTO New, PROTOTYPE *Old) {
194  New->X = CenterX(Old->Mean);
195  New->Y = CenterY(Old->Mean);
196  New->Length = LengthOf(Old->Mean);
197  New->Angle = OrientationOf(Old->Mean);
198  FillABC(New);
199 } /* MakeNewFromOld */
200 
201 /*-------------------once in subfeat---------------------------------*/
202 
208 float SubfeatureEvidence(FEATURE Feature, PROTO Proto) {
209  float Distance;
210  float Dangle;
211 
212  Dangle = Proto->Angle - Feature->Params[PicoFeatDir];
213  if (Dangle < -0.5) Dangle += 1.0;
214  if (Dangle > 0.5) Dangle -= 1.0;
215  Dangle *= training_angle_match_scale;
216 
217  Distance = Proto->A * Feature->Params[PicoFeatX] +
218  Proto->B * Feature->Params[PicoFeatY] +
219  Proto->C;
220 
221  return (EvidenceOf (Distance * Distance + Dangle * Dangle));
222 }
223 
232 double EvidenceOf (double Similarity) {
233 
234  Similarity /= training_similarity_midpoint;
235 
236  if (training_similarity_curl == 3)
237  Similarity = Similarity * Similarity * Similarity;
238  else if (training_similarity_curl == 2)
239  Similarity = Similarity * Similarity;
240  else
241  Similarity = pow (Similarity, training_similarity_curl);
242 
243  return (1.0 / (1.0 + Similarity));
244 }
245 
259 bool DummyFastMatch(FEATURE Feature, PROTO Proto)
260 {
261  FRECT BoundingBox;
262  float MaxAngleError;
263  float AngleError;
264 
265  MaxAngleError = training_angle_pad / 360.0;
266  AngleError = fabs (Proto->Angle - Feature->Params[PicoFeatDir]);
267  if (AngleError > 0.5)
268  AngleError = 1.0 - AngleError;
269 
270  if (AngleError > MaxAngleError)
271  return false;
272 
274  training_tangent_bbox_pad * GetPicoFeatureLength (),
275  training_orthogonal_bbox_pad * GetPicoFeatureLength (),
276  &BoundingBox);
277 
278  return PointInside(&BoundingBox, Feature->Params[PicoFeatX],
279  Feature->Params[PicoFeatY]);
280 } /* DummyFastMatch */
281 
293 void ComputePaddedBoundingBox (PROTO Proto, float TangentPad,
294  float OrthogonalPad, FRECT *BoundingBox) {
295  float Length = Proto->Length / 2.0 + TangentPad;
296  float Angle = Proto->Angle * 2.0 * M_PI;
297  float CosOfAngle = fabs(cos(Angle));
298  float SinOfAngle = fabs(sin(Angle));
299 
300  float Pad = std::max(CosOfAngle * Length, SinOfAngle * OrthogonalPad);
301  BoundingBox->MinX = Proto->X - Pad;
302  BoundingBox->MaxX = Proto->X + Pad;
303 
304  Pad = std::max(SinOfAngle * Length, CosOfAngle * OrthogonalPad);
305  BoundingBox->MinY = Proto->Y - Pad;
306  BoundingBox->MaxY = Proto->Y + Pad;
307 
308 } /* ComputePaddedBoundingBox */
309 
317 bool PointInside(FRECT *Rectangle, float X, float Y) {
318  return (X >= Rectangle->MinX) &&
319  (X <= Rectangle->MaxX) &&
320  (Y >= Rectangle->MinY) &&
321  (Y <= Rectangle->MaxY);
322 } /* PointInside */
DummyFastMatch
bool DummyFastMatch(FEATURE Feature, PROTO Proto)
Definition: mergenf.cpp:259
PROTO_STRUCT::Length
float Length
Definition: protos.h:41
FindClosestExistingProto
int FindClosestExistingProto(CLASS_TYPE Class, int NumMerged[], PROTOTYPE *Prototype)
Definition: mergenf.cpp:155
FRECT
Definition: mergenf.h:42
FRECT::MaxX
float MaxX
Definition: mergenf.h:43
FRECT::MaxY
float MaxY
Definition: mergenf.h:43
ComputeMergedProto
void ComputeMergedProto(PROTO p1, PROTO p2, float w1, float w2, PROTO MergedProto)
Definition: mergenf.cpp:123
PROTO_STRUCT
Definition: protos.h:34
params.h
CLASS_STRUCT::NumProtos
int16_t NumProtos
Definition: protos.h:53
FEATURE_STRUCT
Definition: ocrfeatures.h:58
FRECT::MinY
float MinY
Definition: mergenf.h:43
PicoFeatY
Definition: picofeat.h:43
LengthOf
#define LengthOf(M)
Definition: mergenf.h:51
PicoFeatX
Definition: picofeat.h:43
oldlist.h
PROTO_STRUCT::B
float B
Definition: protos.h:36
PROTOTYPE
Definition: cluster.h:62
ProtoIn
#define ProtoIn(Class, Pid)
Definition: protos.h:82
PicoFeatDir
Definition: picofeat.h:43
EvidenceOf
double EvidenceOf(double Similarity)
Definition: mergenf.cpp:232
CompareProtos
float CompareProtos(PROTO p1, PROTO p2)
Definition: mergenf.cpp:63
PointInside
bool PointInside(FRECT *Rectangle, float X, float Y)
Definition: mergenf.cpp:317
NO_PROTO
#define NO_PROTO
Definition: matchdefs.h:40
ocrfeatures.h
PROTO_STRUCT::Y
float Y
Definition: protos.h:39
FreeFeature
void FreeFeature(FEATURE Feature)
Definition: ocrfeatures.cpp:53
PROTO_STRUCT::C
float C
Definition: protos.h:37
PROTO_STRUCT::X
float X
Definition: protos.h:38
MakeNewFromOld
void MakeNewFromOld(PROTO New, PROTOTYPE *Old)
Definition: mergenf.cpp:193
CLASS_STRUCT
Definition: protos.h:45
PROTO_STRUCT::Angle
float Angle
Definition: protos.h:40
CenterY
#define CenterY(M)
Definition: mergenf.h:50
FillABC
void FillABC(PROTO Proto)
Definition: protos.cpp:105
FEATURE_STRUCT::Params
float Params[1]
Definition: ocrfeatures.h:60
mergenf.h
ComputePaddedBoundingBox
void ComputePaddedBoundingBox(PROTO Proto, float TangentPad, float OrthogonalPad, FRECT *BoundingBox)
Definition: mergenf.cpp:293
double_VAR
#define double_VAR(name, val, comment)
Definition: params.h:309
MAX_LENGTH_MISMATCH
#define MAX_LENGTH_MISMATCH
Definition: mergenf.h:32
FRECT::MinX
float MinX
Definition: mergenf.h:43
NewFeature
FEATURE NewFeature(const FEATURE_DESC_STRUCT *FeatureDesc)
Definition: ocrfeatures.cpp:77
OrientationOf
#define OrientationOf(M)
Definition: mergenf.h:52
PicoFeatDesc
const TESS_API FEATURE_DESC_STRUCT PicoFeatDesc
PROTO_STRUCT::A
float A
Definition: protos.h:35
cluster.h
protos.h
PROTOTYPE::Mean
float * Mean
Definition: cluster.h:73
featdefs.h
WORST_EVIDENCE
#define WORST_EVIDENCE
Definition: mergenf.h:31
intproto.h
CenterX
#define CenterX(M)
Definition: mergenf.h:49
SubfeatureEvidence
float SubfeatureEvidence(FEATURE Feature, PROTO Proto)
Definition: mergenf.cpp:208
clusttool.h
WORST_MATCH_ALLOWED
#define WORST_MATCH_ALLOWED
Definition: mergenf.h:30
GetPicoFeatureLength
#define GetPicoFeatureLength()
Definition: picofeat.h:56