|
|
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//
// Copyright (c) 2001 Microsoft Corporation. All rights reserved.
//
// Module:
// volcano/dll/segm.c
//
// Description:
// Functions to implement the functionality of managing segmentation structures.
//
// Author:
// ahmadab 11/14/01
//
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
#include "common.h"
#include "volcanop.h"
#include "lattice.h"
#include "runnet.h"
#include "brknet.h"
#include "segm.h"
#include "nnet.h"
float FuguSegScore(int cStrokes, STROKE *pStrokes, LOCRUN_INFO *pLocRunInfo);
// enumerate all the segmentations currently present in the lattice
// for the specified ink segment
BOOL EnumerateInkSegmentations (LATTICE *pLat, INK_SEGMENT *pInkSegment) { int cAlt, iAlt, iPrevAlt; LATTICE_ALT_LIST *pAlt;
// find unique segmentations
pAlt = pLat->pAltList + pInkSegment->StrokeRange.iEndStrk; cAlt = pAlt->nUsed;
// for each alt find out if there is any prev alt that suggests the same stroke count
for (iAlt = 0; iAlt < cAlt; iAlt++) { for (iPrevAlt = 0; iPrevAlt < iAlt; iPrevAlt++) { // found one, that is enough exit this prev loop
if (pAlt->alts[iAlt].nStrokes == pAlt->alts[iPrevAlt].nStrokes) { break; } }
// if we found no match, then this is the first existense of this count, we want it
if (iPrevAlt == iAlt) { ELEMLIST *pSegm; int iStrk, iStrkAlt; LATTICE_ALT_LIST *pStrkAlt;
// now we want to create a new segmentation
pInkSegment->ppSegm = (ELEMLIST **) ExternRealloc (pInkSegment->ppSegm, (pInkSegment->cSegm + 1) * sizeof (*pInkSegment->ppSegm));
if (!pInkSegment->ppSegm) { return FALSE; } pInkSegment->ppSegm[pInkSegment->cSegm] = (ELEMLIST *) ExternAlloc (sizeof (*pInkSegment->ppSegm[pInkSegment->cSegm]));
if (!pInkSegment->ppSegm[pInkSegment->cSegm]) { return FALSE; }
pSegm = pInkSegment->ppSegm[pInkSegment->cSegm]; pInkSegment->cSegm++;
memset (pSegm, 0, sizeof (*pSegm));
iStrk = pInkSegment->StrokeRange.iEndStrk; iStrkAlt = iAlt;
while (iStrk >= pInkSegment->StrokeRange.iStartStrk) { pStrkAlt = pLat->pAltList + iStrk;
if (!InsertListElement (pSegm, iStrk, iStrkAlt, pStrkAlt->alts + iStrkAlt)) { return FALSE; }
iStrk -= pStrkAlt->alts[iStrkAlt].nStrokes; iStrkAlt = pStrkAlt->alts[iStrkAlt].iPrevAlt; }
ReverseElementList (pSegm);
// if we had already exceed the maximum number of segmentations, return
if (pInkSegment->cSegm > MAX_SEGMENTATIONS) { return TRUE; } } }
return TRUE; }
// computes the set of features for a segmentation
int FeaturizeSegmentation (LATTICE *pLat, ELEMLIST *pSeg, int *pFeat) { int cFeat = 0; LATTICE_ELEMENT *pElem, *pPrevElem; LATTICE_PATH_ELEMENT *pPathElem; int iChar, iBrkNetOut; pPrevElem = NULL; iBrkNetOut = 0; pPathElem = pSeg->pElem;
for (iChar = 0; iChar < MAX_SEG_CHAR; iChar++, pPathElem++) { // we going beyond the actual number of chars
if (iChar >= pSeg->cElem) { // char features
// FEATURE 0: is this a real char
pFeat[cFeat++] = 0;
// FEATURE 1: # of strokes
pFeat[cFeat++] = 0;
// FEATURE 2: -log prob
pFeat[cFeat++] = 65535;
// FEATURE 3: unigram of code point
pFeat[cFeat++] = 65535;
// FEATURE 3: fake fugu score
pFeat[cFeat++] = 0;
// char pair features
if (iChar > 0) { // FEATURE 0: bigram pair
pFeat[cFeat++] = 65535;
// FEATURE 1: normalized delx
pFeat[cFeat++] = 0;
// FEATURE 2: output of brk net
pFeat[cFeat++] = 0; }
pPrevElem = NULL; } else { ASSERT (pPathElem->iStroke < pLat->nStrokes); ASSERT (pPathElem->iAlt < pLat->pAltList[pPathElem->iStroke].nUsed);
pElem = pLat->pAltList[pPathElem->iStroke].alts + pPathElem->iAlt;
// FEATURE 0: is this a real char
pFeat[cFeat++] = 65535;
// FEATURE 1: # of strokes
pFeat[cFeat++] = min (65535, pElem->nStrokes * 1000);
// FEATURE 2: -log prob
pFeat[cFeat++] = min (65535, (int) (-1000.0 * pElem->logProb));
// FEATURE 3: unigram of code point
pFeat[cFeat++] = min (65535, (int) (-255.0 * UnigramCost (&g_unigramInfo, pElem->wChar)));
// feature 4: char detector score
if (pElem->iCharDetectorScore == -1) { pElem->iCharDetectorScore = min (65535, (int) (65535.0 * FuguSegScore (pElem->nStrokes, pLat->pStroke + pPathElem->iStroke - pElem->nStrokes + 1, &g_locRunInfo))); }
pFeat[cFeat++] = max (min (65535, pElem->iCharDetectorScore), 0);
// char pair features
if (iChar > 0) { int xDist, yHgt;
ASSERT (pPrevElem != NULL);
// FEATURE 0: bigram pair
pFeat[cFeat++] = min (65536, (int) (-1000.0 * BigramTransitionCost (&g_locRunInfo, &g_bigramInfo, pPrevElem->wChar, pElem->wChar)));
// FEATURE 1: normalized delx
xDist = pElem->bbox.left - pPrevElem->bbox.right; yHgt = 1 + ( (pElem->bbox.bottom - pElem->bbox.top) + (pPrevElem->bbox.bottom - pPrevElem->bbox.top) ) / 2;
pFeat[cFeat++] = 32768 + max (-32767, min (32767, (int)(32768.0 * xDist / (abs(xDist) + yHgt))));
// FEATURE 2: output of brk net after prev char
pFeat[cFeat++] = iBrkNetOut; }
iBrkNetOut = pLat->pAltList[pPathElem->iStroke].iBrkNetScore; pPrevElem = pElem; } } return cFeat; }
// frees an ink segment
void FreeInkSegment (INK_SEGMENT *pInkSegment) { int iSeg;
for (iSeg = 0; iSeg < pInkSegment->cSegm; iSeg++) { if (pInkSegment->ppSegm[iSeg]) { FreeElemList (pInkSegment->ppSegm[iSeg]);
ExternFree (pInkSegment->ppSegm[iSeg]); } }
if (pInkSegment->ppSegm) { ExternFree (pInkSegment->ppSegm); } }
// featurize an ink segment
int FeaturizeInkSegment (LATTICE *pLat, INK_SEGMENT *pInkSegment, int *pFeat) { int iSeg, cSegFeat, cFeat = 0;
for (iSeg = 0; iSeg < pInkSegment->cSegm; iSeg++) { // featurize this segmentation
cSegFeat = FeaturizeSegmentation (pLat, pInkSegment->ppSegm[iSeg], pFeat + cFeat);
// did we fail
if (cSegFeat <= 0) { return -1; }
// increment the number of features
cFeat += cSegFeat; }
return cFeat; }
|