windows-nt/Source/XPSP1/NT/drivers/tpg/hwx/volcano/dll/segm.c
2020-09-26 16:20:57 +08:00

272 lines
6.2 KiB
C

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//
// 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;
}