2007-03-08 04:03:40 +08:00
|
|
|
/******************************************************************************
|
|
|
|
** Filename: mfx.c
|
|
|
|
** Purpose: Micro feature extraction routines
|
|
|
|
** Author: Dan Johnson
|
|
|
|
** History: 7/21/89, DSJ, Created.
|
|
|
|
**
|
|
|
|
** (c) Copyright Hewlett-Packard Company, 1988.
|
|
|
|
** Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
** you may not use this file except in compliance with the License.
|
|
|
|
** You may obtain a copy of the License at
|
|
|
|
** http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
** Unless required by applicable law or agreed to in writing, software
|
|
|
|
** distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
** See the License for the specific language governing permissions and
|
|
|
|
** limitations under the License.
|
|
|
|
******************************************************************************/
|
2014-09-13 04:41:19 +08:00
|
|
|
/*----------------------------------------------------------------------------
|
2007-03-08 04:03:40 +08:00
|
|
|
Include Files and Type Defines
|
2014-09-13 04:41:19 +08:00
|
|
|
----------------------------------------------------------------------------*/
|
2007-03-08 04:03:40 +08:00
|
|
|
#include "mfdefs.h"
|
|
|
|
#include "mfoutline.h"
|
|
|
|
#include "clusttool.h" //NEEDED
|
|
|
|
#include "const.h"
|
|
|
|
#include "intfx.h"
|
2010-11-24 02:34:14 +08:00
|
|
|
#include "normalis.h"
|
|
|
|
#include "params.h"
|
2009-07-11 10:17:36 +08:00
|
|
|
|
2007-03-08 04:03:40 +08:00
|
|
|
#include <math.h>
|
|
|
|
|
2014-09-13 04:41:19 +08:00
|
|
|
/*----------------------------------------------------------------------------
|
2009-07-11 10:17:36 +08:00
|
|
|
Variables
|
2014-09-13 04:41:19 +08:00
|
|
|
----------------------------------------------------------------------------*/
|
2009-07-11 10:17:36 +08:00
|
|
|
|
2007-03-08 04:03:40 +08:00
|
|
|
/* old numbers corresponded to 10.0 degrees and 80.0 degrees */
|
2009-07-11 10:17:36 +08:00
|
|
|
double_VAR(classify_min_slope, 0.414213562,
|
|
|
|
"Slope below which lines are called horizontal");
|
|
|
|
double_VAR(classify_max_slope, 2.414213562,
|
|
|
|
"Slope above which lines are called vertical");
|
2007-03-08 04:03:40 +08:00
|
|
|
|
2014-09-13 04:41:19 +08:00
|
|
|
/*----------------------------------------------------------------------------
|
2007-03-08 04:03:40 +08:00
|
|
|
Macros
|
2014-09-13 04:41:19 +08:00
|
|
|
----------------------------------------------------------------------------*/
|
2007-03-08 04:03:40 +08:00
|
|
|
/* miscellaneous macros */
|
|
|
|
#define NormalizeAngle(A) ( (((A)<0)?((A)+2*PI):(A)) / (2*PI) )
|
|
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
|
|
Private Function Prototypes
|
|
|
|
-----------------------------------------------------------------------------*/
|
|
|
|
FLOAT32 ComputeOrientation(MFEDGEPT *Start, MFEDGEPT *End);
|
|
|
|
|
|
|
|
MICROFEATURES ConvertToMicroFeatures(MFOUTLINE Outline,
|
|
|
|
MICROFEATURES MicroFeatures);
|
|
|
|
|
|
|
|
MICROFEATURE ExtractMicroFeature(MFOUTLINE Start, MFOUTLINE End);
|
|
|
|
|
2014-09-13 04:41:19 +08:00
|
|
|
/*----------------------------------------------------------------------------
|
2007-03-08 04:03:40 +08:00
|
|
|
Public Code
|
2014-09-13 04:41:19 +08:00
|
|
|
----------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This routine extracts micro-features from the specified
|
|
|
|
* blob and returns a list of the micro-features. All
|
|
|
|
* micro-features are normalized according to the specified
|
|
|
|
* line statistics.
|
|
|
|
* @param Blob blob to extract micro-features from
|
|
|
|
* @param cn_denorm control parameter to feature extractor
|
|
|
|
* @return List of micro-features extracted from the blob.
|
|
|
|
* @note Exceptions: none
|
|
|
|
* @note History: 7/21/89, DSJ, Created.
|
2007-03-08 04:03:40 +08:00
|
|
|
*/
|
2014-09-13 04:41:19 +08:00
|
|
|
MICROFEATURES BlobMicroFeatures(TBLOB* Blob, const DENORM& cn_denorm) {
|
2010-11-24 02:34:14 +08:00
|
|
|
MICROFEATURES MicroFeatures = NIL_LIST;
|
2007-03-08 04:03:40 +08:00
|
|
|
LIST Outlines;
|
|
|
|
LIST RemainingOutlines;
|
|
|
|
MFOUTLINE Outline;
|
|
|
|
|
|
|
|
if (Blob != NULL) {
|
2013-09-23 23:15:06 +08:00
|
|
|
Outlines = ConvertBlob(Blob);
|
2007-03-08 04:03:40 +08:00
|
|
|
|
|
|
|
RemainingOutlines = Outlines;
|
2007-05-16 09:30:20 +08:00
|
|
|
iterate(RemainingOutlines) {
|
|
|
|
Outline = (MFOUTLINE) first_node (RemainingOutlines);
|
2013-09-23 23:15:06 +08:00
|
|
|
CharNormalizeOutline(Outline, cn_denorm);
|
2007-03-08 04:03:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
RemainingOutlines = Outlines;
|
|
|
|
iterate(RemainingOutlines) {
|
2013-09-23 23:15:06 +08:00
|
|
|
Outline = (MFOUTLINE) first_node(RemainingOutlines);
|
2009-07-11 10:17:36 +08:00
|
|
|
FindDirectionChanges(Outline, classify_min_slope, classify_max_slope);
|
2007-03-08 04:03:40 +08:00
|
|
|
MarkDirectionChanges(Outline);
|
2013-09-23 23:15:06 +08:00
|
|
|
MicroFeatures = ConvertToMicroFeatures(Outline, MicroFeatures);
|
2007-03-08 04:03:40 +08:00
|
|
|
}
|
|
|
|
FreeOutlines(Outlines);
|
|
|
|
}
|
2015-05-13 06:22:34 +08:00
|
|
|
return MicroFeatures;
|
2007-03-08 04:03:40 +08:00
|
|
|
} /* BlobMicroFeatures */
|
|
|
|
|
|
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
|
|
Private Code
|
|
|
|
---------------------------------------------------------------------------*/
|
|
|
|
|
2014-09-13 04:41:19 +08:00
|
|
|
/**
|
|
|
|
* This routine computes the orientation parameter of the
|
|
|
|
* specified micro-feature. The orientation is the angle of
|
|
|
|
* the vector from Start to End. It is normalized to a number
|
|
|
|
* between 0 and 1 where 0 corresponds to 0 degrees and 1
|
|
|
|
* corresponds to 360 degrees. The actual range is [0,1), i.e.
|
|
|
|
* 1 is excluded from the range (since it is actual the
|
|
|
|
* same orientation as 0). This routine assumes that Start
|
|
|
|
* and End are not the same point.
|
|
|
|
* @param Start starting edge point of micro-feature
|
|
|
|
* @param End ending edge point of micro-feature
|
|
|
|
* @note Globals: none
|
|
|
|
* @return Orientation parameter for the specified micro-feature.
|
|
|
|
* @note Exceptions: none
|
|
|
|
* @note History: 7/27/89, DSJ, Created.
|
2007-03-08 04:03:40 +08:00
|
|
|
*/
|
2014-09-13 04:41:19 +08:00
|
|
|
FLOAT32 ComputeOrientation(MFEDGEPT *Start, MFEDGEPT *End) {
|
2007-03-08 04:03:40 +08:00
|
|
|
FLOAT32 Orientation;
|
|
|
|
|
2009-07-11 10:17:36 +08:00
|
|
|
Orientation = NormalizeAngle (AngleFrom (Start->Point, End->Point));
|
2007-03-08 04:03:40 +08:00
|
|
|
|
|
|
|
/* ensure that round-off errors do not put circular param out of range */
|
|
|
|
if ((Orientation < 0) || (Orientation >= 1))
|
|
|
|
Orientation = 0;
|
|
|
|
return (Orientation);
|
|
|
|
} /* ComputeOrientation */
|
|
|
|
|
|
|
|
|
2014-09-13 04:41:19 +08:00
|
|
|
/**
|
|
|
|
* Convert Outline to MicroFeatures
|
|
|
|
* @param Outline outline to extract micro-features from
|
|
|
|
* @param MicroFeatures list of micro-features to add to
|
|
|
|
* @return List of micro-features with new features added to front.
|
|
|
|
* @note Globals: none
|
|
|
|
* @note Exceptions: none
|
|
|
|
* @note History: 7/26/89, DSJ, Created.
|
|
|
|
*/
|
2007-03-08 04:03:40 +08:00
|
|
|
MICROFEATURES ConvertToMicroFeatures(MFOUTLINE Outline,
|
|
|
|
MICROFEATURES MicroFeatures) {
|
|
|
|
MFOUTLINE Current;
|
|
|
|
MFOUTLINE Last;
|
|
|
|
MFOUTLINE First;
|
|
|
|
MICROFEATURE NewFeature;
|
|
|
|
|
|
|
|
if (DegenerateOutline (Outline))
|
|
|
|
return (MicroFeatures);
|
|
|
|
|
|
|
|
First = NextExtremity (Outline);
|
|
|
|
Last = First;
|
|
|
|
do {
|
|
|
|
Current = NextExtremity (Last);
|
2010-11-24 02:34:14 +08:00
|
|
|
if (!PointAt(Current)->Hidden) {
|
|
|
|
NewFeature = ExtractMicroFeature (Last, Current);
|
|
|
|
if (NewFeature != NULL)
|
|
|
|
MicroFeatures = push (MicroFeatures, NewFeature);
|
|
|
|
}
|
2007-03-08 04:03:40 +08:00
|
|
|
Last = Current;
|
|
|
|
}
|
|
|
|
while (Last != First);
|
|
|
|
|
|
|
|
return (MicroFeatures);
|
|
|
|
} /* ConvertToMicroFeatures */
|
|
|
|
|
|
|
|
|
2014-09-13 04:41:19 +08:00
|
|
|
/**
|
|
|
|
* This routine computes the feature parameters which describe
|
|
|
|
* the micro-feature that starts and Start and ends at End.
|
|
|
|
* A new micro-feature is allocated, filled with the feature
|
|
|
|
* parameters, and returned. The routine assumes that
|
|
|
|
* Start and End are not the same point. If they are the
|
|
|
|
* same point, NULL is returned, a warning message is
|
|
|
|
* printed, and the current outline is dumped to stdout.
|
|
|
|
* @param Start starting point of micro-feature
|
|
|
|
* @param End ending point of micro-feature
|
|
|
|
* @return New micro-feature or NULL if the feature was rejected.
|
|
|
|
* @note Globals: none
|
|
|
|
* @note Exceptions: none
|
|
|
|
* @note History:
|
|
|
|
* - 7/26/89, DSJ, Created.
|
|
|
|
* - 11/17/89, DSJ, Added handling for Start and End same point.
|
2007-03-08 04:03:40 +08:00
|
|
|
*/
|
2014-09-13 04:41:19 +08:00
|
|
|
MICROFEATURE ExtractMicroFeature(MFOUTLINE Start, MFOUTLINE End) {
|
2007-03-08 04:03:40 +08:00
|
|
|
MICROFEATURE NewFeature;
|
|
|
|
MFEDGEPT *P1, *P2;
|
|
|
|
|
2010-11-24 02:34:14 +08:00
|
|
|
P1 = PointAt(Start);
|
|
|
|
P2 = PointAt(End);
|
2007-03-08 04:03:40 +08:00
|
|
|
|
|
|
|
NewFeature = NewMicroFeature ();
|
2010-11-24 02:34:14 +08:00
|
|
|
NewFeature[XPOSITION] = AverageOf(P1->Point.x, P2->Point.x);
|
|
|
|
NewFeature[YPOSITION] = AverageOf(P1->Point.y, P2->Point.y);
|
|
|
|
NewFeature[MFLENGTH] = DistanceBetween(P1->Point, P2->Point);
|
2009-07-11 10:17:36 +08:00
|
|
|
NewFeature[ORIENTATION] = NormalizedAngleFrom(&P1->Point, &P2->Point, 1.0);
|
2010-11-24 02:34:14 +08:00
|
|
|
NewFeature[FIRSTBULGE] = 0.0f; // deprecated
|
|
|
|
NewFeature[SECONDBULGE] = 0.0f; // deprecated
|
2007-03-08 04:03:40 +08:00
|
|
|
|
2010-11-24 02:34:14 +08:00
|
|
|
return NewFeature;
|
|
|
|
} /* ExtractMicroFeature */
|