
[業務改善]ChatGPTに、表データが記載された紙を読み込み、表を再現する機能をつくってもらった!(pytesseract, OCR)
以前ChatGPTに作ってもらった「文字画像を抽出する機能」が使えそうなので、もうちょっとカスタマイズしてみることにしました。
今回もChatGPTを使用して、表データが記載された画像ファイルを読み込み、表形式で画面表示するような機能を作成していこうと思います。
以前ChatGPTに作ってもらった「文字画像を抽出する機能」
目的
手作業をなくし、すべての工程を自動化することを目標として、検討を進めて参ります。

紙データを手書きで転記する必要がなくなり、さらにデジタルデータを整形することができる
「文字画像を抽出する機能」を使用すれば、紙からデジタルに移行する際に、手で書き写す必要がなくなりますし、独自のフォーマットに応じて、デジタルデータ化する際にプログラミングすることでカスタマイズできますので、そのあたりは作るメリットがあるのかなと。
デジタル化したあとに、そのデジタルデータを整形し直す工程を極力少なくすることを目標に作っていこうと思います!
表が記載された画像データをどのように取り込むかを検討する
表が記載された画像データを表形式として取り込む方法を考えていきます!
まずはChatGPTに聞いてみようと思います。
プロンプト
画像ファイルから表形式のデータを抽出したいです
ChatGPTの回答(コード箇所は割愛)
画像ファイルから表形式のデータを抽出するためには、いくつかの方法がありますが、一般的な方法は次のとおりです。
OCR(Optical Character Recognition)を使用する: OCRライブラリ(例: Tesseract)を使用して画像からテキストを抽出し、そのテキストを解析して表形式のデータを抽出します。
画像処理を使用する: 画像処理ライブラリ(例: OpenCV)を使用して画像から表形式のデータを抽出します。これには、輪郭検出、領域の分割、文字認識などの手法が含まれます。
以下では、上記の方法のうちの1つを使って表形式のデータを抽出する方法を示します。
1. OCRを使用する方法
まず、PythonでTesseractを使用して画像からテキストを抽出します。その後、抽出されたテキストから表形式のデータをパースします。
このコードでは、まず画像からテキストを抽出し、その後テキストから表形式のデータを抽出する関数を定義しています。テキストからのデータの抽出方法は、テキストの形式によって異なりますので、実際のデータに適した抽出方法を選択する必要があります。例えば、正規表現や文字列の分割を使ってデータを抽出することが考えられます。
表を再現するには、テキストを解析し、改行やスペースなどを頼りに表を作る
表を再現するには、テキストを解析し、改行やスペースなどを頼りに表となるように組み立てていくみたいですので、専用の加工処理が必要になってきそうです。
一撃では、いい感じの表形式にならなそうですね、、
イメージ的には、画像ファイルから以下のように文字を抽出し、このデータの内容で表形式を作れば、表が再現できるようなイメージです。
ああ[スペース]いい[スペース]うう[スペース]ええ[改行]
かか[スペース]きき[スペース]くく[スペース]けけ[改行]
設計イメージを作る
次に設計イメージを作っていきます。
設計イメージを作ると、作成する機能を整理できる
設計イメージを作ることで、これから作成する機能を整理できるのと、中断した際に作成内容を思い出すのに楽ですし。
作成する機能は、「画像ファイルを読み込み、表形式で画面表示する」
赤枠が今回の作成する箇所です。
表データが記載された画像ファイルを読み込み、最終的に表形式で画面表示するような機能を作成していこうと思います。
後日、表データをPDF化やエクセル化していくなど、さらに機能追加をしていこうかと思います。ベースの機能があると色々な機能に応用しやすいですね。

設計イメージもChatGPTと一緒に作る
上記設計イメージを作る際にも、ChatGPTに「画像ファイルを読み込み、表形式で画面表示する」コードを教えてもらい、そのコードの内容を参考に、どのようなコードを作っていくかをフローとして簡単にまとめていきます。
ChatGPTへの指示出しは、少ないコード量でまとまるような指示の方が、微調整しやすい
ChatGPTにコーディング依頼をする際には、長文の指示でコード量が多いコーディングより、少ないコード量でまとまるような指示の方が、微調整しやすいのと、今後の改修もしやすいので、ファンクション単位での指示を出すのが良いかと思います。どのあたりをファンクションとして切り出すのを検討するのに設計メモは参考になります。
動作確認その1
ChatGPTに作ってもらったコーディングについては、以前に作成したもの(上記リンク)と、そこまで大幅に変わらないので割愛します。
読み取り対象の画像ファイル
ちょうど表形式の画像ファイルがあったので、このスクショ画像を使っていきます。(以前ChatGPTで作ったもの)

結果
おっと・・!
全然表になりませんね、、
読み取り対象の画像ファイルと比較すると、左上から右側に読み込まれておりませんね、、

左上から右側に読み込まれる方法についてChatGPTに聞く
プロンプト
pytesseract.image_to_string
上記、表形式のデータを読み込みたいのですが、 左から右に読み込まれず、左から下に読み込んでしまいます
表形式のデータをOCRで読み取る場合、テキストが左から右に読み込まれず、左から下に読み込まれる問題が発生することがあります。これは、OCRエンジンがテキストを連続したブロックとして読み取るためであり、表形式のデータを構造化して正確に解釈するのが難しいためです。
このような場合、いくつかのアプローチが考えられます。事前の画像処理: 表形式のデータを含む画像を事前に処理して、OCRエンジンによる認識の精度を向上させることができます。例えば、画像を回転させてテキストを水平方向に配置する、または列ごとにテキストを切り分けるなどの処理を行うことが考えられます。
OCRエンジンの設定の調整: pytesseractなどのOCRエンジンには、テキストの方向や言語、文字セットなどの設定を変更するオプションがあります。これらの設定を調整して、表形式のデータをより適切に認識することができるかもしれません。
OCR後のテキスト処理: OCRによって得られたテキストを処理して、表形式のデータを抽出するアルゴリズムを実装することも可能です。テキストのパターンを解析し、セルや行ごとにデータを分割して解釈する方法があります。この場合、正規表現や文字列操作などのテキスト処理の技術が役立ちます。
これらのアプローチのうち、特定のケースに最適なものは、テキストや表形式のデータの特性によって異なります。
プロンプト
上記2について、具体的なやり方を教えてください
OCRエンジンの設定の調整について具体的には、pytesseractの場合、言語やテキストの方向、ページのセグメンテーションなどを設定することができます。
以下に、それぞれの設定の調整方法を示します。
言語の設定: langパラメータを使用して、認識する言語を指定します。たとえば、日本語の場合はlang='jpn'とします。他の言語を使用する場合は、言語コードに合わせて指定します。
テキストの方向の設定: psmパラメータを使用して、OCR処理するテキストの方向を指定します。たとえば、テキストが単一の行であることを示す場合はpsm=6、単一の文字であることを示す場合はpsm=10を使用します。これにより、OCRエンジンがテキストの方向を正しく認識できる可能性が高まります。
ページのセグメンテーション: oemパラメータを使用して、OCRエンジンのモードを指定します。デフォルトでは、oem=3でTesseractのモードが使用されますが、oem=1やoem=2などの異なるモードも使用できます。これにより、テキストのレイアウトやセグメンテーションが改善される可能性があります。
以下は、これらの設定を組み合わせたpytesseract.image_to_stringの使用例です。
import pytesseract
from PIL import Image
# 画像からテキストをOCR処理して抽出する関数
def extract_text_from_image(image_path):
try:
# 画像を開く
image = Image.open(image_path)
# 画像からテキストを抽出
text = pytesseract.image_to_string(image, lang='jpn', psm=6, oem=3) # 日本語の場合の設定例
return text
except Exception as e:
print("テキストの抽出中にエラーが発生しました:", e)
return None
# 使用例
image_path = 'path/to/your/image.jpg'
text = extract_text_from_image(image_path)
print(text)
これらの設定を調整することで、表形式のデータを正確に認識する可能性が高まります。ただし、依然として特定の条件やフォーマットによっては正確な認識が難しい場合もありますので、その場合は他のアプローチを検討する必要があります。
pytesseract.image_to_stringの設定値で微調整ができる
pytesseract.image_to_stringの引数の設定(テキストの方向の設定: psm、ページのセグメンテーション: oem)により、微調整できるとのことです。
psmとoemのそれぞれのモードをChatGPTに聞いたところ、ネットで調べた内容と色々と異なっていたので、モードの記載は割愛します。
また、上記でChatGPTに教えてもらったコードではエラーとなり、エラーメッセージを伝えたところエラーとならないロジックを提示してくれました、、
修正前
text = pytesseract.image_to_string(image, lang='jpn', psm=6, oem=3)
修正後
# psmとoemのパラメータが未指定の場合は、デフォルト値を設定する
config = f'--psm {psm}' if psm is not None else ''
config += f' --oem {oem}' if oem is not None else ''
# 画像からテキストを抽出して返す
text = pytesseract.image_to_string(image, lang='jpn', config=config)
動作確認その2
pytesseract.image_to_stringの設定値が、psm=6, oem=3となるように設定し、動作確認!
読み取り結果
今度は左上から右側へ読みこんでくれました!
ただ表としてはかなり崩れてしまってますね、、

pytesseract.image_to_stringの抽出内容として、何の空白文字や制御文字が返却されるか精査する
ChatGPTに、「pytesseract.image_to_stringの抽出内容として、何の空白文字や制御文字が返却されるか」を聞いたところ、思った通りの回答とならなかったので、1文字ずつ文字コードをデバックするコードをChatGPTに作ってもらいました。
返却された制御文字は、改行コードと半角スペースのみ
上記ChatGPTに作ってもらったコードを実行したところ、返却された制御文字は、改行コードと半角スペースのみで、タブ文字はありませんでした。
Character Code: 10 改行コード
Character Code: 32 半角スペース
Character: 変, Character Code: 22793
Character: 更, Character Code: 26356
Character:
, Character Code: 10
Character: 1, Character Code: 49
Character: , Character Code: 32
Character: , Character Code: 32
Character: , Character Code: 32
Character: , Character Code: 32
Character: , Character Code: 32
Character: , Character Code: 32
Character: , Character Code: 32
Character: , Character Code: 32
Character: , Character Code: 32
Character: , Character Code: 32
Character: , Character Code: 32
Character: , Character Code: 32
Character: , Character Code: 32
Character: , Character Code: 32
Character: , Character Code: 32
Character: , Character Code: 32
Character: , Character Code: 32
Character: , Character Code: 32
Character: , Character Code: 32
Character: , Character Code: 32
Character: , Character Code: 32
Character: , Character Code: 32
Character: , Character Code: 32
Character: , Character Code: 32
Character: , Character Code: 32
Character: , Character Code: 32
Character: , Character Code: 32
Character: , Character Code: 32
Character: , Character Code: 32
Character: , Character Code: 32
Character: , Character Code: 32
Character: , Character Code: 32
Character: , Character Code: 32
Character: , Character Code: 32
Character: , Character Code: 32
Character: , Character Code: 32
Character: , Character Code: 32
Character: , Character Code: 32
Character: , Character Code: 32
Character: , Character Code: 32
Character: , Character Code: 32
Character: , Character Code: 32
Character: 山, Character Code: 23665
Character: 田, Character Code: 30000
Character: , Character Code: 32
Character: 太, Character Code: 22826
Character: 郎, Character Code: 37070
Character: , Character Code: 32
半角スペースが複数続いた場合は、半角スペース1つに置換する
一旦、半角スペースが複数続いた場合は、半角スペース1つに置換することにしました。
表形式のデータとしては、未入力のカラムも存在するので、この対応では元データの内容によってはずれてしまうので、よろしくないのですが一旦このロジックで実施し、未入力パターンについてはその後検討しようと思います、、
動作確認その3
上記修正後に動作確認をしたところ、ようやく表が再現することができました!
あとは本来、表でないところは、表形式としないようなロジックとすれば大体のまとまってきそうです!

おわりに
最後まで読んで頂き、ありがとうございます!
まだ完成はしていませんが、記事が長くなってきたので、このあたりで終わりにしようと思います、、
取り込む表データのバリエーションはまだ少なく、課題がまだ残っている状況ですが、機能のベースができ、方向性も固まってきたので、今後もChatGPTと共にこのシステムを拡張していきたいと思います!
おまけ
最近クイズサイトを作りました!
1問でも実施していただけると嬉しいです!!!
それと、ChatGPTを使用し、色々なことを模索しています。
もしよければ、以下の記事も見て頂けると嬉しいです!