https://axross-recipe.com/recipes/1741
を参考いgemini で広告解析とレシピ提案と読み上げ
pip install streamlit google-generativeai pillow pyttsx3
で必要なライブラリインストール
import streamlit as st
import google.generativeai as genai
from io import BytesIO
from PIL import Image
import io
import pyttsx3
import queue
# Gemini API設定
genai.configure(api_key="YOUR_API_KEY_HERE")
# TTSエンジンの初期化
engine = pyttsx3.init()
is_speaking = False # 音声合成中かどうかを示すフラグ
tts_queue = queue.Queue() # 音声合成リクエストのキュー
def extract_text_from_image(image):
model = genai.GenerativeModel(model_name="gemini-1.5-pro-latest")
response = model.generate_content([
image,
{"text": "画像からテキストを抽出してください。"}
])
return response.text if response else ""
def parse_product_data(text):
lines = text.split("\n")
ingredients = set()
for line in lines:
line = line.strip()
ingredients.update(line.split())
return list(ingredients)
def suggest_recipes(ingredients):
model = genai.GenerativeModel(model_name="gemini-1.5-pro-latest")
prompt = f"以下の食材を使って作れる料理のレシピを提案してください: {', '.join(ingredients)}"
response = model.generate_content(prompt)
return response.text if response else ""
def read_aloud(text):
tts_queue.put(text) # リクエストをキューに追加
process_queue() # キューを処理
def process_queue():
global is_speaking
if not tts_queue.empty() and not is_speaking:
text = tts_queue.get() # キューからテキストを取得
is_speaking = True # 音声合成中フラグを立てる
engine.say(text) # 音声合成を実行
engine.runAndWait() # 音声合成が完了するまで待機
is_speaking = False # 音声合成が完了したらフラグをリセット
process_queue() # 次のリクエストを処理
def start_reading(text):
read_aloud(text)
st.title("チラシ画像からレシピ提案")
uploaded_file = st.file_uploader("チラシ画像をアップロード", type=["jpg", "png", "jpeg"])
if uploaded_file:
st.image(uploaded_file, caption="アップロードされた画像", use_column_width=True)
image_bytes = uploaded_file.read()
image = Image.open(BytesIO(image_bytes))
# 一時的に画像ファイルとして保存する例(環境に合わせて変更すること)
img_byte_arr = io.BytesIO()
image.save(img_byte_arr, format='PNG')
img_byte_arr = img_byte_arr.getvalue()
with open("uploaded_tirashi_image.png", "wb") as f:
f.write(img_byte_arr)
input_file = genai.upload_file(path="uploaded_tirashi_image.png", display_name="image")
with st.spinner("データを解析中..."):
extracted_text = extract_text_from_image(input_file)
st.subheader("抽出されたテキスト")
st.text_area("テキスト", extracted_text, height=200)
ingredients = parse_product_data(extracted_text)
if ingredients:
st.subheader("提案されたレシピ")
recipes = suggest_recipes(ingredients)
st.write(recipes)
if st.button("提案されたレシピを読み上げる"):
# レシピが長すぎる場合は最初の部分だけ読み上げるなどの調整も可能
start_reading("提案されたレシピは次の通りです。 " + recipes)
# 停止ボタンの実装
if st.button("読み上げ停止"):
engine.stop()
engine.endLoop()
st.info("読み上げを停止しました。")
が全体コード
このコードはダウンロードできる
あとチラシ画像もダウンロードしておく
これでやることは
アップロードされたチラシ画像をGemini APIに送信し、商品情報やキャンペーン内容などのテキストを抽出
抽出されたテキストから使用可能な食材を解析し、Gemini APIにより最適なレシピを生成
Pyttsx3ライブラリを用い、提案された情報やレシピを音声で読み上げます。
ユーザーは「停止」ボタンにより、いつでも読み上げを中断
この中で欲しい機能は
Gemini のチラシ解析
Python でgemini の結果の読み上げ
touch voice_resipi.py
でファイルを作成
import streamlit as st import google.generativeai as genai from io import BytesIO from PIL import Image import io import pyttsx3 import queue
で必要なライブラリのインポート
* streamlit: Webアプリ開発を簡単に行えるライブラリ。
* google.generativeai (Gemini): 画像やテキストの解析・生成を行うGoogleの生成AI。
* BytesIO, PIL.Image, io: 画像データの取り扱いに使用。
* pyttsx3: テキストを音声に変換するためのTTSライブラリ。
* queue: 複数の処理を順次実行するための仕組みを提供。
次にGemini APIとTTSエンジンの初期設定
# Gemini APIの設定 genai.configure(api_key="YOUR_API_KEY_HERE") # TTSエンジンの初期化 engine = pyttsx3.init() is_speaking = False # 音声合成中かどうかのフラグ tts_queue = queue.Queue() # 音声合成リクエストのキュー
* APIキーを設定し、Geminiサービスの利用を可能にします。
* pyttsx3を初期化して音声読み上げの準備を行い、フラグとキューで複数のリクエストを管理
やっぱり設定は gemini.configure で行っている
以前参考にしたサイトのコードは間違っていた
https://qiita.com/shisuto3141/items/2f9349e96703c189f572
のように
self.client = genai.Client(api_key=API_KEY)
は間違い
次に画像からテキストを抽出する関数
def extract_text_from_image(image):
model = genai.GenerativeModel(model_name="gemini-1.5-pro-latest")
response = model.generate_content([
image,
{"text": "画像からテキストを抽出してください。"}
])
return response.text if response else ""
* アップロードされた画像をGemini APIに送信し、画像内の文字情報を抽出します。
* エラーが発生した場合は、空文字を返す
もし動かないのならモデル名を変更する
次に
テキストから商品情報を解析する関数
def parse_product_data(text):
lines = text.split("\n")
ingredients = set()
for line in lines:
line = line.strip()
ingredients.update(line.split())
return list(ingredients)
* 各行の単語をセットに追加して重複を排除し、食材や商品名を抽出
次に
Gemini APIでレシピを提案する関数
def suggest_recipes(ingredients):
model = genai.GenerativeModel(model_name="gemini-1.5-pro-latest")
prompt = f"以下の食材を使って作れる料理のレシピを提案してください: {', '.join(ingredients)}"
response = model.generate_content(prompt)
return response.text if response else ""
* 解析された食材情報を基に、Gemini APIにレシピ生成を依頼します。
* 提案されたレシピをテキスト形式で返す
なおingreduebtsはリストで
def parse_product_data(text):
の処理結果の食材のリストになる
これを使って処理して結果はtext に入る
つまりgeminiの処理結果、つまり提案されたレシピがテキスト情報として格納される
次に音声読み上げリクエストを管理する関数群
リクエスト追加用関数を作成しておく
def read_aloud(text):
tts_queue.put(text) # 読み上げリクエストをキューに追加
process_queue() # キューを処理
これで
ユーザーが「読み上げ」ボタンを押すと、対象のテキストがキューに追加され、順次処理
次にリクエスト処理用関数
def process_queue():
global is_speaking
if not tts_queue.empty() and not is_speaking:
text = tts_queue.get() # キューからテキストを取得
is_speaking = True # 読み上げ中のフラグを立てる
engine.say(text) # テキストを音声合成
engine.runAndWait() # 読み上げ完了まで待機
is_speaking = False # フラグをリセット
process_queue() # 次のリクエストを処理
キューに溜まったリクエストを1件ずつ順次処理し、同時に複数の読み上げが行われないよう制御
次に ラッパー関数
def start_reading(text):
read_aloud(text)
これは
「read_aloud」を呼び出すラッパー関数で、コード全体の可読性を向上
次にStreamlitによるWeb画面の基本設定
st.title("チラシ画像からレシピ提案")
アプリのタイトルをWeb画面に表示し、ユーザーに内容を即座に伝える
次に画像アップロード機能の実装
uploaded_file = st.file_uploader("チラシ画像をアップロード", type=["jpg", "png", "jpeg"])
if uploaded_file:
st.image(uploaded_file, caption="アップロードされた画像", use_column_width=True)
ユーザーがチラシ画像をアップロードできるようにし、選択した画像を画面に表示
次に画像の読み込みと変換
image_bytes = uploaded_file.read()
image = Image.open(BytesIO(image_bytes))
アップロードされた画像ファイルをバイナリデータとして読み込み、PILで画像オブジェクトに変換
次に画像を一時ファイルとして保存
# 一時的に画像ファイルとして保存する例(環境に合わせて調整してください)
img_byte_arr = io.BytesIO()
image.save(img_byte_arr, format='PNG')
img_byte_arr = img_byte_arr.getvalue()
画像データをPNG形式で一時ファイルに変換し、Gemini APIに渡す準備を行う
次に画像ファイルのアップロードとGemini API連携
with open("uploaded_tirashi_image.png", "wb") as f:
f.write(img_byte_arr)
input_file = genai.upload_file(path="uploaded_tirashi_image.png", display_name="image")
一時ファイルとして保存した画像をGemini APIへアップロードし、テキスト抽出を実行可能にする
次にテキスト抽出と結果表示
with st.spinner("データを解析中..."):
extracted_text = extract_text_from_image(input_file)
st.subheader("抽出されたテキスト")
st.text_area("テキスト", extracted_text, height=200)
処理中はスピナーを表示し、抽出されたテキストをテキストエリアでユーザーに提示
次にレシピの生成
ingredients = parse_product_data(extracted_text)
抽出テキストから食材情報を解析し、該当する場合は音声読み上げ機能でお知らせ
次にレシピ提案の表示と音声読み上げ
if ingredients:
st.subheader("提案されたレシピ")
recipes = suggest_recipes(ingredients)
st.write(recipes)
if st.button("提案されたレシピを読み上げる"):
start_reading("提案されたレシピは次の通りです。 " + recipes)
解析した食材情報を元に、Gemini APIで生成されたレシピを画面に表示し、音声でも確認
次に読み上げ停止機能の実装
if st.button("読み上げ停止"):
engine.stop()
engine.endLoop()
st.info("読み上げを停止しました。")
ユーザーが「読み上げ停止」ボタンを押すと、現在の音声再生を即座に中断し、停止完了のメッセージを表示
これらを保存し
streamlit run voice_resipi.py
で起動
自動でブラウザが立ち上がるので
テスト画像をアップ
すると食材とレシピが表示される
なお読み上げには1分以上経ってからにしないとAPIリクエストが多すぎてエラーになるので注意
不要な情報(価格、電話番号、住所、営業時間など)を取り除き、食材に焦点を当ててレシピを提案します。 鶏むね肉と夏野菜の炒め物 材料: * 鶏むね肉 (100g):一口大に切る * トウモロコシ:実を外す * ピーマン (1パック):種を取り、細切りにする * トマト (1パック):くし切りにする * キュウリ (1パック):薄切りにする * 旬彩盛 (1パック):内容に応じて適当な大きさに切る (例:もやしならそのまま、ニラなら3cm程度に切る) * サラダ油:大さじ1 * 塩コショウ:少々 * 醤油:小さじ1 * 酒:小さじ1 * 鶏ガラスープの素:小さじ1/2 作り方: 1. フライパンにサラダ油を熱し、鶏むね肉を炒める。 2. 鶏肉の色が変わったら、ピーマン、キュウリ、旬彩盛を加えて炒める。 3. 野菜がしんなりしてきたら、トウモロコシ、トマトを加えて軽く炒める。 4. 塩コショウ、醤油、酒、鶏ガラスープの素で調味する。 5. 全体に味がなじんだら、火を止めて完成。 うなぎと野菜の丼 材料: * うなぎ (1串):温める * ピーマン (1パック):千切りにする * キュウリ (1パック):千切りにする * トマト (1パック):薄切りにする * 温かいご飯:適量 * 刻み海苔:適量 作り方: 1. 温かいご飯を丼によそう。 2. ピーマン、キュウリ、トマトを丼に盛り付ける。 3. うなぎを乗せる。 4. 刻み海苔を散らして完成。 国産牛ロースのミニステーキ 材料: * 国産牛ロース (100g):軽く塩コショウを振る * サラダ油:小さじ1 * 醤油:小さじ1/2 * わさび:お好みで 作り方: 1. フライパンにサラダ油を熱し、牛ロースを焼く。 2. 片面1~2分ずつ焼き、焼き加減を調整する。 3. 醤油を回し入れて香りを出す。 4. 皿に盛り付け、お好みでわさびを添えて完成。 これらのレシピは、提示された少ない食材で簡単に作れるものです。旬彩盛の内容がわからないため、具体的な調理法は示していませんが、他の野菜と同様に炒めたり、丼に添えたりできます。 必要に応じて、他の調味料や食材を追加してアレンジしてみてください。
この内容の長さでも pyttxs なら macなら読み上げ可能
Ubuntuだと音源がないのでできないので
別のものを試す