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.

290 lines
6.3 KiB

  1. //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
  2. //
  3. // Copyright (c) 2001 Microsoft Corporation. All rights reserved.
  4. //
  5. // Module:
  6. // volcano/dll/segmnet.c
  7. //
  8. // Description:
  9. // Functions to implement the functionality of the segmentation Neural net that
  10. // modifies the lattice structure to correct segmentation errors.
  11. //
  12. // Author:
  13. // ahmadab 11/05/01
  14. //
  15. //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
  16. #include "common.h"
  17. #include "volcanop.h"
  18. #include "lattice.h"
  19. #include "runnet.h"
  20. #include "brknet.h"
  21. #include "segm.h"
  22. #include "nnet.h"
  23. // the size and structure representing the segmentations net used in Free mode
  24. static int s_aiSegmNetSize[MAX_SEGMENTATIONS + 1];
  25. static LOCAL_NET s_aSegmNet[MAX_SEGMENTATIONS + 1];
  26. // validates the header of the brknet
  27. int CheckSegmNetHeader (void *pData)
  28. {
  29. NNET_HEADER *pHeader = (NNET_HEADER *)pData;
  30. // wrong magic number
  31. ASSERT (pHeader->dwFileType == SEGMNET_FILE_TYPE);
  32. if (pHeader->dwFileType != SEGMNET_FILE_TYPE)
  33. {
  34. return FALSE;
  35. }
  36. // check version
  37. ASSERT(pHeader->iFileVer >= SEGMNET_OLD_FILE_VERSION);
  38. ASSERT(pHeader->iMinCodeVer <= SEGMNET_CUR_FILE_VERSION);
  39. ASSERT ( !memcmp ( pHeader->adwSignature,
  40. g_locRunInfo.adwSignature,
  41. sizeof (pHeader->adwSignature)
  42. )
  43. );
  44. if ( pHeader->iFileVer >= SEGMNET_OLD_FILE_VERSION &&
  45. pHeader->iMinCodeVer <= SEGMNET_CUR_FILE_VERSION &&
  46. !memcmp ( pHeader->adwSignature,
  47. g_locRunInfo.adwSignature,
  48. sizeof (pHeader->adwSignature)
  49. )
  50. )
  51. {
  52. return pHeader->cSpace;
  53. }
  54. else
  55. {
  56. return 0;
  57. }
  58. }
  59. // does the necessary preparations for a net to be used later
  60. static BOOL PrepareSegmNet(BYTE *pData)
  61. {
  62. int iSpc, cSpc, iSpaceID;
  63. NNET_SPACE_HEADER *pSpaceHeader;
  64. BYTE *pPtr, *pNetData;
  65. if (!pData)
  66. {
  67. return FALSE;
  68. }
  69. // init all nets data
  70. memset (s_aiSegmNetSize, 0, sizeof (s_aiSegmNetSize));
  71. memset (s_aSegmNet, 0, sizeof (s_aSegmNet));
  72. // check the header info
  73. cSpc = CheckSegmNetHeader (pData);
  74. if (cSpc <= 0)
  75. {
  76. return FALSE;
  77. }
  78. pPtr = pData + sizeof (NNET_HEADER);
  79. for (iSpc = 0; iSpc < cSpc; iSpc++)
  80. {
  81. // point to the one and only space that we have
  82. pSpaceHeader = (NNET_SPACE_HEADER *)pPtr;
  83. pPtr += sizeof (NNET_SPACE_HEADER);
  84. // point to the actual data
  85. pNetData = pData + pSpaceHeader->iDataOffset;
  86. iSpaceID = pSpaceHeader->iSpace;
  87. if (iSpaceID < 2 || iSpaceID > MAX_SEGMENTATIONS)
  88. {
  89. ASSERT (iSpaceID >= 2 && iSpaceID <= MAX_SEGMENTATIONS);
  90. return FALSE;
  91. }
  92. // restore the connections
  93. if (!restoreLocalConnectNet(pNetData, 0, s_aSegmNet + iSpaceID))
  94. {
  95. return FALSE;
  96. }
  97. // compute the run time memory requirements of the net
  98. s_aiSegmNetSize[iSpaceID] = getRunTimeNetMemoryRequirements(pNetData);
  99. if (s_aiSegmNetSize[iSpaceID] <= 0)
  100. {
  101. return FALSE;
  102. }
  103. }
  104. return TRUE;
  105. }
  106. // load the brk net from resources
  107. BOOL LoadSegmNetFromFile(wchar_t *pwszRecogDir, LOAD_INFO *pLoadInfo)
  108. {
  109. BYTE *pData;
  110. wchar_t awszFileName[MAX_PATH];
  111. wsprintf (awszFileName, L"%s\\segmnet.bin", pwszRecogDir);
  112. // memory map the file
  113. pData = DoOpenFile (pLoadInfo, awszFileName);
  114. if (!pData)
  115. {
  116. return FALSE;
  117. }
  118. // prepare Brk net
  119. if (!PrepareSegmNet(pData))
  120. {
  121. return FALSE;
  122. }
  123. return TRUE;
  124. }
  125. // load the brk net from resources
  126. BOOL LoadSegmNetFromResource (HINSTANCE hInst, int nResID, int nType)
  127. {
  128. BYTE *pData;
  129. LOAD_INFO LoadInfo;
  130. // init the size to zero, in case we fail
  131. pData = DoLoadResource (&LoadInfo, hInst, nResID, nType);
  132. if (!pData)
  133. {
  134. return FALSE;
  135. }
  136. // prepare Brk net
  137. if (!PrepareSegmNet(pData))
  138. {
  139. return FALSE;
  140. }
  141. return TRUE;
  142. }
  143. // update segmentations in the lattice by running a neural
  144. // net that picks a segmentation from a list within an inksegment
  145. BOOL UpdateSegmentations (LATTICE *pLat, int iStrtStrk, int iEndStrk)
  146. {
  147. int iNet,
  148. iSeg,
  149. jSeg,
  150. cStrk,
  151. cFeat,
  152. iWinner,
  153. cOut,
  154. iWord,
  155. iStrk,
  156. iAlt;
  157. BOOL bRet = FALSE,
  158. b;
  159. RREAL *pNetBuffer, *pNetOut;
  160. INK_SEGMENT InkSegment;
  161. // Check to see if we loaded the segmentation nets.
  162. // If not just exit
  163. if (s_aiSegmNetSize[2] <= 0)
  164. {
  165. return TRUE;
  166. }
  167. // create the range
  168. memset (&InkSegment, 0, sizeof (INK_SEGMENT));
  169. InkSegment.StrokeRange.iStartStrk = iStrtStrk;
  170. InkSegment.StrokeRange.iEndStrk = iEndStrk;
  171. // alloc memory for the back path
  172. cStrk = iEndStrk - iStrtStrk + 1;
  173. // harvest the segmentations that made it to the final stroke in the ink segment
  174. b = EnumerateInkSegmentations (pLat, &InkSegment);
  175. if (!b || InkSegment.cSegm < 1)
  176. {
  177. goto exit;
  178. }
  179. // if the number of segmentations is greater than max_seg, or less than two
  180. // then there is nothing for us to do
  181. if (InkSegment.cSegm < 2 || InkSegment.cSegm > MAX_SEGMENTATIONS)
  182. {
  183. iWinner = 0;
  184. }
  185. else
  186. {
  187. // sort segmentations by char count
  188. for(iSeg = 0; iSeg < (InkSegment.cSegm - 1); iSeg++)
  189. {
  190. ELEMLIST *pSeg;
  191. for (jSeg = iSeg + 1; jSeg < InkSegment.cSegm; jSeg++)
  192. {
  193. if (InkSegment.ppSegm[iSeg]->cElem > InkSegment.ppSegm[jSeg]->cElem)
  194. {
  195. pSeg = InkSegment.ppSegm[iSeg];
  196. InkSegment.ppSegm[iSeg] = InkSegment.ppSegm[jSeg];
  197. InkSegment.ppSegm[jSeg] = pSeg;
  198. }
  199. }
  200. }
  201. // run the appropriate segmentation net
  202. iNet = InkSegment.cSegm;
  203. pNetBuffer = (RREAL *) ExternAlloc (s_aiSegmNetSize[iNet] * sizeof (*pNetBuffer));
  204. if (!pNetBuffer)
  205. {
  206. goto exit;
  207. }
  208. // featurize this inksegment
  209. cFeat = FeaturizeInkSegment (pLat, &InkSegment, (int *)pNetBuffer);
  210. // run the net
  211. pNetOut = runLocalConnectNet (&s_aSegmNet[iNet], pNetBuffer, &iWinner, &cOut);
  212. ASSERT (cOut == InkSegment.cSegm);
  213. if (!pNetOut)
  214. {
  215. goto exit;
  216. }
  217. ExternFree (pNetBuffer);
  218. }
  219. // reset the current path in the specified stroke range
  220. for (iStrk = iStrtStrk; iStrk <= iEndStrk; iStrk++)
  221. {
  222. for (iAlt = 0; iAlt < pLat->pAltList[iStrk].nUsed; iAlt++)
  223. {
  224. pLat->pAltList[iStrk].alts[iAlt].fCurrentPath = FALSE;
  225. }
  226. }
  227. // now mark the characters proposed by the winning segmentation as part
  228. // of the best path
  229. for (iWord = 0; iWord < InkSegment.ppSegm[iWinner]->cElem; iWord++)
  230. {
  231. iStrk = InkSegment.ppSegm[iWinner]->pElem[iWord].iStroke;
  232. iAlt = InkSegment.ppSegm[iWinner]->pElem[iWord].iAlt;
  233. pLat->pAltList[iStrk].alts[iAlt].fCurrentPath = TRUE;
  234. }
  235. bRet = TRUE;
  236. exit:
  237. FreeInkSegment (&InkSegment);
  238. return bRet;
  239. }