|
|
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//
// Copyright (c) 2001 Microsoft Corporation. All rights reserved.
//
// Module:
// fugu.h
//
// Description:
// Declarations for the Fugu recognizer
//
// Author:
// hrowley
//
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
#pragma once
#include <limits.h>
#include "common.h"
// How many strokes Fugu processes
#define FUGU_MIN_STROKES 1
#define FUGU_MAX_STROKES 2
// How wide the pen is when rendering the characters to a bitmap
#define FUGU_PEN_WIDTH 5
// Dimensions of the input
#define FUGU_INPUT_WIDTH 29
#define FUGU_INPUT_HEIGHT 29
// Dimensions of the first layer of convolution kernels
#define FUGU_KERNEL_WIDTH1 5
#define FUGU_KERNEL_HEIGHT1 5
#define FUGU_KERNELS1 5
#define FUGU_KERNEL_SUBSAMPLE1 2
// Dimensions of the image after the first convolutional layer
#define FUGU_HIDDEN_WIDTH1 13
#define FUGU_HIDDEN_HEIGHT1 13
// Dimensions of the second layer of convolution kernels
#define FUGU_KERNEL_WIDTH2 5
#define FUGU_KERNEL_HEIGHT2 5
#define FUGU_KERNELS2 50
#define FUGU_KERNEL_SUBSAMPLE2 2
// Dimensions of the image after the second convolutional layer
#define FUGU_HIDDEN_WIDTH2 5
#define FUGU_HIDDEN_HEIGHT2 5
// For the fixed point math used at runtime, this specifies how much
// the activation values are shifted to the left.
#define FUGU_ACTIVATION_SHIFT 11
// Similarly, this is the multiplicative factor
#define FUGU_ACTIVATION_SCALE (1 << FUGU_ACTIVATION_SHIFT)
// Given the scaling of the activations above, this is the largest number
// which can be multiplied by an activation (between -1 and 1) and still
// have the result fit in a 32 bit signed integer.
#define FUGU_WEIGHT_SCALE (INT_MAX >> FUGU_ACTIVATION_SHIFT)
// The structure is used to specify the architecture of the Fugu network.
// Currently it only has the number of fully connected hidden and output
// nodes, but it may eventually be generalized.
typedef struct FUGU_ARCHITECTURE_HEADER { INT nHiddens; // Number of hidden units
INT nOutputs; // Number of output units
} FUGU_ARCHITECTURE_HEADER;
// The integer version of the fugu database requires some extra fields.
typedef struct FUGU_INTEGER_WEIGHTS_HEADER { FUGU_ARCHITECTURE_HEADER arch; // Architecture
INT iScale; // Scale factor applied to weights to make them be integers
INT aiWeightLookup[256]; // Lookup table to map bytes to weights
} FUGU_INTEGER_WEIGHTS_HEADER;
// This structure represents the fugu database
typedef struct FUGU_INTEGER_WEIGHTS { FUGU_INTEGER_WEIGHTS_HEADER *pHeader; // Pointer to the above header
WCHAR *pfdchMapping; // Pointer to the mapping from outputs to code points
BYTE *pbWeights; // Pointer to the weights
} FUGU_INTEGER_WEIGHTS;
// This structure is used to represent a fugu databased mapped from a file or resource.
typedef struct FUGU_LOAD_INFO { FUGU_INTEGER_WEIGHTS fugu; LOAD_INFO info; } FUGU_LOAD_INFO;
// Magic key the identifies the fugu NN bin file
#define FUGU_FILE_TYPE 0xF040F040
// Version information for file.
#define FUGU_MIN_FILE_VERSION 0 // First version of code that can read this file
#define FUGU_OLD_FILE_VERSION 0 // Oldest file version this code can read.
#define FUGU_CUR_FILE_VERSION 0 // Current version of code.
// Magic key the identifies the fugu NN bin file
#define CHARDET_FILE_TYPE 0xC3A8DE7C
// Version information for file.
#define CHARDET_MIN_FILE_VERSION 0 // First version of code that can read this file
#define CHARDET_OLD_FILE_VERSION 0 // Oldest file version this code can read.
#define CHARDET_CUR_FILE_VERSION 0 // Current version of code.
///////////////////////////////////////
//
// FuguNumberWeights
//
// Calculate the number of weights in a Fugu net given its architecture
//
// Parameters:
// pArch: [in] Pointer to the architecture description header
//
// Return values:
// Number of weights in the Fugu network
//
//////////////////////////////////////
int FuguNumberWeights(FUGU_ARCHITECTURE_HEADER *pArch);
///////////////////////////////////////
//
// FuguRender
//
// Renders a glyph to an image, each pixel has a value from 0 to FUGU_ACTIVATION_SCALE
//
// Parameters:
// pGlyph: [in] Pointer to the ink to render
// pGuide: [in] Guide to scale ink to, or NULL to use the ink bounds
// aiInput: [out] Array that will be used as input to Fugu
//
// Return values:
// TRUE: Finished without errors
// FALSE: An error occured
//
//////////////////////////////////////
BOOL FuguRender(GLYPH *pGlyph, RECT *pGuide, int aiInput[FUGU_INPUT_WIDTH][FUGU_INPUT_HEIGHT]);
///////////////////////////////////////
//
// ApplyFuguInteger
//
// Apply the integer version of the Fugu network to an input image (fixed point format),
// and return an array of outputs (also in fixed point). Return NULL if there is an
// error in allocating memory for the output.
//
// Parameters:
// pFugu: [in] Pointer to the fugu database to use
// aiInput: [in] Input image to process, in fixed point format
//
// Return values:
// An array of output activations in fixed point format, or NULL on error
//
//////////////////////////////////////
int *ApplyFuguInteger(FUGU_INTEGER_WEIGHTS *pFugu, int aiInput[FUGU_INPUT_WIDTH][FUGU_INPUT_HEIGHT]);
///////////////////////////////////////
//
// FuguLoadPointer
//
// Set up the Fugu database using a pointer to the data itself
//
// Parameters:
// pInfo: [in] Structure with mapping information.
// [out] Returns with the pointers to the fugu database set
// pLocRunInfo: [in] Locale database to check header on file
// iSize: [in] Size of database in bytes
//
// Return values:
// TRUE: Finished without errors
// FALSE: An error occured
//
//////////////////////////////////////
BOOL FuguLoadPointer(FUGU_LOAD_INFO *pInfo, LOCRUN_INFO *pLocRunInfo, int iSize);
///////////////////////////////////////
//
// FuguLoadRes
//
// Load an integer Fugu database from a resource
//
// Parameters:
// pInfo: [out] Structure where information for unloading is stored
// hInst: [in] Handle to the DLL containing the recognizer
// iResNumber: [in] Number of the resource (ex RESID_FUGU)
// iResType: [in] Number of the recognizer (ex VOLCANO_RES)
// pLocRunInfo: [in] Locale database to check header on file
//
// Return values:
// TRUE: Finished without errors
// FALSE: An error occured
//
//////////////////////////////////////
BOOL FuguLoadRes(FUGU_LOAD_INFO *pFugu, HINSTANCE hInst, int iResNumber, int iResType, LOCRUN_INFO *pLocRunInfo);
///////////////////////////////////////
//
// FuguLoadFile
//
// Load an integer Fugu database from a file
//
// Parameters:
// pInfo: [out] Structure where information for unloading is stored
// wszPath: [in] Path to load the database from
// pLocRunInfo: [in] Locale database to check header on file
//
// Return values:
// TRUE: Finished without errors
// FALSE: An error occured
//
//////////////////////////////////////
BOOL FuguLoadFile(FUGU_LOAD_INFO *pInfo, wchar_t *wszPath, LOCRUN_INFO *pLocRunInfo);
///////////////////////////////////////
//
// FuguUnLoadFile
//
// Unload a Fugu database loaded from a file
//
// Parameters:
// pInfo: [in] Load information for unloading
//
// Return values:
// TRUE: Finished without errors
// FALSE: An error occured
//
//////////////////////////////////////
BOOL FuguUnLoadFile(FUGU_LOAD_INFO *pInfo);
///////////////////////////////////////
//
// FuguMatch
//
// Invoke Fugu on a character
//
// Parameters:
// pFugu: [in] Fugu database to use
// pAltList: [out] Alt list
// cAlt: [in] The maximum number of alternates to return
// pGlyph: [in] The ink to recognize
// pGuide: [in] Guide to scale ink to, or NULL to use the ink bounds
// pCharSet: [in] Filter for the characters to be returned
// pLocRunInfo: [in] Pointer to the locale database
//
// Return values:
// Returned the number of items in the alt list, or -1 if there is an error
//
//////////////////////////////////////
int FuguMatch(FUGU_INTEGER_WEIGHTS *pFugu, // Fugu database
ALT_LIST *pAltList, // Alt list where the results are returned
int cAlt, // Maximum number of results requested
GLYPH *pGlyph, // Pointer to the strokes
RECT *pGuide, // Guide to scale ink to
CHARSET *pCharSet, // Filters to apply to the results
LOCRUN_INFO *pLocRunInfo); // Locale database
///////////////////////////////////////
//
// FuguMatchRescore
//
// Invoke Fugu on a character. Returns the top 1 result, and
// also rewrites the scores for the topN alternates returned by
// another recognizer (say Otter).
//
// Parameters:
// pFugu: [in] Fugu database to use
// pwchTop1: [out] Top one result
// pflTop1: [out] Top one score
// pAltList: [in/out] Alt list to rewrite the scores of
// cAlt: [in] The maximum number of alternates to return
// pGlyph: [in] The ink to recognize
// pGuide: [in] Guide to scale ink to, or NULL to use the ink bounds
// pCharSet: [in] Filter for the characters to be returned
// pLocRunInfo: [in] Pointer to the locale database
//
// Return values:
// Returned the number of items in the alt list, or -1 if there is an error
//
//////////////////////////////////////
int FuguMatchRescore( FUGU_INTEGER_WEIGHTS *pFugu, // Fugu recognizer
wchar_t *pwchTop1, // Top one result
float *pflTop1, // Top one score
ALT_LIST *pAltList, // Alt list where the results are returned
int cAlt, // Maximum number of results requested
GLYPH *pGlyph, // Pointer to the strokes
RECT *pGuide, // Guide to scale ink to
CHARSET *pCharSet, // Filters to apply to the results
LOCRUN_INFO *pLocRunInfo); // Locale database
// The following declarations are used at training time
#ifndef HWX_PRODUCT
// An entry in the index file used during training
typedef struct FUGU_INDEX { SHORT fdch; // Folded dense code
USHORT usFile; // The file number which this sample is in
union { UINT uiOffset; // Offset of stroke data in file.
BYTE *pbData; // The offset gets converted to a pointer to the
// stroke data in the training program
}; } FUGU_INDEX;
// Data structure to access floating point weight database
typedef struct FUGU_FLOAT_WEIGHTS { FUGU_ARCHITECTURE_HEADER *pArch; // Pointer to the architecture description
WCHAR *pfdchMapping; // Pointer to the mapping from outputs to folded dense codes
FLOAT *pflWeights; // Pointer to the array of weights
} FUGU_FLOAT_WEIGHTS;
///////////////////////////////////////
//
// FuguForwardPassFloat
//
// Run a forward pass of the floating point network
//
// Parameters:
// pFugu: [in] Fugu network
// aflInput: [in] Input image to work from
//
// Return values:
// Array of output activations, or NULL if an error occurs
//
//////////////////////////////////////
float *FuguForwardPassFloat( FUGU_FLOAT_WEIGHTS *pFugu, float aflInput[FUGU_INPUT_WIDTH][FUGU_INPUT_HEIGHT]);
///////////////////////////////////////
//
// FuguForwardBackwardFloat
//
// Run a training pass of the floating point network
//
// Parameters:
// pFugu: [in/out] Fugu network, which is updated for this sample
// aflInput: [in] Input image to train on
// iDesiredOutput: [in] The training output
// pflPrevUpdate: [in] Pointer to an array of previous weight updates
// for momentum, or NULL if there was no previous update.
// flRate: [in] Learning rate
// flMomentum: [in] Momentum
//
// Return values:
// Returns NULL if there was an error.
// Otherwise, if pflPrevUpdate was non-NULL, it is returned with the
// updates for this sample. If
// pflPrevUpdate was NULL, an array of updates is allocated and
// returned, and it should be passed in on the next call.
//
//////////////////////////////////////
float *FuguForwardBackwardFloat( FUGU_FLOAT_WEIGHTS *pFugu, float aflInput[FUGU_INPUT_WIDTH][FUGU_INPUT_HEIGHT], int iDesiredOutput, float *pflPrevUpdate, float flRate, float flMomentum);
///////////////////////////////////////
//
// FuguSaveIntegerWeights
//
// Write out an integer weights database
//
// Parameters:
// wszFileName: [in] File name to write to
// pFugu: [in] Pointer to Fugu data structure which is written
//
// Return values:
// TRUE: Finished without errors
// FALSE: An error occured
//
//////////////////////////////////////
BOOL FuguSaveIntegerWeights(wchar_t *wszFileName, FUGU_INTEGER_WEIGHTS *pFugu);
///////////////////////////////////////
//
// FuguSaveFloatWeights
//
// Write out a floating point weights database
//
// Parameters:
// wszFileName: [in] File name to write to
// pFugu: [in] Pointer to Fugu data structure which is written
//
// Return values:
// TRUE: Finished without errors
// FALSE: An error occured
//
//////////////////////////////////////
BOOL FuguSaveFloatWeights(wchar_t *wszFileName, FUGU_FLOAT_WEIGHTS *pFugu);
///////////////////////////////////////
//
// FuguLoadFloatWeights
//
// Read in a floating point weights database
//
// Parameters:
// wszFileName: [in] File name to read from
// pFugu: [in] Pointer to structure which gets filled in
//
// Return values:
// TRUE: Finished without errors
// FALSE: An error occured
//
//////////////////////////////////////
BOOL FuguLoadFloatWeights(wchar_t *wszFileName, FUGU_FLOAT_WEIGHTS *pFugu);
///////////////////////////////////////
//
// FuguSaveBitmap
//
// Write out an image to a .bmp file, for debugging
//
// Parameters:
// wszFileName: [in] File to write to
// pBitmap: [in] Pointer to the bitmap header structure
// pvBitBuf: [in] Pointer to the actual bits
//
// Return values:
//
//////////////////////////////////////
void FuguSaveBitmap(wchar_t *wszFileName, BITMAPINFOHEADER *pBitmap, void *pvBitBuf);
///////////////////////////////////////
//
// FuguSaveNetworkInput
//
// Write out the network's input image to a .pgm file, for debugging
//
// Parameters:
// wszFileName: [in] File to write to
// aiInput: [in] Image to write out, in fixed point format
//
// Return values:
//
//////////////////////////////////////
void FuguSaveNetworkInput(wchar_t *wszFileName, int aiInput[FUGU_INPUT_WIDTH][FUGU_INPUT_HEIGHT]);
///////////////////////////////////////
//
// FuguScaleGlyph
//
// Scales the coordinate values in the glyph to fit in a 256x256 range.
//
// Parameters:
// pGlyph: [in] Ink to be scaled
// [out] Scaled version of Ink
// pGuide: [in] Guide to scale ink to, or NULL to use the ink bounds
//
// Return values:
//
//////////////////////////////////////
void FuguScaleGlyph(GLYPH *pGlyph, RECT *pGuide);
///////////////////////////////////////
//
// FuguRenderNoScale
//
// Renders a glyph to an image, each pixel has a value from 0 to FUGU_ACTIVATION_SCALE.
// Unlike FuguRender, this function does not scale the ink to the image, but rather
// assumes the ink is already in scaled form as produced by FuguScaleGlyph().
//
// Parameters:
// pGlyph: [in] Pointer to the ink to render
// aiInput: [out] Array that will be used as input to Fugu
//
// Return values:
// TRUE: Finished without errors
// FALSE: An error occured
//
//////////////////////////////////////
BOOL FuguRenderNoScale(GLYPH *pGlyph, int aiInput[FUGU_INPUT_WIDTH][FUGU_INPUT_HEIGHT]);
// This was the structure used to read the weights from Dave's trainer
/*
typedef struct tagFuguFloatWeights { float _weights1[FuguKernels1][FuguKernelWidth1][FuguKernelHeight1]; float _tweights1[FuguKernels1]; float _weights2[FuguKernels2][FuguKernels1][FuguKernelWidth2][FuguKernelHeight2]; float _tweights2[FuguKernels2]; float _weights_fc[200][FuguKernels2][FuguHiddenWidth2][FuguHiddenHeight2]; float _tweights_fc[200]; float _weights_out[462][200]; float _tweights_out[462]; wchar_t mapping[462]; } FuguFloatWeights; */
#endif // !defined(HWX_PRODUCT)
|