【VBA機能拡張】Tesseract OCRを使ってExcel VBAで文字認識(OCR)
Excelはデータ管理や計算処理において非常に便利なツールですが、時には印刷物やスクリーンショットなどの画像に含まれるテキスト情報をExcelで利用したい場合があります。このような場合に役立つのが、文字認識(OCR)です。
このページではGoogle社が開発しているオープンソースの文字認識エンジン『Tesseract OCR』をそのまま利用してExcelマクロ上で文字認識を行うための機能を実装していきます。オープンソースなので内部で何しているかは調べれば出てきますしカスタマイズしてもOK、使用料もなくオフラインでも利用できるのでいろいろと融通が利くマクロを作成することができます。
本ページではTesseract OCRの内部処理については解説していないので、しっかりと中身を確認しておきたい方は予め調べておくことをオススメします。また文字認識は入力画像の解像度や文字以外の情報(表の罫線やイラストなど)によって期待とは違う結果を出力する場合があります。
より高みを目指す場合は、Tesseract OCRを改造してより精度がでるよう挑戦してみて下さい。
Tesseract OCR
Tesseract OCRはGoogle社が開発しているオープンソースの光学式文字認識エンジンです。画像データといくつかのパラメータを入力することで、その画像データに記載されてる文字をテキストファイルにして出力してくれます。
TesseractOCRは高い精度と多言語サポートしているとともに、オープンソースであるため自由にカスタマイズや拡張が可能であり、個々のニーズに合わせてカスタム設定や追加の言語パックを使用することができます。
Tesseract OCRをインストールする
まずはTesseract OCRをインストールします。
Tessearact OCR の公式ドキュメント(github)よりインストーラのダウンロードができます。
画像付きの詳細なインストール手順が必要な場合は下記をクリックしてください。
1. リンク先ページの「Windows – Tesseract at UB Mannheim」をクリック
2.「tesseract-ocr-w64-setup-5.3.1.20230401.exe (64bit)」をクリック
(※バージョンによって文字列は異なるが最新版を選択すればOK)
インストーラがダウンロード出来たらexeファイルを実行してTesseract OCRをインストールします。exeファイルを実行するとインストーラの言語設定ができるので好きな言語を選択して[OK]をクリックします。(日本語はないです)
3.指示に従って進める。(ライセンス条項は要確認のこと)
4.文字認識をする対象の言語として日本語を追加でインストール
[Additional script data (download)] で [Japanese script][Japanese vertical script]、
[Additional language data (download)] で [Japanese][Japanese (vertical)」を選択
5.インストールするフォルダを選択する
スタートメニューフォルダは特に変更せずに[Install]ボタンをクリック
6.インストールが完了したら[Next]ボタン、[Finish]ボタンの順にクリック
以上でTesseract OCRのインストールは完了です。
Tesseract OCRを利用する
Tesseract OCRのインストールが完了したら実際に使って入力出力のイメージをつかんでみましょう。
「Tesseract-OCR」フォルダ内に「tesseract.exe」というTesseract OCRの実行ファイル(exeファイル)があります。このexeファイルはコマンドプロンプトより実行します。
Tesseract OCRはコマンドプロンプト上で下記のコマンドを打ち込むことで実行が可能です。
1 |
<exeファイルパス> <画像ファイルパス> <出力パス> -l jpn |
<exeファイルパス>部分には「tesseract.exe」のフルパスを入力します。
<画像ファイルパス>部分には文字認識を行う画像ファイルのフルパスを入力します。
入力可能な画像形式は「JPEG/png/tiff/webp/jepg2000/bmp/pnm/gif」です。
<出力パス>部分には文字認識の結果を出力するテキストファイルのフルパスを入力します。
ただし、このフルパスには拡張子(.txt)を除いたものを入力します。
-l jpn 部分では言語の設定を行っています。
–l は言語(language)の設定を行うパラメータを表しており、英語の場合は「-l eng」、日本語横書きの場合は「-l jpn」、日本語縦書きの場合は「-l jpn_vert」と入力します。
※それぞれの入力値の間は半角スペース[ ]で区切ります。
-l 以外にも入力可能なパラメータが存在しますがここでは説明を省略します。
たとえば下記のようにパスを入力するとデスクトップの「test.jpg」ファイルに書かれている文字を認識して、デスクトップに「output.txt」というファイルで結果を出力することができます。
<画像ファイルパス> “C:\Users\liclog\Desktop\test.jpg”
<出力パス> “C:\Users\liclog\Desktop\output”
本来、パス部分はカレントのディレクトリを考慮することでフルパスを入力する必要はありませんが、ここではVBAで利用することを考えてフルパスを入力することにします。
Excel VBAでTesseractOCRを起動
VBAはWshShellオブジェクトを利用することでコマンドプロンプト経由でexeファイルを実行することができます。Tesseract OCRはtesseract.exeを実行することで指定のディレクトリに文字認識の結果が書き出されたテキストファイルを出力することができます。そしてVBAは指定のテキストファイル内に書かれている文字列を読み取ることができます。
つまり、下記のような手順を行えばTesseract OCRを経由してVBAで文字認識を行うことが出来ます。
(コマンドプロンプトで[<exeファイルパス> <画像ファイルパス> <出力パス> -l jpn]を実行と同義)
2. <画像ファイルパス>の文字認識の結果が<出力パス>.txtとして出力される
3. VBAで<出力パス>.txtにアクセスしてファイルに書かれている文字列を取得する
サンプルコード
以降では実際にVBAのコードを見ながら詳しく処理の流れを解説していきます。新規Excelブック(.xlsm)の標準モジュールに下記コードをコピペして、インストールした「Tesseract-OCR」フォルダをExcelブックと同階層にそのまま配置することですぐに利用可能な状態になっています。
mainを実行すると画像ファイル選択ダイアログが表示されるので、文字認識したい画像を選びます。画像を選ぶと処理がTesseract OCRに渡り、文字認識とその結果のテキストファイル出力が行われます。そして再び処理がVBAに戻ってきてそのテキストファイルの文字列を取得しアクティブシートに出力するという流れになっています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
Const TESSERACT_OCR_DIR_NAME As String = "Tesseract-OCR" 'TesseractOCR ディレクトリ名 Const TESSERACT_OCR_EXE_NAME As String = "tesseract.exe" 'TesseractOCR exeファイル名 Const TESSERACT_OCR_TXT_NAME As String = "OutputText.txt" 'TesseractOCR 出力テキスト名 '選択ダイアログフィルタ Const FILE_FILTER As String = "画像(*.png; *.jpg; *.jpeg; *.gif; *.tiff)," & _ "*.png; *.jpg; *.jpeg; *.gif; *.tiff" 'コマンドプロンプトの表示状態(0:非表示 1:表示) Const PROMPT_VISIBL As Long = 0 Dim oWSH As Object Dim oFSO As Object Dim oADO As Object Dim sPathInputImage As String '入力画像フルパス(文字認識対象) Dim sPathOutputText As String 'TesseractOCRの出力ファイルのフルパス(拡張子不要) Dim sPathTesseractDir As String 'TesseractOCRディレクトリのフルパス Dim sPathTesseractExe As String 'TesseractOCRのexeファイルのフルパス Sub main() Dim sCmd As String Dim sOutputText As String Dim flgIsError As Boolean Set oWSH = CreateObject("WScript.Shell") Set oFSO = CreateObject("Scripting.FileSystemObject") Set oADO = CreateObject("ADODB.Stream") 'TesseractOCRパス sPathTesseractDir = ThisWorkbook.Path & "\" & TESSERACT_OCR_DIR_NAME '" sPathTesseractExe = sPathTesseractDir & "\" & TESSERACT_OCR_EXE_NAME '" '出力ファイルパス設定 sPathOutputText = ThisWorkbook.Path & "\" & TESSERACT_OCR_TXT_NAME '" '画像ファイルパス取得 sPathInputImage = Application.GetOpenFilename(FILE_FILTER, , "画像ファイル選択") If sPathInputImage = "False" Then Exit Sub 'コマンド作成 sCmd = CreateCommand(sPathTesseractExe, sPathInputImage, sPathOutputText, 1) 'TesseractOCR実行(コマンドプロンプト) On Error Resume Next Call oWSH.Run(sCmd, PROMPT_VISIBLE, True) If Err.Number <> 0 Then flgIsError = True On Error GoTo 0 'TesseractOCRの結果ファイルを読み込む If oFSO.FileExists(sPathOutputText) = False Or flgIsError = True Then Call MsgBox("文字認識に失敗しました。", vbExclamation) Exit Sub Else '文字認識結果をシートに出力 sOutputText = GetText(sPathOutputText) Call ExportExcelSheet(ThisWorkbook.ActiveSheet, sOutputText) End If Set oWSH = Nothing Set oFSO = Nothing Set oADO = Nothing End Sub '------------------------------------------------------------------------------- '- 実行コマンドの作成 '- sPathExe: TesseractOCRのExeファイルのフルパス '- sPathIn : 文字認識対象の画像 (JPEG/png/tiff/webp/jepg2000/bmp/pnm/gif) '- sPathOut: 出力ファイルのフルパス '- (iLang) : 文字認識する言語 (0:英語/1:日本語[横書]/2:日本語[縦書]) '- 戻り値 : 実行コマンド文字列 '------------------------------------------------------------------------------- Private Function CreateCommand(ByVal sPathExe As String, _ ByVal sPathIn As String, _ ByVal sPathOut As String, _ Optional iLang As Long = 0) As String Dim sCmd As String Dim sLang As String 'TesseractOCRの入力に不要な拡張子を除去 sPathOut = Replace(sPathOut, ".txt", "") '文字認識の言語設定 Select Case iLang Case 0 sLang = "-l eng" Case 1 sLang = "-l jpn" Case 2 sLang = "-l jpn_vert" End Select '実行コマンド作成 sCmd = WrapWQuot(sPathExe) & " " & _ WrapWQuot(sPathIn) & " " & _ WrapWQuot(sPathOut) & " " & _ sLang CreateCommand = sCmd End Function '---------------------------------------------------------------- '- 文字列をダブルクォーテーションで囲む '- sTgt: 対象文字列 '- 戻り値: 対象文字列の前後に["]が付いた文字列 '- ex) Input Str → "Input Str" '---------------------------------------------------------------- Private Function WrapWQuot(sTgt As String) As String WrapWQuot = """" & sTgt & """" End Function '---------------------------------------------------------------- '- 指定ファイルパス内のテキストを取得する '- sPath: テキストファイルのパス '- 戻り値: テキスト '---------------------------------------------------------------- Private Function GetText(sPath As String) As String Dim oFile As Object Dim sText As String 'TesseracctOCRの出力ファイルの文字コードは 'Unicode(UTF-8)なので変換して読込(文字化け回避) With oADO .Charset = "UTF-8" .Open .LoadFromFile sPath Do Until .EOS sText = .ReadText(-2) '-2: 1行ずつ読みとり Loop .Close End With GetText = sText End Function '---------------------------------------------------------------- '- シートにテキストを出力する '---------------------------------------------------------------- Private Sub ExportExcelSheet(wsExport As Worksheet, sText As String) Dim vSplitText Dim i As Long vSplitText = Split(sText, vbLf) wsExport.Cells.Clear For i = 0 To UBound(vSplitText) wsExport.Cells(i + 1, 1).Value = vSplitText(i) Next End Sub |
コード解説
サンプルコードの肝となる部分は「コマンドの作成」です。Tesseract OCRは、下記のような”コマンド”をコマンドプロンプトに入力して実行することで文字認識の処理を行うことが出来ました。
VBAではWshShellオブジェクトのRunメソッドを使うことで、これと同じようにコマンドプロンプトの操作を行うことができます。Runメソッドは下記のように書いて使用します。
Set oWSH = CreateObject(“WScript.Shell”) ‘WshShellオブジェクトを生成
Call oWSH.Run(sCmd, 0, True) ‘コマンド実行
Set oWSH = Nothing ‘WshShellオブジェクト解放
第一引数にはコマンドプロンプトに入力したいコマンドの文字列を入力します。
今回の場合は”<exeファイルパス> <画像ファイルパス> <出力パス> -l jpn”という文字列を入力します。
第二引数にはコマンドプロンプトの表示状態を入力します。0にするとコマンドプロンプトを表示せずに実行可能です。表示させたい場合は1を入力します。
第三引数にはTrueをいれます。これは同期の設定となっており、Trueにすることで入力したコマンドの実行が終わるまでVBAは処理を待機してくれます。これにより文字認識の結果が出力されるまではVBAが処理を待機してくれるので、確実に結果のテキストファイルを取得することが可能になります。
サンプルコードでは処理の7, 8割がこのコマンド(sCmd)の作成処理となっています。
<exeファイルパス>と<出力パス>はExcelブックのパスから辿って作成し、<画像ファイルパス>はファイル選択ダイアログを使ってユーザ選択させるというような動的なコードになっていて、Tesseract OCRのパラメータである「-l」もコード内の引数の数字で簡単に切り替えられるようになっています。基本的にサンプルコードのコメントを読めば何をしているのかは理解できるはずです。
文字認識の精度は100%ではないですが大半の文字の認識は可能です。(英語はより精度が高いです)