Roshan1162003 commited on
Commit
9d8c3ac
·
1 Parent(s): fcca1a0

Initial setup for image generation UI v2

Browse files
Files changed (6) hide show
  1. Dockerfile +26 -0
  2. README.md +17 -9
  3. app.py +114 -0
  4. assets/logo.png +0 -0
  5. index.html +148 -0
  6. requirements.txt +10 -0
Dockerfile ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.10-slim
2
+ # Install system dependencies
3
+ RUN apt-get update && apt-get install -y \
4
+ git git-lfs ffmpeg libsm6 libxext6 cmake rsync libgl1-mesa-glx \
5
+ && rm -rf /var/lib/apt/lists/* \
6
+ && git lfs install
7
+
8
+ # Set working directory
9
+ WORKDIR /app
10
+
11
+ # Install Python dependencies
12
+ COPY requirements.txt .
13
+ RUN pip install --no-cache-dir -r requirements.txt
14
+
15
+ # Copy application files
16
+ COPY . .
17
+
18
+ # Set user
19
+ RUN useradd -m -u 1000 user && chown -R user:user /app
20
+ USER user
21
+
22
+ # Expose port
23
+ EXPOSE 7860
24
+
25
+ # Run the app
26
+ CMD ["python", "app.py"]
README.md CHANGED
@@ -1,10 +1,18 @@
1
- ---
2
- title: Image Generation Ui V2
3
- emoji: 🚀
4
- colorFrom: indigo
5
- colorTo: pink
6
- sdk: docker
7
- pinned: false
8
- ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Image Generation UI v2
2
+ A custom Hugging Face Space for generating images using SSD-1B and Stable Diffusion v1-5 models.
 
 
 
 
 
 
3
 
4
+ ## Setup
5
+ - Clone the repository: `git clone https://huggingface.co/spaces/remiai3/image-generation-ui-v2`.
6
+ - Install dependencies: `pip install -r requirements.txt`.
7
+ - Set `HF_TOKEN` environment variable with your Hugging Face Access Token.
8
+ - Run: `python app.py`.
9
+
10
+ ## Features
11
+ - Select between SSD-1B and Stable Diffusion v1-5 models.
12
+ - Choose image ratios: 1:1, 3:4, 16:9.
13
+ - Generate up to 4 images (SSD-1B limited to 1).
14
+ - Custom UI with logo.
15
+
16
+ ## Models
17
+ - [SSD-1B](https://huggingface.co/remiai3/ssd-1b)
18
+ - [Stable Diffusion v1-5](https://huggingface.co/remiai3/stable-diffusion-v1-5)
app.py ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, request, jsonify
2
+ from flask_cors import CORS
3
+ from diffusers import StableDiffusionPipeline, DiffusionPipeline, DPMSolverMultistepScheduler
4
+ import torch
5
+ import os
6
+ from PIL import Image
7
+ import base64
8
+ import time
9
+ from accelerate import Accelerator
10
+ import logging
11
+
12
+ app = Flask(__name__)
13
+ CORS(app)
14
+
15
+ # Configure logging
16
+ logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
17
+ logger = logging.getLogger(__name__)
18
+
19
+ # Initialize Accelerator for CPU
20
+ accelerator = Accelerator(cpu=True)
21
+
22
+ # Model cache
23
+ model_cache = {}
24
+ model_paths = {
25
+ "ssd-1b": "remiai3/ssd-1b",
26
+ "sd-v1-5": "remiai3/stable-diffusion-v1-5"
27
+ }
28
+
29
+ # Image ratio to dimensions (optimized for CPU)
30
+ ratio_to_dims = {
31
+ "1:1": (256, 256),
32
+ "3:4": (192, 256),
33
+ "16:9": (256, 144)
34
+ }
35
+
36
+ def load_model(model_id):
37
+ if model_id not in model_cache:
38
+ logger.info(f"Loading model {model_id}...")
39
+ try:
40
+ pipe = StableDiffusionPipeline.from_pretrained(
41
+ model_paths[model_id],
42
+ torch_dtype=torch.float32,
43
+ use_auth_token=os.getenv("HF_TOKEN"),
44
+ use_safetensors=True,
45
+ low_cpu_mem_usage=True
46
+ )
47
+ pipe.scheduler = DPMSolverMultistepScheduler.from_config(pipe.scheduler.config)
48
+ pipe = accelerator.prepare(pipe)
49
+ pipe.enable_attention_slicing()
50
+ pipe.enable_sequential_cpu_offload()
51
+ model_cache[model_id] = pipe
52
+ logger.info(f"Model {model_id} loaded successfully")
53
+ except Exception as e:
54
+ logger.error(f"Error loading model {model_id}: {str(e)}")
55
+ raise
56
+ return model_cache[model_id]
57
+
58
+ @app.route('/')
59
+ def index():
60
+ return app.send_static_file('index.html')
61
+
62
+ @app.route('/generate', methods=['POST'])
63
+ def generate():
64
+ try:
65
+ data = request.json
66
+ model_id = data.get('model', 'ssd-1b')
67
+ prompt = data.get('prompt', '')
68
+ ratio = data.get('ratio', '1:1')
69
+ num_images = min(int(data.get('num_images', 1)), 4)
70
+ guidance_scale = float(data.get('guidance_scale', 7.5))
71
+
72
+ if not prompt:
73
+ return jsonify({"error": "Prompt is required"}), 400
74
+
75
+ if model_id == 'ssd-1b' and num_images > 1:
76
+ return jsonify({"error": "SSD-1B allows only 1 image per generation"}), 400
77
+ if model_id == 'ssd-1b' and ratio != '1:1':
78
+ return jsonify({"error": "SSD-1B supports only 1:1 ratio"}), 400
79
+ if model_id == 'sd-v1-5' and len(prompt.split()) > 77:
80
+ return jsonify({"error": "Prompt exceeds 77 tokens for Stable Diffusion v1.5"}), 400
81
+
82
+ width, height = ratio_to_dims.get(ratio, (256, 256))
83
+ pipe = load_model(model_id)
84
+
85
+ images = []
86
+ for _ in range(num_images):
87
+ image = pipe(
88
+ prompt=prompt,
89
+ height=height,
90
+ width=width,
91
+ num_inference_steps=20,
92
+ guidance_scale=guidance_scale
93
+ ).images[0]
94
+ images.append(image)
95
+
96
+ output_dir = "outputs"
97
+ os.makedirs(output_dir, exist_ok=True)
98
+ image_urls = []
99
+ for i, img in enumerate(images):
100
+ img_path = os.path.join(output_dir, f"generated_{int(time.time())}_{i}.png")
101
+ img.save(img_path)
102
+ with open(img_path, "rb") as f:
103
+ img_data = base64.b64encode(f.read()).decode('utf-8')
104
+ image_urls.append(f"data:image/png;base64,{img_data}")
105
+ os.remove(img_path)
106
+
107
+ return jsonify({"images": image_urls})
108
+
109
+ except Exception as e:
110
+ logger.error(f"Image generation failed: {str(e)}")
111
+ return jsonify({"error": f"Image generation failed: {str(e)}"}), 500
112
+
113
+ if __name__ == '__main__':
114
+ app.run(host='0.0.0.0', port=7860)
assets/logo.png ADDED
index.html ADDED
@@ -0,0 +1,148 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Image Generation UI</title>
7
+ <style>
8
+ body {
9
+ font-family: Arial, sans-serif;
10
+ text-align: center;
11
+ margin: 0;
12
+ padding: 20px;
13
+ background-color: #f0f0f0;
14
+ }
15
+ .container {
16
+ max-width: 800px;
17
+ margin: 0 auto;
18
+ }
19
+ img.logo {
20
+ max-width: 150px;
21
+ margin-bottom: 20px;
22
+ }
23
+ select, input, button {
24
+ margin: 10px;
25
+ padding: 8px;
26
+ font-size: 16px;
27
+ border-radius: 4px;
28
+ border: 1px solid #ccc;
29
+ }
30
+ button {
31
+ background-color: #4CAF50;
32
+ color: white;
33
+ cursor: pointer;
34
+ }
35
+ button:hover {
36
+ background-color: #45a049;
37
+ }
38
+ #prompt {
39
+ width: 300px;
40
+ }
41
+ #output {
42
+ margin-top: 20px;
43
+ display: flex;
44
+ flex-wrap: wrap;
45
+ justify-content: center;
46
+ gap: 10px;
47
+ }
48
+ .output-image {
49
+ max-width: 200px;
50
+ border: 1px solid #ddd;
51
+ border-radius: 4px;
52
+ }
53
+ .error {
54
+ color: red;
55
+ margin-top: 10px;
56
+ }
57
+ .loading {
58
+ display: none;
59
+ margin-top: 10px;
60
+ font-style: italic;
61
+ }
62
+ </style>
63
+ </head>
64
+ <body>
65
+ <div class="container">
66
+ <img src="/assets/logo.png" alt="Logo" class="logo">
67
+ <h1>Image Generation UI</h1>
68
+ <div>
69
+ <label for="model-select">Select Model:</label>
70
+ <select id="model-select">
71
+ <option value="ssd-1b">SSD-1B</option>
72
+ <option value="sd-v1-5">Stable Diffusion v1-5</option>
73
+ </select>
74
+ </div>
75
+ <div>
76
+ <label for="ratio-select">Image Ratio:</label>
77
+ <select id="ratio-select">
78
+ <option value="1:1">1:1</option>
79
+ <option value="3:4">3:4</option>
80
+ <option value="16:9">16:9</option>
81
+ </select>
82
+ </div>
83
+ <div>
84
+ <label for="num-images">Number of Images (1-4):</label>
85
+ <input type="number" id="num-images" min="1" max="4" value="1">
86
+ </div>
87
+ <div>
88
+ <label for="prompt">Prompt:</label>
89
+ <input type="text" id="prompt" placeholder="Enter your prompt">
90
+ </div>
91
+ <div>
92
+ <label for="guidance-scale">Guidance Scale:</label>
93
+ <input type="number" id="guidance-scale" min="1" max="20" step="0.5" value="7.5">
94
+ </div>
95
+ <button onclick="generateImages()">Generate Images</button>
96
+ <div id="loading" class="loading">Generating images, please wait...</div>
97
+ <div id="error" class="error"></div>
98
+ <div id="output"></div>
99
+ </div>
100
+ <script>
101
+ async function generateImages() {
102
+ const model = document.getElementById('model-select').value;
103
+ const ratio = document.getElementById('ratio-select').value;
104
+ const numImages = document.getElementById('num-images').value;
105
+ const prompt = document.getElementById('prompt').value;
106
+ const guidanceScale = document.getElementById('guidance-scale').value;
107
+ const outputDiv = document.getElementById('output');
108
+ const errorDiv = document.getElementById('error');
109
+ const loadingDiv = document.getElementById('loading');
110
+
111
+ outputDiv.innerHTML = '';
112
+ errorDiv.innerText = '';
113
+ loadingDiv.style.display = 'block';
114
+
115
+ try {
116
+ const response = await fetch('/generate', {
117
+ method: 'POST',
118
+ headers: { 'Content-Type': 'application/json' },
119
+ body: JSON.stringify({
120
+ model,
121
+ prompt,
122
+ ratio,
123
+ num_images: numImages,
124
+ guidance_scale: guidanceScale
125
+ })
126
+ });
127
+
128
+ loadingDiv.style.display = 'none';
129
+ const data = await response.json();
130
+
131
+ if (response.ok) {
132
+ data.images.forEach(imgSrc => {
133
+ const img = document.createElement('img');
134
+ img.src = imgSrc;
135
+ img.className = 'output-image';
136
+ outputDiv.appendChild(img);
137
+ });
138
+ } else {
139
+ errorDiv.innerText = data.error || 'Failed to generate images';
140
+ }
141
+ } catch (error) {
142
+ loadingDiv.style.display = 'none';
143
+ errorDiv.innerText = 'Error: ' + error.message;
144
+ }
145
+ }
146
+ </script>
147
+ </body>
148
+ </html>
requirements.txt ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ flask==2.0.1
2
+ werkzeug==2.0.2
3
+ flask-cors==4.0.1
4
+ torch==2.0.1
5
+ diffusers==0.30.0
6
+ transformers==4.31.0
7
+ pillow==10.0.0
8
+ huggingface_hub==0.16.4
9
+ safetensors==0.3.3
10
+ accelerate==0.21.0