The developed software name is HWRAnuj. This software is developed by Anuj Sharma to recognize handwriting while writing on digital devices. The development of this software happened subject to research work done in this area by author. An online handwriting recognition software mainly include components as data collection, preprocessing, feature extraction, segmentation, recognition and post-processing. The developed software HWRAnuj includes all these components. This software has been developed using VC++.Net and XML technologies. The CHWRAnujView is the main class that include necessary code to display GUI and start the procedure of calling handwriting recognition components mentioned above. These components are referred as modules too. The data collection module store handwritten strokes to respective XML format and its necessary code included in CHWRAnujView class where pen up, down and move methods are used. The preprocessing module include code for size normalization, centering, interpolation of missing points, smoothing, slant correction of strokes and equidistancing of points. These features are in class CPreprocessing. The Feature extraction module includes extraction of low-level and high-level features from handwriting. Some of the low-level features are area, aspect ratio, linearity, curliness, slope etc. of a handwritten stroke and high-level features are loops, crossing, nature of stroke as headline or straight etc. These features are in class CFeature. The Segmentation, Recognition and Post-processing modules are coded in CHWRAnujView and CRecognitionDialog classes. The recognition module include recognition of words through Hidden Markov Model and Elastic matching techniques. The system work for English, Devanagiri and Gurmukhi handwriting. The user need to select the writing language option and recognition method before writing. The developed software while recognition of word has been shown in following screen shot.
The following codes presents the some of the classes definitions used to develop HWRAnuj. The classes CHWRAnujView, Cpreprocessing, CFeature and CRecognitionDialog are presented.
/*Some of the common Classes definitions of Handwriting recognition software (HWRAnuj), ask for details of inside code used in methods*/
/*Below classes for setting visual environment of HWRAnuj that include start of application and calling other classes methods*/
typedef struct{
double xMin, xMax, yMin, yMax;
int SR; ///Stroke Result
}CWordR;
class CHWRAnujView : public CScrollView
{
protected: // create from serialization only
// CHWRAnujView();
DECLARE_DYNCREATE(CHWRAnujView)
// Attributes
public:
CHWRAnujDoc* GetDocument();
CHWRAnujView();
CArray<CPointNormalized, const CPointNormalized&> m_Array;
CStdioFile m_RRLog;
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CHWRAnujView)
public:
virtual void OnDraw(CDC* pDC); // overridden to draw this view
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
virtual void OnInitialUpdate();
virtual void OnPrepareDC(CDC* pDC, CPrintInfo* pInfo = NULL);
protected:
virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
virtual void OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint);
//}}AFX_VIRTUAL
// Implementation
public:
void ResetScrollSizes();
virtual ~CHWRAnujView();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
CElement* CreateElement();
CElement* SelectElement(CPoint apoint);
void MoveElement(CClientDC& aDC, const CPoint& point);
CPoint m_FirstPoint;
CPoint m_SecondPoint;
CElement* m_pTempElement;
CElement* m_pSelected;
BOOL m_MoveMode;
CPoint m_CursorPos;
CPoint m_FirstPos;
int m_Scale, m_Result, m_I, m_CEdit_Line, m_Method, m_WordR, m_S12;
long int m_files, m_segments, m_chars, m_chars4;
unsigned long int m_CharID;
char m_CharIDStr[20]; CString m_Character, m_CharStr;
double m_HLMinX, m_HLMaxX, m_HLMinY, m_HLMaxY;
CList<CPoint, const CPoint&> m_PointListXY;
CArray<int, const int&> m_ResultArray;
CArray<CWordR, const CWordR&> m_WordResultArray;
CRecognitionDialog ObjRD; CPreprocessing ObjPP;
CString FileName, OFileName, FilePath, Data;
CStdioFile ObjF, ObjOF;
void GetArrayAfterPreprocessing(CPreprocessing&);
int GetFEResults(int);
void WordCalculations();
protected:
//{{AFX_MSG(CHWRAnujView)
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
afx_msg void OnCancelMode();
afx_msg void OnMove();
afx_msg void OnDelete();
afx_msg void OnRButtonUp(UINT nFlags, CPoint point);
afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
afx_msg void OnSendtoback();
afx_msg void OnViewScale();
afx_msg void OnAddFile();
afx_msg void OnBuildNormalize();
afx_msg void OnRecognition();
afx_msg void OnFileNew();
afx_msg void OnDot();
afx_msg void OnHMMStart();
afx_msg void OnElasticMatching();
afx_msg void OnUpdateElasticMatching(CCmdUI* pCmdUI);
afx_msg void OnHmm();
afx_msg void OnUpdateHmm(CCmdUI* pCmdUI);
afx_msg void OnSls();
afx_msg void OnUpdateSls(CCmdUI* pCmdUI);
afx_msg void OnRRLog();
afx_msg void OnWordr();
afx_msg void OnUpdateWordr(CCmdUI* pCmdUI);
afx_msg void OnWordRecognition();
afx_msg void OnAboveHLBindi();
afx_msg void OnAddFileConfirm();
afx_msg void OnCollectCancel();
afx_msg void OnFormSls();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
/*Below classes for Preprocessing module of HWRAnuj*/
class CPreprocessing : public CObject
{
public:
CPreprocessing();
virtual ~CPreprocessing();
int AddToPPList(CList<CPoint, const CPoint&>*);
double CalculateSlope(CPointNormalized&, CPointNormalized&);
double Distance(CPointNormalized&, CPointNormalized&);
double Round(double Value, int Precision);
void SizeCentering2();
CArray<CPointNormalized, const CPointNormalized&> m_PPArray;
public:
CFeature ObjFeature; double m_MinX, m_MaxX, m_MinY, m_MaxY;
protected:
char m_BufferX[20], m_BufferY[20];
int m_xNor, m_yNor, m_xTextLength, m_yTextLength, m_I, m_pointsBeforePP, m_pointsAfterPP;
double m_xFactor, m_yFactor, m_yxRatio;
double xMax, xMin, yMax, yMin, m_xL, m_yL, m_Factor;
double xLen, yLen;
CString m_FileName;
CArray<CPointNormalized, const CPointNormalized&> m_TempArray2;
CArray<CPointNormalized, const CPointNormalized&> m_TempArray;
CStdioFile m_PPTextFile;
protected:
void BSpline();
void BSplineFormula(CPointNormalized&, CPointNormalized&,
CPointNormalized&, CPointNormalized&);
void CalculateMaxMinText();
void Centering();
double ChainCodeMethod(int, int);
void CreateTextFile(CString);
void EquiStraightLines();
void EqualDistance(int, int);
void Equidistancing();
void EquiDistantPoints();
void EquiDistantPointsNotFixed();
void FilterClosePoints();
void FilterSamePoints();
double FindStraightLine(int, int, int);
void GuassianArray(double, double, double, double, double, int, int);
double GuassianFormulaX(double, int, int);
double GuassianFormulaY(double, int, int);
void GuassianSmoothing();
void Interpolation();
void NeighbourMean(int);
void NeighbouringPoints();
void NonDecimalPoints();
void OriginalTextFile();
void RoundPoints();
void RoundPointsZero();
void SizeCentering();
void SizeNormalization();
void SlantAdjustment(int, int);
void SlantCorrectionMethod();
void SlantCorrection();
void Smoothing();
void UpdateArray();
void UpdateSlant(int, int, double);
};
/*Below classes for Feature Extraction module of HWRAnuj*/
typedef struct{
int SN;
CPointNormalized TopP, BottomP, LeftP, RightP, StartP, EndP;
double Slope, Linearity, Curliness, ApsectRatio; ///L and CL are linearity and curliness
}CLowLevelF;
typedef struct{
int StrokeNumber, Loop, Crossing, HL, SL, Dot;
}CHighLevelF;
class CFeature : public CObject
{
public:
CArray<CLowLevelF, const CLowLevelF&> m_LowLevelFArray;
CArray<CHighLevelF, const CHighLevelF&> m_HighLevelFArray;
CHighLevelF H; CLowLevelF LL;
public:
CFeature();
virtual ~CFeature();
void ExtractFeatures(CArray<CPointNormalized, const CPointNormalized&>*);
protected:
int m_I, IC;
char Buffer[20]; ////important to define as char array as required for _gcvt function
CArray<CPointNormalized, const CPointNormalized&> m_PointArray;
// CArray<CLowLevelF, const CLowLevelF&> m_LowLevelFArray;
// CArray<CHighLevelF, const CHighLevelF&> m_HighLevelFArray;
CStdioFile m_FeatureFileText;
protected:
void AddToFeatureFile();
double AspectRatio(CPointNormalized&, CPointNormalized&, CPointNormalized&, CPointNormalized&);
CPointNormalized BottomP(int, int);
double BP();
int Crossing(int, int);
double Curliness(int, int, CPointNormalized&, CPointNormalized&, CPointNormalized&, CPointNormalized&);
int Dot(int, int, int, int, int);
void FilterRepeatPoints();
int HeadLine(int, int);
void HighLevelFeatures();
CPointNormalized LeftP(int, int);
double Linearity(int, int, CPointNormalized&, CPointNormalized&);
int Loop(int, int);
int LoopCheck(int, int, int);
int LoopExists(CPointNormalized&, CPointNormalized&, CPointNormalized&,
CPointNormalized&, CPointNormalized&);
void LowLevelFeatures();
CPointNormalized RightP(int, int);
double PerpendicularDistance(double, double, double, double);
int StraightLine(int, int, int);
CPointNormalized TopP(int, int);
double TP();
};
/*Below classes and structures used in Recognition module of HWRAnuj*/
typedef struct
{
int SN;
double avg;
}CStrokeResult;
typedef struct
{
CPointNormalized P;
double Angle;
}CTemplate;
typedef struct
{
long int Id;
double Prob;
}CHMM8;
typedef struct
{
int StrokeID, FromState, ToState, FromDir, ToDir;
double Prob;
}CHMMAK;
typedef struct
{
int StrokeID, State, Dir;
double Prob;
}CHMMBPIK;
/////////////////////////////////////////////////////////////////////////////
// CRecognitionDialog dialog
class CRecognitionDialog : public CDialog
{
// Construction
public:
CRecognitionDialog(CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(CRecognitionDialog)
enum { IDD = IDD_RECOGNITION_DIALOG };
// NOTE: the ClassWizard will add data members here
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CRecognitionDialog)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
public:
double Angle(CPointNormalized, CPointNormalized);
void AddToDB();
void IncreaseSamples();
void InitializeRecognitionArray(CArray<CPointNormalized, const CPointNormalized&>*);
CString GetCharacterName(unsigned long int); //To get chracter
int GetStrokeNumberXML(); //Elastic mathing method
int GetStrokeIDEMP(); //SLS method
int GetStrokeHMM8(); //HMM8 method
int GetStrokeHMMK(); //HMMK method, k=13
int GetStrokeIDFV(CStdioFile*); //Forward Variable HMM method
int GetStrokeIDSSXML();
int GetStrokeIDHMM(); //HMM method
int GetStrokeIDTryHMM(); //Old Try HMM based method
int GetStrokeIDBW(); //Bit Wise method
int GetStrokeIDStat(); //Bit Wise method
///below functions for ACCESS
int GetStrokeNumber();
void ShowCharacter(CString);
virtual void OnOK();
char GetRecognizedCharacter(CArray<CPointNormalized, const CPointNormalized&>*);
void GetRecognizedCharacterSLS(CString, CString);
void GetRecognizedCharacterTM(CString, CString);
//for HMM8
void FormA8DB();
void FormB8DB();
void FormPI8DB();
void FormHMM8DB();
//for HMMK
void FormAKDB();
void FormBKDB();
void FormPIKDB();
void FormHMMKDB();
//for HMM-old
void FormAXMLDB();
void FormBXMLDB();
void FormHMMDB();
//for SLS
void FormLineDB();
//other
void FormHMMTrainingDB();
void FormHMMTrainingNumberDB();
void FormSSXMLDB();
void FormStatDB();
void FormBWXMLDB();
void FormTryHMMDB();
void FormSLSDatabase(); //for english language
void GetHMMData();
// CString GetCharacterName(CString);
protected:
// Generated message map functions
//{{AFX_MSG(CRecognitionDialog)
virtual BOOL OnInitDialog();
afx_msg void OnRecognize();
// virtual void OnOK();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
public:
CArray<CPointNormalized, const CPointNormalized&> m_RArray;
CEdit* pEdit;
CFont* font;
CString m_RecognizedCharacterSymbol;
protected:
int m_RCount, m_Index;
double A[328][8], B[328][20], PI[328]; //984,24
// CString m_RecognizedCharacterSymbol;
CArray<CHMM8, const CHMM8&> m_A8, m_B8, m_PI8; //HMM8
CArray<CHMMAK, const CHMMAK&> m_AK; //HMMK
CArray<CHMMBPIK, const CHMMBPIK&> m_BK, m_PIK; //HMMK
CArray<CTemplate, const CTemplate&> m_TemplateArray;
CArray<CTemplate, const CTemplate&> m_TempArray;
CArray<CStrokeResult, const CStrokeResult&> m_ResultArray;
CArray<CString, const CString&> m_StringArray;
CStdioFile m_RecognitionFile;
CStdioFile m_TemplateXMLDB, m_DataFile, m_SLSDataFile;
CString FileName;
protected:
CString AddToHMMTrainingDB(CArray<CTemplate, const CTemplate&>*);
// double Angle(CPointNormalized, CPointNormalized);
void CheckPointExistence(int, CString, CString);
double Distance(CPointNormalized&, CPointNormalized&);
int FindCount(CRecordset&);
int FindStrokeNumber(int);
CPointNormalized FindThirdPoint(CPointNormalized, CPointNormalized, CPointNormalized);
char GetDirection(double);
char GetDirectionStat(double);
char GetDirectionNum8(double);
CString GetDirectionStraight(double);
CString GetDirectionAntiClockwise(double, double);
CString GetDirectionClockwise(double, double);
CString GetDirectionClockAntiClockwise(double, double);
CString GetDirectionNumber(CString);
CString GetMaxS(CString);
CString GetStrInputSS();
CString GetStrInputStatSS();
double PerpendicularDistance(double, double, double, double);
void SizeCentering2(CArray<CTemplate, const CTemplate&>*);
//for HMM8
void GetA8Data();
void GetB8Data();
void GetPI8Data();
CString GetIHSArray8(CArray<CTemplate, const CTemplate&>*);
//for HMMK
void GetAKData();
void GetBKData();
void GetPIKData();
CString GetIHSArrayK(CArray<CTemplate, const CTemplate&>*);
//for HMM-old
void GetAData();
void GetBData();
void GetPIData();
void GetIHSArray(int[], CString);
int WriteToAFile(CString, CString, CStdioFile*);
void WriteToBFile(CString, CString, CStdioFile*);
void WriteToPIFile(CString, CString, CStdioFile*);
void WriteToHMMFile(CString, CString, CStdioFile*);
};