OCRのモジュール化
画像ファイルを引数にして使うのでモジュール化する
from google.cloud import vision
client = vision.ImageAnnotatorClient()
with open("test.jpg", "rb") as fb:
content = fb.read()
image = vision.Image(content=content)
response = client.document_text_detection(image=image)
texts = response.text_annotations
print(texts[0].description)
をモジュールにする
touch ocr_module.py
コードは
# ocr_module.py
from google.cloud import vision
class OCRProcessor:
def __init__(self):
# Vision APIクライアントの初期化
self.client = vision.ImageAnnotatorClient()
def extract_text_from_image(self, image_path):
"""
画像からテキストを抽出するメソッド
Args:
image_path (str): 画像ファイルのパス
Returns:
str: 画像から抽出されたテキスト
"""
with open(image_path, "rb") as fb:
content = fb.read()
image = vision.Image(content=content)
response = self.client.document_text_detection(image=image)
texts = response.text_annotations
if texts:
return texts[0].description
else:
return ""
使う時には
# main.py
from ocr_module import OCRProcessor
def main():
# OCRProcessorのインスタンスを作成
ocr_processor = OCRProcessor()
# 画像ファイルパスを指定
image_path = "test.jpg"
# 画像からテキストを抽出
extracted_text = ocr_processor.extract_text_from_image(image_path)
# 抽出されたテキストを出力
print("抽出されたテキスト:")
print(extracted_text)
if __name__ == "__main__":
main()
というようにする
さらに
import re
import csv
from datetime import datetime
# ファイルからテキストを読み込む
with open('ocr.txt', 'r', encoding='utf-8') as file:
text = file.read()
# 情報を抽出
date_match = re.search(r'\d{4}年\d{1,2}月\d{1,2}日', text)
date = datetime.strptime(date_match.group(), '%Y年%m月%d日').strftime('%Y-%m-%d')
shop_name_match = re.search(r'とれたて食楽部', text)
shop_name = shop_name_match.group()
# 商品情報を正規表現で抽出
items = re.findall(r'内\d+ (.+?) ¥(\d+)', text)
# 現在のタイムスタンプを生成
timestamp = datetime.now().strftime('%Y%m%d%H%M%S')
# 出力ファイル名にタイムスタンプを付ける
csv_filename = f'receipt_data_{timestamp}.csv'
# CSVファイルに出力
with open(csv_filename, mode='w', newline='', encoding='utf-8') as csvfile:
csv_writer = csv.writer(csvfile)
# ヘッダー行を書き込み
csv_writer.writerow(["日付", "店名", "商品名", "数量", "金額"])
for item in items:
product_name, price = item
# 商品名の「/」以降を削除
product_name_clean = product_name.split('/')[0]
# 出力: 日付, 店名, 商品名, 数量, 金額
row = f"{date},{shop_name},{product_name_clean},1,{price}"
csv_writer.writerow(row.split(','))
print(f"CSVファイル '{csv_filename}' に出力しました。")
のCSV変換もモジュール化する
touch ocr_to_csv.py
# ocr_to_csv.py
import re
import csv
from datetime import datetime
class OCRToCSV:
def __init__(self, input_file):
self.input_file = input_file
self.text = self._read_text_from_file()
self.date = self._extract_date()
self.shop_name = self._extract_shop_name()
self.items = self._extract_items()
def _read_text_from_file(self):
with open(self.input_file, 'r', encoding='utf-8') as file:
return file.read()
def _extract_date(self):
date_match = re.search(r'\d{4}年\d{1,2}月\d{1,2}日', self.text)
if date_match:
return datetime.strptime(date_match.group(), '%Y年%m月%d日').strftime('%Y-%m-%d')
return None
def _extract_shop_name(self):
shop_name_match = re.search(r'とれたて食楽部', self.text)
return shop_name_match.group() if shop_name_match else None
def _extract_items(self):
return re.findall(r'内\d+ (.+?) ¥(\d+)', self.text)
def generate_csv(self, output_dir='.', timestamp=None):
if timestamp is None:
timestamp = datetime.now().strftime('%Y%m%d%H%M%S')
csv_filename = f'{output_dir}/receipt_data_{timestamp}.csv'
with open(csv_filename, mode='w', newline='', encoding='utf-8') as csvfile:
csv_writer = csv.writer(csvfile)
csv_writer.writerow(["日付", "店名", "商品名", "数量", "金額"])
for item in self.items:
product_name, price = item
product_name_clean = product_name.split('/')[0]
row = f"{self.date},{self.shop_name},{product_name_clean},1,{price}"
csv_writer.writerow(row.split(','))
print(f"CSVファイル '{csv_filename}' に出力しました。")
return csv_filename
この2つを使い
OCRした結果を受け取りCSVファイルにするようにする
touch main_ocr.py
# main.py
from ocr_module import OCRProcessor
from ocr_to_csv import OCRToCSV
def main():
# OCRProcessorのインスタンスを作成
ocr_processor = OCRProcessor()
# 画像ファイルパスを指定
image_path = 'test.jpg'
# 画像からテキストを抽出
extracted_text = ocr_processor.extract_text_from_image(image_path)
# OCRToCSVのインスタンスを作成し、抽出されたテキストを処理
ocr_to_csv = OCRToCSV(extracted_text)
ocr_to_csv.generate_csv()
if __name__ == "__main__":
main()
しかし、これで実行すると
I0000 00:00:1723753428.164426 15335390 config.cc:230] gRPC experiments enabled: call_status_override_on_cancellation, event_engine_dns, event_engine_listener, http2_stats_fix, monitoring_experiment, pick_first_new, trace_record_callops, work_serializer_clears_time_cache
Traceback (most recent call last):
File "/Users/snowpool/aw10s/receit_ocr/main_ocr.py", line 21, in <module>
main()
File "/Users/snowpool/aw10s/receit_ocr/main_ocr.py", line 17, in main
ocr_to_csv = OCRToCSV(extracted_text)
File "/Users/snowpool/aw10s/receit_ocr/ocr_to_csv.py", line 10, in __init__
self.text = self._read_text_from_file()
File "/Users/snowpool/aw10s/receit_ocr/ocr_to_csv.py", line 16, in _read_text_from_file
with open(self.input_file, 'r', encoding='utf-8') as file:
FileNotFoundError: [Errno 2] No such file or directory: 'それで食楽部\n登録番号 15080401017738\nとれたて食楽部\n2024年8月10日 (土) 08:59 #000011\n000801精算機 1 000801精算機1\n3901\nお会計券 #000003 R9309 09:08\n000008 西澤\n内8 きゅうり/鈴木仁 ¥150\nP2023300101503\n内8 きゅうり/小林宗作 ¥130\nP2055600101303\n内8 リーフレタス/(有)成神工 ¥216\nP2086402402169\n小計\n¥496\n(内税8%対象額\n¥496)\n買上点数\n3点\n合計\n¥496\n(税率8%対象額\n¥496)\n(内消費税等 8%\n¥36)\n課税事業者\n(税率 8%対象額\n¥216)\n(内消費税等 8%\n¥16)\n免税事業者\n(税率 8%対象額\n¥280)\nクレジット\n¥496\n(内消費税等\n¥36)\n8、内容は軽減税率対象商品です。\n約專業者商品'
となる
原因はモジュールがファイルを渡す前提になっているため
渡されたテキストを処理するようにする
OCRToCSVクラスの__init__メソッドで、self.textとして直接テキストを受け取るように変更しました。
_read_text_from_fileメソッドは削除しました。代わりに、コンストラクタで直接テキストを受け取ります。
import re
import csv
from datetime import datetime
class OCRToCSV:
def __init__(self, text):
self.text = text
self.date = self._extract_date()
self.shop_name = self._extract_shop_name()
self.items = self._extract_items()
def _extract_date(self):
date_match = re.search(r'\d{4}年\d{1,2}月\d{1,2}日', self.text)
if date_match:
return datetime.strptime(date_match.group(), '%Y年%m月%d日').strftime('%Y-%m-%d')
return None
def _extract_shop_name(self):
shop_name_match = re.search(r'とれたて食楽部', self.text)
return shop_name_match.group() if shop_name_match else None
def _extract_items(self):
return re.findall(r'内\d+ (.+?) ¥(\d+)', self.text)
def generate_csv(self, output_dir='.', timestamp=None):
if timestamp is None:
timestamp = datetime.now().strftime('%Y%m%d%H%M%S')
csv_filename = f'{output_dir}/receipt_data_{timestamp}.csv'
with open(csv_filename, mode='w', newline='', encoding='utf-8') as csvfile:
csv_writer = csv.writer(csvfile)
csv_writer.writerow(["日付", "店名", "商品名", "数量", "金額"])
for item in self.items:
product_name, price = item
product_name_clean = product_name.split('/')[0]
row = f"{self.date},{self.shop_name},{product_name_clean},1,{price}"
csv_writer.writerow(row.split(','))
print(f"CSVファイル '{csv_filename}' に出力しました。")
return csv_filename
これで再度実行すると問題なくCSVファイルが作成される