515 lines
17 KiB
C
515 lines
17 KiB
C
// xrcreslts.c
|
|
// James A. Pittman
|
|
// Jan 7, 1999
|
|
|
|
// A container object to hold the results of recognition.
|
|
|
|
// This is currently used by Inferno, MadCow, and Famine.
|
|
|
|
#ifndef _XRCRESLTS_
|
|
#define _XRCRESLTS_
|
|
|
|
#define MAXMAXALT 32
|
|
|
|
// Spped Accuracy tradeof values
|
|
#define HWX_MIN_SPEED 0
|
|
#define HWX_MAX_SPEED 100
|
|
|
|
#ifdef UNDER_CE
|
|
#define HWX_DEFAULT_SPEED 50
|
|
#else
|
|
#define HWX_DEFAULT_SPEED 0
|
|
#endif
|
|
|
|
#define PHRASE_GROW_SIZE 4
|
|
|
|
#define NOT_RECOGNIZED "\a"
|
|
|
|
#define BASELIMIT 700 // scale ink to this guide hgt if we have a guide
|
|
#define MAX_SCALE 10 // We will not scale more than this.
|
|
|
|
#define MAX_SEG 5 // maximum number of segmentations to resolve among
|
|
#define MAX_SEG_WORD 5 // maximum number of wordmaps in a segmentation
|
|
|
|
#ifdef __cplusplus
|
|
extern "C"
|
|
{
|
|
#endif
|
|
|
|
typedef struct tagWORDMAP WORDMAP;
|
|
|
|
typedef struct tagLATINLAYOUT
|
|
{
|
|
// the first 4 fields are y-values for 4 lines relative to the bounding rect of ink
|
|
// see the functions AbsoluteToLatinLayout() and LatinLayoutToAbsolute() for details
|
|
short iBaseLine;
|
|
short iMidLine;
|
|
short iAscenderLine;
|
|
short iDescenderLine;
|
|
// the next 4 fields indicate which of the previous 4 are computed
|
|
unsigned char bBaseLineSet;
|
|
unsigned char bMidLineSet;
|
|
unsigned char bAscenderLineSet;
|
|
unsigned char bDescenderLineSet;
|
|
} LATINLAYOUT;
|
|
|
|
// The XRCRESULT object describes a single alternative interpretation of the ink.
|
|
// There are 2 types: phrase and word. Both have a string and a cost.
|
|
// Word XRCRESULT objects have a 0 cWords and a NULL pMap.
|
|
// Phrase XRCRESULT objects have pMap pointing to an array of word mappings,
|
|
// with the count of mappings in cWords. The PenWin API represents this
|
|
// with an HRCRESULT.
|
|
|
|
typedef struct tagXRCRESULT
|
|
{
|
|
unsigned char *szWord; // we use malloc for this string/phrase
|
|
int cost; // 0 for perfect match, intmax for no match, neg numbers meaningless
|
|
unsigned int cWords; // 0 in word mode, count of space delimited words in panel mode
|
|
DWORD iLMcomponent; // Portion of LM generating this result
|
|
WORDMAP *pMap; // NULL in word mode, valid in panel mode.
|
|
void *pXRC; // Pointer to the xrc.
|
|
} XRCRESULT;
|
|
|
|
// The ALTERNATES object represents a set of alternative results for the
|
|
// same ink. It has a count of alternates, and an array of XRCRESULT objects.
|
|
// The array is in-line, with a length of MAXMAXALT. The alternates stay sorted
|
|
// in increasing cost order. This is not represented in the PenWin API.
|
|
|
|
// The users code, an implementation of HRC, should probably include an ALTERNATES
|
|
// object in-line. On initialization the field cAlt should be zeroed.
|
|
// Use RCRESALTInsert() to insert answers into the list of alternates.
|
|
|
|
typedef struct tagALTERNATES
|
|
{
|
|
unsigned int cAlt; // how many (up to 10) actual answers do we have
|
|
unsigned int cAltMax; // I can use this to say "I only want 4". !!! should be in xrc
|
|
XRCRESULT aAlt[MAXMAXALT]; // The array of XRCRESULT structures
|
|
LATINLAYOUT all[MAXMAXALT]; // baseline stuff for each alternate
|
|
int iConfidence; //Contains the confidence level
|
|
} ALTERNATES;
|
|
|
|
// The WORDMAP contains a description of a word within the phrase
|
|
// (the start index and the length), and a ALTERNATES to hold the alternative
|
|
// results for this word. This is not represented in the PenWin API.
|
|
|
|
typedef struct tagWORDMAP
|
|
{
|
|
unsigned short start; // start of the word in the phrase
|
|
unsigned short len; // len of word in the phrase
|
|
int cStrokes; // Count of strokes in this word
|
|
int *piStrokeIndex; // Stroke indexes for this word
|
|
ALTERNATES alt; // alternates for the word (only)
|
|
} WORDMAP;
|
|
|
|
// The XINKSET is the struct pointed to by an HINKSET.
|
|
// It contains a counted array of INTERVALs, describing a (sub)set
|
|
// of the ink in an HRC. The INTERVAL struct is defined in penwin.h
|
|
|
|
typedef struct tagXINKSET
|
|
{
|
|
unsigned int count;
|
|
INTERVAL interval[1];
|
|
} XINKSET;
|
|
|
|
// Verifies that the count of alternates is between 0 and 10 (inclusive).
|
|
// Verifies that each live alternate has a non-NULL szWord.
|
|
|
|
typedef struct tagANSWER_SET
|
|
{
|
|
ALTERNATES *pAlternates;
|
|
int capSegments;
|
|
int cAnsSets;
|
|
} ANSWER_SET;
|
|
|
|
|
|
// place holders for segmentation and SegCol structures
|
|
typedef struct tagSEGMENTATION SEGMENTATION;
|
|
typedef struct tagSEG_COLLECTION SEG_COLLECTION;
|
|
|
|
// structure representing a single word alternate
|
|
typedef struct tagWORD_ALT
|
|
{
|
|
unsigned char *pszStr; // CP1252 string
|
|
int iCost; // cost assigned to the string by the recognizer
|
|
LATINLAYOUT ll;
|
|
}
|
|
WORD_ALT;
|
|
|
|
// structure representing a single word alternate list
|
|
typedef struct tagWORD_ALT_LIST
|
|
{
|
|
int cAlt; // number of alternates
|
|
WORD_ALT *pAlt; // list of alternates
|
|
}
|
|
WORD_ALT_LIST;
|
|
|
|
// structure describing the set of features for a word map
|
|
typedef struct tagWORD_FEAT
|
|
{
|
|
RECT rect;
|
|
int cSeg;
|
|
|
|
int iInfernoScore; // score inferno assign to Top1 of wordmap
|
|
int iInfernoUnigram; // unigram value for Inferno's Top1 of wordmap
|
|
int bInfTop1Supported; // Is inferno's Top1 word supported
|
|
|
|
int iInfCharCost;
|
|
int iInfAspect;
|
|
int iInfHeight;
|
|
int iInfMidLine;
|
|
|
|
int iInfRelUni;
|
|
int iInfRelBi;
|
|
|
|
int iBearScore; // score Bear assign to Top1 of wordmap
|
|
int iBearUnigram; // unigram value for Bear's Top1 of wordmap
|
|
int bBearTop1Supported; // Is Bear's Top1 word supported
|
|
|
|
int iBearCharCost;
|
|
int iBearAspect;
|
|
int iBearHeight;
|
|
int iBearMidLine;
|
|
|
|
int iBearRelUni;
|
|
int iBearRelBi;
|
|
|
|
int bIdentical; // are Inferno and Bear's output identical
|
|
}
|
|
WORD_FEAT;
|
|
|
|
// structure representing a single word map (an ink chunk hypothesized to be a word)
|
|
typedef struct tagWORD_MAP
|
|
{
|
|
int cStroke; // number of strokes
|
|
int *piStrokeIndex; // list of stroke IDs (Frame IDs)
|
|
|
|
WORD_ALT_LIST *pInfernoAltList; // alt list produced by inferno
|
|
WORD_ALT_LIST *pBearAltList; // alt list produced by bear
|
|
WORD_ALT_LIST *pFinalAltList; // final alt list
|
|
|
|
int iConfidence; // confidence value assigned to this word
|
|
|
|
WORD_FEAT *pFeat; // word map features used for segmentation
|
|
}
|
|
WORD_MAP;
|
|
|
|
|
|
// structure describing the set of features for a segmentation.
|
|
typedef struct tagSEG_FEAT
|
|
{
|
|
BOOL bInfernoTop1; // is this Inferno 's Top1 segmentation
|
|
BOOL bBearTop1; // is this Bear 's Top1 segmentation
|
|
|
|
int iSort1; // Sort criteria 1, currently for USA = cWord
|
|
int iSort2; // Sort criteria 2, currently for USA = Avg. Inferno score
|
|
}
|
|
SEG_FEAT;
|
|
|
|
// structure describing a particular segmentation of a chunk of ink into word_map(s)
|
|
typedef struct tagSEGMENTATION
|
|
{
|
|
int cWord; // # of word maps
|
|
WORD_MAP **ppWord; // list of wordmaps
|
|
|
|
int iScore; // score assigned to this segmentation by
|
|
// the segmentation classifier. Ranges from 0-0xFFFF
|
|
|
|
SEG_FEAT *pFeat; // Segmentation feature vector
|
|
|
|
SEG_COLLECTION *pSegCol; // the SegCol that this segmentation belongs to
|
|
}
|
|
SEGMENTATION;
|
|
|
|
// structure describing all the possible segmentations of a chunk of ink referred to as a
|
|
// segmentation set
|
|
typedef struct tagSEG_COLLECTION
|
|
{
|
|
int cSeg; // # of possible segmenatations
|
|
SEGMENTATION **ppSeg; // list of possible segmentations
|
|
}
|
|
SEG_COLLECTION;
|
|
|
|
// structure describing a whole piece of ink as a number of seg_set (s)
|
|
typedef struct tagLINE_SEGMENTATION
|
|
{
|
|
int iyDev; // yDev for the whole ink line
|
|
|
|
int cSegCol; // # of SegCols
|
|
SEG_COLLECTION **ppSegCol; // list of SegCols
|
|
|
|
int cWord; // # of wordmaps constiuting the seg_set segmentations
|
|
WORD_MAP **ppWord; // list of word maps constiuting the seg_set segmentations
|
|
}
|
|
LINE_SEGMENTATION;
|
|
|
|
|
|
// structure used in Word breaking; similar to wordmap but got rid of unused entries.
|
|
typedef struct tagWORDINFO
|
|
{
|
|
int cStrokes; // Count of strokes in this word
|
|
int *piStrokeIndex; // Stroke indexes for this word
|
|
ALTERNATES alt;
|
|
}
|
|
WORDINFO;
|
|
|
|
// line structure
|
|
typedef struct tagINKLINE
|
|
{
|
|
DWORD dwCheckSum;
|
|
BOOL bRecognized;
|
|
|
|
RECT rect;
|
|
int cStroke;
|
|
int cPt;
|
|
POINT **ppPt;
|
|
int *pcPt;
|
|
GLYPH *pGlyph;
|
|
|
|
LINE_SEGMENTATION *pResults;
|
|
|
|
__int64 Mean;
|
|
__int64 SD;
|
|
}INKLINE;
|
|
|
|
|
|
// line breaking structure
|
|
typedef struct tagLINEBRK
|
|
{
|
|
int cLine;
|
|
INKLINE *pLine;
|
|
|
|
RECT Rect;
|
|
}
|
|
LINEBRK;
|
|
|
|
#ifndef NDEBUG
|
|
extern void ValidateALTERNATES(ALTERNATES *pAlt);
|
|
#endif
|
|
|
|
// Inserts a new word and its cost into the set of alternates.
|
|
// The alternates remain in sorted order.
|
|
extern int InsertALTERNATES(ALTERNATES *pAlt, int cost, unsigned char *word, void *pxrc);
|
|
|
|
// Initializes a XRCRESULT object to represent a phrase.
|
|
// The caller passes in a vector of pointers to ALTERNATES, representing
|
|
// the sequence of words and their alternates. We steal them into
|
|
// a vector of WORDMAP structs, and set up an XRCRESULT object
|
|
// to own that vector of maps.
|
|
|
|
// If an ALTERNATES object contains 0 answers, we insert "???" into the
|
|
// phrase string, and in the word map we set the start and len fields
|
|
// to refer to the "???".
|
|
|
|
// We assume the caller passes at least 1 ALTERNATES, even though
|
|
// it might have 0 answers.
|
|
|
|
// Should the symbol be something special for "???".
|
|
|
|
// Currently this version handles isolated periods and commas
|
|
// correctly (they do not get a space before them). This is
|
|
// to accomodate the current MadCow, which handles periods and
|
|
// commas separately.
|
|
|
|
// This should probably change to init (rather than malloc) an alt set
|
|
// to have 1 result.
|
|
extern int RCRESULTInitPhrase(XRCRESULT *pRes, ALTERNATES **ppWords, unsigned int cWords, int cost);
|
|
|
|
// Sets the backpointers in all XRCRESULT objects within and ALTERNATES object,
|
|
// including any contained within word mappings.
|
|
//extern void SetXRCALTERNATES(ALTERNATES *pAlt, void *pxrc);
|
|
|
|
|
|
// A destruction function that should only be used by an HRC destroying
|
|
// the result objects that it owns. The PenWin function DestroyHRCRESULT()
|
|
// is a no-op, since the result objects are internal to larger data structures.
|
|
extern void ClearALTERNATES(ALTERNATES *pAlt);
|
|
|
|
// Truncates the alt list to cAltmax, From cAltMax onwards: Does what ClearALTERNATES
|
|
// Only intended for WORD ALTERNATES
|
|
extern void TruncateWordALTERNATES(ALTERNATES *pAlt, unsigned int cAltMax);
|
|
|
|
// Frees the stroke index array associated with a wordmap.
|
|
void FreeIdxWORDMAP(XRCRESULT *pMap);
|
|
|
|
// Add a stroke to the wordmap checking for duplicates and maintaining the a sorted list
|
|
extern void AddThisStroke(WORDMAP *pMap, int iInsertStroke);
|
|
|
|
// Locates WORDMAP under a specified result phrase based on the word position and length.
|
|
extern WORDMAP *findWORDMAP(XRCRESULT *pRes, unsigned int iWord, unsigned int cWord);
|
|
|
|
// Locates WORDMAP under a specified phrase result that contains a specified word result.
|
|
extern WORDMAP *findResultInWORDMAP(XRCRESULT *pPhrase, XRCRESULT *pWord);
|
|
extern WORDMAP *findResultAndIndexInWORDMAP(XRCRESULT *pPhrase, XRCRESULT *pWord, int *pindex);
|
|
|
|
// Copy word maps into an xrCresult
|
|
extern BOOL XRCRESULTcopyWordMaps(XRCRESULT *pRes, int cWord, WORDMAP *pMap);
|
|
|
|
// Returns an array of RES pointers, one for each alternative interpretation of the
|
|
// same word. The word is designated by RES object, start index, and letter count.
|
|
// We return the pointers in ppRes, and return the count.
|
|
// We only do whole words, so if the caller requests a substring that is not a word,
|
|
// we return 0. If the word is the special marker "???" meaning the recognizer could
|
|
// not produce interpretations, we return 0.
|
|
extern int RCRESULTWords(XRCRESULT *pRes, unsigned int iWord, unsigned int cWord, XRCRESULT **ppRes, unsigned int cRes);
|
|
|
|
// Returns (in a buffer provided by the caller) the "symbols" of the
|
|
// word or phrase represented by pRes. Symbols are 32 bit codes.
|
|
// Here the null byte at the end of a string is part of the string and
|
|
// is copied into the symbol value array if there is room.
|
|
// Returns the number of symbols inserted.
|
|
extern int RCRESULTSymbols(XRCRESULT *pRes, unsigned int iSyv, int *pSyv, unsigned int cSyv);
|
|
|
|
// Translates an array of symbols into an ANSI (codepage 1252) string.
|
|
// This and SymbolToUnicode() below both translate until either cSyv is
|
|
// exhausted or until they hit a NULL symbol or a NULL character.
|
|
// The both return the count of symbols translated in *pCount.
|
|
// Both return 1 if successful, or 0 if they encountered something
|
|
// that could not be translated.
|
|
extern int SymbolToANSI(unsigned char *sz, int *pSyv, int cSyv, int *pCount);
|
|
|
|
// Translates an array of symbols into a Unicode string.
|
|
extern int SymbolToUnicode(WCHAR *wsz, int *pSyv, int cSyv, int *pCount);
|
|
|
|
// Backward compatibility.
|
|
// These 2 functions exist to support the old API.
|
|
|
|
extern int ALTERNATESString(ALTERNATES *pAlt, char *buffer, int buflen, int max);
|
|
extern int ALTERNATESCosts(ALTERNATES *pAlt, int max, int *pCost);
|
|
|
|
// Creates an InkSet to represent the part of pGlyph included within
|
|
// a specified WORDMAP.
|
|
extern XINKSET *mkInkSetWORDMAP(GLYPH *pGlyph, WORDMAP *pMap);
|
|
|
|
// Creates an InkSet to represent the part of pGlyph included
|
|
// within a specified word within a phrase.
|
|
extern XINKSET *mkInkSetPhrase(GLYPH *pGlyph, XRCRESULT *pRes, unsigned int iWord, unsigned int cWord);
|
|
|
|
// given a main glyph and a wordmap,
|
|
// this function returns a pointer to glyph representing the word only
|
|
extern GLYPH *GlyphFromWordMap (GLYPH *pMainGlyph, WORDMAP *pMap);
|
|
extern GLYPH *GlyphFromNewWordMap (GLYPH *pMainGlyph, WORD_MAP *pMap);
|
|
|
|
// given a main glyph and set of strokes,
|
|
// this function returns a pointer to glyph representing only those strokes
|
|
extern GLYPH *GlyphFromStrokes(GLYPH *pMainGlyph, int cStroke, int *piStrokeIndex);
|
|
|
|
// Frees a word alt
|
|
void FreeWordAlt (WORD_ALT *pAlt);
|
|
|
|
// Frees a word alt list
|
|
void FreeWordAltList (WORD_ALT_LIST *pAltList);
|
|
|
|
// Frees a word map
|
|
void FreeWordMap (WORD_MAP *pWordMap);
|
|
|
|
// Frees a specific segmentation
|
|
void FreeSegmentation (SEGMENTATION *pSeg);
|
|
|
|
// frees the word maps in a segmentation
|
|
void FreeSegmentationWordMaps (SEGMENTATION *pSeg);
|
|
|
|
// Frees a segmentation set
|
|
void FreeSegCol (SEG_COLLECTION *pSegCol);
|
|
|
|
// Frees an ink line segmentation
|
|
void FreeLineSegm (LINE_SEGMENTATION *pLineSegm);
|
|
|
|
// compares the stroke contents of two word maps
|
|
BOOL IsEqualWordMap (WORD_MAP *pMap1, WORD_MAP *pMap2);
|
|
|
|
// compares the stroke contents of two word maps
|
|
BOOL IsEqualOldWordMap (WORDMAP *pMap1, WORDMAP *pMap2);
|
|
|
|
// compares two segmentations
|
|
BOOL IsEqualSegmentation (SEGMENTATION *pSeg1, SEGMENTATION *pSeg2);
|
|
|
|
// clones a wordmap, only copies the stroke part
|
|
WORD_MAP *CloneWordMap (WORD_MAP *pOldWordMap);
|
|
|
|
// finds a word_map in pool or wordmaps
|
|
// returns the pointer to the word map if found
|
|
// if the bAdd parameter is TRUE: adds the new word map if not found a return a pointer
|
|
// other wise returns false
|
|
WORD_MAP *FindWordMap (LINE_SEGMENTATION *pLineSegm, WORD_MAP *pWordMap, BOOL bAdd);
|
|
|
|
|
|
// adds a new SegCol to a line segmentation
|
|
SEG_COLLECTION *AddNewSegCol (LINE_SEGMENTATION *pLineSegm);
|
|
|
|
// adds a new segmentation to a SegCol if it is a new one
|
|
// returns TRUE: if the segmentation is added to the SegCol (new words are also added to
|
|
// the word map pool in the line segmentation).
|
|
// return FALSE: if no addition was made, TRUE otherwise
|
|
BOOL AddNewSegmentation ( LINE_SEGMENTATION *pLineSegm,
|
|
SEG_COLLECTION *pSegCol,
|
|
SEGMENTATION *pNewSeg,
|
|
BOOL bCheckForDuplicates
|
|
);
|
|
|
|
|
|
// adds a new word_map to a segmentation
|
|
WORD_MAP *AddNewWordMap (SEGMENTATION *pSeg);
|
|
|
|
|
|
// appends the wordmaps of one segmentation to another
|
|
BOOL AppendSegmentation ( SEGMENTATION *pSrcSeg,
|
|
int iStWrd,
|
|
int iEndWrd,
|
|
SEGMENTATION *pDestSeg
|
|
);
|
|
|
|
|
|
// adds a new stroke to a wordmap
|
|
BOOL AddNewStroke (WORD_MAP *pWordMap, int iStrk);
|
|
|
|
// reverses the order of words maps with a segmentation
|
|
void ReverseSegmentationWords (SEGMENTATION *pSeg);
|
|
|
|
// determines the min & max value for a strokeID in a wordmap
|
|
int GetMinMaxStrokeID (WORD_MAP *pWord, int *piMin, int *piMax);
|
|
|
|
BOOL InsertNewAlternate (WORD_ALT_LIST *pAltList, int iCost, unsigned char *pszWord);
|
|
|
|
// This function finds the range on wordmaps in the search segmentation that
|
|
// use exactly the same strokes in the specified wordmap map range in the matching
|
|
// segmentation
|
|
// The passed bEnd flag specified whether piEndWordMap has to be the last wordmap
|
|
// of the search segmentation or not.
|
|
// The return value will be FALSE if no wordmap range with the required specification
|
|
// is found
|
|
BOOL GetMatchingWordMapRange ( SEGMENTATION *pMatchSeg,
|
|
int iStartWordMap,
|
|
int iEndWordMap,
|
|
SEGMENTATION *pSearchSeg,
|
|
int *piStartWordMap,
|
|
int *piEndWordMap,
|
|
BOOL bBegin,
|
|
BOOL bEnd
|
|
);
|
|
|
|
BOOL WordMapNew2Old (WORD_MAP *pNewWordMap, WORDMAP *pWordMap, BOOL bClone);
|
|
|
|
BOOL AltListOld2New (ALTERNATES *pOldAltList, WORD_ALT_LIST *pAltList, BOOL bClone);
|
|
|
|
BOOL AltListNew2Old ( HRC hrc,
|
|
WORD_MAP *pNewWordMap,
|
|
WORD_ALT_LIST *pAltList,
|
|
ALTERNATES *pOldAltList,
|
|
BOOL bClone
|
|
);
|
|
|
|
void FreeLines (LINEBRK *pLineBrk);
|
|
|
|
BOOL AddNewStroke2Line (int cPt, POINT *pPt, FRAME *pFrame, INKLINE *pLine);
|
|
|
|
int FindWordMapInXRCRESULT (XRCRESULT *pRes, WORDMAP *pMap);
|
|
|
|
short AbsoluteToLatinLayout(int y, RECT *pRect);
|
|
int LatinLayoutToAbsolute(short y, RECT *pRect);
|
|
|
|
#ifdef __cplusplus
|
|
};
|
|
#endif
|
|
|
|
#endif
|