LINE通知の時の画像サイズ変更
3M以上の画像サイズになると
File: runs/detect/predict3/image0.jpg 400 {"status":400,"message":"Image size must be less than 3MB."}
となるため、画像ファイルの大きさを変更するプログラムが必要
なお画像については
results = model(image, save=True, conf=0.2, iou=0.5)
というように
save=True をつければ検出結果が出力されるので
その画像を使う
画像サイズが3MB以下になるように画像を1/4にリサイズして送信するようにコード変更
import requests import os from utils import load_config, get_latest_directory, get_image_files # 設定ファイルを読み込む config = load_config('config.json') # 設定ファイルからトークンとディレクトリパスを取得 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' message = 'ファイルパス自動取得テスト' headers = {'Authorization': f"Bearer {token}"} params = {'message': message} # 最新のpredictディレクトリ内の全ての画像ファイルに対してLINE Notify APIにリクエストを送信 for image_file_path in image_files: files = {'imageFile': open(image_file_path, 'rb')} # 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)
を
import requests import os from PIL import Image from io import BytesIO from utils import load_config, get_latest_directory, get_image_files # 設定ファイルを読み込む config = load_config('config.json') # 設定ファイルからトークンとディレクトリパスを取得 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' message = 'ファイルパス自動取得テスト' 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() # 画像ファイルのサイズをチェック if len(img_data) > 3 * 1024 * 1024: # 3MB # 画像をリサイズ image = Image.open(BytesIO(img_data)) new_size = (image.width // 2, image.height // 2) image = image.resize(new_size, Image.ANTIALIAS) # リサイズした画像をバイトデータに変換 output = BytesIO() image.save(output, format=image.format) img_data = output.getvalue() # ファイルデータをバイトデータとして用意 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)
としたが
/Users/snowpool/aw10s/inventory/line_order.py:34: DeprecationWarning: ANTIALIAS is deprecated and will be removed in Pillow 10 (2023-07-01). Use LANCZOS or Resampling.LANCZOS instead. image = image.resize(new_size, Image.ANTIALIAS) Traceback (most recent call last): File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/PIL/Image.py", line 2408, in save format = EXTENSION[ext] KeyError: '' The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/Users/snowpool/aw10s/inventory/line_order.py", line 38, in <module> image.save(output, format=image.format) File "/Users/snowpool/.pyenv/versions/3.10.6/lib/python3.10/site-packages/PIL/Image.py", line 2411, in save raise ValueError(msg) from e ValueError: unknown file extension:
となる
これは
ANTIALIASの非推奨:ANTIALIASがPillow 10で非推奨となり、代わりにLANCZOSを使用する必要がある
画像の形式が不明:image.saveメソッドに指定された形式が正しく解釈されていないため、KeyErrorが発生しています。これは、image.formatが正しく設定されていないか、空であるため
の2つが原因
import requests import os from PIL import Image from io import BytesIO from utils import load_config, get_latest_directory, get_image_files # 設定ファイルを読み込む config = load_config('config.json') # 設定ファイルからトークンとディレクトリパスを取得 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' message = 'ファイルパス自動取得テスト' 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() # 画像ファイルのサイズをチェック if len(img_data) > 3 * 1024 * 1024: # 3MB # 画像をリサイズ image = Image.open(BytesIO(img_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' # デフォルトでJPEG形式を設定 image.save(output, format=image_format) img_data = output.getvalue() # ファイルデータをバイトデータとして用意 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)
とすることで
File: runs/detect/predict3/image0.jpg 200 {"status":200,"message":"ok"}
となり、元の画像サイズが大きくても問題なく送信できるようになった