Skip to content

Instantly share code, notes, and snippets.

@Shinichi-Ohki
Last active May 14, 2025 14:43
Show Gist options
  • Save Shinichi-Ohki/a2e08e774b9f56f751d3263370b8f016 to your computer and use it in GitHub Desktop.
Save Shinichi-Ohki/a2e08e774b9f56f751d3263370b8f016 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
# This script is a modified version of the one published at https://zenn.dev/wmoto_ai/articles/58e6bcf58d6032
# このスクリプトは https://zenn.dev/wmoto_ai/articles/58e6bcf58d6032 で公開されたものを変更したものです
import sys
import os
import warnings
import logging
import re
import datetime
import argparse
# すべての警告を抑制
warnings.filterwarnings('ignore')
logging.getLogger().setLevel(logging.ERROR)
logging.getLogger('transformers').setLevel(logging.ERROR)
import mlx.core as mx
from mlx_vlm import load, generate
from mlx_vlm.prompt_utils import apply_chat_template
from mlx_vlm.utils import load_config
tz_jst = 9
def extract_datetime(filename):
# 正規表現パターン
pattern = r"スクリーンショット (\d{4})-(\d{2})-(\d{2}) (\d+)\.(\d+)\.(\d+)(?: ([0-9]+))?(?:(([0-9]+)))?"
# 正規表現で検索
match = re.search(pattern, filename)
if match:
year = int(match.group(1))
month = int(match.group(2))
day = int(match.group(3))
hour = int(match.group(4))
minute = int(match.group(5))
second = int(match.group(6))
index1 = int(match.group(7)) if match.group(7) else None
index2 = int(match.group(8)) if match.group(8) else None
return year, month, day, hour, minute, second, index1, index2
else:
raise ValueError("ファイル名から日時を抽出できませんでした")
def suppress_output():
"""標準出力と標準エラー出力を抑制するコンテキストマネージャー"""
class DummyFile:
def write(self, x): pass
def flush(self): pass
return DummyFile()
def sanitize_filename(filename: str) -> str:
"""
OS で利用できない文字などを除去・置換して簡易的にサニタイズする。
"""
sanitized = re.sub(r'[\\/:*?"<>|]+', '_', filename)
sanitized = sanitized.strip().strip('.')
if len(sanitized) > 100:
sanitized = sanitized[:100]
return sanitized
def main():
parser = argparse.ArgumentParser(description="Rename an image file based on Qwen2-VL inference")
parser.add_argument("image_path", type=str, help="Path to the image file")
parser.add_argument("--resize-shape", type=int, nargs="+", default=[512, 512],
help="Resize shape for the image (e.g. --resize-shape 512 512). Default is 512x512.")
args = parser.parse_args()
# print(args)
image_path = args.image_path
try:
# 標準エラー出力と標準出力を一時的に抑制
original_stderr = sys.stderr
original_stdout = sys.stdout
sys.stderr = suppress_output()
sys.stdout = suppress_output()
# モデルとプロセッサのロード
model_path = 'mlx-community/Qwen2.5-VL-3B-Instruct-4bit'
model, processor = load(model_path)
config = load_config(model_path)
# 標準出力と標準エラー出力を復元
sys.stderr = original_stderr
sys.stdout = original_stdout
# メッセージの設定 このへんは適宜ご自身の用途でアレンジください
messages = [
{
"role": "system",
"content": """あなたは画像を説明するファイル名を生成するプロフェッショナルです。
'Cap_'で始めて、その後に日本語で画像を説明する単語を連結してください
以下のルールを必ず守ってください:
- 'Cap_'ではじめる
- 簡潔で、かつ説明的で
- 文章ではなく複数の単語で
- 単語は4つまで
- 英語が一般的な単語は英語で
- 例: 「Cap_Pythonスクリプト」, 「Cap_電機回路図」, 「Cap_横スクロールゲーム」, 「Cap_ラーメンとチャーハンと餃子」, 「Cap_チャットのログ」"""
},
{
"role": "user",
"content": "この画像の説明を生成してください。"
}
]
# チャットテンプレートの適用
formatted_prompt = apply_chat_template(processor, config, messages, num_images=1)
# リサイズ形状を設定
resize_shape = None
if args.resize_shape is not None:
if len(args.resize_shape) == 1:
resize_shape = (args.resize_shape[0], args.resize_shape[0])
elif len(args.resize_shape) == 2:
resize_shape = (args.resize_shape[0], args.resize_shape[1])
else:
raise ValueError("--resize-shape must have 1 or 2 integers.")
# 画像の説明を生成
output = generate(
model,
processor,
formatted_prompt,
[image_path],
verbose=False,
temperature=0.7,
max_tokens=100,
resize_shape=resize_shape,
use_fast=True
)
description = output[0].strip()
print(description)
# ファイル名から年月日時分秒を取得
year, month, day, hour, minute, second, index1, index2 = extract_datetime(image_path)
# 拡張子を抽出
extension = os.path.splitext(image_path)[1]
# 説明文をファイル名に使える形へサニタイズ
safe_description = sanitize_filename(description)
# 日本時間(東京)を取得
tz = datetime.timezone(datetime.timedelta(hours=tz_jst))
now_japan = datetime.datetime.now(tz)
# date_str = now_japan.strftime('%Y-%m-%d_%H-%M-%S')
date_str = f"{year:04}-{month:02}-{day:02}_{hour:02}-{minute:02}-{second:02}"
date_str = f"{date_str}_{index1}" if index1 else date_str
date_str = f"{date_str}_({index2})" if index2 else date_str
# 新しいファイル名を作成
new_file_name = f"{date_str}_{safe_description}{extension}"
new_file_path = os.path.join(os.path.dirname(image_path), new_file_name)
# リネーム実行
os.rename(image_path, new_file_path)
print(f"ファイルをリネームしました: {new_file_path}")
except Exception as e:
# エラー時に標準出力と標準エラー出力を確実に復元
if sys.stderr != original_stderr:
sys.stderr = original_stderr
if sys.stdout != original_stdout:
sys.stdout = original_stdout
print(f"エラーが発生しました: {str(e)}")
sys.exit(1)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment