字符匹配字符串
标题可能表达的不太准确,需求是这样的:我们对用户语音通过TensorFlowLite识别,识别结果是26字母中的字母,然后要得到语音句子中哪些单词说对了哪些说错了,比如句子是“I am a ball”识别结果是“i a m b l l”。这样的识别结果应该是I AM BALL是对的 A是错误的。
#pragma mark ==========AVAudioRecorderDelegate==========
- (void) audioRecorderDidFinishRecording:(AVAudioRecorder *)avrecorder successfully:(BOOL)flag{
NSLog(@"录音完毕。开始识别");
NSLog(@"当前句子%@",self.sentenceModel.sentence_en);
//去掉标点符号
NSString * res = [[TFLiteManager shareManager] recognizeAudioWithPath:[self getRecorderPath] text:self.sentenceModel.sentence_en];
NSLog(@"识别结果:%@",res);
[self setupRecognizeRes:res];
}
- (void)setupRecognizeRes:(NSString *)res{
self.recognizeCorrectCount = 0;
self.totalPhomeCount = 0;
[self.recognizeRes removeAllObjects];
//识别结果通过空格分割后的集合
self.recognizeRes = [NSMutableArray arrayWithArray:[res componentsSeparatedByString:@" "]];
//lowerString小写文本、为了查询字母在原文本中的位置
NSString * sentence_en = [self.sentenceModel.sentence_en mutableCopy];
self.upperString = [[NSMutableAttributedString alloc]initWithString:sentence_en];
self.lowerString = [[NSMutableAttributedString alloc]initWithString:[sentence_en lowercaseString]];
//目标文本
NSString * orgin_text = [self.sentenceModel.sentence_en mutableCopy];
//删除特殊字符便于后面处理
orgin_text = [orgin_text stringByReplacingOccurrencesOfString:@"\"" withString:@""];
orgin_text = [orgin_text stringByReplacingOccurrencesOfString:@"." withString:@""];
orgin_text = [orgin_text stringByReplacingOccurrencesOfString:@"," withString:@""];
orgin_text = [orgin_text stringByReplacingOccurrencesOfString:@"!" withString:@""];
orgin_text = [orgin_text stringByReplacingOccurrencesOfString:@"?" withString:@""];
//全部变小写
orgin_text = [orgin_text lowercaseString];
//先将目标文本根据空格分割
NSArray * originWords = [orgin_text componentsSeparatedByString:@" "];
self.totalPhomeCount = originWords.count;
for (NSString * sub in originWords) {
[self isCorrectSub:sub];
}
//识别结果处理完毕
[self updateDownbooks];
BOOL allRecorded = [self checkBookPagesisAllRecorded];
NSLog(@"是否全录音:%d",allRecorded);
if (allRecorded) {
NSLog(@"全录完,上传音频,获取最终得分");
self.bookModel.recorderIndex = [AppSingle sharedAppSingle].record_id;
self.bookModel.bookScore = [self getBookScore];
self.bookModel.time = [YCUtils getTimestampString];
[[AppSingle sharedAppSingle].recordedBooks addObject:self.bookModel];
[AppSingle sharedAppSingle].record_id ++ ;
[SaveCachesFile saveDataList:[AppSingle sharedAppSingle].recordedBooks fileName:RecordedList];
}
}
//计算所有句子的平均分
- (float)getBookScore{
NSInteger sentenceCount = 0;
NSInteger sentenceScore = 0;
for (NSInteger i = 0 ;i < self.bookModel.pages.count ; i++) {
PageModel * page = self.bookModel.pages[i];
for (NSInteger j = 0; j < page.sentences.count ; j ++) {
SentenceModel * sentence = page.sentences[j];
sentenceScore += sentence.score;
sentenceCount ++ ;
}
}
float res = (float)sentenceScore/(float)sentenceCount;
NSLog(@"最终得分:%f",res);
return res;
}
//更新本地数据
- (void)updateDownbooks{
float score = (float)self.recognizeCorrectCount/(float)self.totalPhomeCount;
self.currentSpeakCell.scoreView.score = score;
//再找到对应的page
for (PageModel * page in self.bookModel.pages) {
if ([page.page_id isEqualToString:self.sentenceModel.page_id]) {
//再找到对应的句子
for (SentenceModel * sentence in page.sentences) {
if ([sentence.sentence_id isEqualToString:self.sentenceModel.sentence_id]) {
sentence.attributedString = (NSMutableAttributedString *)self.currentBookCell.lb.attributedText;
sentence.score = score;
sentence.hasRecord = YES;
}
}
}
}
}
/**
检查是否本书内句子是否全部录音
全部已录音返回YES;
*/
- (BOOL)checkBookPagesisAllRecorded{
for (PageModel * page in self.bookModel.pages) {
for (SentenceModel * sentence in page.sentences) {
if (sentence.hasRecord == NO) {
return NO;
}
}
}
return YES;
}
- (void)isCorrectSub:(NSString *)sub{
self.right = 0;
self.wrong = 0;
//sub是单词,分割为字母
for (NSInteger i = 0; i < sub.length; i++) {
NSString * phomes = [sub substringWithRange:NSMakeRange(i, 1)];
NSInteger index = [self getIndexWithTemp:phomes];
if (index == -1) {
//没有找到对应的,开始进行下一次的遍历
//字母错误
self.wrong ++;
}else{
//字母正确
self.right ++;
}
//正确与否都降遍历后的删除掉,进行后续遍历
[self.recognizeRes removeObjectsInRange:NSMakeRange(0, index+1)];
//单词遍历完成
if (i == sub.length - 1) {
//查找单词在文本中的位置
NSMutableArray *locationArr = [self calculateSubStringCount:self.lowerString.string str:sub];
//筛选正确位置
NSInteger loc = [self getCorrectLoc:locationArr sub:sub];
if (loc == -1) {
NSLog(@"loction error");
return;
}
float score = (float)self.right/(float)sub.length;
if (score >= 0.5) {
self.recognizeCorrectCount ++;
//变绿色
[self.upperString addAttribute:NSForegroundColorAttributeName value:greenColor range:NSMakeRange(loc, sub.length)];
}else{
//变红色
[self.upperString addAttribute:NSForegroundColorAttributeName value:redColor range:NSMakeRange(loc, sub.length)];
}
self.currentBookCell.lb.attributedText = self.upperString;
}
}
}
- (NSInteger)getCorrectLoc:(NSMutableArray *)locationArr sub:(NSString *)sub{
//筛选正确的location 比如this is 中匹配 is。mom o
for (NSInteger i = 0; i < locationArr.count; i ++) {
NSInteger loc = [locationArr[i] integerValue];
if (loc == 0) {
return 0;
}else{
//前一位必须是空格
NSMutableAttributedString * fontLocString =(NSMutableAttributedString *)[self.lowerString attributedSubstringFromRange:NSMakeRange(loc - 1, 1)];
//字符匹配
NSMutableAttributedString * other_sub = (NSMutableAttributedString *)[self.lowerString attributedSubstringFromRange:NSMakeRange(loc , sub.length)];
//后一位不能是字母
NSMutableAttributedString * afterLocString = (NSMutableAttributedString *)[self.lowerString attributedSubstringFromRange:NSMakeRange(loc + sub.length, 1)];
//同时满足这三个情况才是正确的loc
if ([@" " isEqualToString:fontLocString.string] && [sub isEqualToString:other_sub.string] && ![self inputIsPhome:afterLocString.string]) {
return loc;
}
}
}
return -1;
}
//判断字符是否是26个字母中的一个
- (BOOL)inputIsPhome:(NSString *)input{
for (NSString * sub in self.phomes) {
if ([input isEqualToString:sub]) {
return YES;
}
}
return NO;
}
/**
查找子字符串在父字符串中的所有位置
@param content 父字符串
@param tab 子字符串
@return 返回位置数组
*/
- (NSMutableArray*)calculateSubStringCount:(NSString *)content str:(NSString *)tab {
int location = 0;
NSMutableArray *locationArr = [NSMutableArray new];
NSRange range = [content rangeOfString:tab];
if (range.location == NSNotFound){
return locationArr;
}
//声明一个临时字符串,记录截取之后的字符串
NSString * subStr = content;
while (range.location != NSNotFound) {
if (location == 0) {
location += range.location;
} else {
location += range.location + tab.length;
}
//记录位置
NSNumber *number = [NSNumber numberWithUnsignedInteger:location];
[locationArr addObject:number];
//每次记录之后,把找到的字串截取掉
subStr = [subStr substringFromIndex:range.location + range.length];
// NSLog(@"subStr %@",subStr);
range = [subStr rangeOfString:tab];
// NSLog(@"rang %@",NSStringFromRange(range));
}
return locationArr;
}
- (NSInteger )getIndexWithTemp:(NSString *)temp{
NSInteger index;
for (NSInteger i = 0; i < self.recognizeRes.count; i ++) {
NSString *index_str = self.recognizeRes[i];
if ([index_str isEqualToString:temp]) {
index = i;
return index;
}
}
//如果都没有匹配到返回-1
index = - 1;
return index;
}
核心代码是isCorrectSub。注释挺多的,有疑问可以评论。
那个获取location的最优解应该有更好的方法。有更好的方法希望不吝赐教。

浙公网安备 33010602011771号