Spaces:
Runtime error
Runtime error
Create app.py
Browse files
app.py
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Hugging Face's logo
|
| 2 |
+
Hugging Face
|
| 3 |
+
Search models, datasets, users...
|
| 4 |
+
Models
|
| 5 |
+
Datasets
|
| 6 |
+
Spaces
|
| 7 |
+
Posts
|
| 8 |
+
Docs
|
| 9 |
+
Solutions
|
| 10 |
+
Pricing
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
Spaces:
|
| 15 |
+
|
| 16 |
+
fotographer
|
| 17 |
+
/
|
| 18 |
+
fai-lanthos
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
like
|
| 22 |
+
0
|
| 23 |
+
|
| 24 |
+
Logs
|
| 25 |
+
App
|
| 26 |
+
Files
|
| 27 |
+
Community
|
| 28 |
+
Settings
|
| 29 |
+
fai-lanthos
|
| 30 |
+
/
|
| 31 |
+
app.py
|
| 32 |
+
|
| 33 |
+
comdoleger's picture
|
| 34 |
+
comdoleger
|
| 35 |
+
Update app.py
|
| 36 |
+
d677fb1
|
| 37 |
+
VERIFIED
|
| 38 |
+
about 1 hour ago
|
| 39 |
+
raw
|
| 40 |
+
|
| 41 |
+
Copy download link
|
| 42 |
+
history
|
| 43 |
+
blame
|
| 44 |
+
edit
|
| 45 |
+
delete
|
| 46 |
+
No virus
|
| 47 |
+
|
| 48 |
+
7.87 kB
|
| 49 |
+
import os
|
| 50 |
+
import math
|
| 51 |
+
import gradio as gr
|
| 52 |
+
import numpy as np
|
| 53 |
+
import requests
|
| 54 |
+
import json
|
| 55 |
+
import base64
|
| 56 |
+
from PIL import Image
|
| 57 |
+
from io import BytesIO
|
| 58 |
+
import runpod
|
| 59 |
+
from enum import Enum
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
api_key = os.getenv("FAI_API_KEY")
|
| 63 |
+
api = os.getenv("FAI_API")
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
def image_to_base64(image):
|
| 67 |
+
# Open the image file
|
| 68 |
+
with image:
|
| 69 |
+
# Create a buffer to hold the binary data
|
| 70 |
+
buffered = BytesIO()
|
| 71 |
+
# Save the image in its original format to the buffer
|
| 72 |
+
#print(image.format)
|
| 73 |
+
image.save(buffered, format="PNG")
|
| 74 |
+
# Get the byte data from the buffer
|
| 75 |
+
binary_image_data = buffered.getvalue()
|
| 76 |
+
# Encode the binary data to a base64 string
|
| 77 |
+
base64_image = base64.b64encode(binary_image_data).decode("utf-8")
|
| 78 |
+
return base64_image
|
| 79 |
+
|
| 80 |
+
|
| 81 |
+
def process(data, api, api_key):
|
| 82 |
+
|
| 83 |
+
runpod.api_key = api_key
|
| 84 |
+
input_payload = {"input": data }
|
| 85 |
+
|
| 86 |
+
try:
|
| 87 |
+
endpoint = runpod.Endpoint(api)
|
| 88 |
+
run_request = endpoint.run(input_payload)
|
| 89 |
+
|
| 90 |
+
# Initial check without blocking, useful for quick tasks
|
| 91 |
+
status = run_request.status()
|
| 92 |
+
print(f"Initial job status: {status}")
|
| 93 |
+
|
| 94 |
+
if status != "COMPLETED":
|
| 95 |
+
# Polling with timeout for long-running tasks
|
| 96 |
+
output = run_request.output(timeout=60)
|
| 97 |
+
else:
|
| 98 |
+
output = run_request.output()
|
| 99 |
+
print(f"Job output: {output}")
|
| 100 |
+
except Exception as e:
|
| 101 |
+
print(f"An error occurred: {e}")
|
| 102 |
+
|
| 103 |
+
|
| 104 |
+
image_data = output['image']
|
| 105 |
+
# Decode the Base64 string
|
| 106 |
+
image_bytes = base64.b64decode(image_data)
|
| 107 |
+
# Convert binary data to image
|
| 108 |
+
image = Image.open(BytesIO(image_bytes))
|
| 109 |
+
|
| 110 |
+
return image
|
| 111 |
+
|
| 112 |
+
def process_generate(fore, prompt, image_width, image_height, intensity, mode, refprompt):
|
| 113 |
+
|
| 114 |
+
print(f"MODE: {mode}, INTENSITY: {intensity}, WIDTH: {image_width}, HEIGHT: {image_height}")
|
| 115 |
+
|
| 116 |
+
|
| 117 |
+
forestr = image_to_base64(fore.convert("RGBA"))
|
| 118 |
+
data = {
|
| 119 |
+
"foreground_image64": forestr,
|
| 120 |
+
"prompt" : prompt,
|
| 121 |
+
"mode" : mode,
|
| 122 |
+
"intensity" : float(intensity),
|
| 123 |
+
"width" : int(image_width),
|
| 124 |
+
"height" : int(image_height),
|
| 125 |
+
"refprompt" : refprompt
|
| 126 |
+
}
|
| 127 |
+
|
| 128 |
+
image = process(data, api, api_key)
|
| 129 |
+
|
| 130 |
+
return image
|
| 131 |
+
|
| 132 |
+
|
| 133 |
+
class Stage(Enum):
|
| 134 |
+
FIRST_STAGE = "first-stage"
|
| 135 |
+
SECOND_STAGE = "refiner"
|
| 136 |
+
FULL = "full"
|
| 137 |
+
|
| 138 |
+
css="""#disp_image {
|
| 139 |
+
text-align: center; /* Horizontally center the content */
|
| 140 |
+
}
|
| 141 |
+
#share-btn-container {padding-left: 0.5rem !important; padding-right: 0.5rem !important; background-color: #000000; justify-content: center; align-items: center; border-radius: 9999px !important; max-width: 13rem; margin-left: auto;}
|
| 142 |
+
div#share-btn-container > div {flex-direction: row;background: black;align-items: center}
|
| 143 |
+
#share-btn-container:hover {background-color: #060606}
|
| 144 |
+
#share-btn {all: initial; color: #ffffff;font-weight: 600; cursor:pointer; font-family: 'IBM Plex Sans', sans-serif; margin-left: 0.5rem !important; padding-top: 0.5rem !important; padding-bottom: 0.5rem !important;right:0;}
|
| 145 |
+
#share-btn * {all: unset}
|
| 146 |
+
#share-btn-container div:nth-child(-n+2){width: auto !important;min-height: 0px !important;}
|
| 147 |
+
#share-btn-container .wrap {display: none !important}
|
| 148 |
+
#share-btn-container.hidden {display: none!important}
|
| 149 |
+
#duplicate-button {
|
| 150 |
+
margin-left: auto;
|
| 151 |
+
color: #fff;
|
| 152 |
+
background: #1565c0;
|
| 153 |
+
}
|
| 154 |
+
"""
|
| 155 |
+
block = gr.Blocks(css=css, title="## F.ai Lanthos").queue()
|
| 156 |
+
with block:
|
| 157 |
+
gr.HTML("""
|
| 158 |
+
<center><h1 style="color:#000">Fotographer AI Lanthos</h1></center>""")
|
| 159 |
+
|
| 160 |
+
gr.HTML('''
|
| 161 |
+
<div>
|
| 162 |
+
<a style="display:inline-block; margin-left: .5em" href="https://app.fotographer.ai/home"><img src="https://img.shields.io/badge/2310.15110-f9f7f7?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADcAAABMCAYAAADJPi9EAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAuIwAALiMBeKU/dgAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAa2SURBVHja3Zt7bBRFGMAXUCDGF4rY7m7bAwuhlggKStFgLBgFEkCIIRJEEoOBYHwRFYKilUgEReVNJEGCJJpehHI3M9vZvd3bUP1DjNhEIRQQsQgSHiJgQZ5dv7krWEvvdmZ7d7vHJN+ft/f99pv5XvOtJMFCqvoCUpTdIEeRLC+L9Ox5i3Q9LACaCeK0kXoSChVcD3C/tQPHpAEsquQ73IkUcEz2kcLCknyGW5MGjkljRFVL8xJOKyi4CwCOuQAeAkfTP1+tNxLkogvgEbDgffkJqKqvuMA5ifOpqg/5qWecRstNg7xoUTI1Fovdxg8oy2s5AP8CGeYHmGngeZaOL4I4LXLcpHg4149/GDz4xqgsb+UAbMKKUpkrqHA43MUyyJpWUK0EHeG2YKRXr7tB+QMcgGewLD+ebTDbtrtbBt7UPlhS4rV4IvcDI7J8P1OeA/AcAI7LHljN7aB8XTowJmZt9EFRD/o0SDMH4HlwMhMyDWZZSAHFf3YDs3RS49WDLuaAY3IJq+qzmQKLxXAZKN7oDoYbdV3v5elPqiSpMyiOuAEVZVqHXb1OhloUH+MA+ztO0cAO/RkrfyBE7OAEbAZvO8vzVtTRWFD6DAfY5biBM3PWiaL0a4lvXICwnV8WjmE6ntYmhqX2jjp5LbMZjCw/wbYeN6CizOa2GMVzQOlmHjB4Ceuyk6LJ8huccEmR5Xddg7OOV/NAtchW+E3XbOag60QA4Qwuarca0bRuEJyr+cFQwzcY98huxhAKdQelt4kAQpj4qJ3gvFXAYn+aJumXk1yPlpQUgtIHhbYoFMUstNRRWgjnpl4A7IKlayNymqFHFaWCpV9CFry3LGxR1CgA5kB5M8OX2goApwpaz6mdOMGxtAgXWJySxb4WuQD4qTDgU+N5AAnzpr7ChSWpCyisiQJqY0Y7FtmSKpbV23b45kC0KHBxcQ9QeI8w4KgnHRPVtIU7rOtbioLVg5Hl/qDwSVFAMqLSMSObroCdZYlzIJtMRFVHCaRo/wFWPgaAXzdbBpkc2A4aKzCNd97+URQuESYGDDhIVfWOQIKZJu4D2+oXlgDTV1865gUQZDts756BArMNMoR1oa46BYqbyPixZz1ZUFV3sgwoGBajuBKATl3btIn8QYYMuezRgrsiRUWyr2BxA40EkPMpA/Hm6gbUu7fjEXA3azP6AsbKD9bxdUuhjM9W7fII52BF+daRpE4+WA3P501+jbfmHvQKyFqMuXf7Ot4mkN2fr50y+bRH61X7AXdUpHSxaPQ4GVbR5AGw3g+434XgQGKfr72I+vQRhfsu92dOx7WicInzt3CBg1RVpMm0NveWo2SqFzgmdNZMbriILD+S+zoueWf2vSdAipzacWN5nMl6XxNlUHa/J8DoJodUDE0HR8Ll5V0lPxcrLEHZPV4AzS83OLis7FowVa3RSku7BSNxJqQAlN3hBTC2apmDSkpaw22wJemGQFUG7J4MlP3JC6A+f96V7vRyX9It3nzT/GrjIU8edM7rMSnIi10f476lzbE1K7yEiEuWro0OJBguLCwDuFOJc1Na6sRWL/cCeMIwUN9ggSVbe3v/5/EgzTKWLvEAiBrYRUkgwNI2ZaFQNT75UDxEUEx97zYnzpmiLEmbaYCbNxYtFAb0/Z4AztgUrhyxuNgxPnhfHFDHz/vTgFWUQZxTRkkJhQ6YNdVUEPAfO6ZV5BRss6LcCVb7VaAma9giy0XJZBt9IQh42NY0NSdgbLIPlLUF6rEdrdt0CUCK1wsCbkcI3ZSLc7ZSwGLbmJXbPsNxnE5xilYKAobZ77LpGZ8TAIun+/iCKQoF71IxQDI3K2CCd+ARNvXg9sykBcnHAoCZG4u66hlDoQLe6QV4CRtFSxZQ+D0BwNO2jgdkzoGoah1nj3FVlSR19taTSYxI8QLut23U8dsgzqHulJNCQpcqBnpTALCuQ6NSYLHpmR5i42gZzuIdcrMMvMJbQlxe3jXxyZnLACl7ARm/FjPIDOY8ODtpM71sxwfcZpvBeUzKWmfNINM5AS+wO0Khh7dMqKccu4+qatarZjYAwDlgetzStHtEt+XedsBOQtU9XMrRgjg4KTnc5nr+dmqadit/4C4uLm8DuA9koJTj1TL7fI5nDL+qqoo/FLGAzL7dYT17PzvAcQONYSUQRxW/QMrHZVIyik0ZuQA2mzp+Ji8BW4YM3Mbzm9inaHkJCGfrUZZjujiYailfFwA8DHIy3acwUj4v9vUVa+SmgNsl5fuyDTKovW9/IAmfLV0Pi2UncA515kjYdrwC9i9rpuHiq3JwtAAAAABJRU5ErkJggg=="></a>
|
| 163 |
+
<a style="display:inline-block; margin-left: .5em" href='https://app.fotographer.ai/home'><img src='https://img.shields.io/github/stars/SUDO-AI-3D/zero123plus?style=social' /></a>
|
| 164 |
+
Check out our App<a href="https://app.fotographer.ai/home">Fotographer.ai</a>!
|
| 165 |
+
</div>
|
| 166 |
+
''')
|
| 167 |
+
|
| 168 |
+
with gr.Row():
|
| 169 |
+
gr.Markdown("### F.ai Lanthos: Real Composite Photography in 2 minutes!")
|
| 170 |
+
with gr.Row():
|
| 171 |
+
fore = gr.Image(source='upload', type="pil", label="Foreground Image", height=400)
|
| 172 |
+
with gr.Column():
|
| 173 |
+
|
| 174 |
+
result_gallery = gr.Image(label='Output') #gr.Gallery(height=400, object_fit='contain', label='Outputs')
|
| 175 |
+
with gr.Row():
|
| 176 |
+
prompt = gr.Textbox(label="Prompt")
|
| 177 |
+
with gr.Column():
|
| 178 |
+
refprompt = gr.Textbox(label="Refiner Prompt")
|
| 179 |
+
with gr.Row():
|
| 180 |
+
mode = gr.Radio(choices=[e.value for e in Stage],
|
| 181 |
+
value=Stage.FULL.value,
|
| 182 |
+
label="Generation Mode", type='value')
|
| 183 |
+
with gr.Column():
|
| 184 |
+
image_width = gr.Slider(label="Image Width", minimum=256, maximum=1500, value=1024, step=64)
|
| 185 |
+
image_height = gr.Slider(label="Image Height", minimum=256, maximum=1500, value=1024, step=64)
|
| 186 |
+
|
| 187 |
+
with gr.Row():
|
| 188 |
+
intensity = gr.Slider(label="Refiner Strength", minimum=1, maximum=7, value=3, step=0.5)
|
| 189 |
+
generate_button = gr.Button(value="Generate")
|
| 190 |
+
|
| 191 |
+
|
| 192 |
+
|
| 193 |
+
|
| 194 |
+
ips = [fore, prompt, image_width, image_height, intensity, mode, refprompt]
|
| 195 |
+
generate_button.click(fn=process_generate, inputs=ips, outputs=[result_gallery])
|
| 196 |
+
|
| 197 |
+
|
| 198 |
+
block.launch()
|
| 199 |
+
|