File size: 3,847 Bytes
1fb6258
0887ac5
1fb6258
e92c365
1fb6258
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0887ac5
e775448
1fb6258
 
 
0887ac5
1fb6258
 
 
 
 
 
 
 
 
 
 
 
 
 
0887ac5
1fb6258
 
0887ac5
1fb6258
 
0887ac5
e775448
1fb6258
 
 
0887ac5
1fb6258
 
 
 
 
 
 
 
 
 
 
 
0887ac5
 
e775448
1fb6258
 
 
0887ac5
 
1fb6258
0887ac5
 
1fb6258
0887ac5
1fb6258
0887ac5
1fb6258
0887ac5
1fb6258
 
 
 
0887ac5
1fb6258
 
 
 
 
0887ac5
1fb6258
 
 
0887ac5
e775448
0887ac5
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import streamlit as st
from PIL import Image
from transformers import pipeline

# ----------------------------
# 生成图像描述函数
# ----------------------------
def generate_caption(image_file):
    """
    使用 Hugging Face pipeline 的 image-to-text 模型生成图片描述
    参数:
        image_file: 上传的图片文件(文件对象或文件路径)
    返回:
        caption: 生成的图片描述文本
    """
    # 打开图片(如果上传的是文件流,可以直接传给 pipeline)
    image = Image.open(image_file)
    # 利用 image-to-text pipeline 加载 Salesforce/blip-image-captioning-base 模型
    caption_generator = pipeline("image-to-text", model="Salesforce/blip-image-captioning-base")
    # 直接将图片传入 pipeline,返回结果是一个列表,每个元素是一个字典
    caption_results = caption_generator(image)
    caption = caption_results[0]['generated_text']  # 取第一个结果
    return caption

# ----------------------------
# 基于图片描述生成完整故事的函数
# ----------------------------
def generate_story(caption):
    """
    基于图片描述生成完整故事,确保生成的故事至少包含100个单词。
    参数:
        caption: 图片描述文本
    返回:
        story: 生成的故事文本
    """
    # 使用 text-generation pipeline 加载 GPT-2 模型
    story_generator = pipeline("text-generation", model="gpt2")
    # 构建生成故事的提示语
    prompt = f"Based on the following image caption: '{caption}', generate a complete fairy tale story for children with at least 100 words. "
    
    # 生成故事文本
    result = story_generator(prompt, max_length=300, num_return_sequences=1)
    story = result[0]['generated_text']
    
    # 简单检查生成的故事单词数是否达到100,否则再生成部分文本补充
    if len(story.split()) < 100:
        additional = story_generator(prompt, max_length=350, num_return_sequences=1)[0]['generated_text']
        story += " " + additional
    return story

# ----------------------------
# 文字转语音 (TTS) 函数
# ----------------------------
def text_to_speech(text, output_file="output.mp3"):
    """
    将文本转换为语音并保存为 mp3 文件
    参数:
        text: 要转换的文本
        output_file: 保存的音频文件名
    返回:
        output_file: 转换后的音频文件路径
    """
    from gtts import gTTS
    # 这里语言参数设为英语 "en",
    # 如需中文可修改 lang="zh-cn",但对应文本生成模型也需生成中文
    tts = gTTS(text=text, lang="en")
    tts.save(output_file)
    return output_file

# ----------------------------
# 主函数:构建 Streamlit 界面
# ----------------------------
def main():
    st.title("儿童故事生成应用")
    st.write("上传一张图片,我们将根据图片生成有趣的故事,并转换成语音播放!")
    
    uploaded_file = st.file_uploader("选择一张图片", type=["png", "jpg", "jpeg"])
    
    if uploaded_file is not None:
        # 显示上传的图片
        image = Image.open(uploaded_file)
        st.image(image, caption="上传的图片", use_column_width=True)
        
        # 生成图片描述
        with st.spinner("正在生成图片描述..."):
            caption = generate_caption(uploaded_file)
        st.write("图片描述:", caption)
        
        # 根据图片描述生成完整故事
        with st.spinner("正在生成故事..."):
            story = generate_story(caption)
        st.write("生成的故事:")
        st.write(story)
        
        # 文本转语音
        with st.spinner("正在转换成语音..."):
            audio_file = text_to_speech(story)
        st.audio(audio_file, format="audio/mp3")

if __name__ == "__main__":
    main()