Spaces:
Running
Running
Upload folder using huggingface_hub
Browse files- README.md +119 -8
- SD3 Batch Imagine.rar +3 -0
- app.py +311 -0
- requirements.txt +3 -0
- sd3.json +187 -0
README.md
CHANGED
@@ -1,12 +1,123 @@
|
|
1 |
---
|
2 |
-
title:
|
3 |
-
emoji: 🏢
|
4 |
-
colorFrom: red
|
5 |
-
colorTo: yellow
|
6 |
-
sdk: gradio
|
7 |
-
sdk_version: 4.36.1
|
8 |
app_file: app.py
|
9 |
-
|
|
|
10 |
---
|
11 |
|
12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
---
|
2 |
+
title: SD3_Batch_Imagine
|
|
|
|
|
|
|
|
|
|
|
3 |
app_file: app.py
|
4 |
+
sdk: gradio
|
5 |
+
sdk_version: 4.31.5
|
6 |
---
|
7 |
|
8 |
+
|
9 |
+
Sure, here is a detailed README for your script:
|
10 |
+
|
11 |
+
GroOvy SD3 Batch Imagine
|
12 |
+
Overview
|
13 |
+
The GroOvy SD3 Batch Imagine tool is designed for batch image generation using the SD3 Medium model. This tool allows users to input multiple prompts and generate images in batches, with options for negative prompts, and automated zipping of generated images for easy download. The integration with ComfyUI ensures a seamless workflow for AI-powered image generation.
|
14 |
+
|
15 |
+
Features
|
16 |
+
Batch Image Generation: Enter multiple prompts and generate images in bulk.
|
17 |
+
Negative Prompts: Specify negative prompts to refine image outputs.
|
18 |
+
Zip Interval: Set the interval at which images are zipped.
|
19 |
+
Real-time Progress Monitoring: Watch the progress of image generation in real-time.
|
20 |
+
Automated File Management: Generated images are automatically copied to user-specific folders and zipped at specified intervals.
|
21 |
+
Detailed Logging: Monitor detailed logs of the image generation process.
|
22 |
+
Prerequisites
|
23 |
+
Python 3.7 or higher
|
24 |
+
Required Python packages: requests, gradio, logging, shutil, zipfile, os, json, random, time
|
25 |
+
Installation
|
26 |
+
Clone the repository:
|
27 |
+
bash
|
28 |
+
Copy code
|
29 |
+
git clone https://github.com/your-repo/groovy-sd3-batch-imagine.git
|
30 |
+
Navigate to the project directory:
|
31 |
+
bash
|
32 |
+
Copy code
|
33 |
+
cd groovy-sd3-batch-imagine
|
34 |
+
Install the required packages:
|
35 |
+
bash
|
36 |
+
Copy code
|
37 |
+
pip install -r requirements.txt
|
38 |
+
Usage
|
39 |
+
Running the Application
|
40 |
+
To run the application, execute the following command in your terminal:
|
41 |
+
|
42 |
+
bash
|
43 |
+
Copy code
|
44 |
+
python app.py
|
45 |
+
Accessing the Interface
|
46 |
+
Once the application is running, you can access the Gradio interface via the provided local URL (http://127.0.0.1:7860) or a public URL if you choose to share it.
|
47 |
+
|
48 |
+
Interface Overview
|
49 |
+
Developer Information
|
50 |
+
This section provides information about the developer, BeWiZ, including contact details and social media links.
|
51 |
+
|
52 |
+
About SD3 Batch Imagine
|
53 |
+
Learn about the purpose and features of the GroOvy SD3 Batch Imagine tool.
|
54 |
+
|
55 |
+
Instructions
|
56 |
+
Follow these instructions to use the tool effectively:
|
57 |
+
|
58 |
+
Enter your prompts, one per empty line.
|
59 |
+
Enter your negative prompts, one per line (optional).
|
60 |
+
Set the zip interval to determine how many images will be included in each zip file.
|
61 |
+
Click "Process Prompts" to start generating images.
|
62 |
+
Click "Cancel Processing" to stop the current batch run.
|
63 |
+
Monitor the progress in real-time.
|
64 |
+
Download the generated zip files at the end of the process.
|
65 |
+
Components
|
66 |
+
Enter Prompts
|
67 |
+
Prompts: Input your image generation prompts here, one per empty line.
|
68 |
+
Negative Prompts: Input negative prompts here, one per line (optional).
|
69 |
+
Zip Interval: Specify the number of images per zip file.
|
70 |
+
Process Prompts Button: Start the batch image generation process.
|
71 |
+
Cancel Processing Button: Cancel the current batch run.
|
72 |
+
Progress: Displays real-time progress of image generation.
|
73 |
+
Generated Images
|
74 |
+
Gallery: Displays the generated images.
|
75 |
+
Zip Files
|
76 |
+
Zip Files: Displays the generated zip files for download.
|
77 |
+
Detailed Logs
|
78 |
+
Logs: Displays detailed logs of the image generation process.
|
79 |
+
Script Details
|
80 |
+
Constants
|
81 |
+
COMFYUI_DIR: Directory path for ComfyUI.
|
82 |
+
WORKFLOW_PATH: Path to the workflow JSON file.
|
83 |
+
OUTPUT_DIR: Directory path for output images.
|
84 |
+
URL: URL for sending the workflow to ComfyUI.
|
85 |
+
Functions
|
86 |
+
read_workflow(file_path)
|
87 |
+
Reads and returns the workflow JSON from the specified file path.
|
88 |
+
|
89 |
+
update_workflow(workflow, prompt, negative_prompt)
|
90 |
+
Updates the workflow with new prompts and negative prompts.
|
91 |
+
|
92 |
+
write_workflow(workflow, file_path)
|
93 |
+
Writes the updated workflow back to the specified file path.
|
94 |
+
|
95 |
+
send_workflow_to_comfyui(workflow, url)
|
96 |
+
Sends the updated workflow to ComfyUI and logs the response.
|
97 |
+
|
98 |
+
monitor_output_images(output_dir, previous_images, timeout=60)
|
99 |
+
Monitors the output directory for new images, returning the latest image found within the timeout period.
|
100 |
+
|
101 |
+
copy_file_with_retry(src, dst_dir, file_index, retries=5, delay=1)
|
102 |
+
Copies a file from the source to the destination directory, with retries in case of permission errors.
|
103 |
+
|
104 |
+
zip_files(output_images: List[str], zip_interval: int, zip_folder: str)
|
105 |
+
Creates zip files from the list of output images at specified intervals and saves them to the zip folder.
|
106 |
+
|
107 |
+
process_prompts(prompts_text, negative_prompt_text, user_folder, zip_interval)
|
108 |
+
Processes the prompts, generates images, copies them to the user folder, and zips them at specified intervals.
|
109 |
+
|
110 |
+
cancel_processing_fn()
|
111 |
+
Sets the cancel processing flag to True to stop the current batch run.
|
112 |
+
|
113 |
+
reset_cancel_processing_fn()
|
114 |
+
Resets the cancel processing flag to False.
|
115 |
+
|
116 |
+
Main Function
|
117 |
+
The main() function initializes the Gradio interface and sets up the UI components for entering prompts, monitoring progress, displaying generated images, zip files, and logs.
|
118 |
+
|
119 |
+
License
|
120 |
+
This project is licensed under the MIT License. See the LICENSE file for more details.
|
121 |
+
|
122 |
+
Contact
|
123 |
+
For any queries or support, please contact downlifted@gmail.com or reach out on Twitter @AiAnarchist.
|
SD3 Batch Imagine.rar
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:f1cd79d8cb6d2b736058367c93f8a7c4bf137af4782d9624080c4436475ee7ac
|
3 |
+
size 7112
|
app.py
ADDED
@@ -0,0 +1,311 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import json
|
3 |
+
import requests
|
4 |
+
import gradio as gr
|
5 |
+
import random
|
6 |
+
import time
|
7 |
+
import logging
|
8 |
+
import shutil
|
9 |
+
import zipfile
|
10 |
+
from typing import List
|
11 |
+
|
12 |
+
# Define constants
|
13 |
+
WORKFLOW_FILENAME = 'sd3.json'
|
14 |
+
ROOT_DIR = os.getcwd() # Root directory of the project
|
15 |
+
OUTPUT_DIR = os.path.join(ROOT_DIR, 'output')
|
16 |
+
URL = "http://127.0.0.1:8188/prompt" # Ensure the URL is correct
|
17 |
+
|
18 |
+
# Configure logging
|
19 |
+
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
20 |
+
|
21 |
+
# Shared state for cancellation
|
22 |
+
cancel_processing = False
|
23 |
+
log_messages = ""
|
24 |
+
|
25 |
+
def log_message(message):
|
26 |
+
global log_messages
|
27 |
+
log_messages += message + "\n"
|
28 |
+
logging.info(message)
|
29 |
+
|
30 |
+
def find_workflow_in_root(root_dir, filename):
|
31 |
+
log_message(f"Searching for {filename} in root directory {root_dir}")
|
32 |
+
for root, _, files in os.walk(root_dir):
|
33 |
+
if filename in files:
|
34 |
+
file_path = os.path.join(root, filename)
|
35 |
+
log_message(f"Found workflow file at {file_path}")
|
36 |
+
return file_path
|
37 |
+
log_message(f"Workflow file {filename} not found in root directory {root_dir}")
|
38 |
+
return None
|
39 |
+
|
40 |
+
def read_workflow(file_path):
|
41 |
+
log_message(f"Reading workflow from {file_path}")
|
42 |
+
try:
|
43 |
+
with open(file_path, 'r') as file:
|
44 |
+
workflow = json.load(file)
|
45 |
+
return workflow
|
46 |
+
except Exception as e:
|
47 |
+
log_message(f"Error reading workflow: {e}")
|
48 |
+
return None
|
49 |
+
|
50 |
+
def update_workflow(workflow, prompt, negative_prompt):
|
51 |
+
log_message(f"Updating workflow with new prompts: {prompt}, negative: {negative_prompt}")
|
52 |
+
workflow["6"]["inputs"]["text"] = prompt
|
53 |
+
workflow["71"]["inputs"]["text"] = negative_prompt
|
54 |
+
return workflow
|
55 |
+
|
56 |
+
def write_workflow(workflow, file_path):
|
57 |
+
log_message(f"Writing updated workflow to {file_path}")
|
58 |
+
try:
|
59 |
+
with open(file_path, 'w') as file:
|
60 |
+
json.dump(workflow, file, indent=4)
|
61 |
+
except Exception as e:
|
62 |
+
log_message(f"Error writing workflow: {e}")
|
63 |
+
|
64 |
+
def send_workflow_to_comfyui(workflow, url):
|
65 |
+
headers = {"Content-Type": "application/json"}
|
66 |
+
try:
|
67 |
+
response = requests.post(url, headers=headers, json={"prompt": workflow})
|
68 |
+
response.raise_for_status()
|
69 |
+
log_message(f"Workflow sent successfully: {response.status_code}")
|
70 |
+
log_message(f"Response content: {response.content}")
|
71 |
+
except requests.exceptions.RequestException as e:
|
72 |
+
log_message(f"Error sending workflow to ComfyUI: {e}")
|
73 |
+
raise
|
74 |
+
|
75 |
+
def monitor_output_images(output_dir, previous_images, timeout=60):
|
76 |
+
start_time = time.time()
|
77 |
+
log_message(f"Monitoring {output_dir} for new images...")
|
78 |
+
while time.time() - start_time < timeout:
|
79 |
+
current_images = os.listdir(output_dir)
|
80 |
+
new_images = [img for img in current_images if img not in previous_images]
|
81 |
+
if new_images:
|
82 |
+
latest_image = new_images[-1]
|
83 |
+
log_message(f"New image found: {latest_image}")
|
84 |
+
return latest_image
|
85 |
+
time.sleep(1)
|
86 |
+
log_message(f"Timeout while waiting for new images in {output_dir}")
|
87 |
+
return None
|
88 |
+
|
89 |
+
def copy_file_with_retry(src, dst_dir, file_index, retries=5, delay=1):
|
90 |
+
dst = os.path.join(dst_dir, f"SD3_{file_index:05d}.png")
|
91 |
+
for _ in range(retries):
|
92 |
+
try:
|
93 |
+
shutil.copy(src, dst)
|
94 |
+
return dst
|
95 |
+
except PermissionError:
|
96 |
+
time.sleep(delay)
|
97 |
+
raise PermissionError(f"Failed to copy {src} to {dst} after {retries} retries")
|
98 |
+
|
99 |
+
def zip_files(output_images: List[str], zip_interval: int, zip_folder: str):
|
100 |
+
zip_files = []
|
101 |
+
for i in range(0, len(output_images), zip_interval):
|
102 |
+
zip_filename = os.path.join(zip_folder, f"images_{i//zip_interval + 1}_{time.time_ns()}.zip")
|
103 |
+
with zipfile.ZipFile(zip_filename, 'w') as zipf:
|
104 |
+
for img in output_images[i:i+zip_interval]:
|
105 |
+
zipf.write(img, os.path.basename(img))
|
106 |
+
zip_files.append(zip_filename)
|
107 |
+
return zip_files
|
108 |
+
|
109 |
+
def process_prompts(prompts_text, negative_prompt_text, user_folder, zip_interval):
|
110 |
+
global cancel_processing
|
111 |
+
prompts = [line.strip() for line in prompts_text.split('\n\n') if line.strip()]
|
112 |
+
negative_prompts = [line.strip() for line in negative_prompt_text.split('\n') if line.strip()]
|
113 |
+
output_images = []
|
114 |
+
zip_files_list = []
|
115 |
+
file_index = 1
|
116 |
+
|
117 |
+
workflow_path = find_workflow_in_root(ROOT_DIR, WORKFLOW_FILENAME)
|
118 |
+
if workflow_path is None:
|
119 |
+
log_message("Workflow file not found. Exiting process_prompts.")
|
120 |
+
return [], []
|
121 |
+
|
122 |
+
workflow = read_workflow(workflow_path)
|
123 |
+
if workflow is None:
|
124 |
+
log_message("Workflow is None, exiting process_prompts.")
|
125 |
+
return [], []
|
126 |
+
|
127 |
+
total_prompts = len(prompts)
|
128 |
+
previous_images = os.listdir(OUTPUT_DIR)
|
129 |
+
|
130 |
+
logs = ""
|
131 |
+
|
132 |
+
try:
|
133 |
+
for i, prompt in enumerate(prompts):
|
134 |
+
if cancel_processing:
|
135 |
+
log_message("Processing cancelled by user.")
|
136 |
+
break
|
137 |
+
if not prompt.strip():
|
138 |
+
continue
|
139 |
+
|
140 |
+
negative_prompt = negative_prompts[i] if i < len(negative_prompts) else ""
|
141 |
+
|
142 |
+
updated_workflow = update_workflow(workflow, prompt, negative_prompt)
|
143 |
+
write_workflow(updated_workflow, workflow_path)
|
144 |
+
|
145 |
+
log_message(f"Updated workflow: {json.dumps(updated_workflow, indent=4)}")
|
146 |
+
|
147 |
+
send_workflow_to_comfyui(updated_workflow, URL)
|
148 |
+
log_message(f"Sent workflow to ComfyUI for prompt {i + 1}/{total_prompts}")
|
149 |
+
|
150 |
+
new_image = None
|
151 |
+
retries = 0
|
152 |
+
while new_image is None and retries < 5:
|
153 |
+
new_image = monitor_output_images(OUTPUT_DIR, previous_images)
|
154 |
+
if new_image is None:
|
155 |
+
retries += 1
|
156 |
+
log_message(f"Retrying ({retries}/5)...")
|
157 |
+
time.sleep(5)
|
158 |
+
else:
|
159 |
+
time.sleep(2)
|
160 |
+
|
161 |
+
if new_image is None:
|
162 |
+
log_message("Error monitoring output images: Timed out waiting for new image.")
|
163 |
+
continue
|
164 |
+
|
165 |
+
new_image_path = os.path.join(OUTPUT_DIR, new_image)
|
166 |
+
try:
|
167 |
+
copied_image_path = copy_file_with_retry(new_image_path, user_folder, file_index)
|
168 |
+
log_message(f"New image generated and copied to user folder: {copied_image_path}")
|
169 |
+
except PermissionError as e:
|
170 |
+
log_message(f"Failed to copy file after retries: {e}")
|
171 |
+
continue
|
172 |
+
|
173 |
+
output_images.append(copied_image_path)
|
174 |
+
previous_images.append(new_image)
|
175 |
+
file_index += 1
|
176 |
+
|
177 |
+
if len(output_images) % zip_interval == 0 and not cancel_processing:
|
178 |
+
zip_folder = os.path.join(user_folder, "zipped_images")
|
179 |
+
os.makedirs(zip_folder, exist_ok=True)
|
180 |
+
new_zip_files = zip_files(output_images[-zip_interval:], zip_interval, zip_folder)
|
181 |
+
zip_files_list.extend(new_zip_files)
|
182 |
+
|
183 |
+
logs += f"Processed {i + 1}/{total_prompts} - Done: {i + 1}, Left: {total_prompts - (i + 1)}\n"
|
184 |
+
yield output_images, zip_files_list, logs + log_messages
|
185 |
+
|
186 |
+
if cancel_processing or (len(output_images) % zip_interval != 0):
|
187 |
+
zip_folder = os.path.join(user_folder, "zipped_images")
|
188 |
+
os.makedirs(zip_folder, exist_ok=True)
|
189 |
+
new_zip_files = zip_files(output_images, zip_interval, zip_folder)
|
190 |
+
zip_files_list.extend(new_zip_files)
|
191 |
+
|
192 |
+
except Exception as e:
|
193 |
+
log_message(f"Exception during prompt processing: {e}")
|
194 |
+
|
195 |
+
return output_images, zip_files_list
|
196 |
+
|
197 |
+
def cancel_processing_fn():
|
198 |
+
global cancel_processing
|
199 |
+
cancel_processing = True
|
200 |
+
|
201 |
+
def reset_cancel_processing_fn():
|
202 |
+
global cancel_processing
|
203 |
+
cancel_processing = False
|
204 |
+
|
205 |
+
def main():
|
206 |
+
with gr.Blocks(css="""
|
207 |
+
.gradio-container {font-family: Arial, sans-serif;}
|
208 |
+
.psychedelic-text span {
|
209 |
+
animation: colorchange 10s infinite;
|
210 |
+
}
|
211 |
+
@keyframes colorchange {
|
212 |
+
0% { color: #ff69b4; }
|
213 |
+
10% { color: #ba55d3; }
|
214 |
+
20% { color: #7b68ee; }
|
215 |
+
30% { color: #00bfff; }
|
216 |
+
40% { color: #3cb371; }
|
217 |
+
50% { color: #ffff54; }
|
218 |
+
60% { color: #ffa500; }
|
219 |
+
70% { color: #ff4500; }
|
220 |
+
80% { color: #ff1493; }
|
221 |
+
90% { color: #da70d6; }
|
222 |
+
100% { color: #ff69b4; }
|
223 |
+
}
|
224 |
+
.image-container img {
|
225 |
+
width: 250px;
|
226 |
+
height: 250px;
|
227 |
+
}
|
228 |
+
""") as demo:
|
229 |
+
with gr.Row():
|
230 |
+
with gr.Column(scale=1):
|
231 |
+
gr.Markdown("### beWiZ's GroOvy SD3 Batch Imagine")
|
232 |
+
gr.HTML('<div class="image-container"><img src="https://raw.githubusercontent.com/downlifted/Groovy-StyleSuite/main/groovy.png" alt="GroOvy - SD3 Batch Imagine Logo"></div>')
|
233 |
+
with gr.Accordion("Developer Information", open=False):
|
234 |
+
gr.Markdown("### Made by BeWiZ")
|
235 |
+
gr.Markdown('<div class="image-container"><a href="https://twitter.com/AiAnarchist"><img src="https://raw.githubusercontent.com/downlifted/pictoprompt/master/aia.png" alt="BeWiZ Logo"></a></div>')
|
236 |
+
gr.Markdown("Contact: [downlifted@gmail.com](mailto:downlifted@gmail.com)")
|
237 |
+
gr.Markdown("Twitter: [@AiAnarchist](https://x.com/AiAnarchist)")
|
238 |
+
with gr.Accordion("About SD3 Batch Imagine", open=False):
|
239 |
+
gr.Markdown("""
|
240 |
+
### SD3 Batch Imagine: Batch Image Generation
|
241 |
+
Produce large batches of images using the latest SD3 Medium model. This tool allows you to generate images quickly and efficiently.
|
242 |
+
- **ComfyUI**: For seamless integration and image processing.
|
243 |
+
- **Hugging Face**: For state-of-the-art language models.
|
244 |
+
- **Gradio**: For an intuitive user interface.
|
245 |
+
""")
|
246 |
+
|
247 |
+
with gr.Accordion("Instructions", open=True):
|
248 |
+
gr.Markdown("""
|
249 |
+
**SD3 Batch Imagine Instructions**
|
250 |
+
- Enter your prompts below, one per empty line.
|
251 |
+
- Enter your negative prompts below, one per line. (Optional)
|
252 |
+
- Set the zip interval to determine how many images will be included in each zip file.
|
253 |
+
- Click "Process Prompts" to start generating images.
|
254 |
+
- Click "Cancel Processing" to stop the current batch run.
|
255 |
+
- Watch the progress as images are generated in real-time.
|
256 |
+
- At the end of the process, zip files containing your images will be available for download.
|
257 |
+
""")
|
258 |
+
|
259 |
+
with gr.Column(scale=2):
|
260 |
+
gr.Markdown("### Enter Prompts")
|
261 |
+
prompts_text = gr.Textbox(lines=20, placeholder="Enter your prompts here, one per empty line.", label="Prompts")
|
262 |
+
negative_prompts_text = gr.Textbox(lines=5, placeholder="Enter your negative prompts here, one per line.", label="Negative Prompts")
|
263 |
+
zip_interval = gr.Number(value=10, label="Zip Interval", precision=0)
|
264 |
+
process_btn = gr.Button("Process Prompts")
|
265 |
+
cancel_btn = gr.Button("Cancel Processing")
|
266 |
+
progress_text = gr.Markdown("Progress")
|
267 |
+
gallery_output = gr.Gallery(label="Generated Images")
|
268 |
+
zip_files_output = gr.Files(label="Zip Files")
|
269 |
+
|
270 |
+
with gr.Column(scale=1):
|
271 |
+
gr.Markdown("### Detailed Logs")
|
272 |
+
logs_output = gr.Textbox(lines=10, interactive=False, label="Logs")
|
273 |
+
|
274 |
+
def generate_user_folder():
|
275 |
+
user_folder = os.path.normpath(os.path.join(OUTPUT_DIR, f'SD3{random.randint(1000, 9999)}'))
|
276 |
+
os.makedirs(user_folder, exist_ok=True)
|
277 |
+
log_message(f"Generated user folder: {user_folder}")
|
278 |
+
return user_folder
|
279 |
+
|
280 |
+
def on_click(prompts_text, negative_prompts_text, zip_interval):
|
281 |
+
reset_cancel_processing_fn()
|
282 |
+
user_folder = generate_user_folder()
|
283 |
+
output_images, zip_files_list = [], []
|
284 |
+
logs = ""
|
285 |
+
try:
|
286 |
+
for images, zip_files, log_msg in process_prompts(prompts_text, negative_prompts_text, user_folder, zip_interval):
|
287 |
+
output_images = images
|
288 |
+
zip_files_list = zip_files
|
289 |
+
logs = log_msg
|
290 |
+
yield images, zip_files_list, logs + log_messages
|
291 |
+
except Exception as e:
|
292 |
+
log_message(f"Error during prompt processing: {e}")
|
293 |
+
logs += f"Error: {e}\n"
|
294 |
+
yield output_images, zip_files_list, logs + log_messages
|
295 |
+
|
296 |
+
process_btn.click(
|
297 |
+
fn=on_click,
|
298 |
+
inputs=[prompts_text, negative_prompts_text, zip_interval],
|
299 |
+
outputs=[gallery_output, zip_files_output, logs_output]
|
300 |
+
)
|
301 |
+
|
302 |
+
cancel_btn.click(
|
303 |
+
fn=cancel_processing_fn,
|
304 |
+
inputs=[],
|
305 |
+
outputs=[]
|
306 |
+
)
|
307 |
+
|
308 |
+
demo.launch(share=True)
|
309 |
+
|
310 |
+
if __name__ == "__main__":
|
311 |
+
main()
|
requirements.txt
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
gradio
|
2 |
+
requests
|
3 |
+
numpy
|
sd3.json
ADDED
@@ -0,0 +1,187 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"6": {
|
3 |
+
"inputs": {
|
4 |
+
"text": "\"A graffiti art comparison featuring the word 'Creativity' across three different styles. First, SD1.5: a simple graffiti-style text on a plain urban wall, with basic lettering and minimal background details. BAD QUALITY.. labeled in words \"SD 1.5\" \n\nSecond, SDXL: detailed graffiti art on a vibrant wall, with bold colors, stylish fonts, and some 3D elements that add depth and creativity. GOOD QUALITY - LABELED in words \"SDXL\"\n\nThird, SD3: ultra-realistic graffiti with dynamic and intricate textures, shadows, and depth. The word 'Creativity' appears to pop out from the wall, with advanced 3D effects and lifelike details, creating a stunning visual impact.\" AMAZING QUALITY TEXT \"SD3\"\n\n",
|
5 |
+
"clip": [
|
6 |
+
"11",
|
7 |
+
0
|
8 |
+
]
|
9 |
+
},
|
10 |
+
"class_type": "CLIPTextEncode",
|
11 |
+
"_meta": {
|
12 |
+
"title": "CLIP Text Encode (Prompt)"
|
13 |
+
}
|
14 |
+
},
|
15 |
+
"11": {
|
16 |
+
"inputs": {
|
17 |
+
"clip_name1": "clip_g.safetensors",
|
18 |
+
"clip_name2": "clip_l.safetensors",
|
19 |
+
"clip_name3": "t5xxl_fp16.safetensors"
|
20 |
+
},
|
21 |
+
"class_type": "TripleCLIPLoader",
|
22 |
+
"_meta": {
|
23 |
+
"title": "TripleCLIPLoader"
|
24 |
+
}
|
25 |
+
},
|
26 |
+
"13": {
|
27 |
+
"inputs": {
|
28 |
+
"shift": 3,
|
29 |
+
"model": [
|
30 |
+
"252",
|
31 |
+
0
|
32 |
+
]
|
33 |
+
},
|
34 |
+
"class_type": "ModelSamplingSD3",
|
35 |
+
"_meta": {
|
36 |
+
"title": "ModelSamplingSD3"
|
37 |
+
}
|
38 |
+
},
|
39 |
+
"67": {
|
40 |
+
"inputs": {
|
41 |
+
"conditioning": [
|
42 |
+
"71",
|
43 |
+
0
|
44 |
+
]
|
45 |
+
},
|
46 |
+
"class_type": "ConditioningZeroOut",
|
47 |
+
"_meta": {
|
48 |
+
"title": "ConditioningZeroOut"
|
49 |
+
}
|
50 |
+
},
|
51 |
+
"68": {
|
52 |
+
"inputs": {
|
53 |
+
"start": 0.1,
|
54 |
+
"end": 1,
|
55 |
+
"conditioning": [
|
56 |
+
"67",
|
57 |
+
0
|
58 |
+
]
|
59 |
+
},
|
60 |
+
"class_type": "ConditioningSetTimestepRange",
|
61 |
+
"_meta": {
|
62 |
+
"title": "ConditioningSetTimestepRange"
|
63 |
+
}
|
64 |
+
},
|
65 |
+
"69": {
|
66 |
+
"inputs": {
|
67 |
+
"conditioning_1": [
|
68 |
+
"68",
|
69 |
+
0
|
70 |
+
],
|
71 |
+
"conditioning_2": [
|
72 |
+
"70",
|
73 |
+
0
|
74 |
+
]
|
75 |
+
},
|
76 |
+
"class_type": "ConditioningCombine",
|
77 |
+
"_meta": {
|
78 |
+
"title": "Conditioning (Combine)"
|
79 |
+
}
|
80 |
+
},
|
81 |
+
"70": {
|
82 |
+
"inputs": {
|
83 |
+
"start": 0,
|
84 |
+
"end": 0.4533332519531249,
|
85 |
+
"conditioning": [
|
86 |
+
"71",
|
87 |
+
0
|
88 |
+
]
|
89 |
+
},
|
90 |
+
"class_type": "ConditioningSetTimestepRange",
|
91 |
+
"_meta": {
|
92 |
+
"title": "ConditioningSetTimestepRange"
|
93 |
+
}
|
94 |
+
},
|
95 |
+
"71": {
|
96 |
+
"inputs": {
|
97 |
+
"text": "bad quality, poor quality, doll, disfigured, jpg, toy, bad anatomy, missing limbs, missing fingers, 3d, cgi",
|
98 |
+
"clip": [
|
99 |
+
"11",
|
100 |
+
0
|
101 |
+
]
|
102 |
+
},
|
103 |
+
"class_type": "CLIPTextEncode",
|
104 |
+
"_meta": {
|
105 |
+
"title": "CLIP Text Encode (Negative Prompt)"
|
106 |
+
}
|
107 |
+
},
|
108 |
+
"135": {
|
109 |
+
"inputs": {
|
110 |
+
"width": 1024,
|
111 |
+
"height": 1024,
|
112 |
+
"batch_size": 1
|
113 |
+
},
|
114 |
+
"class_type": "EmptySD3LatentImage",
|
115 |
+
"_meta": {
|
116 |
+
"title": "EmptySD3LatentImage"
|
117 |
+
}
|
118 |
+
},
|
119 |
+
"231": {
|
120 |
+
"inputs": {
|
121 |
+
"samples": [
|
122 |
+
"271",
|
123 |
+
0
|
124 |
+
],
|
125 |
+
"vae": [
|
126 |
+
"252",
|
127 |
+
2
|
128 |
+
]
|
129 |
+
},
|
130 |
+
"class_type": "VAEDecode",
|
131 |
+
"_meta": {
|
132 |
+
"title": "VAE Decode"
|
133 |
+
}
|
134 |
+
},
|
135 |
+
"252": {
|
136 |
+
"inputs": {
|
137 |
+
"ckpt_name": "3\\sd3_medium_incl_clips_t5xxlfp8.safetensors"
|
138 |
+
},
|
139 |
+
"class_type": "CheckpointLoaderSimple",
|
140 |
+
"_meta": {
|
141 |
+
"title": "Load Checkpoint"
|
142 |
+
}
|
143 |
+
},
|
144 |
+
"271": {
|
145 |
+
"inputs": {
|
146 |
+
"seed": 945512652412924,
|
147 |
+
"steps": 28,
|
148 |
+
"cfg": 4.5,
|
149 |
+
"sampler_name": "dpmpp_2m",
|
150 |
+
"scheduler": "sgm_uniform",
|
151 |
+
"denoise": 1,
|
152 |
+
"model": [
|
153 |
+
"13",
|
154 |
+
0
|
155 |
+
],
|
156 |
+
"positive": [
|
157 |
+
"6",
|
158 |
+
0
|
159 |
+
],
|
160 |
+
"negative": [
|
161 |
+
"69",
|
162 |
+
0
|
163 |
+
],
|
164 |
+
"latent_image": [
|
165 |
+
"135",
|
166 |
+
0
|
167 |
+
]
|
168 |
+
},
|
169 |
+
"class_type": "KSampler",
|
170 |
+
"_meta": {
|
171 |
+
"title": "KSampler"
|
172 |
+
}
|
173 |
+
},
|
174 |
+
"273": {
|
175 |
+
"inputs": {
|
176 |
+
"filename_prefix": "SD3",
|
177 |
+
"images": [
|
178 |
+
"231",
|
179 |
+
0
|
180 |
+
]
|
181 |
+
},
|
182 |
+
"class_type": "SaveImage",
|
183 |
+
"_meta": {
|
184 |
+
"title": "Save Image"
|
185 |
+
}
|
186 |
+
}
|
187 |
+
}
|