File size: 11,037 Bytes
ee3b2de 490262d 775e2c4 6752228 ee3b2de 6371eda ee3b2de 0efff39 ee3b2de 76f0426 6371eda fe15754 6371eda ee3b2de fe15754 3fa258b 6e0790c abf9f32 6e0790c 3fa258b 6e0790c df8cf30 6e0790c df8cf30 6e0790c 176f241 775e2c4 fe15754 39daff5 99642bc 6e0790c 39daff5 6e0790c 330dc1c 6e0790c 26049de 7f90752 6e0790c 4e6741b 330dc1c 39daff5 6e0790c fe15754 6e0790c 39daff5 99642bc 6e0790c 3fa258b ee3b2de 6e0790c fe15754 f630054 9276e05 dfea60b fe15754 6e0790c ee3b2de 6e0790c f630054 6e0790c f5501f6 6e0790c f5501f6 65a446a 26049de 7f9dcb6 6e0790c d850e97 1ac78b1 f5501f6 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 |
import PIL
import requests
import torch
import gradio as gr
import random
from PIL import Image
import os
import time
from diffusers import StableDiffusionInstructPix2PixPipeline, EulerAncestralDiscreteScheduler
#Loading from Diffusers Library
model_id = "timbrooks/instruct-pix2pix"
pipe = StableDiffusionInstructPix2PixPipeline.from_pretrained(model_id, torch_dtype=torch.float16, revision="fp16") #, safety_checker=None)
pipe.to("cuda")
#pipe.enable_attention_slicing()
pipe.enable_xformers_memory_efficient_attention()
pipe.unet.to(memory_format=torch.channels_last)
help_text = """
**Note: Please be advised that a safety checker has been implemented in this public space.
Any attempts to generate inappropriate or NSFW images will result in the display of a black screen
as a precautionary measure to protect all users. We appreciate your cooperation in
maintaining a safe and appropriate environment for all members of our community.**
New features and bug-fixes:
1. Chat style interface
2. Now use **'reverse'** as prompt to get back the previous image after an unwanted edit
3. Use **'restart'** as prompt to get back to original image and start over!
4. Now you can load larger image files (~5 mb) as well
Some notes from the official [instruct-pix2pix](https://huggingface.co/spaces/timbrooks/instruct-pix2pix) Space by the authors and from the official [Diffusers docs](https://huggingface.co/docs/diffusers/main/en/api/pipelines/stable_diffusion/pix2pix) -
If you're not getting what you want, there may be a few reasons:
1. Is the image not changing enough? Your guidance_scale may be too low. It should be >1. Higher guidance scale encourages to generate images
that are closely linked to the text `prompt`, usually at the expense of lower image quality. This value dictates how similar the output should
be to the input. This pipeline requires a value of at least `1`. It's possible your edit requires larger changes from the original image.
2. Alternatively, you can toggle image_guidance_scale. Image guidance scale is to push the generated image towards the inital image. Image guidance
scale is enabled by setting `image_guidance_scale > 1`. Higher image guidance scale encourages to generate images that are closely
linked to the source image `image`, usually at the expense of lower image quality.
3. I have observed that rephrasing the instruction sometimes improves results (e.g., "turn him into a dog" vs. "make him a dog" vs. "as a dog").
4. Increasing the number of steps sometimes improves results.
5. Do faces look weird? The Stable Diffusion autoencoder has a hard time with faces that are small in the image. Try:
* Cropping the image so the face takes up a larger portion of the frame.
"""
css = """
#col-container {max-width: 580px; margin-left: auto; margin-right: auto;}
a {text-decoration-line: underline; font-weight: 600;}
.footer {
margin-bottom: 45px;
margin-top: 10px;
text-align: center;
border-bottom: 1px solid #e5e5e5;
}
.footer>p {
font-size: .8rem;
display: inline-block;
padding: 0 10px;
transform: translateY(10px);
background: white;
}
.dark .footer {
border-color: #303030;
}
.dark .footer>p {
background: #0b0f19;
}
.animate-spin {
animation: spin 1s linear infinite;
}
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
"""
def previous(image):
return image
def upload_image(file):
return Image.open(file)
def chat(btn_upload, image_in, in_steps, in_guidance_scale, in_img_guidance_scale, image_hid, img_name, counter_out, image_oneup, prompt, history, progress=gr.Progress(track_tqdm=True)):
progress(0, desc="Starting...")
if prompt != '' and prompt.lower() == 'reverse' : #--to add revert functionality later
history = history or []
temp_img_name = img_name[:-4]+str(int(time.time()))+'.png'
image_oneup.save(temp_img_name)
response = 'Reverted to the last image ' + '<img src="/file=' + temp_img_name + '">'
history.append((prompt, response))
return history, history, image_oneup, temp_img_name, counter_out
if prompt != '' and prompt.lower() == 'restart' : #--to add revert functionality later
history = history or []
temp_img_name = img_name[:-4]+str(int(time.time()))+'.png'
#Resizing the image
basewidth = 512
wpercent = (basewidth/float(image_in.size[0]))
hsize = int((float(image_in.size[1])*float(wpercent)))
image_in = image_in.resize((basewidth,hsize), Image.Resampling.LANCZOS)
image_in.save(temp_img_name)
response = 'Reverted to the last image ' + '<img src="/file=' + temp_img_name + '">'
history.append((prompt, response))
return history, history, image_in, temp_img_name, counter_out
#adding supportive sample text
add_text_list = ["There you go", "Enjoy your image!", "Nice work! Wonder what you gonna do next!", "Way to go!", "Does this work for you?", "Something like this?"]
if counter_out > 1:
edited_image = pipe(prompt, image=image_hid, num_inference_steps=int(in_steps), guidance_scale=float(in_guidance_scale), image_guidance_scale=float(in_img_guidance_scale)).images[0]
if os.path.exists(img_name):
os.remove(img_name)
temp_img_name = img_name[:-4]+str(int(time.time()))[-4:]+'.png'
# Create a file-like object
with open(temp_img_name, "wb") as fp:
# Save the image to the file-like object
edited_image.save(fp)
#Get the name of the saved image
saved_image_name2 = fp.name
#edited_image.save(temp_img_name) #, overwrite=True)
history = history or []
response = random.choice(add_text_list) + '<img src="/file=' + saved_image_name2 + '">'
history.append((prompt, response))
counter_out += 1
return history, history, edited_image, temp_img_name, counter_out
elif counter_out == 0:
seed = random.randint(0, 1000000)
img_name = f"./edited_image_{seed}.png"
#convert file object to image
image_in = Image.open(btn_upload)
#Resizing the image
basewidth = 512
wpercent = (basewidth/float(image_in.size[0]))
hsize = int((float(image_in.size[1])*float(wpercent)))
image_in = image_in.resize((basewidth,hsize), Image.Resampling.LANCZOS)
if os.path.exists(img_name):
os.remove(img_name)
with open(img_name, "wb") as fp:
# Save the image to the file-like object
image_in.save(fp)
#Get the name of the saved image
saved_image_name0 = fp.name
history = history or []
response = '<img src="/file=' + img_name + '">' #IMG_NAME
history.append((prompt, response))
counter_out += 1
return history, history, image_in, img_name, counter_out
elif counter_out == 1:
#instruct-pix2pix inference
edited_image = pipe(prompt, image=image_in, num_inference_steps=int(in_steps), guidance_scale=float(in_guidance_scale), image_guidance_scale=float(in_img_guidance_scale)).images[0]
if os.path.exists(img_name):
os.remove(img_name)
temp_img_name = img_name[:-4]+str(int(time.time()))[-4:]+'.png'
with open(temp_img_name, "wb") as fp:
# Save the image to the file-like object
edited_image.save(fp)
#Get the name of the saved image
saved_image_name1 = fp.name
history = history or []
response = random.choice(add_text_list) + '<img src="/file=' + saved_image_name1 + '">' #IMG_NAME
history.append((prompt, response))
counter_out += 1
return history, history, edited_image, temp_img_name, counter_out
#Blocks layout
with gr.Blocks(css="style.css") as demo:
with gr.Column(elem_id="col-container"):
gr.HTML("""<div style="text-align: center; max-width: 700px; margin: 0 auto;">
<div
style="
display: inline-flex;
align-items: center;
gap: 0.8rem;
font-size: 1.75rem;
"
>
<h1 style="font-weight: 900; margin-bottom: 7px; margin-top: 5px;">
ChatPix2Pix: Image Editing by Instructions
</h1>
</div>
<p style="margin-bottom: 10px; font-size: 94%">
Hi, I'm a photoshop expert bot, start by uploading your image using the upload button, and then tell me what changes you want to make to it.<br>
<a href="https://huggingface.co/spaces/ysharma/InstructPix2Pix_Chatbot?duplicate=true"><img src="https://bit.ly/3gLdBN6" alt="Duplicate Space"></a>Duplicate Space with GPU Upgrade for fast Inference & no queue<br>
Based on <a href="https://huggingface.co/timbrooks/instruct-pix2pix" target="_blank">Diffusers implementation</a> of InstructPix2Pix.
</p>
</div>""")
#gr.Markdown("""<h1><center>dummy</h1></center> """)
chatbot = gr.Chatbot()
state_in = gr.State()
with gr.Row():
text_in = gr.Textbox(value='', placeholder="Type your instructions here and press Enter")
btn_upload = gr.UploadButton("Upload image", file_types=["image"], file_count="single")
with gr.Accordion("Advance settings for Training and Inference", open=False):
image_in = gr.Image(visible=False,type='pil', label="Original Image")
gr.Markdown("Advance settings for - Number of Inference steps, Guidanace scale, and Image guidance scale.")
in_steps = gr.Number(label="Enter the number of Inference steps", value = 20)
in_guidance_scale = gr.Slider(1,10, step=0.5, label="Set Guidance scale", value=7.5)
in_img_guidance_scale = gr.Slider(1,10, step=0.5, label="Set Image Guidance scale", value=1.5)
image_hid = gr.Image(type='pil', visible=False)
image_oneup = gr.Image(type='pil', visible=False)
img_name_temp_out = gr.Textbox(visible=False)
counter_out = gr.Number(visible=False, value=0, precision=0)
btn_upload.upload(chat,
[btn_upload, image_in, in_steps, in_guidance_scale, in_img_guidance_scale, image_hid, img_name_temp_out,counter_out, image_oneup, text_in, state_in],
[chatbot, state_in, image_in, img_name_temp_out, counter_out])
text_in.submit(chat,[btn_upload, image_in, in_steps, in_guidance_scale, in_img_guidance_scale, image_hid, img_name_temp_out,counter_out, image_oneup, text_in, state_in], [chatbot, state_in, image_hid, img_name_temp_out, counter_out])
text_in.submit(previous, [image_hid], [image_oneup])
gr.Markdown(help_text)
demo.queue(concurrency_count=10)
demo.launch(debug=True, width="80%", height=2000) |