tesseract 4.1.1
Loading...
Searching...
No Matches
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---------------------------------*/
36static double_VAR(training_angle_match_scale, 1.0, "Angle Match Scale ...");
37
38static double_VAR(training_similarity_midpoint, 0.0075, "Similarity Midpoint ...");
39
40static double_VAR(training_similarity_curl, 2.0, "Similarity Curl ...");
41
42/*-----------------------------once in fasttrain----------------------------------*/
43static double_VAR(training_tangent_bbox_pad, 0.5, "Tangent bounding box pad ...");
44
45static double_VAR(training_orthogonal_bbox_pad, 2.5, "Orthogonal bounding box pad ...");
46
47static double_VAR(training_angle_pad, 45.0, "Angle pad ...");
48
63float 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
155int 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
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
208float 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
232double 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
259bool 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
293void 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
317bool 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 */
#define double_VAR(name, val, comment)
Definition: params.h:312
TESS_API const FEATURE_DESC_STRUCT PicoFeatDesc
FEATURE NewFeature(const FEATURE_DESC_STRUCT *FeatureDesc)
Definition: ocrfeatures.cpp:78
void FreeFeature(FEATURE Feature)
Definition: ocrfeatures.cpp:54
#define GetPicoFeatureLength()
Definition: picofeat.h:57
@ PicoFeatY
Definition: picofeat.h:44
@ PicoFeatDir
Definition: picofeat.h:44
@ PicoFeatX
Definition: picofeat.h:44
void FillABC(PROTO Proto)
Definition: protos.cpp:108
#define ProtoIn(Class, Pid)
Definition: protos.h:84
#define NO_PROTO
Definition: matchdefs.h:41
bool PointInside(FRECT *Rectangle, float X, float Y)
Definition: mergenf.cpp:317
bool DummyFastMatch(FEATURE Feature, PROTO Proto)
Definition: mergenf.cpp:259
void ComputeMergedProto(PROTO p1, PROTO p2, float w1, float w2, PROTO MergedProto)
Definition: mergenf.cpp:123
void MakeNewFromOld(PROTO New, PROTOTYPE *Old)
Definition: mergenf.cpp:193
float CompareProtos(PROTO p1, PROTO p2)
Definition: mergenf.cpp:63
double EvidenceOf(double Similarity)
Definition: mergenf.cpp:232
float SubfeatureEvidence(FEATURE Feature, PROTO Proto)
Definition: mergenf.cpp:208
void ComputePaddedBoundingBox(PROTO Proto, float TangentPad, float OrthogonalPad, FRECT *BoundingBox)
Definition: mergenf.cpp:293
int FindClosestExistingProto(CLASS_TYPE Class, int NumMerged[], PROTOTYPE *Prototype)
Definition: mergenf.cpp:155
#define CenterX(M)
Definition: mergenf.h:50
#define MAX_LENGTH_MISMATCH
Definition: mergenf.h:33
#define CenterY(M)
Definition: mergenf.h:51
#define WORST_MATCH_ALLOWED
Definition: mergenf.h:31
#define LengthOf(M)
Definition: mergenf.h:52
#define WORST_EVIDENCE
Definition: mergenf.h:32
#define OrientationOf(M)
Definition: mergenf.h:53
float * Mean
Definition: cluster.h:74
float Params[1]
Definition: ocrfeatures.h:61
float Angle
Definition: protos.h:42
float Length
Definition: protos.h:43
float Y
Definition: protos.h:41
float B
Definition: protos.h:38
float A
Definition: protos.h:37
float C
Definition: protos.h:39
float X
Definition: protos.h:40
int16_t NumProtos
Definition: protos.h:55
Definition: mergenf.h:43
float MaxY
Definition: mergenf.h:44
float MinX
Definition: mergenf.h:44
float MinY
Definition: mergenf.h:44
float MaxX
Definition: mergenf.h:44