Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

194 lines
4.6 KiB

#include "common.h"
#include "glyph.h"
#include "score.h"
#include "fugu.h"
#include "volcanop.h"
#include "nnet.h"
#define FUGU_SEG_MAX_SPACES 32
static int g_cSpaces;
static FUGU_INTEGER_WEIGHTS g_aCharDetNet[FUGU_SEG_MAX_SPACES];
POINT *DupPoints(POINT *pOldPoints, int nPoints);
GLYPH *GlyphFromStrokes(UINT cStrokes, STROKE *pStrokes);
// prepare net from pointer
BOOL PrepareCharDetNet (BYTE *pb, FUGU_INTEGER_WEIGHTS *pCharDetNet)
{
pCharDetNet->pHeader = (FUGU_INTEGER_WEIGHTS_HEADER *) pb;
pCharDetNet->pfdchMapping = (WCHAR *) (pb + sizeof(FUGU_INTEGER_WEIGHTS_HEADER));
pCharDetNet->pbWeights = pb + sizeof(FUGU_INTEGER_WEIGHTS_HEADER) +
sizeof(WCHAR) * pCharDetNet->pHeader->arch.nOutputs;
return TRUE;
}
// validates the header of the brknet
int CheckCharDetHeader (void *pData)
{
NNET_HEADER *pHeader = (NNET_HEADER *)pData;
// wrong magic number
ASSERT (pHeader->dwFileType == CHARDET_FILE_TYPE);
if (pHeader->dwFileType != CHARDET_FILE_TYPE)
{
return FALSE;
}
// check version
ASSERT(pHeader->iFileVer >= CHARDET_OLD_FILE_VERSION);
ASSERT(pHeader->iMinCodeVer <= CHARDET_CUR_FILE_VERSION);
ASSERT ( !memcmp ( pHeader->adwSignature,
g_locRunInfo.adwSignature,
sizeof (pHeader->adwSignature)
)
);
ASSERT (pHeader->cSpace <= FUGU_SEG_MAX_SPACES);
if ( pHeader->iFileVer >= CHARDET_OLD_FILE_VERSION &&
pHeader->iMinCodeVer <= CHARDET_CUR_FILE_VERSION &&
!memcmp ( pHeader->adwSignature,
g_locRunInfo.adwSignature,
sizeof (pHeader->adwSignature)
) &&
pHeader->cSpace <= FUGU_SEG_MAX_SPACES
)
{
return pHeader->cSpace;
}
else
{
return 0;
}
}
// does the necessary preparations for a net to be used later
static BOOL CharDetLoadFromPointer (BYTE *pData)
{
int iSpc, cSpc, iSpaceID;
NNET_SPACE_HEADER *pSpaceHeader;
BYTE *pPtr;
if (!pData)
{
return FALSE;
}
// check the header info
cSpc = CheckCharDetHeader (pData);
g_cSpaces = cSpc;
if (cSpc <= 0)
{
return FALSE;
}
pPtr = pData + sizeof (NNET_HEADER);
for (iSpc = 0; iSpc < cSpc; iSpc++)
{
// point to the one and only space that we have
pSpaceHeader = (NNET_SPACE_HEADER *)pPtr;
pPtr += sizeof (NNET_SPACE_HEADER);
// point to the actual data
iSpaceID = pSpaceHeader->iSpace;
ASSERT (iSpaceID >= 1 && iSpaceID <= FUGU_SEG_MAX_SPACES);
if (!PrepareCharDetNet ( pData + pSpaceHeader->iDataOffset,
g_aCharDetNet + iSpaceID - 1
)
)
{
return FALSE;
}
}
return TRUE;
}
BOOL LoadCharDetFromFile(wchar_t *wszPath, LOAD_INFO *pLoadInfo)
{
wchar_t awszFileName[MAX_PATH];
// memory map the file
wsprintf (awszFileName, L"%s\\chardet.bin", wszPath);
if (!DoOpenFile(pLoadInfo, awszFileName))
{
return FALSE;
}
return CharDetLoadFromPointer (pLoadInfo->pbMapping);
}
BOOL LoadCharDetFromResource (HINSTANCE hInst, int nResID, int nType)
{
LOAD_INFO LoadInfo;
if (!DoLoadResource (&LoadInfo, hInst, nResID, nType))
{
return FALSE;
}
return CharDetLoadFromPointer (LoadInfo.pbMapping);
}
BOOL CharDetUnloadFile(LOAD_INFO *pInfo)
{
return DoCloseFile(pInfo);
}
int *ApplyFuguInteger(FUGU_INTEGER_WEIGHTS *pFugu, int aiInput[FUGU_INPUT_WIDTH][FUGU_INPUT_HEIGHT]);
float FuguSegScore(int cStrokes, STROKE *pStrokes, LOCRUN_INFO *pLocRunInfo)
{
GLYPH *pGlyph = GlyphFromStrokes(cStrokes, pStrokes);
int i;
int aiInput[FUGU_INPUT_WIDTH][FUGU_INPUT_HEIGHT];
int *piOutput = NULL;
float flOutput = 0;
if (cStrokes >= 1 && cStrokes <= g_cSpaces)
{
// First convert the ink to 29x29 input region
if (!FuguRender(pGlyph, NULL, aiInput))
{
return -1;
}
// Apply the recognizer
piOutput = ApplyFuguInteger(g_aCharDetNet + cStrokes - 1, aiInput);
if (piOutput == NULL)
{
return -1;
}
for (i = 0; i < g_aCharDetNet[cStrokes - 1].pHeader->arch.nOutputs; i++)
{
wchar_t wch = g_aCharDetNet[cStrokes - 1].pfdchMapping[i];
// I'm assuming every space will have "not a char" samples. Note that
// there are two possible mappings for "not a char", the old one L'0'
// and the new one which is simply 0.
if (wch == 0 || wch == L'0')
{
int cRight = FUGU_ACTIVATION_SCALE - piOutput[i];
if (cRight == 0)
{
cRight = 1;
}
flOutput = (float) cRight / (float) FUGU_ACTIVATION_SCALE;
}
}
}
DestroyFramesGLYPH(pGlyph);
DestroyGLYPH(pGlyph);
ExternFree(piOutput);
return flOutput;
}