チラシの商品名をLINE送信
ocr_list.py
でキーワードと一致した商品名の取得ができるので
これを
line_notify.pyにセットして送信するようにする
import json from google.cloud import vision import io # 設定ファイルの読み込み settings_json = open('settings.json', 'r', encoding='utf_8') settings = json.load(settings_json) # OCRで画像からテキストを抽出 def detect_text(image_paths): client = vision.ImageAnnotatorClient() all_text = '' for image_path in image_paths: with io.open(image_path, 'rb') as image_file: content = image_file.read() image = vision.Image(content=content) # document_text_detectionを使用して文書全体のテキストを取得 response = client.document_text_detection(image=image) full_text_annotation = response.full_text_annotation # テキストの抽出 all_text += full_text_annotation.text if response.error.message: raise Exception( '{}\nFor more info on error messages, check: ' 'https://cloud.google.com/apis/design/errors'.format( response.error.message)) return all_text # キーワード検索 def search_words(all_text): hitwords = [] for keyword in settings["keywords"]: if keyword in all_text: hitwords.append(keyword) return hitwords # 例として実行 if __name__ == "__main__": image_paths = ["images/combined_image_20240805.jpg"] extracted_text = detect_text(image_paths) hitwords = search_words(extracted_text) # ヒットしたキーワードのみを表示 if hitwords: print("マッチしたキーワード:", ", ".join(hitwords)) else: print("マッチしたキーワードはありませんでした。")
の中で
import requests import os from PIL import Image from io import BytesIO from utils import load_config, get_latest_directory, get_image_files def resize_image_if_needed(image_data, max_size=3 * 1024 * 1024): if len(image_data) > max_size: image = Image.open(BytesIO(image_data)) new_size = (image.width // 2, image.height // 2) image = image.resize(new_size, Image.LANCZOS) output = BytesIO() image_format = image.format if image.format else 'JPEG' image.save(output, format=image_format) return output.getvalue() return image_data def send_line_notify(message, config_path='config.json'): # 設定ファイルを読み込む config = load_config(config_path) # 設定ファイルからトークンとディレクトリパスを取得 token = config['token'] base_path = config['image_file_path'] # 最新のpredictディレクトリを取得 latest_dir = get_latest_directory(base_path) image_files = get_image_files(latest_dir) url = 'https://notify-api.line.me/api/notify' headers = {'Authorization': f"Bearer {token}"} params = {'message': message} # 最新のpredictディレクトリ内の全ての画像ファイルに対してLINE Notify APIにリクエストを送信 for image_file_path in image_files: with open(image_file_path, 'rb') as img_file: img_data = img_file.read() img_data = resize_image_if_needed(img_data) # ファイルデータをバイトデータとして用意 files = {'imageFile': BytesIO(img_data)} files['imageFile'].name = os.path.basename(image_file_path) # LINE Notify APIにリクエストを送信 res = requests.post(url, headers=headers, params=params, files=files) # レスポンスを出力 print(f"File: {image_file_path}") print(res.status_code) print(res.text)
を呼び出し
hit words を line notifyで送信したい
その前に
import requests import os from PIL import Image from io import BytesIO from utils import load_config, get_latest_directory, get_image_files def resize_image_if_needed(image_data, max_size=3 * 1024 * 1024): if len(image_data) > max_size: image = Image.open(BytesIO(image_data)) new_size = (image.width // 2, image.height // 2) image = image.resize(new_size, Image.LANCZOS) output = BytesIO() image_format = image.format if image.format else 'JPEG' image.save(output, format=image_format) return output.getvalue() return image_data def send_line_notify(message, config_path='config.json'): # 設定ファイルを読み込む config = load_config(config_path) # 設定ファイルからトークンとディレクトリパスを取得 token = config['token'] base_path = config['image_file_path'] # 最新のpredictディレクトリを取得 latest_dir = get_latest_directory(base_path) image_files = get_image_files(latest_dir) url = 'https://notify-api.line.me/api/notify' headers = {'Authorization': f"Bearer {token}"} params = {'message': message} # 最新のpredictディレクトリ内の全ての画像ファイルに対してLINE Notify APIにリクエストを送信 for image_file_path in image_files: with open(image_file_path, 'rb') as img_file: img_data = img_file.read() img_data = resize_image_if_needed(img_data) # ファイルデータをバイトデータとして用意 files = {'imageFile': BytesIO(img_data)} files['imageFile'].name = os.path.basename(image_file_path) # LINE Notify APIにリクエストを送信 res = requests.post(url, headers=headers, params=params, files=files) # レスポンスを出力 print(f"File: {image_file_path}") print(res.status_code) print(res.text)
で今回はyolov8は使ってないので
まずはテキストのみにする
import requests import os from utils import load_config def send_line_notify(message, config_path='config.json'): # 設定ファイルを読み込む config = load_config(config_path) # 設定ファイルからトークンを取得 token = config['token'] url = 'https://notify-api.line.me/api/notify' headers = {'Authorization': f"Bearer {token}"} params = {'message': message} # LINE Notify APIにリクエストを送信 res = requests.post(url, headers=headers, params=params) # レスポンスを出力 print(res.status_code) print(res.text) # 例として実行 if __name__ == "__main__": message = "マッチしたキーワード: サンプルキーワード" send_line_notify(message)
とりあえず main 部分は削除して
ocr_list.pyの中で呼び出したい
import json from google.cloud import vision import io from line_notify import send_line_notify # 設定ファイルの読み込み def load_settings(file_path='settings.json'): with open(file_path, 'r', encoding='utf_8') as settings_json: return json.load(settings_json) # OCRで画像からテキストを抽出 def detect_text(image_paths): client = vision.ImageAnnotatorClient() all_text = '' for image_path in image_paths: with io.open(image_path, 'rb') as image_file: content = image_file.read() image = vision.Image(content=content) # document_text_detectionを使用して文書全体のテキストを取得 response = client.document_text_detection(image=image) full_text_annotation = response.full_text_annotation # テキストの抽出 all_text += full_text_annotation.text if response.error.message: raise Exception( '{}\nFor more info on error messages, check: ' 'https://cloud.google.com/apis/design/errors'.format( response.error.message)) return all_text # キーワード検索 def search_words(all_text, keywords): hitwords = [] for keyword in keywords: if keyword in all_text: hitwords.append(keyword) return hitwords # 例として実行 if __name__ == "__main__": settings = load_settings() image_paths = ["images/combined_image_20240805.jpg"] extracted_text = detect_text(image_paths) hitwords = search_words(extracted_text, settings["keywords"]) # ヒットしたキーワードをLINE Notifyで送信 if hitwords: message = "マッチしたキーワード: " + ", ".join(hitwords) send_line_notify(message) else: print("マッチしたキーワードはありませんでした。")
これを実行したらLINEで送信されたのでOK
このままだとメッセージが分かりにくいので
マッチしたキーワードから
特売リスト
にメッセージを変更
そしてOCRした画像ファイルも一緒にLINE送信するように
line_notify.pyのソースを変更
import requests import os from utils import load_config def send_line_notify(message, config_path='config.json'): # 設定ファイルを読み込む config = load_config(config_path) # 設定ファイルからトークンを取得 token = config['token'] url = 'https://notify-api.line.me/api/notify' headers = {'Authorization': f"Bearer {token}"} params = {'message': message} # LINE Notify APIにリクエストを送信 res = requests.post(url, headers=headers, params=params) # レスポンスを出力 print(res.status_code) print(res.text)
を
import requests from utils import load_config from io import BytesIO from PIL import Image def resize_image_if_needed(image_data, max_size=3 * 1024 * 1024): """ 画像が指定されたサイズを超える場合は、画像のサイズを縮小する。 Args: image_data (bytes): 画像データ。 max_size (int): 最大ファイルサイズ(バイト)。 Returns: bytes: サイズ変更後の画像データ。 """ if len(image_data) > max_size: image = Image.open(BytesIO(image_data)) new_size = (image.width // 2, image.height // 2) image = image.resize(new_size, Image.LANCZOS) output = BytesIO() image_format = image.format if image.format else 'JPEG' image.save(output, format=image_format) return output.getvalue() return image_data def send_line_notify(message, image_path=None, config_path='config.json'): """ LINE Notifyを使用してメッセージとオプションで画像を送信する関数。 Args: message (str): 送信するメッセージ。 image_path (str): 送信する画像のパス。 config_path (str): 設定ファイルのパス。 Returns: None """ # 設定ファイルを読み込む config = load_config(config_path) # 設定ファイルからトークンを取得 token = config['token'] url = 'https://notify-api.line.me/api/notify' headers = {'Authorization': f"Bearer {token}"} params = {'message': message} # 画像がある場合は読み込み files = None if image_path: with open(image_path, 'rb') as img_file: img_data = img_file.read() img_data = resize_image_if_needed(img_data) files = {'imageFile': BytesIO(img_data)} files['imageFile'].name = os.path.basename(image_path) # LINE Notify APIにリクエストを送信 res = requests.post(url, headers=headers, params=params, files=files) # レスポンスを出力 print(res.status_code) print(res.text)
しかし
WARNING: All log messages before absl::InitializeLog() is called are written to STDERR I0000 00:00:1723040085.190147 14567125 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/store_adversting_list/ocr_list.py", line 57, in <module> send_line_notify(message,image_path) File "/Users/snowpool/aw10s/store_adversting_list/line_notify.py", line 54, in send_line_notify with open(image_path, 'rb') as img_file: TypeError: expected str, bytes or os.PathLike object, not list
となる
send_line_notify関数は単一の画像パスを期待しているため、リストから1つずつ画像パスを取り出して送信する必要があります。
ソースを
import requests from utils import load_config from io import BytesIO from PIL import Image import os def resize_image_if_needed(image_data, max_size=3 * 1024 * 1024): """ 画像が指定されたサイズを超える場合は、画像のサイズを縮小する。 Args: image_data (bytes): 画像データ。 max_size (int): 最大ファイルサイズ(バイト)。 Returns: bytes: サイズ変更後の画像データ。 """ if len(image_data) > max_size: image = Image.open(BytesIO(image_data)) new_size = (image.width // 2, image.height // 2) image = image.resize(new_size, Image.LANCZOS) output = BytesIO() image_format = image.format if image.format else 'JPEG' image.save(output, format=image_format) return output.getvalue() return image_data def send_line_notify(message, image_paths=None, config_path='config.json'): """ LINE Notifyを使用してメッセージとオプションで画像を送信する関数。 複数の画像パスをリストとして受け取ることができます。 Args: message (str): 送信するメッセージ。 image_paths (list): 送信する画像のパスのリスト。 config_path (str): 設定ファイルのパス。 Returns: None """ # 設定ファイルを読み込む config = load_config(config_path) # 設定ファイルからトークンを取得 token = config['token'] url = 'https://notify-api.line.me/api/notify' headers = {'Authorization': f"Bearer {token}"} params = {'message': message} # 画像がリストとして渡されている場合に対応 if image_paths is not None: if not isinstance(image_paths, list): image_paths = [image_paths] for image_path in image_paths: if image_path is not None: with open(image_path, 'rb') as img_file: img_data = img_file.read() img_data = resize_image_if_needed(img_data) files = {'imageFile': BytesIO(img_data)} files['imageFile'].name = os.path.basename(image_path) # LINE Notify APIにリクエストを送信 res = requests.post(url, headers=headers, params=params, files=files) # レスポンスを出力 print(f"Sent {image_path}: {res.status_code} {res.text}") else: # 画像がない場合はメッセージのみ送信 res = requests.post(url, headers=headers, params=params) print(f"Sent message: {res.status_code} {res.text}")
とすることで複数の画像に対応
リストに対応: image_paths引数がリスト型で渡されても対応できるようにしました。リストでない場合は、単一の画像パスとしてリストに変換して扱います。
画像のループ処理: 画像が渡された場合はループでそれぞれの画像をLINE Notifyに送信します。
画像なしの場合: 画像が渡されなかった場合は、メッセージのみを送信します。