tesseract 3.04.01

classify/mfoutline.cpp

Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines