テキスト認識の要求
アプリケーションは MappingRecognizeText 関数を呼び出して、特定の ELS サービスからテキスト認識を要求します。 サービスの列挙と解放に関するページで説明されているように、MappingGetServices の以前の呼び出しでサービスが検出されている必要があります。
Note
プラットフォームでは、 MappingRecognizeText 呼び出しを同期的または非同期的に処理できます。
MappingRecognizeText は 、次の種類のテキストを処理します。
- Microsoft 言語の検出。 UTF-16、正規化形式 C、言語を決定するテキスト。
- Microsoft スクリプトの検出。 スクリプト範囲を決定する UTF-16 テキスト。
- 表記変換サービス。 ソース スクリプト (書き込みシステム) で記述された UTF-16 テキスト。
同期テキスト認識を使用する
このセクションでは、同期テキスト認識を実行するいくつかの方法について説明します。
Microsoft 言語検出サービスを使用した同期テキスト認識
次の例は、Microsoft 言語検出サービスでの MappingRecognizeText の使用を示し、サービスによって取得されたすべての結果を出力します。 このサービスの出力形式は、単一 のMAPPING_DATA_RANGE 構造であり、 その pData メンバーは Unicode の二重 null で終わる、レジストリ形式の文字列配列を指しています。 配列のすべての文字列は null で終わり、空の文字列を使用して配列の末尾を指定します。 配列の内容は、信頼度で並べ替えられた言語名です。
#include <windows.h>
#include <stdio.h>
#include <elscore.h>
#include <elssrvc.h>
#define USER_TEXT ( \
L"Skip This is a simple sentence. " \
L"\x0422\x0445\x0438\x0441 \x0438\x0441 \x0415\x043d\x0433\x043b\x0438\x0441\x0445.")
#define USER_TEXT_SKIP (5)
int __cdecl main();
HRESULT CallMappingRecognizeText(PMAPPING_SERVICE_INFO pService);
void PrintAllResults(PMAPPING_PROPERTY_BAG pBag);
int __cdecl main()
{
MAPPING_ENUM_OPTIONS EnumOptions;
PMAPPING_SERVICE_INFO prgServices = NULL;
DWORD dwServicesCount = 0;
HRESULT hResult;
ZeroMemory(&EnumOptions, sizeof (MAPPING_ENUM_OPTIONS));
EnumOptions.Size = sizeof (MAPPING_ENUM_OPTIONS);
// Using the Language Auto-Detection GUID to enumerate LAD only:
EnumOptions.pGuid = (GUID *)&ELS_GUID_LANGUAGE_DETECTION;
hResult = MappingGetServices(&EnumOptions, &prgServices, &dwServicesCount);
if (SUCCEEDED(hResult))
{
hResult = CallMappingRecognizeText(&prgServices[0]);
if (SUCCEEDED(hResult))
{
printf("Calling the service %ws has succeeded!\n",
prgServices[0].pszDescription);
}
else
{
printf("Calling the service %ws has failed, failure = 0x%x!\n",
prgServices[0].pszDescription, hResult);
}
MappingFreeServices(prgServices);
}
return 0;
}
HRESULT CallMappingRecognizeText(PMAPPING_SERVICE_INFO pService)
{
MAPPING_PROPERTY_BAG bag;
HRESULT hResult;
ZeroMemory(&bag, sizeof (MAPPING_PROPERTY_BAG));
bag.Size = sizeof (MAPPING_PROPERTY_BAG);
// MappingRecognizeText's dwIndex parameter specifies the first
// index inside the text from where the recognition should start.
// We pass USER_TEXT_SKIP, thus skipping the "Skip " part
// of the input string.
// Calling without MAPPING_OPTIONS:
hResult = MappingRecognizeText(pService, USER_TEXT, wcslen(USER_TEXT), USER_TEXT_SKIP, NULL, &bag);
if (SUCCEEDED(hResult))
{
printf("Results from service: %ws\n", pService->pszDescription);
PrintAllResults(&bag);
hResult = MappingFreePropertyBag(&bag);
}
return hResult;
}
void PrintAllResults(PMAPPING_PROPERTY_BAG pBag)
{
WCHAR * p;
// The return format of the Language Auto-Detection is a
// double null-terminated registry-formatted array of strings.
// Every string of the array is null-terminated and there's an
// empty string specifying the end of the array.
for (p = (WCHAR *)pBag->prgResultRanges[0].pData; *p; p += wcslen(p) + 1)
{
printf("%ws\n", p);
}
}
Microsoft スクリプト検出サービスを使用した同期テキスト認識
次の例では、Microsoft スクリプト検出サービスでの MappingRecognizeText の使用を示し、取得したすべての結果を出力します。 このサービスの出力形式は、 MAPPING_DATA_RANGE構造体の 配列であり、それぞれが同じスクリプトで書き込まれたテキストを指定します。 前の範囲に共通 (Zyyy) 文字が追加され、前の範囲が存在しない場合は次の範囲に追加されます。 各構造体の pData メンバーは、特定の範囲のスクリプトの標準 Unicode 名を含む Unicode null で終わる文字列を指します。
Note
Windows 7 の時点で、Microsoft スクリプト検出サービスは Unicode 5.1 に準拠しています。
#include <windows.h>
#include <stdio.h>
#include <elscore.h>
#include <elssrvc.h>
#define USER_TEXT ( \
L"Skip This is a simple sentence. " \
L"\x0422\x0445\x0438\x0441 \x0438\x0441 \x0415\x043d\x0433\x043b\x0438\x0441\x0445.")
#define USER_TEXT_SKIP (5)
int __cdecl main();
HRESULT CallMappingRecognizeText(PMAPPING_SERVICE_INFO pService);
void PrintAllResults(PMAPPING_PROPERTY_BAG pBag);
int __cdecl main()
{
MAPPING_ENUM_OPTIONS EnumOptions;
PMAPPING_SERVICE_INFO prgServices = NULL;
DWORD dwServicesCount = 0;
HRESULT hResult;
ZeroMemory(&EnumOptions, sizeof (MAPPING_ENUM_OPTIONS));
EnumOptions.Size = sizeof (MAPPING_ENUM_OPTIONS);
// Using the Script Detection GUID to enumerate SD only:
EnumOptions.pGuid = (GUID *)&ELS_GUID_SCRIPT_DETECTION;
hResult = MappingGetServices(&EnumOptions, &prgServices, &dwServicesCount);
if (SUCCEEDED(hResult))
{
hResult = CallMappingRecognizeText(&prgServices[0]);
if (SUCCEEDED(hResult))
{
printf("Calling the service %ws has succeeded!\n",
prgServices[0].pszDescription);
}
else
{
printf("Calling the service %ws has failed, failure = 0x%x!\n",
prgServices[0].pszDescription, hResult);
}
MappingFreeServices(prgServices);
}
return 0;
}
HRESULT CallMappingRecognizeText(PMAPPING_SERVICE_INFO pService)
{
MAPPING_PROPERTY_BAG bag;
HRESULT hResult;
ZeroMemory(&bag, sizeof (MAPPING_PROPERTY_BAG));
bag.Size = sizeof (MAPPING_PROPERTY_BAG);
// MappingRecognizeText's dwIndex parameter specifies the first
// index inside the text from where the recognition should start.
// We pass USER_TEXT_SKIP, thus skipping the "Skip " part
// of the input string.
// Calling without MAPPING_OPTIONS:
hResult = MappingRecognizeText(pService, USER_TEXT, wcslen(USER_TEXT), USER_TEXT_SKIP, NULL, &bag);
if (SUCCEEDED(hResult))
{
printf("Results from service: %ws\n", pService->pszDescription);
PrintAllResults(&bag);
hResult = MappingFreePropertyBag(&bag);
}
return hResult;
}
void PrintAllResults(PMAPPING_PROPERTY_BAG pBag)
{
DWORD dwRangeIndex;
for (dwRangeIndex = 0; dwRangeIndex < pBag->dwRangesCount; ++dwRangeIndex)
{
if (dwRangeIndex > 0)
{
printf(" ----\n");
}
printf("Range from %u to %u\n",
(unsigned)pBag->prgResultRanges[dwRangeIndex].dwStartIndex,
(unsigned)pBag->prgResultRanges[dwRangeIndex].dwEndIndex);
printf("Data size in WCHARs: %u\n",
(unsigned)pBag->prgResultRanges[dwRangeIndex].dwDataSize / 2);
printf("\"%ws\"\n", (WCHAR *)pBag->prgResultRanges[dwRangeIndex].pData);
}
}
Microsoft キリル文字からラテン文字変換サービスを使用した同期テキスト認識
次の例では、 MappingRecognizeText を Microsoft キリル語からラテン文字起こしサービスと共に使用し、取得した結果を出力する方法を示します。 このサービスを列挙するには、GUID またはカテゴリと入力スクリプトの 2 つの異なる方法に注意してください。
出力形式は、使用可能なすべての音訳サービスで同じです。 これは、pData メンバーが、出力スクリプトに変換された元のテキストを表す Unicode 文字の配列を指す単一のMAPPING_DATA_RANGE構造体であり、特定の音訳サービスの規則のみを適用します。 入力に終端の null 文字が含まれていない場合、このサービスは出力を null 終了しません。
#include <windows.h>
#include <stdio.h>
#include <elscore.h>
#include <elssrvc.h>
#define USER_TEXT (L"Skip The russian word for 'yes' is transliterated to Latin as '\x0434\x0430'.")
#define USER_TEXT_SKIP (5)
int __cdecl main();
HRESULT CallMappingRecognizeText(PMAPPING_SERVICE_INFO pService);
void PrintAllResults(PMAPPING_PROPERTY_BAG pBag);
int __cdecl main()
{
MAPPING_ENUM_OPTIONS EnumOptions;
PMAPPING_SERVICE_INFO prgServices;
DWORD dwServicesCount;
HRESULT hResult;
// 1. Enumerate by GUID:
prgServices = NULL;
dwServicesCount = 0;
ZeroMemory(&EnumOptions, sizeof (MAPPING_ENUM_OPTIONS));
EnumOptions.Size = sizeof (MAPPING_ENUM_OPTIONS);
// Use the Cyrl->Latn Transliteration GUID to enumerate only this service:
EnumOptions.pGuid = (GUID *)&ELS_GUID_TRANSLITERATION_CYRILLIC_TO_LATIN;
hResult = MappingGetServices(&EnumOptions, &prgServices, &dwServicesCount);
if (SUCCEEDED(hResult))
{
hResult = CallMappingRecognizeText(&prgServices[0]);
if (SUCCEEDED(hResult))
{
printf("Calling the service %ws has succeeded!\n",
prgServices[0].pszDescription);
}
else
{
printf("Calling the service %ws has failed, failure = 0x%x!\n",
prgServices[0].pszDescription, hResult);
}
MappingFreeServices(prgServices);
}
printf("--\n");
// 2. Enumerate by input script and category:
prgServices = NULL;
dwServicesCount = 0;
ZeroMemory(&EnumOptions, sizeof (MAPPING_ENUM_OPTIONS));
EnumOptions.Size = sizeof (MAPPING_ENUM_OPTIONS);
EnumOptions.pszCategory = L"Transliteration";
EnumOptions.pszInputScript = L"Cyrl";
hResult = MappingGetServices(&EnumOptions, &prgServices, &dwServicesCount);
if (SUCCEEDED(hResult))
{
hResult = CallMappingRecognizeText(&prgServices[0]);
if (SUCCEEDED(hResult))
{
printf("Calling the service %ws has succeeded!\n",
prgServices[0].pszDescription);
}
else
{
printf("Calling the service %ws has failed, failure = 0x%x!\n",
prgServices[0].pszDescription, hResult);
}
MappingFreeServices(prgServices);
}
return 0;
}
HRESULT CallMappingRecognizeText(PMAPPING_SERVICE_INFO pService)
{
MAPPING_PROPERTY_BAG bag;
HRESULT hResult;
ZeroMemory(&bag, sizeof (MAPPING_PROPERTY_BAG));
bag.Size = sizeof (MAPPING_PROPERTY_BAG);
// MappingRecognizeText's dwIndex parameter specifies the first
// index inside the text from where the recognition should start.
// We pass USER_TEXT_SKIP, thus skipping the "Skip " part
// of the input string.
// Calling without MAPPING_OPTIONS:
// We want the result to be null-terminated for display.
// That's why we will also pass the input null terminator:
hResult = MappingRecognizeText(pService, USER_TEXT, wcslen(USER_TEXT) + 1, USER_TEXT_SKIP, NULL, &bag);
if (SUCCEEDED(hResult))
{
printf("Results from service: %ws\n", pService->pszDescription);
PrintAllResults(&bag);
hResult = MappingFreePropertyBag(&bag);
}
return hResult;
}
void PrintAllResults(PMAPPING_PROPERTY_BAG pBag)
{
printf("\"%ws\"\n", (WCHAR *)pBag->prgResultRanges[0].pData);
}
使用可能なすべてのサービスの呼び出しを使用した同期テキスト認識
次の例は、使用可能なすべてのサービスで MappingRecognizeText を使用し、すべてのサービスに対して取得した結果を出力する方法を示しています。 この例では、各サービスの操作を適切に示します。 サンプル アプリケーションの出力を見ることで、サービスで内部的に何が起こっているのかを簡単に確認できます。 この例では、ELS サービスの呼び出しに使用されるほとんどすべてのコードが同じであることを示しています。
#include <windows.h>
#include <stdio.h>
#include <elscore.h>
#define USER_TEXT ( \
L"Skip This is a simple sentence. " \
L"\x0422\x0445\x0438\x0441 \x0438\x0441 \x0415\x043d\x0433\x043b\x0438\x0441\x0445.")
#define USER_TEXT_SKIP (5)
int __cdecl main();
HRESULT CallMappingRecognizeText(PMAPPING_SERVICE_INFO pService);
void PrintAllResults(PMAPPING_PROPERTY_BAG pBag);
int __cdecl main()
{
PMAPPING_SERVICE_INFO prgServices = NULL;
DWORD dwServicesCount = 0;
HRESULT hResult;
DWORD i;
// Get all installed ELS services:
hResult = MappingGetServices(NULL, &prgServices, &dwServicesCount);
if (SUCCEEDED(hResult))
{
for (i = 0; i < dwServicesCount; ++i)
{
// Do something with each service:
// ... prgServices[i] ...
if (i > 0)
{
printf("--\n");
}
hResult = CallMappingRecognizeText(&prgServices[i]);
if (SUCCEEDED(hResult))
{
printf("Calling the service %ws has succeeded!\n",
prgServices[i].pszDescription);
}
else
{
printf("Calling the service %ws has failed, failure = 0x%x!\n",
prgServices[i].pszDescription, hResult);
}
}
MappingFreeServices(prgServices);
}
return 0;
}
HRESULT CallMappingRecognizeText(PMAPPING_SERVICE_INFO pService)
{
MAPPING_PROPERTY_BAG bag;
HRESULT hResult;
ZeroMemory(&bag, sizeof (MAPPING_PROPERTY_BAG));
bag.Size = sizeof (MAPPING_PROPERTY_BAG);
// MappingRecognizeText's dwIndex parameter specifies the first
// index inside the text from where the recognition should start.
// We pass USER_TEXT_SKIP, thus skipping the "Skip " part
// of the input string.
// Calling without MAPPING_OPTIONS:
hResult = MappingRecognizeText(pService, USER_TEXT, wcslen(USER_TEXT), USER_TEXT_SKIP, NULL, &bag);
if (SUCCEEDED(hResult))
{
printf("Results from service: %ws\n", pService->pszDescription);
PrintAllResults(&bag);
hResult = MappingFreePropertyBag(&bag);
}
return hResult;
}
void PrintAllResults(PMAPPING_PROPERTY_BAG pBag)
{
DWORD dwRangeIndex;
DWORD dwDataIndex;
WCHAR c;
for (dwRangeIndex = 0; dwRangeIndex < pBag->dwRangesCount; ++dwRangeIndex)
{
if (dwRangeIndex > 0)
{
printf(" ----\n");
}
printf("Range from %u to %u\n",
(unsigned)pBag->prgResultRanges[dwRangeIndex].dwStartIndex,
(unsigned)pBag->prgResultRanges[dwRangeIndex].dwEndIndex);
// Currently, we can treat all results as arrays of unicode WCHAR
// characters, but there can be services in the future
// that use different formatting, i.e. XML, HTML, etc.
printf("Data size in WCHARs: %u\n",
(unsigned)pBag->prgResultRanges[dwRangeIndex].dwDataSize / 2);
printf("\"");
for (dwDataIndex = 0; dwDataIndex < pBag->prgResultRanges[dwRangeIndex].dwDataSize / 2; ++dwDataIndex)
{
c = ((WCHAR *)pBag->prgResultRanges[dwRangeIndex].pData)[dwDataIndex];
if (c >= 32 && c < 128 && c != '"') printf("%wc", c);
else printf("#%x", (unsigned)c);
}
printf("\"\n");
}
}
void CallRecognizeText(LPCWSTR Category, LPCWSTR Text)
{
HRESULT Result;
PMAPPING_SERVICE_INFO rgServices;
DWORD ServicesCount;
MAPPING_ENUM_OPTIONS options = {sizeof(MAPPING_ENUM_OPTIONS), (LPWSTR) Category, 0};
Result = MappingGetServices(&options, &rgServices, &ServicesCount);
if (Result == S_OK && ServicesCount > 0)
{
MAPPING_PROPERTY_BAG bag = { sizeof(MAPPING_PROPERTY_BAG), 0};
Result = MappingRecognizeText(&rgServices[0], Text, wcslen(Text), 0, NULL, &bag);
if (Result == S_OK)
{
MappingFreePropertyBag(&bag);
}
MappingFreeServices(rgServices);
}
}
int _tmain(int argc, _TCHAR* argv[])
{
CallRecognizeText(L"Language Detection", L"Text to be recognized");
UNREFERENCED_PARAMETER(argc);
UNREFERENCED_PARAMETER(argv);
return 0;
}
非同期テキスト認識を使用する
次の例は、非同期テキスト認識に MappingRecognizeText を使用する方法を示しています。 コールバックを使用する場合、アプリケーションは、コールバックの実行が完了するまで、プロパティ バッグ、入力テキスト、オプション、およびサービスがすべて有効であることを確認する必要があります。
アプリケーションは、コールバック関数によってバッグが使用された直後に MappingFreePropertyBag を呼び出す必要があります。 詳細については、「 ELS サービスのコールバックの提供」を参照してください。
#include <windows.h>
#include <stdio.h>
#include <elscore.h>
#include <elssrvc.h>
#define USER_TEXT ( \
L"Skip This is a simple sentence. " \
L"\x0422\x0445\x0438\x0441 \x0438\x0441 \x0415\x043d\x0433\x043b\x0438\x0441\x0445.")
#define USER_TEXT_SKIP (5)
int __cdecl main();
HRESULT CallMappingRecognizeText(PMAPPING_SERVICE_INFO pService);
void RecognizeCallback(PMAPPING_PROPERTY_BAG pBag, LPVOID data, DWORD dwDataSize, HRESULT Result);
int __cdecl main()
{
MAPPING_ENUM_OPTIONS EnumOptions;
PMAPPING_SERVICE_INFO prgServices = NULL;
DWORD dwServicesCount = 0;
HRESULT hResult;
ZeroMemory(&EnumOptions, sizeof (MAPPING_ENUM_OPTIONS));
EnumOptions.Size = sizeof (MAPPING_ENUM_OPTIONS);
// Using the Language Auto-Detection GUID to enumerate LAD only:
EnumOptions.pGuid = (GUID *)&ELS_GUID_LANGUAGE_DETECTION;
hResult = MappingGetServices(&EnumOptions, &prgServices, &dwServicesCount);
if (SUCCEEDED(hResult))
{
hResult = CallMappingRecognizeText(&prgServices[0]);
if (SUCCEEDED(hResult))
{
printf("Calling the service %ws has succeeded!\n",
prgServices[0].pszDescription);
}
else
{
printf("Calling the service %ws has failed, failure = 0x%x!\n",
prgServices[0].pszDescription, hResult);
}
MappingFreeServices(prgServices);
}
return 0;
}
HRESULT CallMappingRecognizeText(PMAPPING_SERVICE_INFO pService)
{
MAPPING_PROPERTY_BAG bag;
MAPPING_OPTIONS Options;
HRESULT hResult;
HANDLE SyncEvent;
DWORD dwWaitResult;
SyncEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (SyncEvent == NULL)
{
hResult = E_FAIL;
}
else
{
ZeroMemory(&bag, sizeof (MAPPING_PROPERTY_BAG));
bag.Size = sizeof (MAPPING_PROPERTY_BAG);
ZeroMemory(&Options, sizeof (MAPPING_OPTIONS));
Options.Size = sizeof (MAPPING_OPTIONS);
Options.pfnRecognizeCallback = (PFN_MAPPINGCALLBACKPROC)RecognizeCallback;
Options.pRecognizeCallerData = &SyncEvent;
Options.dwRecognizeCallerDataSize = sizeof (HANDLE);
// MappingRecognizeText's dwIndex parameter specifies the first
// index inside the text from where the recognition should start.
// We pass USER_TEXT_SKIP, thus skipping the "Skip " part
// of the input string.
hResult = MappingRecognizeText(pService, USER_TEXT, wcslen(USER_TEXT), USER_TEXT_SKIP, &Options, &bag);
if (SUCCEEDED(hResult))
{
// We are using an event to synchronize our waiting for the call to end,
// because some objects have to be valid till the end of the callback call:
// - the input text
// - the property bag
// - the options
// - the service
dwWaitResult = WaitForSingleObject(SyncEvent, INFINITE);
if (dwWaitResult != WAIT_OBJECT_0)
{
hResult = E_FAIL;
}
}
CloseHandle(SyncEvent);
}
return hResult;
}
void RecognizeCallback(PMAPPING_PROPERTY_BAG pBag, LPVOID data, DWORD dwDataSize, HRESULT Result)
{
HANDLE SyncEvent;
WCHAR * p;
UNREFERENCED_PARAMETER(dwDataSize);
if (SUCCEEDED(Result))
{
for (p = (WCHAR *)pBag->prgResultRanges[0].pData; *p; p += wcslen(p) + 1)
{
printf("%ws\n", p);
}
MappingFreePropertyBag(pBag);
}
SyncEvent = *((HANDLE *)data);
SetEvent(SyncEvent);
}
関連トピック