1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - PRC -
3 File: prc_algo_light.c
4
5 Copyright 2003-2008 Nintendo. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Date:: 2008-09-18#$
14 $Rev: 8573 $
15 $Author: okubata_ryoma $
16 *---------------------------------------------------------------------------*/
17
18 #include <nitro.h>
19 #include <nitro/prc/algo_light.h>
20
21 /*===========================================================================*
22 Prototype Declarations
23 *===========================================================================*/
24
25 /*===========================================================================*
26 Variable Definitions
27 *===========================================================================*/
28
29 /*===========================================================================*
30 Functions
31 *===========================================================================*/
32
33 /*---------------------------------------------------------------------------*
34 Name: PRC_GetRecognitionBufferSizeEx_Light
35
36 Description: Calculates the work area size required for recognition algorithm.
37
38
39 Arguments: maxPointCount: Upper limit of number of input points (includes pen up marker)
40 maxStrokeCount: Upper limit of stroke count
41 protoDB: Sample DB
42 param: Parameters for recognition processing
43
44 Returns: The memory capacity required for the recognition algorithm.
45 *---------------------------------------------------------------------------*/
46 u32
PRC_GetRecognitionBufferSizeEx_Light(int maxPointCount,int maxStrokeCount,const PRCPrototypeDB_Light * protoDB,const PRCRecognizeParam_Light * param)47 PRC_GetRecognitionBufferSizeEx_Light(int maxPointCount,
48 int maxStrokeCount,
49 const PRCPrototypeDB_Light *protoDB,
50 const PRCRecognizeParam_Light *param)
51 {
52 (void)maxPointCount;
53 (void)maxStrokeCount;
54 (void)protoDB;
55 (void)param;
56
57 return 1; // Because OS_Alloc(0) causes an error
58 }
59
60 /*---------------------------------------------------------------------------*
61 Name: PRC_GetRecognizedEntriesEx_Light
62
63 Description: Compares and recognizes a specific kind entry and input pattern to return the top numRanking ranking of the result.
64
65
66 Arguments: resultEntries: Pointer to array that holds pointers to recognition results.
67 If less than the requested number could be recognized, fill in remainder with NULL.
68
69 resultScores: Pointer to recognition result score array
70 numRanking: Number of returns to result*
71 buffer: Pointer to memory region used by recognition algorithm
72 (Region size >= return value of PRC_GetRecognitionBufferSize)
73 input: Input pattern
74 protoDB: Sample DB
75 kindMask: Takes the logical AND of the 'kind' values for all the sample DB entries. Considered valid if it is non-zero.
76
77 param: Parameters for recognition processing
78
79 Returns: Number of patterns in the compared sample DBs.
80 *---------------------------------------------------------------------------*/
81 int
PRC_GetRecognizedEntriesEx_Light(PRCPrototypeEntry ** resultEntries,fx32 * resultScores,int numRanking,void * buffer,const PRCInputPattern_Light * input,const PRCPrototypeDB_Light * protoDB,u32 kindMask,const PRCRecognizeParam_Light * param)82 PRC_GetRecognizedEntriesEx_Light(PRCPrototypeEntry **resultEntries,
83 fx32 *resultScores,
84 int numRanking,
85 void *buffer,
86 const PRCInputPattern_Light *input,
87 const PRCPrototypeDB_Light *protoDB,
88 u32 kindMask, const PRCRecognizeParam_Light *param)
89 {
90 int i;
91 const PRCiPatternData_Common *inputData;
92 int numCompared;
93
94 (void)buffer;
95 (void)param;
96
97 SDK_ASSERT(resultEntries);
98 SDK_ASSERT(resultScores);
99 SDK_ASSERT(input);
100 SDK_ASSERT(protoDB);
101 SDK_ASSERT(numRanking > 0);
102
103 for (i = 0; i < numRanking; i++)
104 {
105 resultEntries[i] = NULL;
106 resultScores[i] = FX32_ONE * 32768;
107 }
108
109 inputData = &input->data;
110 numCompared = 0;
111
112 {
113 const PRCiPrototypeEntry_Common *proto;
114 int iPattern;
115 fx32 border;
116
117 border = FX32_ONE; // Cutoff level: If this value is set to FX32_ONE/2, then those with a score below 0.5 will not be evaluated at all.
118 border *= 32768; // Coefficient of the internal score
119
120 proto = protoDB->patterns;
121
122 for (iPattern = 0; iPattern < protoDB->patternCount; iPattern++, proto++)
123 {
124 const PRCiPatternData_Common *protoData;
125 int iStroke;
126 fx32 wholeScore;
127 fx32 patternBorder;
128
129 if (!proto->entry->enabled || !(proto->entry->kind & kindMask))
130 continue;
131
132 protoData = &proto->data;
133
134 if (inputData->strokeCount != protoData->strokeCount)
135 continue;
136
137 wholeScore = 0;
138
139 // Set as cutoff the value which returned the amount of correction
140 patternBorder = border;
141 if (proto->entry->correction != 0)
142 {
143 // For parts where [patternBorder *= 1 / (FX32_ONE - correction)] really must be done, cut corners with larger values by suitably approximating with straight lines
144 //
145 if (proto->entry->correction < -FX32_ONE)
146 {
147 patternBorder >>= 1; // Approximated by 1/2 or less
148 }
149 else if (proto->entry->correction < 0)
150 {
151 // -1 < correction < 0 is approximated by correction/2+1
152 patternBorder = FX_Mul(patternBorder, FX32_ONE + proto->entry->correction / 2);
153 }
154 else if (proto->entry->correction < FX32_ONE / 2)
155 {
156 // 0 < correction < 1/2 is approximated by correction*2+1
157 patternBorder = FX_Mul(patternBorder, FX32_ONE + proto->entry->correction * 2);
158 }
159 else
160 {
161 patternBorder = FX32_ONE * 32768;
162 } // Give up on the cutoff
163 }
164
165 for (iStroke = 0; iStroke < inputData->strokeCount; iStroke++)
166 {
167 int iProto, iInput;
168 int protoStrokeIndex, inputStrokeIndex;
169 int protoSize, inputSize;
170 const u16 *protoAngle;
171 const u16 *inputAngle;
172 const fx16 *protoRatio;
173 const fx16 *inputRatio;
174 fx16 protoNextRatio, inputNextRatio;
175 fx32 score;
176 fx32 localBorder;
177 fx16 strokeRatio;
178 int loopEnd;
179
180 score = 0;
181
182 protoStrokeIndex = protoData->strokes[iStroke];
183 inputStrokeIndex = inputData->strokes[iStroke];
184 protoSize = protoData->strokeSizes[iStroke];
185 inputSize = inputData->strokeSizes[iStroke];
186 protoAngle = &protoData->lineSegmentAngleArray[protoStrokeIndex];
187 inputAngle = &inputData->lineSegmentAngleArray[inputStrokeIndex];
188 protoRatio = &protoData->lineSegmentRatioToStrokeArray[protoStrokeIndex];
189 inputRatio = &inputData->lineSegmentRatioToStrokeArray[inputStrokeIndex];
190
191 strokeRatio = protoData->strokeRatios[iStroke]; // If here do inputData->, then the relative weight of the strokes of the input image takes on great importance
192
193 // Set the cutoff level
194 if (strokeRatio == FX32_ONE)
195 {
196 localBorder = patternBorder;
197 }
198 else if (strokeRatio >= FX32_ONE / 2)
199 {
200 localBorder = patternBorder * 2; // No problem with taking excess
201 }
202 else if (strokeRatio >= FX32_ONE / 3)
203 {
204 localBorder = patternBorder * 3; // No problem with taking excess
205 }
206 else
207 {
208 localBorder = FX32_ONE * 32768; // Doesn't consider the cutoff
209 }
210
211 SDK_ASSERT(protoSize >= 2);
212 SDK_ASSERT(inputSize >= 2);
213
214 iProto = iInput = 1;
215 protoNextRatio = protoRatio[iProto];
216 inputNextRatio = inputRatio[iInput];
217 loopEnd = protoSize + inputSize - 3;
218 for (i = 0; i < loopEnd; i++)
219 {
220 int diff;
221 SDK_ASSERT(iProto < protoSize);
222 SDK_ASSERT(iInput < inputSize);
223 diff = (s16)(protoAngle[iProto] - inputAngle[iInput]);
224 if (diff < 0)
225 {
226 diff = -diff;
227 }
228 if (protoNextRatio <= inputNextRatio)
229 {
230 score += protoNextRatio * diff;
231 iProto++;
232 inputNextRatio -= protoNextRatio;
233 protoNextRatio = protoRatio[iProto];
234 }
235 else
236 {
237 score += inputNextRatio * diff;
238 iInput++;
239 protoNextRatio -= inputNextRatio;
240 inputNextRatio = inputRatio[iInput];
241 }
242 // Cutoff check
243 if (score > localBorder)
244 {
245 // The likelihood of getting held up on the lowest-ranked candidate is gone now
246 wholeScore = FX32_ONE * 32768;
247 goto quit_compare;
248 }
249 }
250
251 wholeScore += FX_Mul(score, strokeRatio);
252 }
253
254 if (proto->entry->correction != 0)
255 {
256 wholeScore = FX_Mul(wholeScore, FX32_ONE - proto->entry->correction);
257 }
258
259 // wholeScore = FX_Mul(wholeScore, FX32_ONE - proto->entry->correction)
260 // + proto->entry->correction;
261
262 // Note that low scores are better at this stage
263 quit_compare:
264 numCompared++;
265 if (resultScores[numRanking - 1] > wholeScore)
266 {
267 resultScores[numRanking - 1] = wholeScore;
268 resultEntries[numRanking - 1] = (PRCPrototypeEntry *)proto->entry;
269 for (i = numRanking - 2; i >= 0; i--)
270 {
271 if (resultScores[i] > resultScores[i + 1])
272 {
273 fx32 tmpScore;
274 PRCPrototypeEntry *tmpEntry;
275 tmpScore = resultScores[i];
276 resultScores[i] = resultScores[i + 1];
277 resultScores[i + 1] = tmpScore;
278 tmpEntry = resultEntries[i];
279 resultEntries[i] = resultEntries[i + 1];
280 resultEntries[i + 1] = tmpEntry;
281 }
282 }
283 // Set the cutoff score
284 border = resultScores[numRanking - 1];
285 }
286 }
287 }
288 // Normalize the score
289 {
290 int iRank;
291 fx32 score;
292 for (iRank = 0; iRank < numRanking; iRank++)
293 {
294 if (resultEntries[iRank] == NULL)
295 break;
296
297 score = resultScores[iRank];
298 score = FX32_ONE - (score / 32768);
299 if (score < 0)
300 score = 0;
301 if (score >= FX32_ONE)
302 score = FX32_ONE;
303
304 resultScores[iRank] = score;
305 }
306 }
307
308 return numCompared;
309 }
310
311 /*===========================================================================*
312 Static Functions
313 *===========================================================================*/
314
315
316 /*---------------------------------------------------------------------------*
317 End of file
318 *---------------------------------------------------------------------------*/
319