|
|
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//
// Copyright (c) 2001 Microsoft Corporation. All rights reserved.
//
// Module:
// volcano/dll/brknet.c
//
// Description:
// Functions to implement the functionality of managing breakpoint structures.
//
// Author:
// ahmadab 11/05/01
//
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
#include "common.h"
#include "volcanop.h"
#include "lattice.h"
#include "runnet.h"
#include "brknet.h"
// free an element list
void FreeElemList (ELEMLIST *pList) { if (pList->pElem) { ExternFree (pList->pElem); } }
// reverses the order of entries in an element list
void ReverseElementList (ELEMLIST *pElemList) { LATTICE_PATH_ELEMENT Elem; int iElemFor, iElemBack;
for ( iElemFor = 0, iElemBack = pElemList->cElem -1; iElemFor < pElemList->cElem && iElemBack >= 0 && iElemFor < iElemBack; iElemFor++, iElemBack-- ) { Elem = pElemList->pElem[iElemFor]; pElemList->pElem[iElemFor] = pElemList->pElem[iElemBack]; pElemList->pElem[iElemBack] = Elem; } }
// frees a break point array
void FreeBreaks (int cBrk, BRKPT *pBrk) { int i;
for (i = 0; i < cBrk; i++) { FreeElemList (&pBrk[i].Starting); FreeElemList (&pBrk[i].Ending); FreeElemList (&pBrk[i].Crossing); }
ExternFree (pBrk); }
// insert an element into an element list
BOOL InsertListElement (ELEMLIST *pList, int iStrk, int iAlt, LATTICE_ELEMENT *pLatElem) { LATTICE_PATH_ELEMENT *pElem;
// expand the element list
pList->pElem = (LATTICE_PATH_ELEMENT *) ExternRealloc (pList->pElem, (pList->cElem + 1) * sizeof (*pList->pElem));
if (!pList->pElem) { return FALSE; }
pElem = pList->pElem + pList->cElem; pElem->iAlt = iAlt; pElem->iStroke = iStrk; pElem->nStrokes = pLatElem->nStrokes; pElem->wChar = pLatElem->wChar; pElem->iBoxNum = -1;
pList->cElem++;
return TRUE; }
// makes the break point list
BRKPT *CreateBrkPtList (LATTICE *pLat) { BRKPT *pBrk = NULL; int cStrk = pLat->nStrokes; BOOL bRet = FALSE; int i, iStrk, iAlt, cAlt, iStrtStrk, iPrevAlt; LATTICE_ALT_LIST *pAlt;
// allocate and init buffer
pBrk = (BRKPT *) ExternAlloc (cStrk * sizeof (BRKPT)); if (!pBrk) { goto exit; }
memset (pBrk, 0, cStrk * sizeof (BRKPT));
// all strokes are candidate break points
for (iStrk = 0; iStrk < cStrk; iStrk++) { // look at the alt list of words ending at this stroke
pAlt = pLat->pAltList + iStrk; cAlt = pAlt->nUsed;
// for all alts
for (iAlt = 0; iAlt < cAlt; iAlt++) { // did it occur before
for (iPrevAlt = 0; iPrevAlt < iAlt; iPrevAlt++) { if (pAlt->alts[iAlt].nStrokes == pAlt->alts[iPrevAlt].nStrokes) { break; } }
// there was no previous alt with the same # of strokes
if (iPrevAlt == iAlt) { // update the starting list
iStrtStrk = iStrk - pAlt->alts[iAlt].nStrokes + 1;
// This shouldn't happen, but there is enough code involved in
// building up the lattice that it is probably a good idea to check.
if (iStrtStrk < 0) { ASSERT(("Malformed lattice in CreateBrkPtList()", 0)); goto exit; }
if (iStrtStrk > 0) { if ( !InsertListElement (&pBrk[iStrtStrk - 1].Starting, iStrk, iAlt, pAlt->alts + iAlt) ) { goto exit; } }
// update the ending list
if ( !InsertListElement (&pBrk[iStrk].Ending, iStrk, iAlt, pAlt->alts + iAlt) ) { goto exit; }
// update the crossing list
for (i = iStrtStrk; i < iStrk; i++) { if ( !InsertListElement (&pBrk[i].Crossing, iStrk, iAlt, pAlt->alts + iAlt) ) { goto exit; } } } } }
bRet = TRUE;
exit: if (!bRet) { if (pBrk) { FreeBreaks (cStrk, pBrk); }
return NULL; } else { return pBrk; } }
// find the element with the best probablity in the element list
LATTICE_ELEMENT *FindBestInList ( LATTICE *pLat, ELEMLIST *pList, LATTICE_PATH_ELEMENT **ppBestElem ) { int i, iAlt; LATTICE_ELEMENT *pBest = NULL; LATTICE_ALT_LIST *pAlt;
// go thru all elements
for (i = 0; i < pList->cElem; i++) { pAlt = pLat->pAltList + pList->pElem[i].iStroke; iAlt = pList->pElem[i].iAlt;
// exclude fake elements
if (pAlt->alts[iAlt].wChar == SYM_UNKNOWN) continue;
// update the best
if (!pBest || pBest->logProb < pAlt->alts[iAlt].logProb) { (*ppBestElem) = pList->pElem + i; pBest = pAlt->alts + iAlt; } }
return pBest; }
float FuguSegScore(int cStrokes, STROKE *pStrokes, LOCRUN_INFO *pLocRunInfo);
// compute the set of features for a given break point
// returns the number of features computed
int FeaturizeBrkPt (LATTICE *pLat, BRKPT *pBrk, int *pFeat) { int xDist, iHgt;
int cFeat = 0;
LATTICE_ELEMENT *pBestStart = NULL, *pBestEnd = NULL, *pBestCross = NULL;
LATTICE_PATH_ELEMENT *pBestStartPathElem = NULL, *pBestEndPathElem = NULL, *pBestCrossPathElem = NULL;
ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = pBrk->Starting.cElem * 1000;
ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = pBrk->Ending.cElem * 1000; ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = pBrk->Crossing.cElem * 500;
// find the best chars
pBestStart = FindBestInList (pLat, &pBrk->Starting, &pBestStartPathElem); pBestEnd = FindBestInList (pLat, &pBrk->Ending, &pBestEndPathElem); pBestCross = FindBestInList (pLat, &pBrk->Crossing, &pBestCrossPathElem); // do we have a starting best
if (pBestStart) { // a real char
ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = 65535;
// log prob
ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = min (65535, (int) (-1.0 * pBestStart->logProb * 1000));
// space / area
ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = min (65535, (int) (65535 * (double) pBestStart->space / (pBestStart->area + 1))); ASSERT (pFeat[cFeat - 1] >= 0);
// # of strokes
ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = pBestStart->nStrokes * 1000;
// char unigram
ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = min (65535, (int) (-255 * UnigramCost (&g_unigramInfo, pBestStart->wChar))); // Fugu Char Detector score, compute if did not doo it before
if (pBestStart->iCharDetectorScore == -1) { pBestStart->iCharDetectorScore = min (65535, (int) (65535.0 * FuguSegScore (pBestStart->nStrokes, pLat->pStroke + pBestStartPathElem->iStroke - pBestStart->nStrokes + 1, &g_locRunInfo))); }
ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = max (0, min (65535, pBestStart->iCharDetectorScore)); } else { // not a real char
ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = 0;
// fake log prob
ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = 65535;
// fake space / area
ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = 0;
// fake # of strokes
ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = 0;
// fake unigram
ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = min (65535, (int) (-255 * UnigramCost (&g_unigramInfo, 0xFFFE)));
// fake fugu score
ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = 0; }
if (pBestEnd) { // a real char
ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = 65535;
// log prob
ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = min (65535, (int) (-1.0 * pBestEnd->logProb * 1000));
// space / area
ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = min (65535, (int) (65535 * (double) pBestEnd->space / (pBestEnd->area + 1))); ASSERT (pFeat[cFeat - 1] >= 0);
// # of strokes
ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = pBestEnd->nStrokes * 1000;
// char unigram
ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = min (65535, (int) (-255 * UnigramCost (&g_unigramInfo, pBestEnd->wChar))); // Fugu Char Detector score
if (pBestEnd->iCharDetectorScore == -1) { pBestEnd->iCharDetectorScore = min (65535, (int) (65535.0 * FuguSegScore (pBestEnd->nStrokes, pLat->pStroke + pBestEndPathElem->iStroke - pBestEnd->nStrokes + 1, &g_locRunInfo))); }
ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = max (0, min (65535, pBestEnd->iCharDetectorScore)); } else { // not a real char
ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = 0;
// fake log prob
ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = 65535;
// fake space / area
ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = 0;
// fake # of strokes
ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = 0;
// fake unigram
ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = min (65535, (int) (-255 * UnigramCost (&g_unigramInfo, 0xFFFE)));
// fake fugu score
ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = 0; }
if (pBestCross) { // a real char
ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = 65535;
// log prob
ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = min (65535, (int) (-1.0 * pBestCross->logProb * 1000));
// space / area
ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = min (65535, (int) (65535 * (double) pBestCross->space / (pBestCross->area + 1))); ASSERT (pFeat[cFeat - 1] >= 0);
// # of strokes
ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = pBestCross->nStrokes * 1000;
// char unigram
ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = min (65535, (int) (-255 * UnigramCost (&g_unigramInfo, pBestCross->wChar))); // Fugu Char Detector score
ASSERT (cFeat < MAX_BRK_NET_FEAT); if (pBestCross->iCharDetectorScore == -1) { pBestCross->iCharDetectorScore = min (65535, (int) (65535.0 * FuguSegScore (pBestCross->nStrokes, pLat->pStroke + pBestCrossPathElem->iStroke - pBestCross->nStrokes + 1, &g_locRunInfo))); }
ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = max (0, min (65535, pBestCross->iCharDetectorScore)); } else { // not a real char
ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = 0;
// fake log prob
ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = 65535;
// fake space / area
ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = 0;
// fake # of strokes
ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = 0;
// fake unigram
ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = min (65535, (int) (-255 * UnigramCost (&g_unigramInfo, 0xFFFE)));
// fake fugu score
ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = 0; }
if (pBestStart && pBestEnd) { xDist = pBestStart->bbox.left - pBestEnd->bbox.right; iHgt = 1 + ( (pBestStart->bbox.bottom - pBestStart->bbox.top) + (pBestEnd->bbox.bottom - pBestEnd->bbox.top) ) / 2;
ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = min (65535, 32768 + (int)(32768.0 * xDist / (abs(xDist) + iHgt)));
// bigram
ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = min (65535, (int) (-1.0 * BigramTransitionCost (&g_locRunInfo, &g_bigramInfo, pBestEnd->wChar, pBestStart->wChar) * 65535)); } else { ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = 0;
ASSERT (cFeat < MAX_BRK_NET_FEAT); pFeat[cFeat++] = 65535; }
return cFeat; }
|