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ファイルが作成される