基于科大讯飞Android语音控制,实现模糊识别

基于怎么添加科大讯飞SDK,我在这里不再做过多的阐述,可以参考别人的方案,如https://blog.csdn.net/Liu_ser/article/details/80661603

但是这只是从语音到文字的转换,转换之后如何要识别解析后的文字,还需要做后一步的处理。即字符模糊处理。打个比方:我要在APP里通过语音控制某个热水器。我会对网关喊"天狗天狗,打开热水器"(比如热水器网关取名为天狗)。但是对于普通话不标准的人,你喊天狗,语音识别后会显示”舔狗“,”天候“,”天沟“。。。。等等等等。。那就很难根据字符来做处理了。所以要做字符的模糊处理,当然可以依靠科大讯飞的特殊化定制,但那个需要钱的,出于成本考虑,可以通过以下二种方法处理。

一  在科大讯飞项目中添加热词:

-控制台--我的应用---语音听写---服务管理--上传热词   

在这里添加热词以后,可以模糊匹配到你添加的热词上,但是这样做还不够,还是不能区分平舌翘舌,前鼻音后鼻音,因此还需要做模糊处理。

二  模糊处理:

思路是这样的:

1,将目标字符集转换为拼音;

2,获取科大讯飞语音识别的结果;

3,将识别结果转换为拼音;

4,在目标拼音集中进行拼音的匹配查找;

5,对于查找不到的,进行易混拼音的替换,再次与目标集合匹配查找;

6,对于还没有查找到的,去掉音调,再次与目标集合匹配查找;

7,将模糊匹配后的结果展现出来;

具体Demo如下:

public class PinyinSimilarity {

String[]englishPinYin26={

"EI1", "BI4", "SEI4", "DI4", "YI4", "EFU1", "JI4",

            "EIQI1", "AI4", "JEI4", "KEI4", "EOU1", "EMEN1", "EN1",

            "OU1", "PI1", "KIU1", "A4", "ESI1", "TI4",

            "YOU4", "WEI4", "DABULIU3", "EKESI1", "WAI4", "ZEI4"

    };

    StringenglishString26="ABCDEFGHIJKLMNOPQRSTUVWXYZ";

    StringnumberStringArabic="123456789";

    StringnumberString="一二三四五六七八九十百";//可以打开热水器一,打开热水器二

    StringspecialHanziString="天狗打开热水器";

    StringmyCharAll =numberString +specialHanziString;

    ListnumberPinYin=new ArrayList<>(20);//数字的拼音(10)

    ListspecialHanziPinYin=new ArrayList(10);//特定汉字集的拼音(除了中文的数字之外的)

    ListmyCharAllPinYin=new ArrayList(40);//所有拼音的集合

    boolean fuzzyMatching=true;//是否开启模糊匹配功

    public PinyinSimilarity(boolean fuzzyMatching){

this.fuzzyMatching = fuzzyMatching;

        init();

    }

public void init()

{

try{

String str;

            HanyuPinyinOutputFormat format =new HanyuPinyinOutputFormat();

            format.setCaseType(HanyuPinyinCaseType.UPPERCASE);

            format.setToneType(HanyuPinyinToneType.WITH_TONE_NUMBER);

            str =numberString;//数字

            for (int i =0; i < str.length(); i++) {

char c = str.charAt(i);

                String[] vals = PinyinHelper.toHanyuPinyinStringArray(c, format);

                numberPinYin.add(vals[0]);

            }

str =specialHanziString;//汉字

            for (int i =0; i < str.length(); i++) {

char c = str.charAt(i);

                String[] vals = PinyinHelper.toHanyuPinyinStringArray(c, format);

                specialHanziPinYin.add(vals[0]);

            }

myCharAllPinYin.addAll(numberPinYin);

            myCharAllPinYin.addAll(specialHanziPinYin);

        }catch (Exception e){

e.printStackTrace();

        }

}

public StringchangeOurWordsWithPinyin(String input){

String output=input;

        try{

//处理符号:不关注符合,遇到,就去掉(要保留小数点)

            output = changeWordProcessSignal(output);

            //处理英文字母:转大写

            output = changeWordProcessEnglish(output);

            //所有汉字进行相似替换

            LogUtils.error("input.length()="+input.length());

            int index;

            String str;

            String strChanged;

            StringBuilder strBuilder =new StringBuilder();

            for(index=0;index

str = input.substring(index,index+1);

                strChanged = changeOneWord(str);

                strBuilder.append(strChanged);

            }

output=strBuilder.toString();

            LogUtils.error("after changeAllWord: output="+output);

        }catch (Exception e){

e.printStackTrace();

        }

return output;

    }

public StringchangeWordProcessSignal(String strInput){

String strOutput = strInput;

        //去掉 ,。空格-

        strOutput = strOutput.replace(",", "");

        strOutput = strOutput.replace("。", "");

        strOutput = strOutput.replace("-", "");

        strOutput = strOutput.replace(" ", "");

        return strOutput;

    }

public StringchangeWordProcessEnglish(String strInput){

String strOutput = strInput;

        //转大写

        strOutput = strOutput.toUpperCase();

        return strOutput;

    }

//尾字如果是汉字,进行拼音相同字的替换(零不能替换,可以先转换为0)

    public StringchangeOneWord(String strInput){

//若已经在目标集合中了,就不需要转换了

        if(numberString.contains(strInput)||numberStringArabic.contains(strInput)){

LogUtils.error("is number");

            return strInput;

        }else if(specialHanziString.contains(strInput)){

LogUtils.error("is specialHanziString");

            return strInput;

        }

String strChanged;

        List listEnglishPinYin =new ArrayList();

        strChanged = changeWord(strInput, numberPinYin, numberString);

        if(numberString.contains(strChanged)){

LogUtils.error("is number");

            return strChanged;

        }

return changeWord(strInput, specialHanziPinYin,  specialHanziString);

    }

private StringchangeWord(String strInput, List listPinYin, String strSource) {

//先判断输入,是什么类型的字符:数字、字母、汉字

        String strOutput ="";

        String str = strInput.substring(0, 1);

        String strPinyin ="";

        boolean flagGetPinyin =false;

        try {

if (str.matches("^[A-Z]{1}$")) {

strPinyin =englishPinYin26[englishString26.indexOf(str)];

                LogUtils.error("str=" + str +" Pinyin=" + strPinyin);

                flagGetPinyin =true;

            }else if (str.matches("^[0-9]{1}$")) {

strPinyin =numberPinYin.get(numberString.indexOf(str));

                LogUtils.error("str=" + str +" Pinyin=" + strPinyin);

                flagGetPinyin =true;

            }else if (str.matches("^[\u4e00-\u9fa5]{1}$")) {

HanyuPinyinOutputFormat format =new HanyuPinyinOutputFormat();

                format.setCaseType(HanyuPinyinCaseType.UPPERCASE);

                format.setToneType(HanyuPinyinToneType.WITH_TONE_NUMBER);

                char c = str.charAt(0);

                String[] vals = PinyinHelper.toHanyuPinyinStringArray(c, format);

                strPinyin = vals[0];//token.target;

                flagGetPinyin =true;

            }

if(flagGetPinyin) {

//在目标拼音集合中查找匹配项

                int num = listPinYin.indexOf(strPinyin);

                if (num >=0) {//拼音精确匹配成功

                    return strSource.substring(num, num +1);

                }else {

if (fuzzyMatching) {//若开启了模糊匹配

//声母替换

                        String strPinyinFuzzy =new String(strPinyin);//避免修改原字符串

                        strPinyinFuzzy = replaceHeadString(strPinyinFuzzy);

                        boolean flagReplacedHeadString = (strPinyinFuzzy ==null) ?false :true;

                        if (flagReplacedHeadString) {

num = listPinYin.indexOf(strPinyinFuzzy);

                            if (num >=0) {//拼音模糊匹配成功

                                LogUtils.error("fuzzy match: " + strPinyinFuzzy +" num=" + num);

                                return strSource.substring(num, num +1);

                            }

}

//韵母替换

                        strPinyinFuzzy =new String(strPinyin);//避免修改原字符串,不使用声母替换后的字符串

                        strPinyinFuzzy = replaceTailString(strPinyinFuzzy);

                        boolean flagReplacedTailString = (strPinyinFuzzy ==null) ?false :true;

                        if (flagReplacedTailString) {

num = listPinYin.indexOf(strPinyinFuzzy);

                            if (num >=0) {//拼音模糊匹配成功

                                LogUtils.error("fuzzy match: " + strPinyinFuzzy +" num=" + num);

                                return strSource.substring(num, num +1);

                            }

}

//声母韵母都替换

                        if (flagReplacedHeadString && flagReplacedTailString) {

strPinyinFuzzy = replaceHeadString(strPinyinFuzzy);

                            num = listPinYin.indexOf(strPinyinFuzzy);

                            if (num >=0) {//拼音模糊匹配成功

                                LogUtils.error("fuzzy match: " + strPinyinFuzzy +" num=" + num);

                                return strSource.substring(num, num +1);

                            }

}

strPinyin=strPinyin.substring(0, strPinyin.length()-1);

                        strPinyinFuzzy =new String(strPinyin);//避免修改原字符串

                        num=findPinyin(strPinyinFuzzy,listPinYin);

                        if(num>=0){//拼音模糊匹配成功

                            return strSource.substring(num, num+1);

                        }

//声母替换

                        strPinyinFuzzy = replaceHeadString(strPinyinFuzzy);

                        flagReplacedHeadString = (strPinyinFuzzy==null)?false:true;

                        if(flagReplacedHeadString){

num=findPinyin(strPinyinFuzzy,listPinYin);

                            if(num>=0){//拼音模糊匹配成功

                                return strSource.substring(num, num+1);

                            }

}

//韵母替换

                        strPinyinFuzzy =new String(strPinyin);//避免修改原字符串,不使用声母替换后的字符串

                        strPinyinFuzzy = replaceTailString(strPinyinFuzzy);

                        flagReplacedTailString = (strPinyinFuzzy==null)?false:true;

                        if(flagReplacedTailString){

num=findPinyin(strPinyinFuzzy,listPinYin);

                            if(num>=0){//拼音模糊匹配成功

                                return strSource.substring(num, num+1);

                            }

}

//声母韵母都替换

                        if(flagReplacedHeadString && flagReplacedTailString){

strPinyinFuzzy = replaceHeadString(strPinyinFuzzy);

                            num=findPinyin(strPinyinFuzzy,listPinYin);

                            if(num>=0){//拼音模糊匹配成功

                                LogUtils.error("fuzzy match: "+strPinyinFuzzy+" num="+num);

                                return strSource.substring(num, num+1);

                            }

}

return str;

                    }else {

return str;

                    }

}

}else {//若该字符没有找到相应拼音,使用原字符

                strOutput = strInput;

            }

}catch (Exception e){

e.printStackTrace();

        }

return strOutput;

    }

private StringreplaceHeadString(String strPinyin){

//声母替换

        String strReplaced =null;

        if(strPinyin.contains("ZH")){

strReplaced = strPinyin.replace("ZH", "Z");

        }else if(strPinyin.contains("CH")){

strReplaced = strPinyin.replace("CH", "C");

        }else if(strPinyin.contains("SH")){

strReplaced = strPinyin.replace("SH", "S");

        }

else if(strPinyin.contains("Z")){

strReplaced = strPinyin.replace("Z", "ZH");

        }else if(strPinyin.contains("C")){

strReplaced = strPinyin.replace("C", "CH");

        }else if(strPinyin.contains("S")){

strReplaced = strPinyin.replace("S", "SH");

        }

else if(strPinyin.contains("L")){

strReplaced = strPinyin.replace("L", "N");

        }else if(strPinyin.indexOf('N')==0){//n有在后面的,n只在做声母时易混

            strReplaced = strPinyin.replace("N", "L");

        }else {

return null;

        }

LogUtils.error("strReplaced="+strReplaced);

        return strReplaced;//flagReplaced;

    }

private StringreplaceTailString(String strPinyin) {

// 韵母替换

        String strReplaced =null;

        if (strPinyin.contains("ANG")) {

strReplaced = strPinyin.replace("ANG", "AN");

        }else if (strPinyin.contains("ENG")) {

strReplaced = strPinyin.replace("ENG", "EN");

        }else if (strPinyin.contains("ING")) {

strReplaced = strPinyin.replace("ING", "IN");

        }else if (strPinyin.contains("AN")) {

strReplaced = strPinyin.replace("AN", "ANG");

        }else if (strPinyin.contains("EN")) {

strReplaced = strPinyin.replace("EN", "ENG");

        }else if (strPinyin.contains("IN")) {

strReplaced = strPinyin.replace("IN", "ING");

        }else {

return null;

        }

return strReplaced;

    }

private int findPinyin(String strPinyin, List listPinYin){

int num=0;

        //在目标拼音集合中查找匹配项

        for(String strTmp:listPinYin){

if(strTmp.contains(strPinyin) && strPinyin.length()==(strTmp.length()-1) ){

return num;

            }

num++;

        }

return -1;

    }

}

调用:

StringchangeToOurWords(String input){

String output=input;

    output =new PinyinSimilarity(true).changeOurWordsWithPinyin(output);

    return output;

}   输出自己需要的字符

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349

推荐阅读更多精彩内容