tesseract  4.1.0
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 /*---------------------------------------------------------------------------*/
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  ClearMark(NewPoint);
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 /*---------------------------------------------------------------------------*/
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 /*---------------------------------------------------------------------------*/
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  MarkPoint (PointAt (Current));
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 /*---------------------------------------------------------------------------*/
221  EdgePoint = NextPointAfter(EdgePoint);
222  while (!PointAt(EdgePoint)->ExtremityMark)
223  EdgePoint = NextPointAfter(EdgePoint);
224 
225  return (EdgePoint);
226 
227 } /* NextExtremity */
228 
229 
230 /*---------------------------------------------------------------------------*/
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 {
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 ----------------------------------------------------------------------------*/
309 void ChangeDirection(MFOUTLINE Start, MFOUTLINE End, DIRECTION Direction) {
310  MFOUTLINE Current;
311 
312  for (Current = Start; Current != End; Current = NextPointAfter (Current))
313  PointAt (Current)->Direction = Direction;
314 
315  PointAt (End)->PreviousDirection = Direction;
316 
317 } /* ChangeDirection */
318 
326 void CharNormalizeOutline(MFOUTLINE Outline, const DENORM& cn_denorm) {
327  MFOUTLINE First, Current;
328  MFEDGEPT *CurrentPoint;
329 
330  if (Outline == NIL_LIST)
331  return;
332 
333  First = Outline;
334  Current = First;
335  do {
336  CurrentPoint = PointAt(Current);
337  FCOORD pos(CurrentPoint->Point.x, CurrentPoint->Point.y);
338  cn_denorm.LocalNormTransform(pos, &pos);
339  CurrentPoint->Point.x = (pos.x() - UINT8_MAX / 2) * MF_SCALE_FACTOR;
340  CurrentPoint->Point.y = (pos.y() - UINT8_MAX / 2) * MF_SCALE_FACTOR;
341 
342  Current = NextPointAfter(Current);
343  }
344  while (Current != First);
345 
346 } /* CharNormalizeOutline */
347 
364  MFEDGEPT *Finish,
365  float MinSlope,
366  float MaxSlope) {
367  FVECTOR Delta;
368 
369  Delta.x = Finish->Point.x - Start->Point.x;
370  Delta.y = Finish->Point.y - Start->Point.y;
371  if (Delta.x == 0) {
372  if (Delta.y < 0) {
373  Start->Slope = -FLT_MAX;
374  Start->Direction = south;
375  } else {
376  Start->Slope = FLT_MAX;
377  Start->Direction = north;
378  }
379  } else {
380  Start->Slope = Delta.y / Delta.x;
381  if (Delta.x > 0) {
382  if (Delta.y > 0) {
383  if (Start->Slope > MinSlope) {
384  if (Start->Slope < MaxSlope) {
385  Start->Direction = northeast;
386  } else {
387  Start->Direction = north;
388  }
389  } else {
390  Start->Direction = east;
391  }
392  }
393  else if (Start->Slope < -MinSlope) {
394  if (Start->Slope > -MaxSlope) {
395  Start->Direction = southeast;
396  } else {
397  Start->Direction = south;
398  }
399  } else {
400  Start->Direction = east;
401  }
402  } else if (Delta.y > 0) {
403  if (Start->Slope < -MinSlope) {
404  if (Start->Slope > -MaxSlope) {
405  Start->Direction = northwest;
406  } else {
407  Start->Direction = north;
408  }
409  } else {
410  Start->Direction = west;
411  }
412  } else if (Start->Slope > MinSlope) {
413  if (Start->Slope < MaxSlope) {
414  Start->Direction = southwest;
415  } else {
416  Start->Direction = south;
417  }
418  } else {
419  Start->Direction = west;
420  }
421  }
422  Finish->PreviousDirection = Start->Direction;
423 }
424 
435  DIRECTION InitialDirection;
436 
437  InitialDirection = PointAt (EdgePoint)->Direction;
438 
439  MFOUTLINE next_pt = nullptr;
440  do {
441  EdgePoint = NextPointAfter(EdgePoint);
442  next_pt = NextPointAfter(EdgePoint);
443  } while (PointAt(EdgePoint)->Direction == InitialDirection &&
444  !PointAt(EdgePoint)->Hidden &&
445  next_pt != nullptr && !PointAt(next_pt)->Hidden);
446 
447  return (EdgePoint);
448 }
void CharNormalizeOutline(MFOUTLINE Outline, const DENORM &cn_denorm)
Definition: mfoutline.cpp:326
TESSLINE * next
Definition: blobs.h:260
void NormalizeOutline(MFOUTLINE Outline, float XOrigin)
Definition: mfoutline.cpp:242
void FreeOutlines(LIST Outlines)
Definition: mfoutline.cpp:167
int16_t x
Definition: blobs.h:73
bool IsHidden() const
Definition: blobs.h:155
float x() const
Definition: points.h:207
Definition: points.h:188
#define set_rest(l, cell)
Definition: oldlist.h:120
OUTLINETYPE
Definition: mfoutline.h:55
EDGEPT * next
Definition: blobs.h:171
Definition: mfoutline.h:38
TESSLINE * outlines
Definition: blobs.h:379
bool Hidden
Definition: mfoutline.h:49
float y
Definition: fpoint.h:30
LIST ConvertOutlines(TESSLINE *outline, LIST mf_outlines, OUTLINETYPE outline_type)
Definition: mfoutline.cpp:89
#define DegenerateOutline(O)
Definition: mfoutline.h:68
void FindDirectionChanges(MFOUTLINE Outline, float MinSlope, float MaxSlope)
Definition: mfoutline.cpp:115
Definition: mfoutline.h:37
EDGEPT * loop
Definition: blobs.h:259
MFOUTLINE NextExtremity(MFOUTLINE EdgePoint)
Definition: mfoutline.cpp:220
TPOINT pos
Definition: blobs.h:165
Definition: blobs.h:263
#define ClearMark(P)
Definition: mfoutline.h:74
void NormalizeOutlines(LIST Outlines, float *XScale, float *YScale)
Definition: mfoutline.cpp:276
LIST push(LIST list, void *element)
Definition: oldlist.cpp:219
#define MarkPoint(P)
Definition: mfoutline.h:75
DIRECTION PreviousDirection
Definition: mfoutline.h:52
float y() const
Definition: points.h:210
int16_t y
Definition: blobs.h:74
const int kBlnBaselineOffset
Definition: normalis.h:25
#define list_rest(l)
Definition: oldlist.h:91
#define NIL_LIST
Definition: oldlist.h:76
Definition: blobs.h:78
#define PointAt(O)
Definition: mfoutline.h:69
DIRECTION
Definition: mfoutline.h:34
void MarkDirectionChanges(MFOUTLINE Outline)
Definition: mfoutline.cpp:183
void ChangeDirection(MFOUTLINE Start, MFOUTLINE End, DIRECTION Direction)
Definition: mfoutline.cpp:309
void FreeMFOutline(void *arg)
Definition: mfoutline.cpp:146
#define NextPointAfter(E)
Definition: mfoutline.h:70
FPOINT Point
Definition: mfoutline.h:46
#define MF_SCALE_FACTOR
Definition: mfoutline.h:65
#define first_node(l)
Definition: oldlist.h:92
#define ASSERT_HOST(x)
Definition: errcode.h:88
MFOUTLINE ConvertOutline(TESSLINE *outline)
Definition: mfoutline.cpp:47
#define MakeOutlineCircular(O)
Definition: mfoutline.h:71
float x
Definition: fpoint.h:30
MFEDGEPT * NewEdgePoint()
Definition: mfoutline.cpp:205
void LocalNormTransform(const TPOINT &pt, TPOINT *transformed) const
Definition: normalis.cpp:306
MFOUTLINE NextDirectionChange(MFOUTLINE EdgePoint)
Definition: mfoutline.cpp:434
void ComputeDirection(MFEDGEPT *Start, MFEDGEPT *Finish, float MinSlope, float MaxSlope)
Definition: mfoutline.cpp:363
DIRECTION Direction
Definition: mfoutline.h:51
LIST ConvertBlob(TBLOB *blob)
Definition: mfoutline.cpp:37
void destroy_nodes(LIST list, void_dest destructor)
Definition: oldlist.cpp:158
float Slope
Definition: mfoutline.h:47
Definition: fpoint.h:29
LIST pop(LIST list)
Definition: oldlist.cpp:202
#define iterate(l)
Definition: oldlist.h:101