OCRのモジュール化とCSVファイルの作成

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

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です