PowerShellコラム:Cognitive Servicesでクリップボードの画像のテキストを日本語に翻訳する

Microsoft

2023.06.09

     

はじめに

私たちは日々、様々な形式の情報に接しています。文章、画像、動画など、これらの情報は私たちの意思決定や学習に大いに役立ちます。しかし、それらの情報が異なる言語で提供されていたり、画像や動画の中に重要な文書が埋め込まれていることがあります。

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をより身近に感じていただけたらと思います。

Cognitive Services

サンプルスクリプト

サンプルスクリプトはこちら。

サンプルスクリプト(ZIP:5.11KB)

翻訳のデモ

ファイル 概要
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にします。

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

info

コマンドは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 を作成します。

GUIで作成する場合

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 も変更してください。

キーとエンドポイントの貼り付け1

キーとエンドポイントの貼り付け2

使い方

「Translate.ps1」を実行すると待ち状態になります。

「Translate.ps1」を実行

Win+Shift+S などで、画像をクリップボードにコピーします。

画像をクリップボードにコピー

コンソールに戻って Enter キーを押すと、認識した結果とその翻訳が表示されます。

コンソールに戻って 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 を使用してリクエストを送信します。

info

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

Computer VisionはAPIの仕様とともに動作確認用サイトがあります。

TOPページには各パラメータの説明があります。リージョンを選ぶとパラメータを埋めるページに。ここでパラメータを埋めるとRequestURLやHTTP request のサンプルが表示されます。
Send で Input requirements を送った結果の確認ができます。
なおRaw image binary も対応していると記載がありますが入力法は不明。

Request URL

OCR処理のためのエンドポイントURL

ReadとOCRの比較

画像文字認識処理にはOCRとReadがあります。

OCR - 光学式文字認識 - Azure Cognitive Services | Microsoft Learn

軽く触った印象だと、このような感じでした。

OCR:
画像やPDFなどから少量のテキストを素早く集出する同期処理。早い。
どの位置にどんな単語があるかわかる。認識した画像を元の画像にオーバーレイさせるといった用途に強そう。

READ:
OCRより高度な多言語の機能。非同期処理が可能。
複数ページのドキュメントなどに対応。言語検出が可能。行と単語の抽出が可能。

印刷したドキュメントの文字列認識はこちらの方がしっかりした印象。

試しにこれを認識させてみました。
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の仕様を見たところ、コンテンツヘッダに情報を入れているようです。

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

※文中の商品名、会社名、団体名は、一般に各社の商標または登録商標です。

PowerShellコラム:Cognitive Servicesでクリップボードの画像のテキストを日本語に翻訳する