1 /******************************************************************************
2 ** Filename: picofeat.c
3 ** Purpose: Definition of pico-features.
4 ** Author: Dan Johnson
5 ** History: 9/4/90, DSJ, Created.
6 **
7 ** (c) Copyright Hewlett-Packard Company, 1988.
8 ** Licensed under the Apache License, Version 2.0 (the "License");
9 ** you may not use this file except in compliance with the License.
10 ** You may obtain a copy of the License at
11 ** http://www.apache.org/licenses/LICENSE-2.0
12 ** Unless required by applicable law or agreed to in writing, software
13 ** distributed under the License is distributed on an "AS IS" BASIS,
14 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 ** See the License for the specific language governing permissions and
16 ** limitations under the License.
17 ******************************************************************************/
18 /**----------------------------------------------------------------------------
19 Include Files and Type Defines
20 ----------------------------------------------------------------------------**/
21 #include "picofeat.h"
22 #include "mfoutline.h"
23 #include "hideedge.h"
24 #include "fpoint.h"
25 #include "varable.h"
26
27 #include <math.h>
28
29 #include "ocrfeatures.h" //Debug
30 #include <stdio.h> //Debug
31 #include "efio.h" //Debug
32
33 /*---------------------------------------------------------------------------
34 Variables
35 ----------------------------------------------------------------------------*/
36
37 double_VAR(classify_pico_feature_length, 0.05, "Pico Feature Length");
38
39 /*---------------------------------------------------------------------------
40 Private Function Prototypes
41 ----------------------------------------------------------------------------*/
42 void ConvertSegmentToPicoFeat(FPOINT *Start,
43 FPOINT *End,
44 FEATURE_SET FeatureSet);
45
46 void ConvertToPicoFeatures2(MFOUTLINE Outline, FEATURE_SET FeatureSet);
47
48 void NormalizePicoX(FEATURE_SET FeatureSet);
49
50 /**----------------------------------------------------------------------------
51 Public Code
52 ----------------------------------------------------------------------------**/
53 /*---------------------------------------------------------------------------*/
ExtractPicoFeatures(TBLOB * Blob,LINE_STATS * LineStats)54 FEATURE_SET ExtractPicoFeatures(TBLOB *Blob, LINE_STATS *LineStats) {
55 /*
56 ** Parameters:
57 ** Blob blob to extract pico-features from
58 ** LineStats statistics on text row blob is in
59 ** Globals:
60 ** classify_norm_method normalization method currently specified
61 ** Operation: Dummy for now.
62 ** Return: Pico-features for Blob.
63 ** Exceptions: none
64 ** History: 9/4/90, DSJ, Created.
65 */
66 LIST Outlines;
67 LIST RemainingOutlines;
68 MFOUTLINE Outline;
69 FEATURE_SET FeatureSet;
70 FLOAT32 XScale, YScale;
71
72 FeatureSet = NewFeatureSet (MAX_PICO_FEATURES);
73
74 Outlines = ConvertBlob (Blob);
75
76 NormalizeOutlines(Outlines, LineStats, &XScale, &YScale);
77 RemainingOutlines = Outlines;
78 iterate(RemainingOutlines) {
79 Outline = (MFOUTLINE) first_node (RemainingOutlines);
80 /*---------Debug--------------------------------------------------*
81 OFile = fopen ("f:/ims/debug/pfOutline.logCPP", "r");
82 if (OFile == NULL)
83 {
84 OFile = Efopen ("f:/ims/debug/pfOutline.logCPP", "w");
85 WriteOutline(OFile, Outline);
86 }
87 else
88 {
89 fclose (OFile);
90 OFile = Efopen ("f:/ims/debug/pfOutline.logCPP", "a");
91 }
92 WriteOutline(OFile, Outline);
93 fclose (OFile);
94 *--------------------------------------------------------------------*/
95 ConvertToPicoFeatures2(Outline, FeatureSet);
96 }
97 if (classify_norm_method == baseline)
98 NormalizePicoX(FeatureSet);
99 /*---------Debug--------------------------------------------------*
100 File = fopen ("f:/ims/debug/pfFeatSet.logCPP", "r");
101 if (File == NULL)
102 {
103 File = Efopen ("f:/ims/debug/pfFeatSet.logCPP", "w");
104 WriteFeatureSet(File, FeatureSet);
105 }
106 else
107 {
108 fclose (File);
109 File = Efopen ("f:/ims/debug/pfFeatSet.logCPP", "a");
110 }
111 WriteFeatureSet(File, FeatureSet);
112 fclose (File);
113 *--------------------------------------------------------------------*/
114 FreeOutlines(Outlines);
115 return (FeatureSet);
116
117 } /* ExtractPicoFeatures */
118
119 /**----------------------------------------------------------------------------
120 Private Code
121 ----------------------------------------------------------------------------**/
122 /*---------------------------------------------------------------------------*/
ConvertSegmentToPicoFeat(FPOINT * Start,FPOINT * End,FEATURE_SET FeatureSet)123 void ConvertSegmentToPicoFeat(FPOINT *Start,
124 FPOINT *End,
125 FEATURE_SET FeatureSet) {
126 /*
127 ** Parameters:
128 ** Start starting point of pico-feature
129 ** End ending point of pico-feature
130 ** FeatureSet set to add pico-feature to
131 ** Globals:
132 ** classify_pico_feature_length length of a single pico-feature
133 ** Operation: This routine converts an entire segment of an outline
134 ** into a set of pico features which are added to
135 ** FeatureSet. The length of the segment is rounded to the
136 ** nearest whole number of pico-features. The pico-features
137 ** are spaced evenly over the entire segment.
138 ** Return: none (results are placed in FeatureSet)
139 ** Exceptions: none
140 ** History: Tue Apr 30 15:44:34 1991, DSJ, Created.
141 */
142 FEATURE Feature;
143 FLOAT32 Angle;
144 FLOAT32 Length;
145 int NumFeatures;
146 FPOINT Center;
147 FPOINT Delta;
148 int i;
149
150 Angle = NormalizedAngleFrom (Start, End, 1.0);
151 Length = DistanceBetween (*Start, *End);
152 NumFeatures = (int) floor (Length / classify_pico_feature_length + 0.5);
153 if (NumFeatures < 1)
154 NumFeatures = 1;
155
156 /* compute vector for one pico feature */
157 Delta.x = XDelta (*Start, *End) / NumFeatures;
158 Delta.y = YDelta (*Start, *End) / NumFeatures;
159
160 /* compute position of first pico feature */
161 Center.x = Start->x + Delta.x / 2.0;
162 Center.y = Start->y + Delta.y / 2.0;
163
164 /* compute each pico feature in segment and add to feature set */
165 for (i = 0; i < NumFeatures; i++) {
166 Feature = NewFeature (&PicoFeatDesc);
167 Feature->Params[PicoFeatDir] = Angle;
168 Feature->Params[PicoFeatX] = Center.x;
169 Feature->Params[PicoFeatY] = Center.y;
170 AddFeature(FeatureSet, Feature);
171
172 Center.x += Delta.x;
173 Center.y += Delta.y;
174 }
175 } /* ConvertSegmentToPicoFeat */
176
177
178 /*---------------------------------------------------------------------------*/
ConvertToPicoFeatures2(MFOUTLINE Outline,FEATURE_SET FeatureSet)179 void ConvertToPicoFeatures2(MFOUTLINE Outline, FEATURE_SET FeatureSet) {
180 /*
181 ** Parameters:
182 ** Outline outline to extract micro-features from
183 ** FeatureSet set of features to add pico-features to
184 ** Globals:
185 ** classify_pico_feature_length
186 ** length of features to be extracted
187 ** Operation:
188 ** This routine steps thru the specified outline and cuts it
189 ** up into pieces of equal length. These pieces become the
190 ** desired pico-features. Each segment in the outline
191 ** is converted into an integral number of pico-features.
192 ** Return: none (results are returned in FeatureSet)
193 ** Exceptions: none
194 ** History: 4/30/91, DSJ, Adapted from ConvertToPicoFeatures().
195 */
196 MFOUTLINE Next;
197 MFOUTLINE First;
198 MFOUTLINE Current;
199
200 if (DegenerateOutline (Outline))
201 return;
202
203 First = Outline;
204 Current = First;
205 Next = NextPointAfter (Current);
206 do {
207 /* note that an edge is hidden if the ending point of the edge is
208 marked as hidden. This situation happens because the order of
209 the outlines is reversed when they are converted from the old
210 format. In the old format, a hidden edge is marked by the
211 starting point for that edge. */
212 if (!(PointAt(Next)->Hidden))
213 ConvertSegmentToPicoFeat (&(PointAt(Current)->Point),
214 &(PointAt(Next)->Point), FeatureSet);
215
216 Current = Next;
217 Next = NextPointAfter (Current);
218 }
219 while (Current != First);
220
221 } /* ConvertToPicoFeatures2 */
222
223
224 /*---------------------------------------------------------------------------*/
NormalizePicoX(FEATURE_SET FeatureSet)225 void NormalizePicoX(FEATURE_SET FeatureSet) {
226 /*
227 ** Parameters:
228 ** FeatureSet pico-features to be normalized
229 ** Globals: none
230 ** Operation: This routine computes the average x position over all
231 ** of the pico-features in FeatureSet and then renormalizes
232 ** the pico-features to force this average to be the x origin
233 ** (i.e. x=0).
234 ** Return: none (FeatureSet is changed)
235 ** Exceptions: none
236 ** History: Tue Sep 4 16:50:08 1990, DSJ, Created.
237 */
238 int i;
239 FEATURE Feature;
240 FLOAT32 Origin = 0.0;
241
242 for (i = 0; i < FeatureSet->NumFeatures; i++) {
243 Feature = FeatureSet->Features[i];
244 Origin += Feature->Params[PicoFeatX];
245 }
246 Origin /= FeatureSet->NumFeatures;
247
248 for (i = 0; i < FeatureSet->NumFeatures; i++) {
249 Feature = FeatureSet->Features[i];
250 Feature->Params[PicoFeatX] -= Origin;
251 }
252 } /* NormalizePicoX */
253