iOS简单的手写汉字识别

简介

前一阵在班讯通上边加了一个小的功能:根据拼音提示写出汉字,提交之后软件会打出分数,其界面如下:

下面简单介绍一下第一个版本识别算法的实现:

记录汉字录入轨迹

iOS中UIView视图继承了UIResponder类,该类中的四个方法是我们需要调用的:

-(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;

// 采集点集- (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]]];}}

// 插入数据库- (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;}

对比用户输入数据和模板数据有了数据,剩下的就是利用数据库的select语句来对比了。但是在实际对比时候会发现~~根本没几个点能匹配的上,原因很简单:在第一步中,记录的是点的绝对坐标。比如我们写个“一”,录入模板的时候,记录的坐标集是{(50, 200), (100, 200), (150, 200), (200, 200), (250, 200)},用户输入的时候记录的是{(60, 220), (90, 220), (130, 220), (160, 220), (200, 220), (230, 220)}, 结果就是零匹配。另外一点很重要,就是屏幕的分辨率……鉴于这种情况, 将输入区域划分为50个格子,每经过一个格子,便将其记录下来作为相对坐标,这样上边的两条数据就成了{(10, 40), (20, 40 ), (30, 40), (40, 40), (50, 40)}和{(10, 40), (20, 40 ), (30, 40), (40, 40), (50, 40), (60, 40)}, 匹配程度就提高了(当然,,这只是举例数据,并不准确)。改为相对坐标存储之后,虽然匹配程度提高不少,但是当笔画上下或者左右位置偏差比较大的时候仍然识别不准确, 比如一个横的模板数据是{(10, 40), (20, 40 ), (30, 40), (40, 40), (50, 40)}, 用户输入的数据是{(10, 41), (20, 41 ), (30, 41), (40, 41), (50, 41)},这样在查询的时候就匹配不到。所以在查询的时候需要将用户输入的笔画做一个偏移,将{(10, 40), (20, 40 ), (30, 40), (40, 40), (50, 40)}和{(10, 41), (20, 41 ), (30, 41), (40, 41), (50, 41)}匹配起来。

// 取相对坐标- (void)turnToGrids {self.strokeCount = self.inputStrokes.count;// 格子宽度float gridWidth = kScreenWidth/10;for (int k=0; k<self.inputStrokes.count; k++) {// 存储一个笔画的所有点到一个数组NSMutableArray *strokPointGrids = [NSMutableArray 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];}}

// 最终的查询语句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.pointX) + 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];我只愿,在你的理想和希望里能为你增加一点鼓励,

iOS简单的手写汉字识别

相关文章:

你感兴趣的文章:

标签云: