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

317 lines
6.4 KiB
C

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//
// Copyright (c) 2001 Microsoft Corporation. All rights reserved.
//
// Module:
// volcano/dll/brknet.c
//
// Description:
// Functions to implement the functionality of the break Neural net that
// modifies the lattice structure to correct segmentation errors.
//
// Author:
// ahmadab 11/05/01
//
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
#include "common.h"
#include "volcanop.h"
#include "lattice.h"
#include "runnet.h"
#include "brknet.h"
#include "segm.h"
#include "nnet.h"
// the size and structure representing the Breaking net used in Free mode
// if the is not available for a particular configuration, s_iBrkNetSize will be zero
static int s_iBrkNetSize = 0;
static LOCAL_NET s_BrkNet;
// validates the header of the brknet
BOOL CheckBrkNetHeader (void *pData)
{
NNET_HEADER *pHeader = (NNET_HEADER *)pData;
// wrong magic number
ASSERT (pHeader->dwFileType == BRKNET_FILE_TYPE);
if (pHeader->dwFileType != BRKNET_FILE_TYPE)
{
return FALSE;
}
// check version
ASSERT(pHeader->iFileVer >= BRKNET_OLD_FILE_VERSION);
ASSERT(pHeader->iMinCodeVer <= BRKNET_CUR_FILE_VERSION);
ASSERT ( !memcmp ( pHeader->adwSignature,
g_locRunInfo.adwSignature,
sizeof (pHeader->adwSignature)
)
);
ASSERT (pHeader->cSpace == 1);
if ( pHeader->iFileVer >= BRKNET_OLD_FILE_VERSION &&
pHeader->iMinCodeVer <= BRKNET_CUR_FILE_VERSION &&
!memcmp ( pHeader->adwSignature,
g_locRunInfo.adwSignature,
sizeof (pHeader->adwSignature)
) &&
pHeader->cSpace == 1
)
{
return TRUE;
}
else
{
return FALSE;
}
}
// does the necessary preparations for a net to be used later
static LOCAL_NET *PrepareBrkNet(BYTE *pData, int *piNetSize, LOCAL_NET *pNet)
{
NNET_SPACE_HEADER *pSpaceHeader;
if (!pData)
{
return FALSE;
}
// check the header info
if (!CheckBrkNetHeader (pData))
{
return NULL;
}
// point to the one and only space that we have
pSpaceHeader = (NNET_SPACE_HEADER *)(pData + sizeof (NNET_HEADER));
// point to the actual data
pData = pData + pSpaceHeader->iDataOffset;
// restore the connections
if (!(pNet = restoreLocalConnectNet(pData, 0, pNet)) )
{
return NULL;
}
// compute the run time memory requirements of the net
(*piNetSize) = getRunTimeNetMemoryRequirements(pData);
if ((*piNetSize) <= 0)
{
return NULL;
}
return pNet;
}
// load the brk net from resources
BOOL LoadBrkNetFromFile(wchar_t *pwszRecogDir, LOAD_INFO *pLoadInfo)
{
BYTE *pData;
wchar_t awszFileName[MAX_PATH];
// init the size to zero, in case we fail
s_iBrkNetSize = 0;
swprintf (awszFileName, L"%s\\brknet.bin", pwszRecogDir);
// memory map the file
pData = DoOpenFile (pLoadInfo, awszFileName);
if (!pData)
{
return FALSE;
}
// prepare Brk net
if (!PrepareBrkNet(pData, &s_iBrkNetSize, &s_BrkNet))
{
return FALSE;
}
return TRUE;
}
// load the brk net from resources
BOOL LoadBrkNetFromResource (HINSTANCE hInst, int nResID, int nType)
{
BYTE *pData;
LOAD_INFO LoadInfo;
// init the size to zero, in case we fail
s_iBrkNetSize = 0;
pData = DoLoadResource (&LoadInfo, hInst, nResID, nType);
if (!pData)
{
return FALSE;
}
// prepare the net
if (!PrepareBrkNet(pData, &s_iBrkNetSize, &s_BrkNet))
{
return FALSE;
}
return TRUE;
}
// update the lattice by running the BRK-NET on all the possible break points.
// Currently only one segmentation survives which is the one suggested by the BRK-NET
// returns the number of charcaters in the updated lattice on success, -1 upon failure
int UpdateLattice (LATTICE *pLat)
{
int iPos,
iStrk,
cStrk,
iWinner,
cOut,
cBrk;
BOOL *pIsBreak = NULL;
BRKPT *pBrk = NULL;
RREAL *pNetMem = NULL,
*pNetOut;
int iRet = -1,
iBrk;
// if the net has not been successfully loaded, we'll fail
if (s_iBrkNetSize <= 0)
{
goto exit;
}
// alloc memory for the Net's running buffer
pNetMem = (RREAL *) ExternAlloc (s_iBrkNetSize * sizeof (*pNetMem));
if (!pNetMem)
{
goto exit;
}
// create the break pts structure
cStrk = pLat->nStrokes;
pBrk = CreateBrkPtList (pLat);
// if we have succeeded, lets process these break points
if (pBrk)
{
// allocate a boolean struct to mark ON break points
pIsBreak = (BOOL *) ExternAlloc (cStrk * sizeof (*pIsBreak));
if (!pIsBreak)
{
goto exit;
}
// for all break points
for (iStrk = 0, cBrk = 0; iStrk < cStrk; iStrk++)
{
int iFeat, cFeat, aFeat[MAX_BRK_NET_FEAT];
// featurize for this break point
cFeat = FeaturizeBrkPt (pLat, pBrk + iStrk, aFeat);
ASSERT (cFeat <= MAX_BRK_NET_FEAT);
// prepare the nets input
for (iFeat = 0; iFeat < cFeat; iFeat++)
{
pNetMem[iFeat] = aFeat[iFeat];
}
// run the net
pNetOut = runLocalConnectNet (&s_BrkNet, pNetMem, &iWinner, &cOut);
ASSERT (cOut == 2);
// this is considered a hard break point if the net's output is higher than the threshold
pIsBreak[iStrk] = pNetOut[1] >= (BREAKING_THRESHOLD);
// mark it a as a breakpoint
if (pIsBreak[iStrk])
{
cBrk++;
}
// copy the score in the lattice
pLat->pAltList[iStrk].iBrkNetScore = pNetOut[1];
}
ASSERT (cBrk <= cStrk);
// make sure there is a break point always at the end,
if (!pIsBreak[cStrk - 1])
{
pIsBreak[cStrk - 1] = TRUE;
cBrk++;
}
// clear out all the existing alternate lists at every stroke
for (iStrk = 0; iStrk < cStrk; iStrk++)
{
ClearAltList (pLat->pAltList + iStrk);
}
// change the lattice to reflect the new segmentation
for (iBrk = iStrk = 0; iBrk < cBrk; iBrk++)
{
iPos = iStrk;
// find the next break point
while (!pIsBreak[iStrk] && iStrk < cStrk)
{
iStrk++;
}
// build the alt list at the the ending stroke with the
// current stroke being the starting one
//BuildStrokeCountRecogAlts(pLat, iStrk, iStrk - iPos + 1);
if (!ProcessLatticeRange (pLat, iPos, iStrk))
{
goto exit;
}
UpdateSegmentations (pLat, iPos, iStrk);
iStrk++;
}
// Mark the best path through the lattice
//iRet = FindFullPath (pLat);
FixupBackPointers (pLat);
}
exit:
// free the local buffers if had been allocated
if (pBrk)
{
FreeBreaks (cStrk, pBrk);
}
if (pIsBreak)
{
ExternFree (pIsBreak);
}
if (pNetMem)
{
ExternFree (pNetMem);
}
return iRet;
}
void BrkNetUnloadfile (LOAD_INFO *pLoadInfo)
{
if (s_iBrkNetSize != 0)
{
DoCloseFile (pLoadInfo);
}
}