Spaces:
Runtime error
Runtime error
Commit
·
959541f
0
Parent(s):
Start fresh from current state
Browse files- .gitignore +1 -0
- LICENSE +11 -0
- README.md +35 -0
- app.py +152 -0
- app_future.py +168 -0
- caller.py +124 -0
- requirements.txt +5 -0
- uni_test/test.jpg +0 -0
.gitignore
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
*pyc
|
LICENSE
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.
|
2 |
+
|
3 |
+
You are free to:
|
4 |
+
- Share — copy and redistribute the material in any medium or format
|
5 |
+
- Adapt — remix, transform, and build upon the material
|
6 |
+
|
7 |
+
Under the following terms:
|
8 |
+
- Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use.
|
9 |
+
- NonCommercial — You may not use the material for commercial purposes.
|
10 |
+
|
11 |
+
No additional restrictions — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits.
|
README.md
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Seed-Edit-APP
|
2 |
+
|
3 |
+
This repository contains the code for the **Seed-Edit** application. Seed-Edit is designed to simplify and enhance editing processes using advanced algorithms and data-driven insights.
|
4 |
+
|
5 |
+
## Overview
|
6 |
+
|
7 |
+
Seed-Edit provides an intuitive interface and integrates with state-of-the-art tools to streamline your editing experience. The app leverages robust models to offer various editing options tailored to user needs.
|
8 |
+
|
9 |
+
## Additional Resources
|
10 |
+
|
11 |
+
For more information and trials, please visit our official webpage for more details: [Seed-Edit Webpage](https://team.doubao.com/seed-edit) and the **[Doubao](https://www.doubao.com/chat/)/[Dreamina](https://dreamina.capcut.com/ai-tool/image/generate) APPs**.
|
12 |
+
|
13 |
+
|
14 |
+
## License
|
15 |
+
|
16 |
+
This project is licensed under the CC BY-NC License. See `LICENSE` for more information.
|
17 |
+
|
18 |
+
## Safety
|
19 |
+
|
20 |
+
<font size=2>
|
21 |
+
We strongly advise users not to knowingly generate or allow others to knowingly generate harmful content,
|
22 |
+
including hate, violence, pornography, deception, etc.
|
23 |
+
(注:本演示受CC BY-NC的许可协议限制。我们强烈建议,用户不应传播及不应允许他人传播以下内容,包括但不限于仇恨、暴力、色情、欺诈相关的有害信息。)
|
24 |
+
|
25 |
+
---
|
26 |
+
title: Seed-Edit
|
27 |
+
emoji: 🌖
|
28 |
+
colorFrom: blue
|
29 |
+
colorTo: red
|
30 |
+
sdk: gradio
|
31 |
+
sdk_version: 4.44.1
|
32 |
+
app_file: app.py
|
33 |
+
pinned: false
|
34 |
+
license: other
|
35 |
+
---
|
app.py
ADDED
@@ -0,0 +1,152 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright (2024) Bytedance Ltd. and/or its affiliates
|
2 |
+
#
|
3 |
+
# This source code is licensed under the license found in the
|
4 |
+
# LICENSE file in the root directory of this source tree.
|
5 |
+
|
6 |
+
from __future__ import annotations
|
7 |
+
import os
|
8 |
+
import random
|
9 |
+
import uuid
|
10 |
+
|
11 |
+
import gradio as gr
|
12 |
+
import numpy as np
|
13 |
+
|
14 |
+
from loguru import logger
|
15 |
+
from caller import (
|
16 |
+
SeedT2ICaller,
|
17 |
+
SeedEditCaller
|
18 |
+
)
|
19 |
+
from PIL import Image
|
20 |
+
|
21 |
+
help_text = """
|
22 |
+
## How to use this Demo
|
23 |
+
1. Type in the caption/instruction text box, and click "Generate" to generate an initial image using Seed-T2I.
|
24 |
+
2. Type in the caption/instruction text box, and click "Edit" to edit the current image using Seed-Edit.
|
25 |
+
|
26 |
+
This is a demo with limited QPS and a simple interface.
|
27 |
+
For a better experience, please use Doubao/Dreamina APP.
|
28 |
+
|
29 |
+
<font size=2>Note: This demo is governed by the license of CC BY-NC \
|
30 |
+
We strongly advise users not to knowingly generate or allow others to knowingly generate harmful content, \
|
31 |
+
including hate speech, violence, pornography, deception, etc. \
|
32 |
+
(注:本演示受CC BY-NC的许可协议限制。我们强烈建议,用户不应传播及不应允许他人传播以下内容,\
|
33 |
+
包括但不限于仇恨言论、暴力、色情、欺诈相关的有害信息。)
|
34 |
+
"""
|
35 |
+
|
36 |
+
example_instructions = [
|
37 |
+
"Make it a picasso painting",
|
38 |
+
"close its eye",
|
39 |
+
"convert to a bronze statue",
|
40 |
+
"make it wearing a hat",
|
41 |
+
"make it wearing a PhD suit",
|
42 |
+
"Turn it into an anime.",
|
43 |
+
"have it look like a graphic novel",
|
44 |
+
"make it gain weight",
|
45 |
+
"what would he look like bald?",
|
46 |
+
"Have it smile",
|
47 |
+
"Put in a cocktail party.",
|
48 |
+
"move to the beach.",
|
49 |
+
"add dramatic lighting",
|
50 |
+
"Convert to black and white",
|
51 |
+
"What if it were snowing?",
|
52 |
+
"Give a leather jacket",
|
53 |
+
"Turn into a cyborg!",
|
54 |
+
]
|
55 |
+
|
56 |
+
def main():
|
57 |
+
resolution = 1024
|
58 |
+
cfg = {"resolution": resolution}
|
59 |
+
model_t2i = SeedT2ICaller(cfg)
|
60 |
+
|
61 |
+
cfg_edit = {}
|
62 |
+
model_edit = SeedEditCaller(cfg_edit)
|
63 |
+
logger.info("All models loaded")
|
64 |
+
|
65 |
+
|
66 |
+
def load_example():
|
67 |
+
example_image = Image.open(f"uni_test/test.jpg").convert("RGB")
|
68 |
+
example_instruction = random.choice(example_instructions)
|
69 |
+
edited_image, example_instruction = generate(example_image,
|
70 |
+
example_instruction,
|
71 |
+
cfg_scale=0.5)
|
72 |
+
return example_image, example_instruction, edited_image
|
73 |
+
|
74 |
+
def generate_t2i(instruction: str, cfg_scale: float = 0.5):
|
75 |
+
if not instruction:
|
76 |
+
return None, ""
|
77 |
+
|
78 |
+
logger.info("Generate images ...")
|
79 |
+
# Call model and capture the status
|
80 |
+
gen_image, success = model_t2i.generate(instruction, batch_size=1, cfg_scale=cfg_scale)
|
81 |
+
if not success or gen_image is None:
|
82 |
+
logger.error("Image generation failed or returned None. please retry")
|
83 |
+
return None, instruction
|
84 |
+
return gen_image, instruction
|
85 |
+
|
86 |
+
def generate(input_image: Image.Image, instruction: str = None, cfg_scale: float = 0.5):
|
87 |
+
logger.info("Generating images ...")
|
88 |
+
if not instruction or input_image is None:
|
89 |
+
return input_image, ""
|
90 |
+
|
91 |
+
logger.info("Running diffusion models ...")
|
92 |
+
edited_image, success = model_edit.edit(input_image, instruction, batch_size=1, cfg_scale=cfg_scale)
|
93 |
+
if not success or edited_image is None:
|
94 |
+
logger.error("Image editting failed or returned None.")
|
95 |
+
return None, instruction
|
96 |
+
|
97 |
+
return edited_image, instruction
|
98 |
+
|
99 |
+
def reset():
|
100 |
+
return None, None, ""
|
101 |
+
|
102 |
+
with gr.Blocks(css="footer {visibility: hidden}") as demo:
|
103 |
+
with gr.Row():
|
104 |
+
with gr.Column(scale=1, min_width=100):
|
105 |
+
generate_button = gr.Button("Generate")
|
106 |
+
with gr.Column(scale=1, min_width=100):
|
107 |
+
edit_button = gr.Button("Edit")
|
108 |
+
with gr.Column(scale=1, min_width=100):
|
109 |
+
load_button = gr.Button("Load Example")
|
110 |
+
with gr.Column(scale=1, min_width=100):
|
111 |
+
reset_button = gr.Button("Reset")
|
112 |
+
|
113 |
+
with gr.Row():
|
114 |
+
with gr.Column(scale=3):
|
115 |
+
instruction = gr.Textbox(lines=1, label="Edit/Caption Instruction", interactive=True, value=None)
|
116 |
+
with gr.Column(scale=1):
|
117 |
+
cfg_scale = gr.Slider(value=0.5, minimum=0.0, maximum=1.0, step=0.1, label="Edit/Text Strength (CFG)", interactive=True)
|
118 |
+
|
119 |
+
with gr.Row():
|
120 |
+
input_image = gr.Image(label="Input Image", type="pil", interactive=True,
|
121 |
+
height=resolution, width=resolution)
|
122 |
+
edited_image = gr.Image(label="Edited Image", type="pil",
|
123 |
+
interactive=False, height=resolution, width=resolution)
|
124 |
+
|
125 |
+
gr.Markdown(help_text)
|
126 |
+
|
127 |
+
load_button.click(
|
128 |
+
fn=load_example,
|
129 |
+
inputs=[],
|
130 |
+
outputs=[input_image, instruction, edited_image]
|
131 |
+
)
|
132 |
+
generate_button.click(
|
133 |
+
fn=generate_t2i,
|
134 |
+
inputs=[instruction, cfg_scale],
|
135 |
+
outputs=[input_image, instruction]
|
136 |
+
)
|
137 |
+
edit_button.click(
|
138 |
+
fn=generate,
|
139 |
+
inputs=[input_image, instruction, cfg_scale],
|
140 |
+
outputs=[edited_image, instruction]
|
141 |
+
)
|
142 |
+
reset_button.click(
|
143 |
+
fn=reset,
|
144 |
+
inputs=[],
|
145 |
+
outputs=[input_image, edited_image, instruction]
|
146 |
+
)
|
147 |
+
|
148 |
+
# demo.launch(server_name="0.0.0.0", server_port=8024)
|
149 |
+
demo.queue().launch(share=False)
|
150 |
+
|
151 |
+
if __name__ == "__main__":
|
152 |
+
main()
|
app_future.py
ADDED
@@ -0,0 +1,168 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright (2024) Bytedance Ltd. and/or its affiliates
|
2 |
+
#
|
3 |
+
# This source code is licensed under the license found in the
|
4 |
+
# LICENSE file in the root directory of this source tree.
|
5 |
+
|
6 |
+
from __future__ import annotations
|
7 |
+
import uuid
|
8 |
+
|
9 |
+
from loguru import logger
|
10 |
+
import hashlib
|
11 |
+
import gradio as gr
|
12 |
+
|
13 |
+
import io
|
14 |
+
import base64
|
15 |
+
|
16 |
+
from caller import (
|
17 |
+
SeedT2ICaller,
|
18 |
+
SeedEditCaller
|
19 |
+
)
|
20 |
+
from PIL import Image
|
21 |
+
|
22 |
+
API_KEY = ""
|
23 |
+
help_text = """
|
24 |
+
## How to use this Demo
|
25 |
+
1. Type-in the caption/instruction text box, and click "Generate" to generate an initial image using Seed_T2I_V14 (CFG and steps are not used here)
|
26 |
+
2. Type-in the caption/instruction text box, and click "Edit" to edit the current image.
|
27 |
+
3. Click Undo if you are not satisfied with the current results, and re-edit. Otherwise, edit will apply to current results.
|
28 |
+
4. Currently, we do not support too many rounds of editing [as shown in our video] since the current API hasn't been updated to the new model yet.
|
29 |
+
|
30 |
+
This is a demo with limited QPS and a simple interface.
|
31 |
+
For a better experience, please use Doubao/Dreamina APP.
|
32 |
+
|
33 |
+
<font size=2>Note: This demo is governed by the license of CC BY-NC \
|
34 |
+
We strongly advise users not to knowingly generate or allow others to knowingly generate harmful content, \
|
35 |
+
including hate speech, violence, pornography, deception, etc. \
|
36 |
+
(注:本演示受CC BY-NC的许可协议限制。我们强烈建议,用户不应传播及不应允许他人传播以下内容,\
|
37 |
+
包括但不限于仇恨言论、暴力、色情、欺诈相关的有害信息。)
|
38 |
+
"""
|
39 |
+
|
40 |
+
def image2str(image):
|
41 |
+
buf = io.BytesIO()
|
42 |
+
image.save(buf, format="PNG")
|
43 |
+
i_str = base64.b64encode(buf.getvalue()).decode()
|
44 |
+
return f'<div style="float:left"><img src="data:image/png;base64, {i_str}"></div>'
|
45 |
+
|
46 |
+
def main():
|
47 |
+
resolution = 1024
|
48 |
+
max_edit_iter = 3
|
49 |
+
|
50 |
+
cfg_t2i = {
|
51 |
+
"resolution": resolution
|
52 |
+
}
|
53 |
+
model_t2i = SeedT2ICaller(cfg_t2i)
|
54 |
+
|
55 |
+
cfg_edit = cfg_t2i
|
56 |
+
|
57 |
+
model_edit = SeedEditCaller(cfg_edit)
|
58 |
+
logger.info("All models loaded")
|
59 |
+
|
60 |
+
def generate_t2i(instruction: str, state):
|
61 |
+
logger.info("Generate images ...")
|
62 |
+
# 调用模型生成图像并捕获返回结果
|
63 |
+
gen_image, success = model_t2i.generate(instruction, batch_size=1)
|
64 |
+
|
65 |
+
# 检查生成是否成功以及生成的图像是否有效
|
66 |
+
if not success or gen_image is None:
|
67 |
+
logger.error("Image generation failed or returned None.")
|
68 |
+
raise ValueError("Image generation was unsuccessful.")
|
69 |
+
|
70 |
+
# Write cache
|
71 |
+
if state is None:
|
72 |
+
state = {}
|
73 |
+
|
74 |
+
output_md5 = hashlib.md5(gen_image.tobytes()).hexdigest()
|
75 |
+
logger.info(output_md5)
|
76 |
+
state[output_md5] = gen_image
|
77 |
+
|
78 |
+
return instruction, gen_image, state
|
79 |
+
|
80 |
+
def generate(prev_image, cur_image, cfg_scale, instruction, state):
|
81 |
+
if len(state.keys()) >= max_edit_iter:
|
82 |
+
return prev_image, cur_image, instruction, state
|
83 |
+
|
84 |
+
try:
|
85 |
+
if cur_image is None:
|
86 |
+
cur_image = prev_image
|
87 |
+
|
88 |
+
logger.info("Generating edited images ...")
|
89 |
+
if not instruction:
|
90 |
+
return prev_image, cur_image, instruction, state
|
91 |
+
|
92 |
+
logger.info("Running diffusion models ...")
|
93 |
+
|
94 |
+
image_out = f"./cache/{'-'.join(instruction.split()[:10])[:50]}_{uuid.uuid4()}.jpg"
|
95 |
+
logger.info(f"Input size {cur_image.size}")
|
96 |
+
|
97 |
+
edited_image, success = model_edit.edit(cur_image, instruction, batch_size=1, cfg_scale=cfg_scale, filename=image_out)
|
98 |
+
if not success or edited_image is None:
|
99 |
+
logger.error("Image generation failed or returned None.")
|
100 |
+
raise ValueError("Image generation was unsuccessful.")
|
101 |
+
|
102 |
+
output_md5 = hashlib.md5(edited_image.tobytes()).hexdigest()
|
103 |
+
logger.info(f"EDIT adding {output_md5}")
|
104 |
+
state[output_md5] = edited_image
|
105 |
+
|
106 |
+
return cur_image, edited_image, instruction, state
|
107 |
+
|
108 |
+
except Exception as e:
|
109 |
+
logger.error(e)
|
110 |
+
return prev_image, cur_image, instruction, state
|
111 |
+
|
112 |
+
def reset():
|
113 |
+
return 0.5, None, None, "", {}
|
114 |
+
|
115 |
+
def undo(prev_image, cur_image, instruction, state):
|
116 |
+
if cur_image is not None:
|
117 |
+
cur_md5 = hashlib.md5(cur_image.tobytes()).hexdigest()
|
118 |
+
if cur_md5 in state:
|
119 |
+
logger.info(f"UNDO removing {cur_md5}")
|
120 |
+
state.pop(cur_md5, None)
|
121 |
+
return prev_image, prev_image, instruction, state
|
122 |
+
|
123 |
+
def show_state(state):
|
124 |
+
num_cache = len(state.keys())
|
125 |
+
return f"Num Cache: {num_cache}" if num_cache < max_edit_iter else "Max edit number reached. Please reset for testing."
|
126 |
+
|
127 |
+
with gr.Blocks(css="footer {visibility: hidden}") as demo:
|
128 |
+
state = gr.State({})
|
129 |
+
|
130 |
+
with gr.Row():
|
131 |
+
with gr.Column(scale=2):
|
132 |
+
prev_image = gr.Image(label="Input Image", type="pil", interactive=True, visible=False, height=resolution, width=resolution)
|
133 |
+
cur_image = gr.Image(label="Edited Image", type="pil", interactive=True, height=resolution, width=resolution)
|
134 |
+
|
135 |
+
with gr.Column(scale=1):
|
136 |
+
with gr.Row():
|
137 |
+
generate_t2i_button = gr.Button("Generate")
|
138 |
+
generate_button = gr.Button("Edit")
|
139 |
+
reset_button = gr.Button("Reset")
|
140 |
+
undo_button = gr.Button("Undo")
|
141 |
+
|
142 |
+
with gr.Row():
|
143 |
+
instruction = gr.Textbox(lines=1, label="Caption (Generate) / Instruction (Edit)", interactive=True)
|
144 |
+
|
145 |
+
with gr.Row():
|
146 |
+
cfg_scale = gr.Slider(value=0.5, minimum=0.0, maximum=1.0, step=0.1, label="Edit Strength (CFG)", interactive=True)
|
147 |
+
|
148 |
+
with gr.Row():
|
149 |
+
output_label = gr.Label()
|
150 |
+
|
151 |
+
gr.Markdown(help_text)
|
152 |
+
|
153 |
+
# Function bindings
|
154 |
+
generate_t2i_button.click(generate_t2i, [instruction, state], [instruction, cur_image, state])
|
155 |
+
generate_button.click(generate, [prev_image, cur_image, cfg_scale, instruction, state], [prev_image, cur_image, instruction, state])
|
156 |
+
reset_button.click(reset, [], [cfg_scale, prev_image, cur_image, instruction, state])
|
157 |
+
undo_button.click(undo, [prev_image, cur_image, instruction, state], [prev_image, cur_image, instruction, state])
|
158 |
+
|
159 |
+
# Update state display
|
160 |
+
generate_t2i_button.click(show_state, [state], output_label)
|
161 |
+
generate_button.click(show_state, [state], output_label)
|
162 |
+
reset_button.click(show_state, [state], output_label)
|
163 |
+
undo_button.click(show_state, [state], output_label)
|
164 |
+
|
165 |
+
demo.launch(server_name="0.0.0.0", server_port=8024)
|
166 |
+
|
167 |
+
if __name__ == "__main__":
|
168 |
+
main()
|
caller.py
ADDED
@@ -0,0 +1,124 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright (2024) Bytedance Ltd. and/or its affiliates
|
2 |
+
#
|
3 |
+
# This source code is licensed under the license found in the
|
4 |
+
# LICENSE file in the root directory of this source tree.
|
5 |
+
|
6 |
+
from PIL import Image, ImageFilter
|
7 |
+
from loguru import logger
|
8 |
+
import requests
|
9 |
+
import base64
|
10 |
+
import json
|
11 |
+
import io
|
12 |
+
|
13 |
+
# 接口 URL
|
14 |
+
t2i_url = 'https://magicarena.bytedance.com/api/evaluate/v1/algo/process'
|
15 |
+
|
16 |
+
#注意:正式上线环境需要不设置header
|
17 |
+
headers = {
|
18 |
+
'X-TT-ENV': 'ppe_general_20',
|
19 |
+
'X-USE-PPE': '1'
|
20 |
+
}
|
21 |
+
|
22 |
+
class SeedT2ICaller():
|
23 |
+
def __init__(self, cfg, *args, **kwargs):
|
24 |
+
self.cfg = cfg
|
25 |
+
|
26 |
+
def generate(self, text, *args, **kwargs):
|
27 |
+
try:
|
28 |
+
logger.info("Generate images ...")
|
29 |
+
req_json = json.dumps({
|
30 |
+
"prompt": str(text),
|
31 |
+
"use_sr": True,
|
32 |
+
"model_version": "general_v2.0_L",
|
33 |
+
"req_schedule_conf": "general_v20_9B_pe"
|
34 |
+
# "width": 64,
|
35 |
+
# "height": 64
|
36 |
+
})
|
37 |
+
logger.info(f"{req_json}")
|
38 |
+
# 请求发送
|
39 |
+
response = requests.post(
|
40 |
+
t2i_url,
|
41 |
+
headers=headers,
|
42 |
+
data={
|
43 |
+
'AlgoType': 1,
|
44 |
+
'ReqJson': req_json,
|
45 |
+
}
|
46 |
+
)
|
47 |
+
logger.info(f"header: {response.headers}")
|
48 |
+
if response.status_code != 200:
|
49 |
+
return None, False
|
50 |
+
resp = response.json()
|
51 |
+
if resp.get('code',{}) != 0:
|
52 |
+
logger.info(f"response error {resp}")
|
53 |
+
return None, False
|
54 |
+
|
55 |
+
binary_data1 = resp.get('data', {}).get('BinaryData')
|
56 |
+
binary_data = binary_data1[0]
|
57 |
+
#logger.info(f"binary_data: {binary_data}")
|
58 |
+
image = Image.open(io.BytesIO(base64.b64decode(binary_data)))
|
59 |
+
#image.save('./t2i_image.png')
|
60 |
+
image = image.resize((self.cfg['resolution'], self.cfg['resolution']))
|
61 |
+
return image, True
|
62 |
+
|
63 |
+
except Exception as e:
|
64 |
+
logger.exception("An error occurred during image generation.")
|
65 |
+
return None, False
|
66 |
+
|
67 |
+
class SeedEditCaller():
|
68 |
+
def __init__(self, cfg, *args, **kwargs):
|
69 |
+
self.cfg = cfg
|
70 |
+
|
71 |
+
def edit(self, image, edit, cfg_scale=0.5, *args, **kwargs):
|
72 |
+
try:
|
73 |
+
image_bytes = io.BytesIO()
|
74 |
+
image.save(image_bytes, format='JPEG') # 或 format='PNG'
|
75 |
+
logger.info("Edit images ...")
|
76 |
+
req_json = json.dumps({
|
77 |
+
"prompt": str(edit),
|
78 |
+
"model_version": "byteedit_v2.0",
|
79 |
+
"scale": cfg_scale,
|
80 |
+
})
|
81 |
+
logger.info(f"{req_json}")
|
82 |
+
binary =base64.b64encode(image_bytes.getvalue()).decode('utf-8')
|
83 |
+
# 请求发送
|
84 |
+
response = requests.post(
|
85 |
+
t2i_url,
|
86 |
+
headers=headers,
|
87 |
+
data=json.dumps({
|
88 |
+
'AlgoType': 2,
|
89 |
+
'ReqJson': req_json,
|
90 |
+
'BinaryData': [binary]
|
91 |
+
# 'Base': base
|
92 |
+
})
|
93 |
+
)
|
94 |
+
|
95 |
+
logger.info(f"header: {response.headers}")
|
96 |
+
if response.status_code != 200:
|
97 |
+
return None, False
|
98 |
+
resp = response.json()
|
99 |
+
if resp.get('code',{}) != 0:
|
100 |
+
logger.info(f"response error {resp}")
|
101 |
+
return None, False
|
102 |
+
|
103 |
+
binary_data = resp.get('data', {}).get('BinaryData')
|
104 |
+
image = Image.open(io.BytesIO(base64.b64decode(binary_data[0])))
|
105 |
+
return image, True
|
106 |
+
|
107 |
+
except Exception as e:
|
108 |
+
logger.exception("An error occurred during image generation.")
|
109 |
+
return None, False
|
110 |
+
|
111 |
+
|
112 |
+
|
113 |
+
if __name__ == "__main__":
|
114 |
+
cfg_t2i = {
|
115 |
+
"resolution": 611
|
116 |
+
}
|
117 |
+
model_t2i = SeedT2ICaller(cfg_t2i)
|
118 |
+
model_t2i.generate("a beautiful girl")
|
119 |
+
|
120 |
+
image_path = "./t2i_image.png"
|
121 |
+
with open(image_path, 'rb') as image:
|
122 |
+
image_bytes = image.read()
|
123 |
+
model_edit = SeedEditCaller(cfg_t2i)
|
124 |
+
model_edit.edit(image=image_bytes,edit="please edit to a good man")
|
requirements.txt
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
gradio
|
2 |
+
numpy
|
3 |
+
loguru
|
4 |
+
Pillow
|
5 |
+
requests
|
uni_test/test.jpg
ADDED
![]() |