tesseract  5.0.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 "mfoutline.h"
19 
20 #include "blobs.h"
21 #include "classify.h"
22 #include "clusttool.h" //If remove you get cought in a loop somewhere
23 #include "mfx.h"
24 #include "params.h"
25 
26 #include <cmath>
27 #include <cstdio>
28 
29 namespace tesseract {
30 
31 /*---------------------------------------------------------------------------*/
35  LIST outlines = NIL_LIST;
36  return (blob == nullptr) ? NIL_LIST : ConvertOutlines(blob->outlines, outlines, outer);
37 }
38 
39 /*---------------------------------------------------------------------------*/
42  auto MFOutline = NIL_LIST;
43 
44  if (outline == nullptr || outline->loop == nullptr) {
45  return MFOutline;
46  }
47 
48  auto StartPoint = outline->loop;
49  auto EdgePoint = StartPoint;
50  do {
51  auto NextPoint = EdgePoint->next;
52 
53  /* filter out duplicate points */
54  if (EdgePoint->pos.x != NextPoint->pos.x || EdgePoint->pos.y != NextPoint->pos.y) {
55  auto NewPoint = new MFEDGEPT;
56  NewPoint->ClearMark();
57  NewPoint->Hidden = EdgePoint->IsHidden();
58  NewPoint->Point.x = EdgePoint->pos.x;
59  NewPoint->Point.y = EdgePoint->pos.y;
60  MFOutline = push(MFOutline, NewPoint);
61  }
62  EdgePoint = NextPoint;
63  } while (EdgePoint != StartPoint);
64 
65  if (MFOutline != nullptr) {
66  MakeOutlineCircular(MFOutline);
67  }
68  return MFOutline;
69 }
70 
71 /*---------------------------------------------------------------------------*/
79 LIST ConvertOutlines(TESSLINE *outline, LIST mf_outlines, OUTLINETYPE outline_type) {
80  MFOUTLINE mf_outline;
81 
82  while (outline != nullptr) {
83  mf_outline = ConvertOutline(outline);
84  if (mf_outline != nullptr) {
85  mf_outlines = push(mf_outlines, mf_outline);
86  }
87  outline = outline->next;
88  }
89  return mf_outlines;
90 }
91 
92 /*---------------------------------------------------------------------------*/
104 void FindDirectionChanges(MFOUTLINE Outline, float MinSlope, float MaxSlope) {
105  MFEDGEPT *Current;
106  MFEDGEPT *Last;
107  MFOUTLINE EdgePoint;
108 
109  if (DegenerateOutline(Outline)) {
110  return;
111  }
112 
113  Last = PointAt(Outline);
114  Outline = NextPointAfter(Outline);
115  EdgePoint = Outline;
116  do {
117  Current = PointAt(EdgePoint);
118  ComputeDirection(Last, Current, MinSlope, MaxSlope);
119 
120  Last = Current;
121  EdgePoint = NextPointAfter(EdgePoint);
122  } while (EdgePoint != Outline);
123 
124 } /* FindDirectionChanges */
125 
126 /*---------------------------------------------------------------------------*/
132 void FreeMFOutline(void *arg) { // MFOUTLINE Outline)
133  auto Outline = static_cast<MFOUTLINE>(arg);
134 
135  /* break the circular outline so we can use std. techniques to deallocate */
136  MFOUTLINE Start = Outline->list_rest();
137  set_rest(Outline, NIL_LIST);
138  while (Start != nullptr) {
139  delete reinterpret_cast<MFEDGEPT *>(Start->first_node());
140  Start = pop(Start);
141  }
142 
143 } /* FreeMFOutline */
144 
145 /*---------------------------------------------------------------------------*/
151 void FreeOutlines(LIST Outlines) {
152  destroy_nodes(Outlines, FreeMFOutline);
153 } /* FreeOutlines */
154 
155 /*---------------------------------------------------------------------------*/
167  MFOUTLINE Current;
168  MFOUTLINE Last;
169  MFOUTLINE First;
170 
171  if (DegenerateOutline(Outline)) {
172  return;
173  }
174 
175  First = NextDirectionChange(Outline);
176  Last = First;
177  do {
178  Current = NextDirectionChange(Last);
179  PointAt(Current)->MarkPoint();
180  Last = Current;
181  } while (Last != First);
182 
183 } /* MarkDirectionChanges */
184 
185 /*---------------------------------------------------------------------------*/
197  EdgePoint = NextPointAfter(EdgePoint);
198  while (!PointAt(EdgePoint)->ExtremityMark) {
199  EdgePoint = NextPointAfter(EdgePoint);
200  }
201 
202  return (EdgePoint);
203 
204 } /* NextExtremity */
205 
206 /*---------------------------------------------------------------------------*/
218 void NormalizeOutline(MFOUTLINE Outline, float XOrigin) {
219  if (Outline == NIL_LIST) {
220  return;
221  }
222 
223  MFOUTLINE EdgePoint = Outline;
224  do {
225  MFEDGEPT *Current = PointAt(EdgePoint);
226  Current->Point.y = MF_SCALE_FACTOR * (Current->Point.y - kBlnBaselineOffset);
227  Current->Point.x = MF_SCALE_FACTOR * (Current->Point.x - XOrigin);
228  EdgePoint = NextPointAfter(EdgePoint);
229  } while (EdgePoint != Outline);
230 } /* NormalizeOutline */
231 
232 /*---------------------------------------------------------------------------*/
249 void Classify::NormalizeOutlines(LIST Outlines, float *XScale, float *YScale) {
250  MFOUTLINE Outline;
251 
252  switch (classify_norm_method) {
253  case character:
254  ASSERT_HOST(!"How did NormalizeOutlines get called in character mode?");
255  break;
256 
257  case baseline:
258  iterate(Outlines) {
259  Outline = static_cast<MFOUTLINE>(Outlines->first_node());
260  NormalizeOutline(Outline, 0.0);
261  }
262  *XScale = *YScale = MF_SCALE_FACTOR;
263  break;
264  }
265 } /* NormalizeOutlines */
266 
267 /*----------------------------------------------------------------------------
268  Private Code
269 ----------------------------------------------------------------------------*/
280 void ChangeDirection(MFOUTLINE Start, MFOUTLINE End, DIRECTION Direction) {
281  MFOUTLINE Current;
282 
283  for (Current = Start; Current != End; Current = NextPointAfter(Current)) {
284  PointAt(Current)->Direction = Direction;
285  }
286 
287  PointAt(End)->PreviousDirection = Direction;
288 
289 } /* ChangeDirection */
290 
298 void CharNormalizeOutline(MFOUTLINE Outline, const DENORM &cn_denorm) {
299  MFOUTLINE First, Current;
300  MFEDGEPT *CurrentPoint;
301 
302  if (Outline == NIL_LIST) {
303  return;
304  }
305 
306  First = Outline;
307  Current = First;
308  do {
309  CurrentPoint = PointAt(Current);
310  FCOORD pos(CurrentPoint->Point.x, CurrentPoint->Point.y);
311  cn_denorm.LocalNormTransform(pos, &pos);
312  CurrentPoint->Point.x = (pos.x() - UINT8_MAX / 2) * MF_SCALE_FACTOR;
313  CurrentPoint->Point.y = (pos.y() - UINT8_MAX / 2) * MF_SCALE_FACTOR;
314 
315  Current = NextPointAfter(Current);
316  } while (Current != First);
317 
318 } /* CharNormalizeOutline */
319 
335 void ComputeDirection(MFEDGEPT *Start, MFEDGEPT *Finish, float MinSlope, float MaxSlope) {
336  FVECTOR Delta;
337 
338  Delta.x = Finish->Point.x - Start->Point.x;
339  Delta.y = Finish->Point.y - Start->Point.y;
340  if (Delta.x == 0) {
341  if (Delta.y < 0) {
342  Start->Slope = -FLT_MAX;
343  Start->Direction = south;
344  } else {
345  Start->Slope = FLT_MAX;
346  Start->Direction = north;
347  }
348  } else {
349  Start->Slope = Delta.y / Delta.x;
350  if (Delta.x > 0) {
351  if (Delta.y > 0) {
352  if (Start->Slope > MinSlope) {
353  if (Start->Slope < MaxSlope) {
354  Start->Direction = northeast;
355  } else {
356  Start->Direction = north;
357  }
358  } else {
359  Start->Direction = east;
360  }
361  } else if (Start->Slope < -MinSlope) {
362  if (Start->Slope > -MaxSlope) {
363  Start->Direction = southeast;
364  } else {
365  Start->Direction = south;
366  }
367  } else {
368  Start->Direction = east;
369  }
370  } else if (Delta.y > 0) {
371  if (Start->Slope < -MinSlope) {
372  if (Start->Slope > -MaxSlope) {
373  Start->Direction = northwest;
374  } else {
375  Start->Direction = north;
376  }
377  } else {
378  Start->Direction = west;
379  }
380  } else if (Start->Slope > MinSlope) {
381  if (Start->Slope < MaxSlope) {
382  Start->Direction = southwest;
383  } else {
384  Start->Direction = south;
385  }
386  } else {
387  Start->Direction = west;
388  }
389  }
390  Finish->PreviousDirection = Start->Direction;
391 }
392 
403  DIRECTION InitialDirection;
404 
405  InitialDirection = PointAt(EdgePoint)->Direction;
406 
407  MFOUTLINE next_pt = nullptr;
408  do {
409  EdgePoint = NextPointAfter(EdgePoint);
410  next_pt = NextPointAfter(EdgePoint);
411  } while (PointAt(EdgePoint)->Direction == InitialDirection && !PointAt(EdgePoint)->Hidden &&
412  next_pt != nullptr && !PointAt(next_pt)->Hidden);
413 
414  return (EdgePoint);
415 }
416 
417 } // namespace tesseract
#define ASSERT_HOST(x)
Definition: errcode.h:59
#define iterate(l)
Definition: oldlist.h:91
#define set_rest(l, cell)
Definition: oldlist.h:101
#define NIL_LIST
Definition: oldlist.h:75
void FreeOutlines(LIST Outlines)
Definition: mfoutline.cpp:151
void MarkDirectionChanges(MFOUTLINE Outline)
Definition: mfoutline.cpp:166
@ northeast
Definition: mfoutline.h:30
@ southeast
Definition: mfoutline.h:30
@ northwest
Definition: mfoutline.h:30
@ southwest
Definition: mfoutline.h:30
@ character
Definition: mfoutline.h:53
@ baseline
Definition: mfoutline.h:53
LIST ConvertBlob(TBLOB *blob)
Definition: mfoutline.cpp:34
void CharNormalizeOutline(MFOUTLINE Outline, const DENORM &cn_denorm)
Definition: mfoutline.cpp:298
const float MF_SCALE_FACTOR
Definition: mfoutline.h:61
MFOUTLINE ConvertOutline(TESSLINE *outline)
Definition: mfoutline.cpp:41
void ChangeDirection(MFOUTLINE Start, MFOUTLINE End, DIRECTION Direction)
Definition: mfoutline.cpp:280
void FreeMFOutline(void *arg)
Definition: mfoutline.cpp:132
LIST ConvertOutlines(TESSLINE *outline, LIST mf_outlines, OUTLINETYPE outline_type)
Definition: mfoutline.cpp:79
LIST pop(LIST list)
Definition: oldlist.cpp:166
MFOUTLINE NextExtremity(MFOUTLINE EdgePoint)
Definition: mfoutline.cpp:196
void ComputeDirection(MFEDGEPT *Start, MFEDGEPT *Finish, float MinSlope, float MaxSlope)
Definition: mfoutline.cpp:335
LIST push(LIST list, void *element)
Definition: oldlist.cpp:178
void destroy_nodes(LIST list, void_dest destructor)
Definition: oldlist.cpp:137
void FindDirectionChanges(MFOUTLINE Outline, float MinSlope, float MaxSlope)
Definition: mfoutline.cpp:104
void NormalizeOutline(MFOUTLINE Outline, float XOrigin)
Definition: mfoutline.cpp:218
const int kBlnBaselineOffset
Definition: normalis.h:34
MFOUTLINE NextDirectionChange(MFOUTLINE EdgePoint)
Definition: mfoutline.cpp:402
EDGEPT * next
Definition: blobs.h:200
EDGEPT * loop
Definition: blobs.h:287
TESSLINE * next
Definition: blobs.h:288
TESSLINE * outlines
Definition: blobs.h:404
void LocalNormTransform(const TPOINT &pt, TPOINT *transformed) const
Definition: normalis.cpp:308
float y() const
Definition: points.h:209
float x() const
Definition: points.h:206
void NormalizeOutlines(LIST Outlines, float *XScale, float *YScale)
Definition: mfoutline.cpp:249
Definition: fpoint.h:29
float y
Definition: fpoint.h:30
float x
Definition: fpoint.h:30
DIRECTION Direction
Definition: mfoutline.h:47
DIRECTION PreviousDirection
Definition: mfoutline.h:48
list_rec * first_node()
Definition: oldlist.h:107
list_rec * list_rest()
Definition: oldlist.h:111