tesseract v5.3.3.20231005
mergenf.h File Reference
#include "cluster.h"
#include "ocrfeatures.h"
#include "picofeat.h"
#include "protos.h"

Go to the source code of this file.

Classes

struct  FRECT
 

Macros

#define WORST_MATCH_ALLOWED   (0.9)
 
#define WORST_EVIDENCE   (1.0)
 
#define MAX_LENGTH_MISMATCH   (2.0 * GetPicoFeatureLength())
 
#define PROTO_SUFFIX   ".mf.p"
 
#define CONFIG_SUFFIX   ".cl"
 
#define NO_PROTO   (-1)
 
#define XPOSITION   0
 
#define YPOSITION   1
 
#define MFLENGTH   2
 
#define ORIENTATION   3
 
#define CenterX(M)   ((M)[XPOSITION])
 
#define CenterY(M)   ((M)[YPOSITION])
 
#define LengthOf(M)   ((M)[MFLENGTH])
 
#define OrientationOf(M)   ((M)[ORIENTATION])
 

Functions

float CompareProtos (tesseract::PROTO_STRUCT *p1, tesseract::PROTO_STRUCT *p2)
 
void ComputeMergedProto (tesseract::PROTO_STRUCT *p1, tesseract::PROTO_STRUCT *p2, float w1, float w2, tesseract::PROTO_STRUCT *MergedProto)
 
int FindClosestExistingProto (tesseract::CLASS_TYPE Class, int NumMerged[], tesseract::PROTOTYPE *Prototype)
 
void MakeNewFromOld (tesseract::PROTO_STRUCT *New, tesseract::PROTOTYPE *Old)
 
float SubfeatureEvidence (tesseract::FEATURE Feature, tesseract::PROTO_STRUCT *Proto)
 
double EvidenceOf (double Similarity)
 
bool DummyFastMatch (tesseract::FEATURE Feature, tesseract::PROTO_STRUCT *Proto)
 
void ComputePaddedBoundingBox (tesseract::PROTO_STRUCT *Proto, float TangentPad, float OrthogonalPad, FRECT *BoundingBox)
 
bool PointInside (FRECT *Rectangle, float X, float Y)
 

Macro Definition Documentation

◆ CenterX

#define CenterX (   M)    ((M)[XPOSITION])

Public Macros

Definition at line 48 of file mergenf.h.

◆ CenterY

#define CenterY (   M)    ((M)[YPOSITION])

Definition at line 49 of file mergenf.h.

◆ CONFIG_SUFFIX

#define CONFIG_SUFFIX   ".cl"

Definition at line 34 of file mergenf.h.

◆ LengthOf

#define LengthOf (   M)    ((M)[MFLENGTH])

Definition at line 50 of file mergenf.h.

◆ MAX_LENGTH_MISMATCH

#define MAX_LENGTH_MISMATCH   (2.0 * GetPicoFeatureLength())

Definition at line 31 of file mergenf.h.

◆ MFLENGTH

#define MFLENGTH   2

Definition at line 38 of file mergenf.h.

◆ NO_PROTO

#define NO_PROTO   (-1)

Definition at line 35 of file mergenf.h.

◆ ORIENTATION

#define ORIENTATION   3

Definition at line 39 of file mergenf.h.

◆ OrientationOf

#define OrientationOf (   M)    ((M)[ORIENTATION])

Definition at line 51 of file mergenf.h.

◆ PROTO_SUFFIX

#define PROTO_SUFFIX   ".mf.p"

Definition at line 33 of file mergenf.h.

◆ WORST_EVIDENCE

#define WORST_EVIDENCE   (1.0)

Definition at line 30 of file mergenf.h.

◆ WORST_MATCH_ALLOWED

#define WORST_MATCH_ALLOWED   (0.9)

Include Files and Type Defines

Definition at line 29 of file mergenf.h.

◆ XPOSITION

#define XPOSITION   0

Definition at line 36 of file mergenf.h.

◆ YPOSITION

#define YPOSITION   1

Definition at line 37 of file mergenf.h.

Function Documentation

◆ CompareProtos()

float CompareProtos ( PROTO_STRUCT p1,
PROTO_STRUCT p2 
)

Public Function Prototypes

Compare protos p1 and p2 and return an estimate of the worst evidence rating that will result for any part of p1 that is compared to p2. In other words, if p1 were broken into pico-features and each pico-feature was matched to p2, what is the worst evidence rating that will be achieved for any pico-feature.

Parameters
p1,p2protos to be compared

Globals: none

Returns
Worst possible result when matching p1 to p2.

Definition at line 66 of file mergenf.cpp.

66 {
67 float WorstEvidence = WORST_EVIDENCE;
68 float Evidence;
69 float Angle, Length;
70
71 /* if p1 and p2 are not close in length, don't let them match */
72 Length = std::fabs(p1->Length - p2->Length);
73 if (Length > MAX_LENGTH_MISMATCH) {
74 return (0.0);
75 }
76
77 /* create a dummy pico-feature to be used for comparisons */
78 auto Feature = new FEATURE_STRUCT(&PicoFeatDesc);
79 Feature->Params[PicoFeatDir] = p1->Angle;
80
81 /* convert angle to radians */
82 Angle = p1->Angle * 2.0 * M_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) {
87 Length = 0;
88 }
89
90 /* set the dummy pico-feature at one end of p1 and match it to p2 */
91 Feature->Params[PicoFeatX] = p1->X + std::cos(Angle) * Length;
92 Feature->Params[PicoFeatY] = p1->Y + std::sin(Angle) * Length;
93 if (DummyFastMatch(Feature, p2)) {
94 Evidence = SubfeatureEvidence(Feature, p2);
95 if (Evidence < WorstEvidence) {
96 WorstEvidence = Evidence;
97 }
98 } else {
99 delete Feature;
100 return 0.0;
101 }
102
103 /* set the dummy pico-feature at the other end of p1 and match it to p2 */
104 Feature->Params[PicoFeatX] = p1->X - std::cos(Angle) * Length;
105 Feature->Params[PicoFeatY] = p1->Y - std::sin(Angle) * Length;
106 if (DummyFastMatch(Feature, p2)) {
107 Evidence = SubfeatureEvidence(Feature, p2);
108 if (Evidence < WorstEvidence) {
109 WorstEvidence = Evidence;
110 }
111 } else {
112 delete Feature;
113 return 0.0;
114 }
115
116 delete Feature;
117 return (WorstEvidence);
118
119} /* CompareProtos */
#define MAX_LENGTH_MISMATCH
Definition: mergenf.h:31
#define WORST_EVIDENCE
Definition: mergenf.h:30
bool DummyFastMatch(FEATURE Feature, PROTO_STRUCT *Proto)
Definition: mergenf.cpp:263
float SubfeatureEvidence(FEATURE Feature, PROTO_STRUCT *Proto)
Definition: mergenf.cpp:209
#define GetPicoFeatureLength()
Definition: picofeat.h:56
@ PicoFeatDir
Definition: picofeat.h:43
@ PicoFeatX
Definition: picofeat.h:43
@ PicoFeatY
Definition: picofeat.h:43
TESS_API const FEATURE_DESC_STRUCT PicoFeatDesc

◆ ComputeMergedProto()

void ComputeMergedProto ( PROTO_STRUCT p1,
PROTO_STRUCT p2,
float  w1,
float  w2,
PROTO_STRUCT MergedProto 
)

This routine computes a proto which is the weighted average of protos p1 and p2. The new proto is returned in MergedProto.

Parameters
p1,p2protos to be merged
w1,w2weight of each proto
MergedProtoplace to put resulting merged proto

Definition at line 130 of file mergenf.cpp.

130 {
131 float TotalWeight;
132
133 TotalWeight = w1 + w2;
134 w1 /= TotalWeight;
135 w2 /= TotalWeight;
136
137 MergedProto->X = p1->X * w1 + p2->X * w2;
138 MergedProto->Y = p1->Y * w1 + p2->Y * w2;
139 MergedProto->Length = p1->Length * w1 + p2->Length * w2;
140 MergedProto->Angle = p1->Angle * w1 + p2->Angle * w2;
141 FillABC(MergedProto);
142} /* ComputeMergedProto */
void FillABC(PROTO_STRUCT *Proto)
Definition: protos.cpp:103

◆ ComputePaddedBoundingBox()

void ComputePaddedBoundingBox ( PROTO_STRUCT Proto,
float  TangentPad,
float  OrthogonalPad,
FRECT BoundingBox 
)

This routine computes a bounding box that encloses the specified proto along with some padding. The amount of padding is specified as separate distances in the tangential and orthogonal directions.

Parameters
Protoproto to compute bounding box for
TangentPadamount of pad to add in direction of segment
OrthogonalPadamount of pad to add orthogonal to segment
[out]BoundingBoxplace to put results

Definition at line 295 of file mergenf.cpp.

296 {
297 float Length = Proto->Length / 2.0 + TangentPad;
298 float Angle = Proto->Angle * 2.0 * M_PI;
299 float CosOfAngle = fabs(std::cos(Angle));
300 float SinOfAngle = fabs(std::sin(Angle));
301
302 float Pad = std::max(CosOfAngle * Length, SinOfAngle * OrthogonalPad);
303 BoundingBox->MinX = Proto->X - Pad;
304 BoundingBox->MaxX = Proto->X + Pad;
305
306 Pad = std::max(SinOfAngle * Length, CosOfAngle * OrthogonalPad);
307 BoundingBox->MinY = Proto->Y - Pad;
308 BoundingBox->MaxY = Proto->Y + Pad;
309
310} /* ComputePaddedBoundingBox */
float MaxY
Definition: mergenf.h:42
float MinX
Definition: mergenf.h:42
float MinY
Definition: mergenf.h:42
float MaxX
Definition: mergenf.h:42

◆ DummyFastMatch()

bool DummyFastMatch ( FEATURE  Feature,
PROTO_STRUCT Proto 
)

This routine returns true if Feature would be matched by a fast match table built from Proto.

Parameters
Featurefeature to be "fast matched" to proto
Protoproto being "fast matched" against

Globals:

  • training_tangent_bbox_pad bounding box pad tangent to proto
  • training_orthogonal_bbox_pad bounding box pad orthogonal to proto
Returns
true if feature could match Proto.

Definition at line 263 of file mergenf.cpp.

263 {
264 FRECT BoundingBox;
265 float MaxAngleError;
266 float AngleError;
267
268 MaxAngleError = training_angle_pad / 360.0;
269 AngleError = std::fabs(Proto->Angle - Feature->Params[PicoFeatDir]);
270 if (AngleError > 0.5) {
271 AngleError = 1.0 - AngleError;
272 }
273
274 if (AngleError > MaxAngleError) {
275 return false;
276 }
277
278 ComputePaddedBoundingBox(Proto, training_tangent_bbox_pad * GetPicoFeatureLength(),
279 training_orthogonal_bbox_pad * GetPicoFeatureLength(), &BoundingBox);
280
281 return PointInside(&BoundingBox, Feature->Params[PicoFeatX], Feature->Params[PicoFeatY]);
282} /* DummyFastMatch */
bool PointInside(FRECT *Rectangle, float X, float Y)
Definition: mergenf.cpp:319
void ComputePaddedBoundingBox(PROTO_STRUCT *Proto, float TangentPad, float OrthogonalPad, FRECT *BoundingBox)
Definition: mergenf.cpp:295
std::vector< float > Params
Definition: ocrfeatures.h:66
Definition: mergenf.h:41

◆ EvidenceOf()

double EvidenceOf ( double  Similarity)

Definition at line 236 of file mergenf.cpp.

236 {
237 Similarity /= training_similarity_midpoint;
238
239 if (training_similarity_curl == 3) {
240 Similarity = Similarity * Similarity * Similarity;
241 } else if (training_similarity_curl == 2) {
242 Similarity = Similarity * Similarity;
243 } else {
244 Similarity = pow(Similarity, training_similarity_curl);
245 }
246
247 return (1.0 / (1.0 + Similarity));
248}

◆ FindClosestExistingProto()

int FindClosestExistingProto ( CLASS_TYPE  Class,
int  NumMerged[],
PROTOTYPE Prototype 
)

This routine searches through all of the prototypes in Class and returns the id of the proto which would provide the best approximation of Prototype. If no close approximation can be found, NO_PROTO is returned.

Parameters
Classclass to search for matching old proto in
NumMerged# of protos merged into each proto of Class
Prototypenew proto to find match for

Globals: none

Returns
Id of closest proto in Class or NO_PROTO.

Definition at line 158 of file mergenf.cpp.

158 {
159 PROTO_STRUCT NewProto;
160 PROTO_STRUCT MergedProto;
161 int Pid;
162 PROTO_STRUCT *Proto;
163 int BestProto;
164 float BestMatch;
165 float Match, OldMatch, NewMatch;
166
167 MakeNewFromOld(&NewProto, Prototype);
168
169 BestProto = NO_PROTO;
170 BestMatch = WORST_MATCH_ALLOWED;
171 for (Pid = 0; Pid < Class->NumProtos; Pid++) {
172 Proto = ProtoIn(Class, Pid);
173 ComputeMergedProto(Proto, &NewProto, static_cast<float>(NumMerged[Pid]), 1.0, &MergedProto);
174 OldMatch = CompareProtos(Proto, &MergedProto);
175 NewMatch = CompareProtos(&NewProto, &MergedProto);
176 Match = std::min(OldMatch, NewMatch);
177 if (Match > BestMatch) {
178 BestProto = Pid;
179 BestMatch = Match;
180 }
181 }
182 return BestProto;
183} /* FindClosestExistingProto */
#define NO_PROTO
Definition: matchdefs.h:41
#define WORST_MATCH_ALLOWED
Definition: mergenf.h:29
void ComputeMergedProto(PROTO_STRUCT *p1, PROTO_STRUCT *p2, float w1, float w2, PROTO_STRUCT *MergedProto)
Definition: mergenf.cpp:130
float CompareProtos(PROTO_STRUCT *p1, PROTO_STRUCT *p2)
Definition: mergenf.cpp:66
void MakeNewFromOld(PROTO_STRUCT *New, PROTOTYPE *Old)
Definition: mergenf.cpp:194
#define ProtoIn(Class, Pid)
Definition: protos.h:70

◆ MakeNewFromOld()

void MakeNewFromOld ( PROTO_STRUCT New,
PROTOTYPE Old 
)

This fills in the fields of the New proto based on the fields of the Old proto.

Parameters
Newnew proto to be filled in
Oldold proto to be converted

Globals: none

Definition at line 194 of file mergenf.cpp.

194 {
195 New->X = CenterX(Old->Mean);
196 New->Y = CenterY(Old->Mean);
197 New->Length = LengthOf(Old->Mean);
198 New->Angle = OrientationOf(Old->Mean);
199 FillABC(New);
200} /* MakeNewFromOld */
#define CenterX(M)
Definition: mergenf.h:48
#define CenterY(M)
Definition: mergenf.h:49
#define LengthOf(M)
Definition: mergenf.h:50
#define OrientationOf(M)
Definition: mergenf.h:51
std::vector< float > Mean
Definition: cluster.h:83

◆ PointInside()

bool PointInside ( FRECT Rectangle,
float  X,
float  Y 
)

Return true if point (X,Y) is inside of Rectangle.

Globals: none

Returns
true if point (X,Y) is inside of Rectangle.

Definition at line 319 of file mergenf.cpp.

319 {
320 return (X >= Rectangle->MinX) && (X <= Rectangle->MaxX) && (Y >= Rectangle->MinY) &&
321 (Y <= Rectangle->MaxY);
322} /* PointInside */

◆ SubfeatureEvidence()

float SubfeatureEvidence ( tesseract::FEATURE  Feature,
tesseract::PROTO_STRUCT Proto 
)

Definition at line 209 of file mergenf.cpp.

209 {
210 float Distance;
211 float Dangle;
212
213 Dangle = Proto->Angle - Feature->Params[PicoFeatDir];
214 if (Dangle < -0.5) {
215 Dangle += 1.0;
216 }
217 if (Dangle > 0.5) {
218 Dangle -= 1.0;
219 }
220 Dangle *= training_angle_match_scale;
221
222 Distance =
223 Proto->A * Feature->Params[PicoFeatX] + Proto->B * Feature->Params[PicoFeatY] + Proto->C;
224
225 return (EvidenceOf(Distance * Distance + Dangle * Dangle));
226}
double EvidenceOf(double Similarity)
Definition: mergenf.cpp:236