Spaces:
Running
Running
import gradio as gr | |
import openai | |
import base64 | |
import pandas as pd | |
import uuid | |
import io | |
import os | |
def analyze_image(image_path, api_key): | |
""" | |
画像を読み込み、base64エンコードした上で | |
指定したOpenAI API (gpt-4o-mini) に投げてCSVを取得し、 | |
テーブル表示用データとダウンロード用ファイルを返す | |
""" | |
# 画像またはAPIキーが未入力の場合はメッセージを返す | |
if not image_path: | |
return "画像をアップロードしてください。", None | |
if not api_key: | |
return "API Key を入力してください。", None | |
# 画像をbase64に変換 | |
with open(image_path, "rb") as f: | |
image_data = f.read() | |
image_base64 = base64.b64encode(image_data).decode("utf-8") | |
# UUIDはOpenAI側に生成を指示してもよいですが、こちらで生成してもOKです。 | |
# ここではOpenAIに完全に任せるため、プロンプトで生成を依頼する例とします。 | |
# 必要に応じてこちらで生成した UUID を挿入することも可能です。 | |
# ChatGPT(gpt-4o-mini)に送るユーザープロンプト | |
user_prompt = f""" | |
以下の画像に写っている各部位の計測値(首、肩、二の腕L、二の腕R、胸、ウエスト、ヒップ、太腿L、太腿R、ふくらはぎL、ふくらはぎR)を読み取り、 | |
次のCSVフォーマットで出力してください。なお、CSVの1行目には列名を、2行目には画像から抽出した数値を入れてください。 | |
左端のID列には自動生成したUUIDを記載してください。 | |
出力には余計な説明文を加えず、CSVテキストのみとせよ。 | |
- CSVフォーマット例: | |
ID,首,肩,二の腕L,二の腕R,胸,ウエスト,ヒップ,太腿L,太腿R,ふくらはぎL,ふくらはぎR | |
<自動生成UUID>,<首の数値>,<肩の数値>,<二の腕L>,<二の腕R>,<胸>,<ウエスト>,<ヒップ>,<太腿L>,<太腿R>,<ふくらはぎL>,<ふくらはぎR> | |
もし画像から読み取れない数値があれば空欄や"N/A"としてください。 | |
""" | |
try: | |
# OpenAI API呼び出し | |
client = openai.OpenAI(api_key=api_key) | |
response = client.chat.completions.create( | |
model="gpt-4o-mini", | |
messages=[ | |
{ | |
"role": "user", | |
"content": [ | |
{ | |
"type": "text", | |
"text": user_prompt, | |
}, | |
{ | |
"type": "image_url", | |
"image_url": { | |
"url": f"data:image/png;base64,{image_base64}", | |
} | |
}, | |
] | |
} | |
], | |
temperature=0.0 | |
) | |
except Exception as e: | |
return f"API呼び出しエラー: {str(e)}", None | |
# APIの応答(CSVテキスト想定) | |
csv_text = response.choices[0].message.content.strip() | |
csv_text = csv_text.replace('```', '') | |
# pandasでテーブルに変換を試みる | |
try: | |
df = pd.read_csv(io.StringIO(csv_text)) | |
except Exception as e: | |
# CSVとしてパースできなければテキストのみ返す | |
return f"CSVとして解析できませんでした。応答内容:\n{csv_text}", None | |
# CSVをtemp.csvに出力する | |
df.to_csv('temp.csv', index=False) | |
return df, 'temp.csv' | |
# Gradioアプリの定義 | |
with gr.Blocks() as demo: | |
gr.Markdown("# 画像から数値を読み取り、CSVを生成するデモアプリ") | |
api_key_input = gr.Textbox( | |
label="OpenAI API Key", | |
placeholder="sk-...", | |
type="password", | |
show_label=True | |
) | |
image_input = gr.Image( | |
label="画像アップロード", | |
type="filepath" | |
) | |
generate_button = gr.Button("CSV生成", variant="primary") | |
download_button = gr.DownloadButton("CSVダウンロード") | |
# 出力は DataFrame と File (ダウンロード用) | |
output_table = gr.DataFrame(label="CSVプレビュー") | |
# ボタンクリック時の動作 | |
generate_button.click( | |
fn=analyze_image, | |
inputs=[image_input, api_key_input], | |
outputs=[output_table, download_button] | |
) | |
if __name__ == "__main__": | |
demo.launch() |