PowerShellコラム:Cognitive Servicesでクリップボードの画像のテキストを日本語に翻訳する
はじめに
私たちは日々、様々な形式の情報に接しています。文章、画像、動画など、これらの情報は私たちの意思決定や学習に大いに役立ちます。しかし、それらの情報が異なる言語で提供されていたり、画像や動画の中に重要な文書が埋め込まれていることがあります。
Microsoft AzureのCognitive Servicesにはこうした問題を解決するための強力なツールを提供しています。特に画像内のテキストを認識するOCR機能「Computer Vision Read API」と、テキストを翻訳する「Translator API」は、情報の抽出と理解を大幅に容易にします。
この記事では、Windowsに標準搭載されているPowerShellからAzureのCognitive Servicesを活用するためのスクリプトを紹介します。このスクリプトは、クリップボードに取り込んだ画像から文字列を抽出し、その文字列を日本語に翻訳します。
本ドキュメントでは、以下の流れで解説していきます。
- 1.Azure上にCognitive Servicesリソースを作成する方法
- 2.エンドポイントとAPIキーを取得し、サンプルスクリプトを更新する手順
- 3.サンプルコードの実行方法
- 4.サンプルコードの概要説明
これらの情報を通じて、AzureのCognitive Servicesをより身近に感じていただけたらと思います。
サンプルスクリプト
サンプルスクリプトはこちら。
ファイル | 概要 |
---|---|
CreateCognitiveServices.ps1 | 「事前準備」のコード。二つのCognitive Servicesを作成する Cloud Shellスクリプト。メモ帳などで開いて使用します。 |
ReadMe | 使用法 |
StartWithProxy.ps1 | プロキシの認証情報の入力を行った後に開始するサンプルスクリプト。 |
Translate.ps1 | サンプルスクリプト。事前準備で作ったリソースのエンドポイントとAPIキーを入力して使用します。 |
<スクリプト名>.bat | 各ps1ファイルをExecutionPolicy Bypass 指定して起動するためのバッチ |
事前準備
事前準備では、二つのCognitive Services を作成します。その後、スクリプトに使用するエンドポイントやAPIキーを生成してサンプルスクリプトに上書きします。
必要なリソースを作る(Cloud Shell)
今回はリソースの作成をCloud Shell で行います。ポータルのGUIで作成することもできます。もしGUIから作成する場合はポータルから「Cognitive Services」を検索し、左ペインにあるComputer Vision と 翻訳から作成してください。
1. クラウドシェルを起動する
初回は「ストレージがマウントされていません」と出てくるので、「ストレージの作成」をクリックして作成します。既にあるストレージアカウントを使用する場合は「詳細設定の表示」から選択してください。
2. PowerShellに切り替え
クラウドシェルはBashとPowerShellがあります。ここではPowerShellにします。
3. CognitiveServiceAccountリソースを作成する
以下のようなコードで作成します。デプロイ先リソースグループ名、二つのリソース名、ロケーション(リージョン)、価格レベルを埋めてCloud Shell に貼り付けて実行してください。
$ResourceGroupName = "<リソースグループ名>" # デプロイ先リソースグループ名
$computerVisionResourceName = "cog-ComputerVision-dev" # 任意のリソース名
$translationResourceName = "cog-Translation-dev" # 任意のリソース名
$location = "japaneast" # ロケーション
$sku = "F0" # 価格レベル
# Computer Vision API の作成
$computerVisionResource = New-AzCognitiveServicesAccount -ResourceGroupName $resourceGroupName `
-Name $computerVisionResourceName -SkuName $sku -Kind "ComputerVision" -Location $location
# 翻訳APIの作成
$translationResource = New-AzCognitiveServicesAccount -ResourceGroupName $resourceGroupName `
-Name $translationResourceName -SkuName $sku -Kind "TextTranslation" -Location $location
コマンドはCtrl+Shift+Vで貼り付けできます。
パラメータの参考:
項目 | 概要 |
---|---|
リソースグループ名 | Get-AzResourceGroup | Select-Object ResourceGroupName |
リソース名 | 自由に。 名前付け規則を定義する https://learn.microsoft.com/ja-jp/azure/cloud-adoption-framework/ready/azure-best-practices/resource-naming#example-names-ai-and-machine-learningcog-computervision-dev |
リージョン名 | "japaneast" など。 Get-AzLocation | Select-Object Location |
価格レベル | F0, S0, S1, S2, S3, S4 がある。 New-AzCognitiveServicesAccount (Az.CognitiveServices) | Microsoft Learn 価格 - コンピュータビジョンAPI |マイクロソフト アズ (microsoft.com) 価格 - Translator | Microsoft Azure |
GUIで作成する場合は「Cognitive Services」をポータルから検索し、翻訳とComputer Vision を作成します。
APIキーとエンドポイントを取得する(Cloud Shell)
APIキーとエンドポイントを取得し、表示された結果をコピーしておきます。
# エンドポイントとキーの取得
$computerVisionResource = Get-AzCognitiveServicesAccount -ResourceGroupName $ResourceGroupName -Name $computerVisionResourceName
$translationResource = Get-AzCognitiveServicesAccount -ResourceGroupName $ResourceGroupName -Name $translationResourceName
# エンドポイント
$translationEndpoint = $translationResource.Endpoint
$computerVisionEndpoint = $computerVisionResource.Endpoint
# API キー
$translationApiKey = (Get-AzCognitiveServicesAccountKey -ResourceGroupName $resourceGroupName `
-Name $translationResourceName).Key1
$computerVisionApiKey = (Get-AzCognitiveServicesAccountKey -ResourceGroupName $resourceGroupName `
-Name $computerVisionResourceName).Key1
# 表示
Write-Host @"
`$computerVisionEndpoint = '$computerVisionEndpoint'
`$computerVisionApiKey = '$computerVisionApiKey'
`$translationEndpoint = '$translationEndpoint'
`$translationApiKey = '$translationApiKey'
"@
GUIの場合は「キーとエンドポイント」から確認できます。今回翻訳対象は抽出した短いテキストなので「テキスト翻訳」のエンドポイントを使いました。
Microsoft Azure Cognitive Services テキスト翻訳とは - Azure Cognitive Services | Microsoft Learn
Microsoft Azure Cognitive Services のドキュメント翻訳とは - Azure Cognitive Services | Microsoft Learn
キーとエンドポイントの貼り付け
「Translate.ps1」を開いて、先ほどの結果を貼り付けます。リージョンがjapaneast以外の場合は $location も変更してください。
↓
使い方
「Translate.ps1」を実行すると待ち状態になります。
Win+Shift+S などで、画像をクリップボードにコピーします。
コンソールに戻って Enter キーを押すと、認識した結果とその翻訳が表示されます。
コードの概要
エンドポイントURLとクエリ文字列
エンドポイントURLに使用するAPIのバージョンやクエリ文字列を指定します。
詳細はAPIの仕様をご確認ください(後述Appendix参照)。
文字認識にはOCRとReadがありますが、今回は文字列認識に強いReadを使用します。サンプルには結果を比較できるようにするため両方入れています。
# OCR処理のためのエンドポイントURL
# OCR : 画像に含まれる短いテキスト抽出 & 同期処理
# Read : Office,HTML,PDFなどのドキュメントやその画像からテキスト抽出 & 非同期処理
$ocrUrl = $computerVisionEndpoint +'vision/v3.2/ocr?language=unk&detectOrientation=true&model-version=latest'
$readUrl = $computerVisionEndpoint +'vision/v3.2/read/analyze?model-version=latest'
# 翻訳のためのエンドポイントURL
$translateUrl = $translationEndpoint + 'translate?api-version=3.0&to=ja'
リクエストヘッダーの作成
文字認識と翻訳用のリクエストヘッダーを作ります。
文字認識はバイナリを送るため Content-Typeを application/octet-streamに。
翻訳に使用するリソースは認証ヘッダーにリージョンの指定が必要な点と charset=utf-8 の指定に注意します。
Azure Cognitive Services での認証 - Azure Cognitive Services | Microsoft Learn
# リクエストヘッダーの設定(Read/OCR共通)
$ocrHeaders = @{
"Ocp-Apim-Subscription-Key" = $computerVisionApiKey
"Content-Type" = "application/octet-stream"
}
# そのままだと "ó" などの文字が含まれる場合に「One of the request inputs isn't valid.」となるため
# charset=utf-8 を指定し Body はバイナリにして送る。
$translateHeaders = @{
"Ocp-Apim-Subscription-Key" = $translationApiKey
"Ocp-Apim-Subscription-Region" = $location
"Content-Type" = "application/json; charset=utf-8"
}
クリップボードから画像を保存
対応するフォーマットが「JPEG, PNG, BMP, PDF and TIFF」なので、Get-Clipboard を使用して取り込んだ後にいったんPNGに保存します。
# クリップボードから画像データを取得
$imageData = Get-Clipboard -Format 'Image'
# pngファイルに保存
$imageData.Save($imagePath,[System.Drawing.Imaging.ImageFormat]::Png)
# 画像データをComputer Vision APIに送信するためにバイナリにする
$imageData = [System.IO.File]::ReadAllBytes($imagePath)
$null = Remove-Item -LiteralPath $imagePath
画像とリクエストを送信
REST API を使用してリクエストを送信します。
RESTAPI を扱うコマンドにはInvoke-RestMethodとInvoke-WebRequestがありますが、Read APIはInvoke-WebRequestを使用する必要があります(後述Appendix参照)。
# Read(非同期)
# Invoke-RestMethod は使えない。
# レスポンスヘッダに情報が入るが、PowerShell 5.1 ではこれを読む術がない。
$ReadResponse = Invoke-WebRequest -Method Post `
-Uri $ReadUrl `
-Headers $ocrHeaders `
-Body $imageData `
-EA STOP
完了待ち
Read APIは即座に応答が返ってくる非同期処理です。
正常に要求が受理されるとステータスコード202とともに、状態確認と結果取得に必要なURLがレスポンスヘッダに格納されます。
これを使用して完了を待ちます。
# Read(非同期)
# Readの結果待ち
$operationId = $ReadResponse.$operationId
$statusUri = $readresponse.headers."Operation-Location"
do{
$ReadStatus = Invoke-RestMethod -Uri $statusUri -Method Get -Headers $ocrHeaders
if($ReadStatus.Status -eq "Running" -or $status.Status -eq "NotStarted") {
Start-Sleep -Seconds 1
}
else {
break
}
} while ($true)
結果取得
うまくいったら結果を取得します。
# Read 結果からテキスト抽出
$textFromRead = $ReadStatus.analyzeResult.readresults.lines.text -join " "
write-host "■ 検出したテキスト(READ):`n $TextFromRead"
テキストを翻訳APIに送信して翻訳実行
Bodyに翻訳文を含めたJSONを入れて送ります。
要求本文は配列なので "[]" を追加する必要があります。
また指定したエンコードはUTF8なので変換します。
Translator の Translate メソッド - Azure Cognitive Services | Microsoft Learn
$translateResponse = Invoke-RestMethod -Method Post `
-Uri $translateUrl `
-Headers $translateHeaders `
-Body ([System.Text.Encoding]::UTF8.GetBytes('[' + ($translateBody | ConvertTo-Json) + ']') )
翻訳結果の表示
翻訳結果を表示します。
# 翻訳結果の取得
$translation = $translateResponse[0].translations[0].text
Write-Host "■ 翻訳結果(READ):"
Write-Host $translation
Appendix
プロキシ認証環境
プロキシ認証が必要な環境の場合 Invoke-WebRequest や Invoke-RestMethod が失敗します。
その場合は事前に以下のようなコードを実行した後に、同じコンソールからスクリプトを実行します。
# OS既定のプロキシ設定を取得
$defaultProxy = [System.Net.WebRequest]::DefaultWebProxy
$defaultProxy.Credentials = Get-Credential -Message "プロキシ認証情報"
# PowerShellでのデフォルトプロキシとして設定
[System.Net.WebRequest]::DefaultWebProxy = $defaultProxy
APIのリファレンス
翻訳先を変更したいなどといった場合はクエリやリクエストヘッダを編集します。
APIのリファレンスはこちら。
Computer Vision API (v3.2)
Cognitive Services APIs Reference (microsoft.com)
Text Translation REST API
Text Translation REST API リファレンス ガイド - Azure Cognitive Services | Microsoft Learn
Computer Vision のAPI
Computer VisionはAPIの仕様とともに動作確認用サイトがあります。
TOPページには各パラメータの説明があります。リージョンを選ぶとパラメータを埋めるページに。ここでパラメータを埋めるとRequestURLやHTTP request のサンプルが表示されます。
Send で Input requirements を送った結果の確認ができます。
なおRaw image binary も対応していると記載がありますが入力法は不明。
↓
ReadとOCRの比較
画像文字認識処理にはOCRとReadがあります。
OCR - 光学式文字認識 - Azure Cognitive Services | Microsoft Learn
軽く触った印象だと、このような感じでした。
OCR:
画像やPDFなどから少量のテキストを素早く集出する同期処理。早い。
どの位置にどんな単語があるかわかる。認識した画像を元の画像にオーバーレイさせるといった用途に強そう。
READ:
OCRより高度な多言語の機能。非同期処理が可能。
複数ページのドキュメントなどに対応。言語検出が可能。行と単語の抽出が可能。
印刷したドキュメントの文字列認識はこちらの方がしっかりした印象。
試しにこれを認識させてみました。
READとOCRの結果をそれぞれ // で連結したところ、このようになりました。
サンプルは少ないですが、文書としての認識はReadの方が優秀なように感じました。
OCR | Read |
---|---|
■ 検出したテキスト(OCR): —//INTELLILlNKisa//coined//word//meaningconnecting//intelligence.//Asa//member//of//the//NTT//DATA//Group,//we//are//expanding//our//business//in//collaboration//with//NTT//DATA//and//the//NTT//Group//to//help//our//customers'//businesses//by//providing//information//system//infrastructure//that//uses//the//latest//technologies.//>//Read//More— |
INTELLILINK is a coined word meaning connecting intelligence. As a member//of the NTT DATA Group, we are expanding our business in collaboration with//NTT DATA and the NTT Group to help our customers' businesses by//providing information system infrastructure that uses the latest//technologies.//> Read More//2/3 |
Readを使う場合は Invoke-WebRequestを使う
以下のように実行すると、空の文字列が返ってきてしまい期待した動作になりません。
$ReadResponse = Invoke-WebMethod -Method Post `
-Uri $ReadUrl `
-Headers $ocrHeaders `
-Body $imageData `
-EA STOP
改めてAPIの仕様を見たところ、コンテンツヘッダに情報を入れているようです。
一方Invoke-WebRequest の仕様によれば、PowerShell 5.1 はInvoke-RestMethod にこれを取得する方法(ResponseHeadersVariableオプション)がないため、今回の目的に使用できないようです。
Invoke-RestMethod (Microsoft.PowerShell.Utility) - PowerShell | Microsoft Learn
代わりにInvoke-WebRequestを使用してください。
Invoke-WebRequest (Microsoft.PowerShell.Utility) - PowerShell | Microsoft Learn
※文中の商品名、会社名、団体名は、一般に各社の商標または登録商標です。