【问题标题】:How to catch words in the middle of sentences with Microsoft SAPI?如何使用 Microsoft SAPI 捕捉句子中间的单词?
【发布时间】:2010-02-08 03:18:27
【问题描述】:

这个 SAPI 语法捕捉单词名称是句子的中间。

<GRAMMAR LANGID="409">
    <RULE NAME="SOUNDLOG" TOPLEVEL="ACTIVE">
        <OPT>
            <DICTATION MAX="INF"/>
        </OPT>
        <L>
            <P>name</P>
        </L>
        <OPT>
            <DICTATION MAX="INF"/>
        </OPT>
    </RULE>
</GRAMMAR>

所以,如果我说“我的名字是安德烈”,那么“名字”这个词就被识别出来了。 有没有更好的方法来做到这一点?

【问题讨论】:

    标签: c# grammar speech-recognition sapi


    【解决方案1】:

    当您获得识别时,与识别关联的 SPPHRASE 数据包含子规则和属性数据以及它们在识别中出现的位置。

    因此,如果您有“姓名”的规则或属性标记,您可以找到与“姓名”相关联的词。

    例如,给定你的语法

    <GRAMMAR LANGID="409"> 
        <RULE NAME="SOUNDLOG" TOPLEVEL="ACTIVE"> 
            <OPT> 
                <DICTATION MAX="INF"/> 
            </OPT> 
            <L> 
                <P>name</P> 
            </L> 
            <OPT> 
                <DICTATION MAX="INF"/> 
            </OPT> 
        </RULE> 
    </GRAMMAR> 
    

    如果你把它改成

    <GRAMMAR LANGID="409"> 
        <RULE NAME="SOUNDLOG" TOPLEVEL="ACTIVE"> 
            <OPT> 
                <DICTATION MAX="INF"/> 
            </OPT> 
            <L PROPNAME='name'> 
                <P VAL='name'>name</P> 
            </L> 
            <OPT> 
                <DICTATION MAX="INF"/> 
            </OPT> 
        </RULE> 
    </GRAMMAR> 
    

    您可以像这样找到与“名称”相对应的单词:

    HRESULT OnRecognition(ISpRecoResult* pResult)
    {
        SPPHRASE *pPhrase;
        HRESULT hr = pResult->GetPhrase(&pPhrase);
        if (SUCCEEDED(hr))
        {
             const SPPHRASEPROPERTY pProp = FindProperty(pPhrase->pProperty, L"name");
             if (pRule)
             {
                 LPWSTR text(NULL);
                 hr = pResult->GetText(pProp->ulFirstElement, pProp->ulCountOfElements, TRUE, &text, NULL);
                 if (SUCCEEDED(hr))
                 {
                     // do something with text
                     ::CoTaskMemFree(text);
                 }
             }
        }
        return hr;
    }
    const SPPHRASEPROPERTY* FindProperty(const SPPHRASEPROPERTY* pProp, LPCWSTR what) const
    {
        while (pProp!=NULL)
        {
            if (pProp->pFirstChild != NULL)
            {
                const SPPHRASEPROPERTY* pFoundProp = FindRule(pProp->pFirstChild, what);
                if (pFoundProp)
                {
                    return pFoundProp;
                }
            }
            if (pProp->pszName != NULL && wcsstr(pProp->pszName, what) != NULL)
            {
                return pProp;
            }
            pProp = pProp->pNextSibling;
        }
        return NULL;
    }
    

    此代码专门查找该属性所涵盖的文本。但是,通常最好使用 val 属性来识别项目,而无需将代码显式绑定到语法。这允许您在不更改代码的情况下调整语法(或添加等效值)。要使用这些值,只需在获取属性后使用 SPPHRASEPROPERTY.pszValue 或 vValue 字段(而不是使用 ISpPhrase::GetText)。

    【讨论】:

    • 您使用的是 Speechlib 还是 System.Speech.Recognition? Speechlib 是 SAPI 的一个薄包装器,代码可以直接翻译(你可以使用 ISpeechPhraseInfo 而不是 SPPHRASE); System.Speech.Recognition 要厚得多;它使用不同的语法格式 (SRGS),虽然绝对可以做同样的事情,但方法略有不同,我不想发表评论。 :)
    猜你喜欢
    • 2014-01-15
    • 1970-01-01
    • 2023-03-30
    • 1970-01-01
    • 2016-06-13
    • 1970-01-01
    • 1970-01-01
    • 2018-10-30
    • 2018-07-28
    相关资源
    最近更新 更多