Coverage Report

Created: 2025-07-23 07:12

/src/tesseract/src/classify/outfeat.cpp
Line
Count
Source (jump to first uncovered line)
1
/******************************************************************************
2
 ** Filename:    outfeat.c
3
 ** Purpose:     Definition of outline-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 "outfeat.h"
19
20
#include "classify.h"
21
#include "featdefs.h"
22
#include "mfoutline.h"
23
#include "ocrfeatures.h"
24
25
#include <cstdio>
26
27
namespace tesseract {
28
29
/*----------------------------------------------------------------------------
30
              Public Code
31
----------------------------------------------------------------------------*/
32
33
/**
34
 * Convert each segment in the outline to a feature
35
 * and return the features.
36
 * @param Blob blob to extract pico-features from
37
 * @return Outline-features for Blob.
38
 * @note Globals: none
39
 */
40
1.48k
FEATURE_SET Classify::ExtractOutlineFeatures(TBLOB *Blob) {
41
1.48k
  auto FeatureSet = new FEATURE_SET_STRUCT(MAX_OUTLINE_FEATURES);
42
1.48k
  if (Blob == nullptr) {
43
0
    return (FeatureSet);
44
0
  }
45
46
1.48k
  auto Outlines = ConvertBlob(Blob);
47
48
1.48k
  float XScale, YScale;
49
1.48k
  NormalizeOutlines(Outlines, &XScale, &YScale);
50
1.48k
  auto RemainingOutlines = Outlines;
51
2.79k
  iterate(RemainingOutlines) {
52
2.79k
    auto Outline = static_cast<MFOUTLINE>(RemainingOutlines->first_node());
53
2.79k
    ConvertToOutlineFeatures(Outline, FeatureSet);
54
2.79k
  }
55
1.48k
  if (classify_norm_method == baseline) {
56
1.48k
    NormalizeOutlineX(FeatureSet);
57
1.48k
  }
58
1.48k
  FreeOutlines(Outlines);
59
1.48k
  return (FeatureSet);
60
1.48k
} /* ExtractOutlineFeatures */
61
62
/*----------------------------------------------------------------------------
63
              Private Code
64
----------------------------------------------------------------------------*/
65
/*---------------------------------------------------------------------------*/
66
/**
67
 * This routine computes the midpoint between Start and
68
 * End to obtain the x,y position of the outline-feature.  It
69
 * also computes the direction from Start to End as the
70
 * direction of the outline-feature and the distance from
71
 * Start to End as the length of the outline-feature.
72
 * This feature is then
73
 * inserted into the next feature slot in FeatureSet.
74
 * @param Start starting point of outline-feature
75
 * @param End ending point of outline-feature
76
 * @param FeatureSet set to add outline-feature to
77
 */
78
15.6k
void AddOutlineFeatureToSet(FPOINT *Start, FPOINT *End, FEATURE_SET FeatureSet) {
79
15.6k
  auto Feature = new FEATURE_STRUCT(&OutlineFeatDesc);
80
15.6k
  Feature->Params[OutlineFeatDir] = NormalizedAngleFrom(Start, End, 1.0);
81
15.6k
  Feature->Params[OutlineFeatX] = AverageOf(Start->x, End->x);
82
15.6k
  Feature->Params[OutlineFeatY] = AverageOf(Start->y, End->y);
83
15.6k
  Feature->Params[OutlineFeatLength] = DistanceBetween(*Start, *End);
84
15.6k
  AddFeature(FeatureSet, Feature);
85
86
15.6k
} /* AddOutlineFeatureToSet */
87
88
/*---------------------------------------------------------------------------*/
89
/**
90
 * This routine steps converts each section in the specified
91
 * outline to a feature described by its x,y position, length
92
 * and angle.
93
 * Results are returned in FeatureSet.
94
 * @param Outline outline to extract outline-features from
95
 * @param FeatureSet set of features to add outline-features to
96
 */
97
2.79k
void ConvertToOutlineFeatures(MFOUTLINE Outline, FEATURE_SET FeatureSet) {
98
2.79k
  MFOUTLINE Next;
99
2.79k
  MFOUTLINE First;
100
2.79k
  FPOINT FeatureStart;
101
2.79k
  FPOINT FeatureEnd;
102
103
2.79k
  if (DegenerateOutline(Outline)) {
104
0
    return;
105
0
  }
106
107
2.79k
  First = Outline;
108
2.79k
  Next = First;
109
15.6k
  do {
110
15.6k
    FeatureStart = PointAt(Next)->Point;
111
15.6k
    Next = NextPointAfter(Next);
112
113
    /* note that an edge is hidden if the ending point of the edge is
114
   marked as hidden.  This situation happens because the order of
115
   the outlines is reversed when they are converted from the old
116
   format.  In the old format, a hidden edge is marked by the
117
   starting point for that edge. */
118
15.6k
    if (!PointAt(Next)->Hidden) {
119
15.6k
      FeatureEnd = PointAt(Next)->Point;
120
15.6k
      AddOutlineFeatureToSet(&FeatureStart, &FeatureEnd, FeatureSet);
121
15.6k
    }
122
15.6k
  } while (Next != First);
123
2.79k
} /* ConvertToOutlineFeatures */
124
125
/*---------------------------------------------------------------------------*/
126
/**
127
 * This routine computes the weighted average x position
128
 * over all of the outline-features in FeatureSet and then
129
 * renormalizes the outline-features to force this average
130
 * to be the x origin (i.e. x=0).
131
 * FeatureSet is changed.
132
 * @param FeatureSet outline-features to be normalized
133
 */
134
1.48k
void NormalizeOutlineX(FEATURE_SET FeatureSet) {
135
1.48k
  int i;
136
1.48k
  FEATURE Feature;
137
1.48k
  float Length;
138
1.48k
  float TotalX = 0.0;
139
1.48k
  float TotalWeight = 0.0;
140
1.48k
  float Origin;
141
142
1.48k
  if (FeatureSet->NumFeatures <= 0) {
143
0
    return;
144
0
  }
145
146
16.8k
  for (i = 0; i < FeatureSet->NumFeatures; i++) {
147
15.3k
    Feature = FeatureSet->Features[i];
148
15.3k
    Length = Feature->Params[OutlineFeatLength];
149
15.3k
    TotalX += Feature->Params[OutlineFeatX] * Length;
150
15.3k
    TotalWeight += Length;
151
15.3k
  }
152
1.48k
  Origin = TotalX / TotalWeight;
153
154
16.8k
  for (i = 0; i < FeatureSet->NumFeatures; i++) {
155
15.3k
    Feature = FeatureSet->Features[i];
156
15.3k
    Feature->Params[OutlineFeatX] -= Origin;
157
15.3k
  }
158
1.48k
} /* NormalizeOutlineX */
159
160
} // namespace tesseract