youneeds commited on
Commit
af0de5a
·
verified ·
1 Parent(s): 86d02c7

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +145 -0
app.py ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import torch
3
+ import json
4
+ from diffusers import AutoPipelineForInpainting, StableDiffusionPipeline
5
+ from PIL import Image
6
+
7
+ # ==========================
8
+ # 模型ID映射
9
+ # ==========================
10
+ MODEL_LIST = {
11
+ "SD1.5 局部重绘": "runwayml/stable-diffusion-inpainting",
12
+ "SD1.5 基础通用": "runwayml/stable-diffusion-v1-5",
13
+ "游戏资产贴图专用": "Yntec/GameAsset",
14
+ "2D手绘场景贴图": "Yaeger/Flat2D",
15
+ "低多边形LowPoly": "NiamaOfficial/LowPolyStyle",
16
+ "体素Voxel艺术": "VoxelArtModels/VoxelBase15",
17
+ "唯美插画风": "andite/pastel-mix",
18
+ "轻量二次元V3": "gsdf/Counterfeit-V3.0",
19
+ "吉卜力手绘动画": "nitrosocke/Ghibli-Style",
20
+ "原神二次元场景": "Linaqruf/giant-squid-ai",
21
+ "王者荣耀国风原画": "WarriorMama777/AbyssOrangeMix2",
22
+ "塞尔达旷野手绘风": "andite/pastel-mix",
23
+ "复古像素艺术": "OnodoAI/PixelArtModel",
24
+ "RPG像素场景贴图": "ZinPixel/RPGMakerTiles",
25
+ "写实建筑场景": "XpucT/Deliberate",
26
+ "写实环境无VAE": "SG161222/Realistic_Vision_V5.1_noVAE",
27
+ "卡通写实融合": "lilpotat/ToonYou",
28
+ "FastSD 极速CPU": "rupeshs/fastsdcpu",
29
+ "BK-SDM 轻量化": "nota-ai/bk-sdm-small",
30
+ "SD-Turbo 超快出图": "stabilityai/sd-turbo"
31
+ }
32
+
33
+ def load_prompt_presets():
34
+ try:
35
+ with open("prompts.json", "r", encoding="utf-8") as f:
36
+ return json.load(f)
37
+ except:
38
+ return {}
39
+
40
+ PROMPT_PRESETS = load_prompt_presets()
41
+ pipe_cache = {}
42
+
43
+ def get_pipe(model_name, mode="txt2img"):
44
+ cache_key = f"{model_name}_{mode}"
45
+ if cache_key in pipe_cache:
46
+ return pipe_cache[cache_key]
47
+ model_id = MODEL_LIST[model_name]
48
+ device = "cuda" if torch.cuda.is_available() else "cpu"
49
+ dtype = torch.float16 if device == "cuda" else torch.float32
50
+ if mode == "inpaint":
51
+ pipe = AutoPipelineForInpainting.from_pretrained(
52
+ model_id, torch_dtype=dtype, low_cpu_mem_usage=True
53
+ ).to(device)
54
+ else:
55
+ pipe = StableDiffusionPipeline.from_pretrained(
56
+ model_id, torch_dtype=dtype, low_cpu_mem_usage=True
57
+ ).to(device)
58
+ pipe_cache[cache_key] = pipe
59
+ return pipe
60
+
61
+ def update_prompts(model_name):
62
+ preset = PROMPT_PRESETS.get(model_name, {})
63
+ return gr.update(value=preset.get("positive", "")), gr.update(value=preset.get("negative", ""))
64
+
65
+ def toggle_input_mode(mode):
66
+ if mode == "文生图(纯文本)":
67
+ return gr.update(visible=False), gr.update(visible=True, value="✨ 文生图模式:无需上传图片,直接使用提示词生成")
68
+ else:
69
+ return gr.update(visible=True), gr.update(visible=False, value="")
70
+
71
+ def update_slider_visibility(mode):
72
+ return gr.update(visible=(mode == "图像编辑(重绘)"))
73
+
74
+ def generate_image(image_data, prompt, neg_prompt, model_name, mode, denoise_str, steps, cfg):
75
+ try:
76
+ device = "cuda" if torch.cuda.is_available() else "cpu"
77
+ if mode == "文生图(纯文本)":
78
+ pipe = get_pipe(model_name, mode="txt2img")
79
+ output = pipe(
80
+ prompt=prompt,
81
+ negative_prompt=neg_prompt,
82
+ num_inference_steps=steps,
83
+ guidance_scale=cfg
84
+ ).images[0]
85
+ else:
86
+ if not image_data or "image" not in image_data:
87
+ return None
88
+ img = image_data["image"].convert("RGB").resize((512, 512))
89
+ mask = image_data["mask"].convert("L").resize((512, 512)) if image_data.get("mask") else None
90
+ pipe = get_pipe(model_name, mode="inpaint")
91
+ output = pipe(
92
+ prompt=prompt,
93
+ negative_prompt=neg_prompt,
94
+ image=img,
95
+ mask_image=mask,
96
+ strength=denoise_str,
97
+ num_inference_steps=steps,
98
+ guidance_scale=cfg
99
+ ).images[0]
100
+ return output
101
+ except Exception as e:
102
+ print(f"生成错误: {e}")
103
+ return None
104
+
105
+ with gr.Blocks(title="全风格AI图像工具", theme=gr.themes.Soft()) as demo:
106
+ gr.Markdown("# 🎨 全风格AI图像生成 + 重绘工具")
107
+ with gr.Row():
108
+ with gr.Column(scale=1):
109
+ mode_radio = gr.Radio(
110
+ choices=["文生图(纯文本)", "图像编辑(重绘)"],
111
+ label="✨ 选择生成模式",
112
+ value="图像编辑(重绘)"
113
+ )
114
+ mode_hint = gr.Markdown("", visible=False)
115
+ input_img = gr.ImageEditor(
116
+ label="上传图片 + 涂抹重绘区域(重绘模式)",
117
+ type="pil",
118
+ height=420,
119
+ visible=True
120
+ )
121
+ model_select = gr.Dropdown(
122
+ label="🎮 选择风格模型",
123
+ choices=list(MODEL_LIST.keys()),
124
+ value="游戏资产贴图专用"
125
+ )
126
+ prompt = gr.Textbox(label="正向提示词(可追加��改)", lines=3)
127
+ neg_prompt = gr.Textbox(label="反向提示词(可追加修改)", lines=2)
128
+ with gr.Column(scale=1):
129
+ denoise_str = gr.Slider(label="重绘强度", minimum=0.1, maximum=0.9, value=0.5, visible=True)
130
+ steps = gr.Slider(label="采样步数", minimum=10, maximum=30, value=20)
131
+ cfg = gr.Slider(label="提示词强度", minimum=1, maximum=15, value=7)
132
+ generate_btn = gr.Button("✨ 一键生成", variant="primary")
133
+ output_img = gr.Image(label="生成结果", height=420)
134
+
135
+ mode_radio.change(toggle_input_mode, inputs=mode_radio, outputs=[input_img, mode_hint])
136
+ mode_radio.change(update_slider_visibility, inputs=mode_radio, outputs=denoise_str)
137
+ model_select.change(update_prompts, inputs=model_select, outputs=[prompt, neg_prompt])
138
+ demo.load(fn=lambda: update_prompts("游戏资产贴图专用"), outputs=[prompt, neg_prompt])
139
+ generate_btn.click(
140
+ fn=generate_image,
141
+ inputs=[input_img, prompt, neg_prompt, model_select, mode_radio, denoise_str, steps, cfg],
142
+ outputs=output_img
143
+ )
144
+
145
+ demo.launch(server_name="0.0.0.0", server_port=7860, share=True)