
ChatGPTを使ったコーディングをしてみる~Tesseractを使ったGoogleColab上で動かすOCR処理~
ChatGPTを使って、日本語のスクショをテキスト形式に変換してもらうことを目標にコーディングしていきます。
尚、ChatGPTに書いてもらうため、コーディングについてはPythonの知識も、何ならコーディングの知識もあまり必要ではありません。
GoogleColabの使い方等を途中長々書いていますが、既にご存じの方は読み飛ばしてください。
もくじの「コード」に全量のせてありますので、それをコピーすればそのまま使えます。
あと、おまけはChatGPTとのやりとりです。参考として載せておきます。
目的
電子書籍を読んでいて「いいね!」と思ってスクショしたものが、ひたすら写真ライブラリにたまっています。
iPhoneの標準写真アプリには、画像からテキストを読み取る機能が実装されていますが、日本語の精度はあまり良くなく、特に縦書きについては不可能です。
他の外部サービスを活用するという方法もありますが、折角なので、自分で使いやすいようにカスタマイズしながらコーディング、実装していこうと思います。
実行環境とコード
コーディングと実行にあたっては、Googleが提供している「GoogleColab」を利用します。無料でサクッと利用できるのでオススメです。
大規模な機械学習等には有料版を契約することをオススメしますが、今のところ簡単なPythonコードを動かすだけなら、無料版でも大丈夫です。
使い方
先ずは自分のGoogledriveから以下のようにノートを作成します。

自分は以下のパスで作成して作業しています。
「マイドライブ\Colab Notebooks」
作成すると、以下のようなノートが開きます。
この「▷(さんかく)」の右の黒い枠の中に、コードを書いていきます。

コードを入力して実行すると、右側のRAM、ディスクと書かれたところで何やら動きがあります。
これが動くことで、RAMや適宜GPUやディスクが使えるようになる、つまり動かせるようになります。

接続したものは「セッション」で管理されており、使用時間(や要求する性能)に応じてコンピューティングユニットが消費されていきます。
分かりにくいですが、上記の画像で言えば、1時間当たり0.08消費されます。
高価なGPUを割り当てると、このコンピューティングユニットの消費量は増加します。
なので、使っていないのに放置していると、無駄にコンピューティングユニットが消費されますので、すぐに切ってしまうことをオススメします。
ただし、環境構築に時間がかかる場合は、あえて繋げておくのも手ですね。
セッションを切断する度に、構築したものは消えます。また最初からです。
更に注意で、有料版でも24時間、無料版だと12時間でセッションは切れます。
なので、作ったもの等がある場合は、これもこまめにGoogledriveに退避するか、zipにしてダウンロードしないと危ないです。
自分はこれで何回かいろいろ無駄にして、闇に消えました。

上記の画像のように、ChatGPTに出力してもらったコードを入力します。
以下の画像はChatGPT側の画面ですが、この赤く囲ったところをクリックするとコピーされます。
それを、GoogleColabの先ほどの「▷(さんかく)」の横に、ctrl+vで貼り付けます。

コメントはあった方が後々見やすいので、適当に#から始まる日本語を入れています。
先頭ですし、入れなくてもよいですが、途中途中は長くなると見辛くなるのであったほうが良いです。
これで、「▷(さんかく)」を押すとコードが実行されます。
緑色のチェックがつくのと、下に実行秒数が表示されます。

エラーがあると以下のようになります。
!マークが表示されるのと、理由がその下部のログに出力されます。

このエラーについても、ChatGPTに聞けば大体解決できるので大丈夫です。
聞くときは、「先ほど示されたコードを実行した際に次のようなエラーが表示されましたが、どうすればよいでしょうか。「~ここにログ~」」のように適当で大丈夫です。

コード
作ってもらったコードは以下です。2つに分割していますが、
先ずは1つめでTesseractと日本語の言語データをインストールします。
TesseractはGoogleが開発したオープンソースのOCRエンジンです。多言語対応しているという特徴があります。
2つめで処理を実行していきます。
中身としては、GoogleDriveの任意のフォルダにアクセスして、その中身を一律OCR処理していくものです。

インストール部分と実行部分は分けた方がよいです。
Googledriveの接続部分も分けた方がよいですが、1度繋げてしまえば何度も要求されるものではない(悪さはしない)ので、そのままにしています。
!apt install -y libtesseract-dev libleptonica-dev liblept5
!apt install -y libtesseract-dev tesseract-ocr tesseract-ocr-jpn tesseract-ocr-jpn-vert
!pip install pytesseract
import pytesseract
from PIL import Image
import os
from google.colab import drive
# Google Driveをマウントします
drive.mount('/content/drive')
# 言語モードを設定します ('horizontal' or 'vertical')
lang_mode = 'horizontal' # ここを 'vertical' に変更すると縦書きの日本語を読み取ります
# 言語モードに基づいてTesseractの言語設定を選択します
tesseract_lang = 'jpn' if lang_mode == 'horizontal' else 'jpn_vert'
# Google Drive内のフォルダにあるすべての画像ファイルに対してOCR処理を行います
folder_path = '/content/drive/MyDrive/your_folder' # フォルダのパスを指定してください
for filename in os.listdir(folder_path):
if filename.endswith('.png') or filename.endswith('.jpg'):
img_path = os.path.join(folder_path, filename)
img = Image.open(img_path)
text = pytesseract.image_to_string(img, lang=tesseract_lang)
text_without_spaces = text.replace(' ', '') # スペースを除去します
print(f"OCR result for {filename}:\n{text_without_spaces}\n")
# Google Driveをマウントします
では、以下のようなダイアログが初回出ます。接続を押して自分のアカウントで入ると、処理が続行されます。1度許可すると、このセッション中は二度と要求されません。

#言語モードを設定します ('horizontal' or 'vertical')
で、縦書きか横書きかを選択します。
#Google Drive内のフォルダにあるすべての画像ファイルに対してOCR処理を行います
のファイルパスですが、自分で好きなフォルダに変えるとよいです。
MyDriveまでは固定なので、その次の名前から変更します。
今回は「OCR」というフォルダを作ってその中に入れています。

その下には、「スペースを除去します」と書いてありますが、縦書きの場合変なスペースが単語の合間合間に入ってしまう問題があったため、簡易的にそういう書き方を追加しています。
この辺については、ステップバイステップで指示を言葉で伝えながらコーディングできるので、大変便利で素晴らしいです。

実装されるものは、必ずしも適切なものでは無いですが、そうであれば都度都度また指示を与えればいくらでも書き換えてくれるのでめちゃくちゃ良いです。
実際の人間にやらせると、レビュー→修正→レビュー2……と無駄に時間がかかると思います。そういうのがなくなるので時短になりますね。
(そうなってくると、要件定義や基本設計の精度の向上が求められますね)
実行結果
話を戻しまして、実行結果が以下になります。
完璧ではないですが、なかなか良い結果だと思います。
これが格納された画像枚数分だけ出力してくれます。

読み込ませた画像が以下です。
青空文庫から取得して、Kindleで開いて、iPhoneでスクショしたものです。

精度については、ふりがなが悪さしている気がします。
後は、本を読み終えるまで、も悪さしていますね。
再度別の本で試してみます。
今度はリサイズ(本文だけになるように)と、ふりがな無しです。


更に精度が上がった気がします。
完璧ではないですが、事前に読み込ませる画像をある程度シンプルにしてあげると、かなり使えそうですね。
1点注意点として、iPhoneでそのままリサイズをかけた場合、Googledriveアプリのアップロードボタンからアップロードしないと、拡張子が「.jpeg」になります。+ボタンのアップロードから行うと「.png」になるので、そのまま使えます。ここだけ注意ですね。
(写真アプリ中で画像を長押しし、ホールドした状態でGoogledriveを起動し、そこではなしてもアップロードできますが、そうすると拡張子が.jpegになって処理されなくなる、ということです。)
まとめ
コーディングがこうも手軽にできると良いですね。
出力結果も単にテキストでログに出されるだけなので、例えば.txtにして終了後にダウンロードするようにしたり等、工夫の余地はありそうですね。
おまけ
ChatGPTとのやりとりです。あまりに長いので一部抜粋です。
オススメのOCRソフト等はありますか?
以下にいくつかのオススメのOCRツールをリストアップします。これらのツールは使いやすさ、精度、多言語対応などの観点から評価されています。ただし、これらのツールの利用条件やプライバシーポリシーは利用者自身で確認するようにしてください。
1. **Google Cloud Vision API**: Googleの提供するAPIで、画像内のテキストの抽出だけでなく、顔認識や物体検出などの機能も備えています。
2. **Tesseract**: Googleが開発したオープンソースのOCRエンジンで、100以上の言語に対応しています。
3. **Adobe Acrobat**: PDFファイルをテキストに変換する際によく使われるツールです。画像ファイルもテキストに変換することが可能です。
4. **ABBYY FineReader**: 商用のOCRソフトで、高精度なテキスト抽出が可能です。多言語に対応しています。
これらのツールの中から、自分のニーズに最も合ったものを選んでみてください。また、これらのツールを使うには、一部のツールでは専門的な知識が必要な場合がありますので、その点もご注意ください。
Tesseractをpythonで実装できますか?
はい、Tesseract OCRエンジンはPythonで利用することができます。PythonからTesseractを使うためには、`pytesseract`というライブラリを使います。以下に基本的な使い方を示します。
まず、Tesseractとpytesseractをインストールします。TesseractはOSによってインストール方法が異なります。以下にUbuntuの場合のインストール方法を示します。
```bash
sudo apt install tesseract-ocr
pip install pytesseract
```
次に、Pythonのコードで画像からテキストを抽出する方法です。
```python
import pytesseract
from PIL import Image
img = Image.open('path_to_your_image.png')
text = pytesseract.image_to_string(img, lang='eng')
print(text)
```
このコードでは、PIL(Python Imaging Library)を使って画像を開き、その画像を`pytesseract.image_to_string`関数に渡しています。この関数は画像からテキストを抽出し、そのテキストを文字列として返します。`lang`引数は抽出するテキストの言語を指定します。ここでは英語('eng')を指定しています。
なお、Tesseractは多言語に対応していますが、追加の言語データをインストールする必要があります。例えば、日本語のテキストを抽出するには、以下のように日本語の言語データをインストールします(Ubuntuの場合)。
```bash
sudo apt install tesseract-ocr-jpn
```
そして、`image_to_string`関数の`lang`引数に'jpn'を指定します。
```python
text = pytesseract.image_to_string(img, lang='jpn')
```
なお、この情報は2021年のもので、それ以降にライブラリのアップデートがあった場合は公式のドキュメンテーションをご確認ください。
GoogleColabでも同じように実装して動かせますか?
はい、Google Colabでも同様の方法でTesseractとpytesseractを利用できます。ただし、Google Colab上でTesseractを利用するためには、TesseractをColab環境にインストールする必要があります。以下にその方法を示します。
まず、以下のコマンドを実行してTesseractと日本語の言語データをインストールします。
```python
!apt install -y libtesseract-dev libleptonica-dev liblept5
!apt install -y libtesseract-dev tesseract-ocr tesseract-ocr-jpn
!pip install pytesseract
```
そして、以下のようにPythonのコードで画像からテキストを抽出します。
```python
import pytesseract
from PIL import Image
from IPython.display import display
# 画像をアップロードします
from google.colab import files
uploaded = files.upload()
# アップロードした画像を開きます
img = Image.open(next(iter(uploaded)))
# 画像を表示します
display(img)
# 画像からテキストを抽出します
text = pytesseract.image_to_string(img, lang='jpn')
print(text)
```
このコードでは、まず`google.colab.files.upload`関数を使って画像をアップロードします。そして、その画像をPILを使って開き、`pytesseract.image_to_string`関数に渡してテキストを抽出します。
なお、この情報は2021年のもので、それ以降にライブラリのアップデートがあった場合は公式のドキュメンテーションをご確認ください。
中略
先ほどのやり方では、縦書きの画像はあまりうまく処理されませんでした。
Tesseractで日本語の縦書きテキストを読み取るためには、`jpn_vert`という名前の言語データをインストールする必要があります。以下に、Google Colab上で`jpn_vert`をインストールする方法を示します。
```python
!apt install -y libtesseract-dev libleptonica-dev liblept5
!apt install -y libtesseract-dev tesseract-ocr tesseract-ocr-jpn tesseract-ocr-jpn-vert
!pip install pytesseract
```
そして、以下のようにPythonのコードで縦書きの日本語テキストを読み取ります。
```python
import pytesseract
from PIL import Image
from IPython.display import display
# 画像をアップロードします
from google.colab import files
uploaded = files.upload()
# アップロードした画像を開きます
img = Image.open(next(iter(uploaded)))
# 画像を表示します
display(img)
# 画像からテキストを抽出します
text = pytesseract.image_to_string(img, lang='jpn_vert')
print(text)
```
このコードでは、`pytesseract.image_to_string`関数の`lang`引数に`'jpn_vert'`を指定しています。これにより、縦書きの日本語テキストを読み取ることができます。
なお、この情報は2021年のもので、それ以降にライブラリのアップデートがあった場合は公式のドキュメンテーションをご確認ください。
フォルダの中に画像を入れて、それをまとめてOCR処理したいので、その機能を実装お願いします。
Google Colab環境でフォルダ内の画像をまとめてOCR処理するための基本的なスクリプトは以下の通りです。ここでは、アップロードした.zipファイルを解凍し、その中に含まれるすべての画像ファイルに対してOCR処理を行います。
まず、Tesseractとpytesseractをインストールします。
```python
!apt install -y libtesseract-dev libleptonica-dev liblept5
!apt install -y libtesseract-dev tesseract-ocr tesseract-ocr-jpn tesseract-ocr-jpn-vert
!pip install pytesseract
```
そして、以下のようにPythonのコードでフォルダ内の画像をまとめてOCR処理します。
```python
import pytesseract
from PIL import Image
import os
from zipfile import ZipFile
from google.colab import files
from IPython.display import display
# .zipファイルをアップロードします
uploaded = files.upload()
# アップロードした.zipファイルを解凍します
zip_name = next(iter(uploaded))
with ZipFile(zip_name, 'r') as zip_ref:
zip_ref.extractall()
# 解凍したフォルダ内のすべての画像ファイルに対してOCR処理を行います
folder_name = zip_name[:-4] # .zip拡張子を削除
for filename in os.listdir(folder_name):
if filename.endswith('.png') or filename.endswith('.jpg'):
img = Image.open(os.path.join(folder_name, filename))
display(img)
text = pytesseract.image_to_string(img, lang='jpn_vert')
print(f"OCR result for {filename}:\n{text}\n")
```
このコードでは、まず`google.colab.files.upload`関数を使って.zipファイルをアップロードします。そして、その.zipファイルを解凍し、解凍したフォルダ内のすべての.pngファイルと.jpgファイルに対してOCR処理を行います。
なお、このコードは一部の画像形式(.pngと.jpg)に対してのみ動作します。他の画像形式に対してもOCR処理を行いたい場合は、`filename.endswith('.png') or filename.endswith('.jpg')`の部分を適切に変更してください。また、この情報は2021年のもので、それ以降にライブラリのアップデートがあった場合は公式のドキュメンテーションをご確認ください。
Googledrive内の画像をまとめてOCR処理できるように、実装してください。
Google Drive内のフォルダにある画像をまとめてOCR処理するための基本的なスクリプトは以下の通りです。ここでは、Google Driveのマウント機能を利用して、Google Colab環境からGoogle Drive内のファイルにアクセスします。
まず、Tesseractとpytesseractをインストールします。
```python
!apt install -y libtesseract-dev libleptonica-dev liblept5
!apt install -y libtesseract-dev tesseract-ocr tesseract-ocr-jpn tesseract-ocr-jpn-vert
!pip install pytesseract
```
そして、以下のようにPythonのコードでGoogle Drive内のフォルダにある画像をまとめてOCR処理します。
```python
import pytesseract
from PIL import Image
import os
from google.colab import drive
# Google Driveをマウントします
drive.mount('/content/drive')
# Google Drive内のフォルダにあるすべての画像ファイルに対してOCR処理を行います
folder_path = '/content/drive/MyDrive/your_folder' # フォルダのパスを指定してください
for filename in os.listdir(folder_path):
if filename.endswith('.png') or filename.endswith('.jpg'):
img_path = os.path.join(folder_path, filename)
img = Image.open(img_path)
text = pytesseract.image_to_string(img, lang='jpn_vert')
print(f"OCR result for {filename}:\n{text}\n")
```
このコードでは、まず`google.colab.drive.mount`関数を使ってGoogle Driveをマウントします。そして、指定したフォルダ内のすべての.pngファイルと.jpgファイルに対してOCR処理を行います。
なお、このコードは一部の画像形式(.pngと.jpg)に対してのみ動作します。他の画像形式に対してもOCR処理を行いたい場合は、`filename.endswith('.png') or filename.endswith('.jpg')`の部分を適切に変更してください。また、この情報は2021年のもので、それ以降にライブラリのアップデートがあった場合は公式のドキュメンテーションをご確認ください。
変なスペースが入るので、スペースを結果から取り除くようなコードを追加できますか?
スペースを除去するために、Pythonの`str.replace`メソッドを使用できます。このメソッドは指定した部分文字列を別の文字列に置換します。スペースを除去するためには、スペース(`' '`)を空文字列(`''`)に置換します。
以下に修正したコードを示します:
```python
import pytesseract
from PIL import Image
import os
from google.colab import drive
# Google Driveをマウントします
drive.mount('/content/drive')
# Google Drive内のフォルダにあるすべての画像ファイルに対してOCR処理を行います
folder_path = '/content/drive/MyDrive/your_folder' # フォルダのパスを指定してください
for filename in os.listdir(folder_path):
if filename.endswith('.png') or filename.endswith('.jpg'):
img_path = os.path.join(folder_path, filename)
img = Image.open(img_path)
text = pytesseract.image_to_string(img, lang='jpn')
text_without_spaces = text.replace(' ', '') # スペースを除去します
print(f"OCR result for {filename}:\n{text_without_spaces}\n")
```
このコードでは、OCR処理の結果を得た後で`text.replace(' ', '')`を呼び出してスペースを除去しています。
なお、`replace`メソッドは全てのスペースを除去しますが、これが適切でない場合(例えば、単語の間のスペースを保持したい場合)は、適切な方法でスペースを処理してください。また、この情報は2021年のもので、それ以降にライブラリのアップデートがあった場合は公式のドキュメンテーションをご確認ください。
上記のコードを縦書きの日本語版にして下さい。可能なら縦書きか、横書きかを入力で選べるようにできませんか
言語設定を横書きの日本語('jpn')または縦書きの日本語('jpn_vert')に切り替えられるようにするために、新たに`lang_mode`という変数を導入します。この変数に`'horizontal'`を設定すると横書きの日本語を、`'vertical'`を設定すると縦書きの日本語を読み取る設定になります。
以下に修正したコードを示します:
```python
import pytesseract
from PIL import Image
import os
from google.colab import drive
# Google Driveをマウントします
drive.mount('/content/drive')
# 言語モードを設定します ('horizontal' or 'vertical')
lang_mode = 'horizontal' # ここを 'vertical' に変更すると縦書きの日本語を読み取ります
# 言語モードに基づいてTesseractの言語設定を選択します
tesseract_lang = 'jpn' if lang_mode == 'horizontal' else 'jpn_vert'
# Google Drive内のフォルダにあるすべての画像ファイルに対してOCR処理を行います
folder_path = '/content/drive/MyDrive/your_folder' # フォルダのパスを指定してください
for filename in os.listdir(folder_path):
if filename.endswith('.png') or filename.endswith('.jpg'):
img_path = os.path.join(folder_path, filename)
img = Image.open(img_path)
text = pytesseract.image_to_string(img, lang=tesseract_lang)
text_without_spaces = text.replace(' ', '') # スペースを除去します
print(f"OCR result for {filename}:\n{text_without_spaces}\n")
```
このコードでは、`lang_mode`変数に基づいてTesseractの言語設定を選択しています。`lang_mode`が`'horizontal'`なら`'jpn'`を、`'vertical'`なら`'jpn_vert'`を使用します。
なお、この情報は2021年のもので、それ以降にライブラリのアップデートがあった場合は公式のドキュメンテーションをご確認ください。