tesseract  5.0.0-alpha-619-ge9db
mfoutline.cpp
Go to the documentation of this file.
1 /******************************************************************************
2  ** Filename: mfoutline.c
3  ** Purpose: Interface to outline struct used for extracting features
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  Include Files and Type Defines
19 ----------------------------------------------------------------------------*/
20 #include "clusttool.h" //If remove you get cought in a loop somewhere
21 #include "mfoutline.h"
22 #include "blobs.h"
23 #include "mfx.h"
24 #include "params.h"
25 #include "classify.h"
26 
27 #include <cmath>
28 #include <cstdio>
29 
30 /*----------------------------------------------------------------------------
31  Public Code
32 ----------------------------------------------------------------------------*/
33 
34 /*---------------------------------------------------------------------------*/
37 LIST ConvertBlob(TBLOB *blob) {
38  LIST outlines = NIL_LIST;
39  return (blob == nullptr)
40  ? NIL_LIST
41  : ConvertOutlines(blob->outlines, outlines, outer);
42 }
43 
44 
45 /*---------------------------------------------------------------------------*/
48  MFEDGEPT *NewPoint;
49  MFOUTLINE MFOutline = NIL_LIST;
50  EDGEPT *EdgePoint;
51  EDGEPT *StartPoint;
52  EDGEPT *NextPoint;
53 
54  if (outline == nullptr || outline->loop == nullptr)
55  return MFOutline;
56 
57  StartPoint = outline->loop;
58  EdgePoint = StartPoint;
59  do {
60  NextPoint = EdgePoint->next;
61 
62  /* filter out duplicate points */
63  if (EdgePoint->pos.x != NextPoint->pos.x ||
64  EdgePoint->pos.y != NextPoint->pos.y) {
65  NewPoint = NewEdgePoint();
66  NewPoint->ClearMark();
67  NewPoint->Hidden = EdgePoint->IsHidden();
68  NewPoint->Point.x = EdgePoint->pos.x;
69  NewPoint->Point.y = EdgePoint->pos.y;
70  MFOutline = push(MFOutline, NewPoint);
71  }
72  EdgePoint = NextPoint;
73  } while (EdgePoint != StartPoint);
74 
75  if (MFOutline != nullptr)
76  MakeOutlineCircular(MFOutline);
77  return MFOutline;
78 }
79 
80 
81 /*---------------------------------------------------------------------------*/
90  LIST mf_outlines,
91  OUTLINETYPE outline_type) {
92  MFOUTLINE mf_outline;
93 
94  while (outline != nullptr) {
95  mf_outline = ConvertOutline(outline);
96  if (mf_outline != nullptr)
97  mf_outlines = push(mf_outlines, mf_outline);
98  outline = outline->next;
99  }
100  return mf_outlines;
101 }
102 
103 /*---------------------------------------------------------------------------*/
115 void FindDirectionChanges(MFOUTLINE Outline,
116  float MinSlope,
117  float MaxSlope) {
118  MFEDGEPT *Current;
119  MFEDGEPT *Last;
120  MFOUTLINE EdgePoint;
121 
122  if (DegenerateOutline (Outline))
123  return;
124 
125  Last = PointAt (Outline);
126  Outline = NextPointAfter (Outline);
127  EdgePoint = Outline;
128  do {
129  Current = PointAt (EdgePoint);
130  ComputeDirection(Last, Current, MinSlope, MaxSlope);
131 
132  Last = Current;
133  EdgePoint = NextPointAfter (EdgePoint);
134  }
135  while (EdgePoint != Outline);
136 
137 } /* FindDirectionChanges */
138 
139 
140 /*---------------------------------------------------------------------------*/
146 void FreeMFOutline(void *arg) { //MFOUTLINE Outline)
147  MFOUTLINE Start;
148  auto Outline = static_cast<MFOUTLINE>(arg);
149 
150  /* break the circular outline so we can use std. techniques to deallocate */
151  Start = list_rest (Outline);
152  set_rest(Outline, NIL_LIST);
153  while (Start != nullptr) {
154  free(first_node(Start));
155  Start = pop (Start);
156  }
157 
158 } /* FreeMFOutline */
159 
160 
161 /*---------------------------------------------------------------------------*/
167 void FreeOutlines(LIST Outlines) {
168  destroy_nodes(Outlines, FreeMFOutline);
169 } /* FreeOutlines */
170 
171 
172 /*---------------------------------------------------------------------------*/
183 void MarkDirectionChanges(MFOUTLINE Outline) {
184  MFOUTLINE Current;
185  MFOUTLINE Last;
186  MFOUTLINE First;
187 
188  if (DegenerateOutline (Outline))
189  return;
190 
191  First = NextDirectionChange (Outline);
192  Last = First;
193  do {
194  Current = NextDirectionChange (Last);
195  PointAt(Current)->MarkPoint();
196  Last = Current;
197  }
198  while (Last != First);
199 
200 } /* MarkDirectionChanges */
201 
202 
203 /*---------------------------------------------------------------------------*/
206  return reinterpret_cast<MFEDGEPT *>(malloc(sizeof(MFEDGEPT)));
207 }
208 
209 /*---------------------------------------------------------------------------*/
220 MFOUTLINE NextExtremity(MFOUTLINE EdgePoint) {
221  EdgePoint = NextPointAfter(EdgePoint);
222  while (!PointAt(EdgePoint)->ExtremityMark)
223  EdgePoint = NextPointAfter(EdgePoint);
224 
225  return (EdgePoint);
226 
227 } /* NextExtremity */
228 
229 
230 /*---------------------------------------------------------------------------*/
242 void NormalizeOutline(MFOUTLINE Outline,
243  float XOrigin) {
244  if (Outline == NIL_LIST)
245  return;
246 
247  MFOUTLINE EdgePoint = Outline;
248  do {
249  MFEDGEPT *Current = PointAt(EdgePoint);
250  Current->Point.y = MF_SCALE_FACTOR *
251  (Current->Point.y - kBlnBaselineOffset);
252  Current->Point.x = MF_SCALE_FACTOR * (Current->Point.x - XOrigin);
253  EdgePoint = NextPointAfter(EdgePoint);
254  } while (EdgePoint != Outline);
255 } /* NormalizeOutline */
256 
257 
258 /*---------------------------------------------------------------------------*/
259 namespace tesseract {
276 void Classify::NormalizeOutlines(LIST Outlines,
277  float *XScale,
278  float *YScale) {
279  MFOUTLINE Outline;
280 
281  switch (classify_norm_method) {
282  case character:
283  ASSERT_HOST(!"How did NormalizeOutlines get called in character mode?");
284  break;
285 
286  case baseline:
287  iterate(Outlines) {
288  Outline = static_cast<MFOUTLINE>first_node(Outlines);
289  NormalizeOutline(Outline, 0.0);
290  }
291  *XScale = *YScale = MF_SCALE_FACTOR;
292  break;
293  }
294 } /* NormalizeOutlines */
295 } // namespace tesseract
296 
297 /*----------------------------------------------------------------------------
298  Private Code
299 ----------------------------------------------------------------------------*/
310 void ChangeDirection(MFOUTLINE Start, MFOUTLINE End, DIRECTION Direction) {
311  MFOUTLINE Current;
312 
313  for (Current = Start; Current != End; Current = NextPointAfter (Current))
314  PointAt (Current)->Direction = Direction;
315 
316  PointAt (End)->PreviousDirection = Direction;
317 
318 } /* ChangeDirection */
319 
327 void CharNormalizeOutline(MFOUTLINE Outline, const DENORM& cn_denorm) {
328  MFOUTLINE First, Current;
329  MFEDGEPT *CurrentPoint;
330 
331  if (Outline == NIL_LIST)
332  return;
333 
334  First = Outline;
335  Current = First;
336  do {
337  CurrentPoint = PointAt(Current);
338  FCOORD pos(CurrentPoint->Point.x, CurrentPoint->Point.y);
339  cn_denorm.LocalNormTransform(pos, &pos);
340  CurrentPoint->Point.x = (pos.x() - UINT8_MAX / 2) * MF_SCALE_FACTOR;
341  CurrentPoint->Point.y = (pos.y() - UINT8_MAX / 2) * MF_SCALE_FACTOR;
342 
343  Current = NextPointAfter(Current);
344  }
345  while (Current != First);
346 
347 } /* CharNormalizeOutline */
348 
364 void ComputeDirection(MFEDGEPT *Start,
365  MFEDGEPT *Finish,
366  float MinSlope,
367  float MaxSlope) {
368  FVECTOR Delta;
369 
370  Delta.x = Finish->Point.x - Start->Point.x;
371  Delta.y = Finish->Point.y - Start->Point.y;
372  if (Delta.x == 0) {
373  if (Delta.y < 0) {
374  Start->Slope = -FLT_MAX;
375  Start->Direction = south;
376  } else {
377  Start->Slope = FLT_MAX;
378  Start->Direction = north;
379  }
380  } else {
381  Start->Slope = Delta.y / Delta.x;
382  if (Delta.x > 0) {
383  if (Delta.y > 0) {
384  if (Start->Slope > MinSlope) {
385  if (Start->Slope < MaxSlope) {
386  Start->Direction = northeast;
387  } else {
388  Start->Direction = north;
389  }
390  } else {
391  Start->Direction = east;
392  }
393  }
394  else if (Start->Slope < -MinSlope) {
395  if (Start->Slope > -MaxSlope) {
396  Start->Direction = southeast;
397  } else {
398  Start->Direction = south;
399  }
400  } else {
401  Start->Direction = east;
402  }
403  } else if (Delta.y > 0) {
404  if (Start->Slope < -MinSlope) {
405  if (Start->Slope > -MaxSlope) {
406  Start->Direction = northwest;
407  } else {
408  Start->Direction = north;
409  }
410  } else {
411  Start->Direction = west;
412  }
413  } else if (Start->Slope > MinSlope) {
414  if (Start->Slope < MaxSlope) {
415  Start->Direction = southwest;
416  } else {
417  Start->Direction = south;
418  }
419  } else {
420  Start->Direction = west;
421  }
422  }
423  Finish->PreviousDirection = Start->Direction;
424 }
425 
436  DIRECTION InitialDirection;
437 
438  InitialDirection = PointAt (EdgePoint)->Direction;
439 
440  MFOUTLINE next_pt = nullptr;
441  do {
442  EdgePoint = NextPointAfter(EdgePoint);
443  next_pt = NextPointAfter(EdgePoint);
444  } while (PointAt(EdgePoint)->Direction == InitialDirection &&
445  !PointAt(EdgePoint)->Hidden &&
446  next_pt != nullptr && !PointAt(next_pt)->Hidden);
447 
448  return (EdgePoint);
449 }
mfx.h
MFEDGEPT::Direction
DIRECTION Direction
Definition: mfoutline.h:56
DIRECTION
DIRECTION
Definition: mfoutline.h:30
south
Definition: mfoutline.h:32
MFEDGEPT::Hidden
bool Hidden
Definition: mfoutline.h:54
MFEDGEPT::Point
FPOINT Point
Definition: mfoutline.h:52
tesseract::Classify::classify_norm_method
int classify_norm_method
Definition: classify.h:434
TESSLINE::loop
EDGEPT * loop
Definition: blobs.h:278
first_node
#define first_node(l)
Definition: oldlist.h:84
FPOINT::y
float y
Definition: fpoint.h:44
destroy_nodes
void destroy_nodes(LIST list, void_dest destructor)
Definition: oldlist.cpp:138
ASSERT_HOST
#define ASSERT_HOST(x)
Definition: errcode.h:87
list_rec
Definition: oldlist.h:73
list_rest
#define list_rest(l)
Definition: oldlist.h:83
TBLOB::outlines
TESSLINE * outlines
Definition: blobs.h:398
baseline
Definition: mfoutline.h:62
mfoutline.h
EDGEPT::IsHidden
bool IsHidden() const
Definition: blobs.h:174
params.h
TESSLINE
Definition: blobs.h:201
MarkDirectionChanges
void MarkDirectionChanges(MFOUTLINE Outline)
Definition: mfoutline.cpp:182
CharNormalizeOutline
void CharNormalizeOutline(MFOUTLINE Outline, const DENORM &cn_denorm)
Definition: mfoutline.cpp:326
NextDirectionChange
MFOUTLINE NextDirectionChange(MFOUTLINE EdgePoint)
Definition: mfoutline.cpp:434
FPOINT
Definition: fpoint.h:28
northwest
Definition: mfoutline.h:36
tesseract::Classify::NormalizeOutlines
void NormalizeOutlines(LIST Outlines, float *XScale, float *YScale)
Definition: mfoutline.cpp:275
MFEDGEPT::PreviousDirection
DIRECTION PreviousDirection
Definition: mfoutline.h:57
FPOINT::x
float x
Definition: fpoint.h:44
MF_SCALE_FACTOR
const float MF_SCALE_FACTOR
Definition: mfoutline.h:70
TESSLINE::next
TESSLINE * next
Definition: blobs.h:279
NIL_LIST
#define NIL_LIST
Definition: oldlist.h:68
FCOORD
Definition: points.h:187
blobs.h
southwest
Definition: mfoutline.h:38
OUTLINETYPE
OUTLINETYPE
Definition: mfoutline.h:60
FindDirectionChanges
void FindDirectionChanges(MFOUTLINE Outline, float MinSlope, float MaxSlope)
Definition: mfoutline.cpp:114
ComputeDirection
void ComputeDirection(MFEDGEPT *Start, MFEDGEPT *Finish, float MinSlope, float MaxSlope)
Definition: mfoutline.cpp:363
TPOINT::x
int16_t x
Definition: blobs.h:91
ConvertBlob
LIST ConvertBlob(TBLOB *blob)
Definition: mfoutline.cpp:36
TPOINT::y
int16_t y
Definition: blobs.h:92
ConvertOutline
MFOUTLINE ConvertOutline(TESSLINE *outline)
Definition: mfoutline.cpp:46
character
Definition: mfoutline.h:62
FreeMFOutline
void FreeMFOutline(void *arg)
Definition: mfoutline.cpp:145
tesseract
Definition: baseapi.h:65
push
LIST push(LIST list, void *element)
Definition: oldlist.cpp:172
NewEdgePoint
MFEDGEPT * NewEdgePoint()
Definition: mfoutline.cpp:204
southeast
Definition: mfoutline.h:37
FreeOutlines
void FreeOutlines(LIST Outlines)
Definition: mfoutline.cpp:166
MFEDGEPT::Slope
float Slope
Definition: mfoutline.h:53
TBLOB
Definition: blobs.h:282
MFEDGEPT::ClearMark
void ClearMark()
Definition: mfoutline.h:44
MFEDGEPT
Definition: mfoutline.h:41
east
Definition: mfoutline.h:33
iterate
#define iterate(l)
Definition: oldlist.h:92
west
Definition: mfoutline.h:34
ChangeDirection
void ChangeDirection(MFOUTLINE Start, MFOUTLINE End, DIRECTION Direction)
Definition: mfoutline.cpp:309
pop
LIST pop(LIST list)
Definition: oldlist.cpp:161
EDGEPT
Definition: blobs.h:97
DENORM::LocalNormTransform
void LocalNormTransform(const TPOINT &pt, TPOINT *transformed) const
Definition: normalis.cpp:305
north
Definition: mfoutline.h:31
classify.h
northeast
Definition: mfoutline.h:35
NextExtremity
MFOUTLINE NextExtremity(MFOUTLINE EdgePoint)
Definition: mfoutline.cpp:219
outer
Definition: mfoutline.h:60
NormalizeOutline
void NormalizeOutline(MFOUTLINE Outline, float XOrigin)
Definition: mfoutline.cpp:241
kBlnBaselineOffset
const int kBlnBaselineOffset
Definition: normalis.h:24
EDGEPT::pos
TPOINT pos
Definition: blobs.h:184
clusttool.h
EDGEPT::next
EDGEPT * next
Definition: blobs.h:190
set_rest
#define set_rest(l, cell)
Definition: oldlist.h:101
ConvertOutlines
LIST ConvertOutlines(TESSLINE *outline, LIST mf_outlines, OUTLINETYPE outline_type)
Definition: mfoutline.cpp:88
DENORM
Definition: normalis.h:49