Brief introduction
A burst in the top of the class to add a small function: According to phonetic prompts to write Chinese characters, after submission of the software will score, the interface is as follows:
The following is a brief introduction to the implementation of the first version recognition algorithm:
- Recording Chinese character entry trajectory
The UIView view in iOS inherits the Uiresponder class, and the four methods in that class are the one we need to call:
-(void) Touchesbegan: (Nsset *) touches withevent: (Uievent *) event;
-(void) touchesmoved: (Nsset *) touches withevent: (Uievent *) event;
-(void) touchesended: (Nsset *) touches withevent: (Uievent *) event;
-(void) touchescancelled: (Nsset *) touches withevent: (Uievent *) event;
- In the first three methods, we record the starting point, the process point, and the end point of a stroke, add the point to the array of savepoint, and in the touchesended method, add the array of savepoint to the array that holds the strokes. So, after writing a word, the array that holds the strokes is the set of points we want for the whole word.
- Save the point set in the Database Template table and use it as a template.
- After the template is complete, the set of points entered by the user is recorded and the data is recorded in the user table.
Acquisition point set-(void) Touchesbegan: (Nsset *) touches withevent: (uievent *) event{for (Uitouch *touch in touches) { Nsmutablearray *newstackofpoints = [Nsmutablearray array]; [Newstackofpoints addobject:[nsvalue Valuewithcgpoint:[touch locationinview:self]]; [Self.strokes addobject:newstackofpoints];} } -(void) touchesmoved: (Nsset *) touches withevent: (uievent *) event{for (Uitouch *touch in touches) { [[ Self.strokes Lastobject] Addobject:[nsvalue Valuewithcgpoint:[touch locationinview:self]]; }} -(void) touchesended: (Nsset *) touches withevent: (uievent *) event{for (uitouch* touch in touches) { [[ Self.strokes Lastobject] Addobject:[nsvalue Valuewithcgpoint:[touch locationinview:self]]; }}
Insert database-(int) Insertchar: (Charactermodel *) model {int Charid = 0; [Self.hanzidb executeupdate:@ "insert into characters (Chinese, pinyin, pointsstring) VALUES (?,?,?)", Model.chinese, Model.pinyin, model.pointsstring]; NSString *querystring = [NSString stringwithformat:@ "select id from characters where Chinese = '%@ '", Model.chinese]; fmresultset* set = [Self.hanzidb executequery:querystring]; if ([Set next]) {Charid = [set intforcolumn:@ "id"]; } for (int i=0; i<model.inputpointgrids.count; i++) {Nsarray *astroke = model.inputpointgrids[i]; For (Nsvalue *apointvalue in Astroke) {cgpoint apoint = [Apointvalue cgpointvalue]; [Self.hanzidb executeupdate:@ "INSERT into points (ID, pointx, pointy, Strokeid) VALUES (?,?,?,?)", [NSNumber Numberwithint:charid],[nsnumber numberwithint: (int) apoint.x],[nsnumber numberwithint: (int) aPoint.y], [NSNumber NUMBERWITHINT:I+1]]; }} return Charid;}
- Compare user input data and template data
-
-
-
Take relative coordinates-(void) turntogrids {self.strokecount = Self.inputStrokes.count; Lattice width float gridwidth = KSCREENWIDTH/10; for (int k=0; k<self.inputstrokes.count; k++) {//store all points of a stroke to an array nsmutablearray *strokpointgrids = [NSM Utablearray array]; Nsarray *inputstrokesarray = self.inputstrokes[k]; for (int l = 0; l<inputstrokesarray.count; l++) {nsvalue *value = inputstrokesarray[l]; if (L = = 0) {[self.strokestartpoints addobject:value]; } if (L = = self.inputstrokes.count-1) {[self.strokeendpoints addobject:value]; } cgpoint point = [value cgpointvalue]; Cgpoint Grid = Cgpointmake (Ceil (point.x/gridwidth), Ceil (Point.y/gridwidth)); BOOL shouldadd = NO; if (Strokpointgrids.count = = 0) {shouldadd = YES; } else {Nsvalue *lastvalue = Strokpointgrids.lastobject; CGPOint Lastgrid = [Lastvalue cgpointvalue]; if (lastgrid.x! = grid.x | | Lastgrid.y! = GRID.Y) {shouldadd = YES; }} if (Shouldadd) {[Strokpointgrids addobject:[nsvalue Valuewithcgpoint:grid]]; if (![ Self.pointsstring isequaltostring: @ ""] &&! [Self.pointsstring hassuffix:@ "*"]) {[self.pointsstring appendstring:[nsstring stringwithformat:@ "|]];} [Self.pointsstring appendstring:[nsstring stringwithformat:@ "%d,%d", (int) grid.x, (int) grid.y]]; }} if (k! = self.inputstrokes.count-1) {[Self.pointsstring appendstring:@ "*"]; } [Self.inputpointgrids Addobject:strokpointgrids]; }}
Final query statement nsstring *QUERYSTRING4 = [NSString stringwithformat:@ "select A.strokeid as strokeid,a.samecount as Samecount,a.ucount as ucount,a.pcount as Pcount from (select Strokeid, COUNT (*) as Samecount, (select COUNT (*) from input _points where id=p.id and strokeid=%d) as Ucount, (select COUNT (*) from points where id=p.id and Strokeid=p.strokeid) as Pcount from points p where exists (SELECT * from Input_points u where U.id=p.id and u.strokeid=%d and (ABS (U.pointx-p.poin TX) + ABS (U.pointy-p.pointy)) <2) and P.strokeid not in (%@) and p.id=%d Group by Strokeid) a ORDER by ABS (A.pcount- A.samecount) ASC ", J, J, Hasstrokeid, Model.charid];
At this point, the function module can be easily recognized from the phone screen written Chinese characters, but this is very chicken, because if the template entry and user input style is relatively large or user-written bias (lower, around the possibility), the recognition rate is straight down, so, we in the second version of the completely changed the recognition algorithm, Greatly improved the recognition rate.
For a second version of handwriting recognition, see the next blog post
Simple handwritten Chinese character recognition for iOS