|
tesseract 3.04.01
|
00001 /****************************************************************************** 00002 ** Filename: mfoutline.c 00003 ** Purpose: Interface to outline struct used for extracting features 00004 ** Author: Dan Johnson 00005 ** History: Thu May 17 08:14:18 1990, DSJ, Created. 00006 ** 00007 ** (c) Copyright Hewlett-Packard Company, 1988. 00008 ** Licensed under the Apache License, Version 2.0 (the "License"); 00009 ** you may not use this file except in compliance with the License. 00010 ** You may obtain a copy of the License at 00011 ** http://www.apache.org/licenses/LICENSE-2.0 00012 ** Unless required by applicable law or agreed to in writing, software 00013 ** distributed under the License is distributed on an "AS IS" BASIS, 00014 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00015 ** See the License for the specific language governing permissions and 00016 ** limitations under the License. 00017 ******************************************************************************/ 00018 /*---------------------------------------------------------------------------- 00019 Include Files and Type Defines 00020 ----------------------------------------------------------------------------*/ 00021 #include "clusttool.h" //If remove you get cought in a loop somewhere 00022 #include "emalloc.h" 00023 #include "mfoutline.h" 00024 #include "blobs.h" 00025 #include "const.h" 00026 #include "mfx.h" 00027 #include "params.h" 00028 #include "classify.h" 00029 00030 #include <math.h> 00031 #include <stdio.h> 00032 00033 /*---------------------------------------------------------------------------- 00034 Public Code 00035 ----------------------------------------------------------------------------*/ 00036 00037 /*---------------------------------------------------------------------------*/ 00039 LIST ConvertBlob(TBLOB *blob) { 00040 LIST outlines = NIL_LIST; 00041 return (blob == NULL) 00042 ? NIL_LIST 00043 : ConvertOutlines(blob->outlines, outlines, outer); 00044 } 00045 00046 00047 /*---------------------------------------------------------------------------*/ 00049 MFOUTLINE ConvertOutline(TESSLINE *outline) { 00050 MFEDGEPT *NewPoint; 00051 MFOUTLINE MFOutline = NIL_LIST; 00052 EDGEPT *EdgePoint; 00053 EDGEPT *StartPoint; 00054 EDGEPT *NextPoint; 00055 00056 if (outline == NULL || outline->loop == NULL) 00057 return MFOutline; 00058 00059 StartPoint = outline->loop; 00060 EdgePoint = StartPoint; 00061 do { 00062 NextPoint = EdgePoint->next; 00063 00064 /* filter out duplicate points */ 00065 if (EdgePoint->pos.x != NextPoint->pos.x || 00066 EdgePoint->pos.y != NextPoint->pos.y) { 00067 NewPoint = NewEdgePoint(); 00068 ClearMark(NewPoint); 00069 NewPoint->Hidden = EdgePoint->IsHidden(); 00070 NewPoint->Point.x = EdgePoint->pos.x; 00071 NewPoint->Point.y = EdgePoint->pos.y; 00072 MFOutline = push(MFOutline, NewPoint); 00073 } 00074 EdgePoint = NextPoint; 00075 } while (EdgePoint != StartPoint); 00076 00077 if (MFOutline != NULL) 00078 MakeOutlineCircular(MFOutline); 00079 return MFOutline; 00080 } 00081 00082 00083 /*---------------------------------------------------------------------------*/ 00091 LIST ConvertOutlines(TESSLINE *outline, 00092 LIST mf_outlines, 00093 OUTLINETYPE outline_type) { 00094 MFOUTLINE mf_outline; 00095 00096 while (outline != NULL) { 00097 mf_outline = ConvertOutline(outline); 00098 if (mf_outline != NULL) 00099 mf_outlines = push(mf_outlines, mf_outline); 00100 outline = outline->next; 00101 } 00102 return mf_outlines; 00103 } 00104 00105 /*---------------------------------------------------------------------------*/ 00120 void FindDirectionChanges(MFOUTLINE Outline, 00121 FLOAT32 MinSlope, 00122 FLOAT32 MaxSlope) { 00123 MFEDGEPT *Current; 00124 MFEDGEPT *Last; 00125 MFOUTLINE EdgePoint; 00126 00127 if (DegenerateOutline (Outline)) 00128 return; 00129 00130 Last = PointAt (Outline); 00131 Outline = NextPointAfter (Outline); 00132 EdgePoint = Outline; 00133 do { 00134 Current = PointAt (EdgePoint); 00135 ComputeDirection(Last, Current, MinSlope, MaxSlope); 00136 00137 Last = Current; 00138 EdgePoint = NextPointAfter (EdgePoint); 00139 } 00140 while (EdgePoint != Outline); 00141 00142 } /* FindDirectionChanges */ 00143 00144 00145 /*---------------------------------------------------------------------------*/ 00154 void FreeMFOutline(void *arg) { //MFOUTLINE Outline) 00155 MFOUTLINE Start; 00156 MFOUTLINE Outline = (MFOUTLINE) arg; 00157 00158 /* break the circular outline so we can use std. techniques to deallocate */ 00159 Start = list_rest (Outline); 00160 set_rest(Outline, NIL_LIST); 00161 while (Start != NULL) { 00162 free_struct (first_node (Start), sizeof (MFEDGEPT), "MFEDGEPT"); 00163 Start = pop (Start); 00164 } 00165 00166 } /* FreeMFOutline */ 00167 00168 00169 /*---------------------------------------------------------------------------*/ 00178 void FreeOutlines(LIST Outlines) { 00179 destroy_nodes(Outlines, FreeMFOutline); 00180 } /* FreeOutlines */ 00181 00182 00183 /*---------------------------------------------------------------------------*/ 00198 void MarkDirectionChanges(MFOUTLINE Outline) { 00199 MFOUTLINE Current; 00200 MFOUTLINE Last; 00201 MFOUTLINE First; 00202 00203 if (DegenerateOutline (Outline)) 00204 return; 00205 00206 First = NextDirectionChange (Outline); 00207 Last = First; 00208 do { 00209 Current = NextDirectionChange (Last); 00210 MarkPoint (PointAt (Current)); 00211 Last = Current; 00212 } 00213 while (Last != First); 00214 00215 } /* MarkDirectionChanges */ 00216 00217 00218 /*---------------------------------------------------------------------------*/ 00220 MFEDGEPT *NewEdgePoint() { 00221 return ((MFEDGEPT *) alloc_struct(sizeof(MFEDGEPT), "MFEDGEPT")); 00222 } 00223 00224 00225 /*---------------------------------------------------------------------------*/ 00238 MFOUTLINE NextExtremity(MFOUTLINE EdgePoint) { 00239 EdgePoint = NextPointAfter(EdgePoint); 00240 while (!PointAt(EdgePoint)->ExtremityMark) 00241 EdgePoint = NextPointAfter(EdgePoint); 00242 00243 return (EdgePoint); 00244 00245 } /* NextExtremity */ 00246 00247 00248 /*---------------------------------------------------------------------------*/ 00264 void NormalizeOutline(MFOUTLINE Outline, 00265 FLOAT32 XOrigin) { 00266 if (Outline == NIL_LIST) 00267 return; 00268 00269 MFOUTLINE EdgePoint = Outline; 00270 do { 00271 MFEDGEPT *Current = PointAt(EdgePoint); 00272 Current->Point.y = MF_SCALE_FACTOR * 00273 (Current->Point.y - kBlnBaselineOffset); 00274 Current->Point.x = MF_SCALE_FACTOR * (Current->Point.x - XOrigin); 00275 EdgePoint = NextPointAfter(EdgePoint); 00276 } while (EdgePoint != Outline); 00277 } /* NormalizeOutline */ 00278 00279 00280 /*---------------------------------------------------------------------------*/ 00281 namespace tesseract { 00300 void Classify::NormalizeOutlines(LIST Outlines, 00301 FLOAT32 *XScale, 00302 FLOAT32 *YScale) { 00303 MFOUTLINE Outline; 00304 00305 switch (classify_norm_method) { 00306 case character: 00307 ASSERT_HOST(!"How did NormalizeOutlines get called in character mode?"); 00308 break; 00309 00310 case baseline: 00311 iterate(Outlines) { 00312 Outline = (MFOUTLINE) first_node(Outlines); 00313 NormalizeOutline(Outline, 0.0); 00314 } 00315 *XScale = *YScale = MF_SCALE_FACTOR; 00316 break; 00317 } 00318 } /* NormalizeOutlines */ 00319 } // namespace tesseract 00320 00321 /*---------------------------------------------------------------------------- 00322 Private Code 00323 ----------------------------------------------------------------------------*/ 00337 void ChangeDirection(MFOUTLINE Start, MFOUTLINE End, DIRECTION Direction) { 00338 MFOUTLINE Current; 00339 00340 for (Current = Start; Current != End; Current = NextPointAfter (Current)) 00341 PointAt (Current)->Direction = Direction; 00342 00343 PointAt (End)->PreviousDirection = Direction; 00344 00345 } /* ChangeDirection */ 00346 00347 00359 void CharNormalizeOutline(MFOUTLINE Outline, const DENORM& cn_denorm) { 00360 MFOUTLINE First, Current; 00361 MFEDGEPT *CurrentPoint; 00362 00363 if (Outline == NIL_LIST) 00364 return; 00365 00366 First = Outline; 00367 Current = First; 00368 do { 00369 CurrentPoint = PointAt(Current); 00370 FCOORD pos(CurrentPoint->Point.x, CurrentPoint->Point.y); 00371 cn_denorm.LocalNormTransform(pos, &pos); 00372 CurrentPoint->Point.x = (pos.x() - MAX_UINT8 / 2) * MF_SCALE_FACTOR; 00373 CurrentPoint->Point.y = (pos.y() - MAX_UINT8 / 2) * MF_SCALE_FACTOR; 00374 00375 Current = NextPointAfter(Current); 00376 } 00377 while (Current != First); 00378 00379 } /* CharNormalizeOutline */ 00380 00381 00401 void ComputeDirection(MFEDGEPT *Start, 00402 MFEDGEPT *Finish, 00403 FLOAT32 MinSlope, 00404 FLOAT32 MaxSlope) { 00405 FVECTOR Delta; 00406 00407 Delta.x = Finish->Point.x - Start->Point.x; 00408 Delta.y = Finish->Point.y - Start->Point.y; 00409 if (Delta.x == 0) 00410 if (Delta.y < 0) { 00411 Start->Slope = -MAX_FLOAT32; 00412 Start->Direction = south; 00413 } 00414 else { 00415 Start->Slope = MAX_FLOAT32; 00416 Start->Direction = north; 00417 } 00418 else { 00419 Start->Slope = Delta.y / Delta.x; 00420 if (Delta.x > 0) 00421 if (Delta.y > 0) 00422 if (Start->Slope > MinSlope) 00423 if (Start->Slope < MaxSlope) 00424 Start->Direction = northeast; 00425 else 00426 Start->Direction = north; 00427 else 00428 Start->Direction = east; 00429 else if (Start->Slope < -MinSlope) 00430 if (Start->Slope > -MaxSlope) 00431 Start->Direction = southeast; 00432 else 00433 Start->Direction = south; 00434 else 00435 Start->Direction = east; 00436 else if (Delta.y > 0) 00437 if (Start->Slope < -MinSlope) 00438 if (Start->Slope > -MaxSlope) 00439 Start->Direction = northwest; 00440 else 00441 Start->Direction = north; 00442 else 00443 Start->Direction = west; 00444 else if (Start->Slope > MinSlope) 00445 if (Start->Slope < MaxSlope) 00446 Start->Direction = southwest; 00447 else 00448 Start->Direction = south; 00449 else 00450 Start->Direction = west; 00451 } 00452 Finish->PreviousDirection = Start->Direction; 00453 } 00454 00466 MFOUTLINE NextDirectionChange(MFOUTLINE EdgePoint) { 00467 DIRECTION InitialDirection; 00468 00469 InitialDirection = PointAt (EdgePoint)->Direction; 00470 00471 MFOUTLINE next_pt = NULL; 00472 do { 00473 EdgePoint = NextPointAfter(EdgePoint); 00474 next_pt = NextPointAfter(EdgePoint); 00475 } while (PointAt(EdgePoint)->Direction == InitialDirection && 00476 !PointAt(EdgePoint)->Hidden && 00477 next_pt != NULL && !PointAt(next_pt)->Hidden); 00478 00479 return (EdgePoint); 00480 }