OneButtonPrompt/call_txt2img.py

211 lines
7.8 KiB
Python

import json
import requests
import io
import base64
import uuid
import sys, os
from PIL import Image, PngImagePlugin
from model_lists import *
def call_txt2img(passingprompt,ratio,upscale,debugmode,filename="",model = "currently selected model",samplingsteps = "40",cfg= "7",hiressteps ="0",denoisestrength="0.6",samplingmethod="DPM++ SDE Karras", upscaler="R-ESRGAN 4x+",hiresscale="2",apiurl="http://127.0.0.1:7860", qualitygate=False,quality="7.6",runs="5",negativeprompt=""):
#set the prompt!
prompt = passingprompt
checkprompt = passingprompt.lower()
#set the URL for the API
url = apiurl
#rest of prompt things
sampler_index = samplingmethod
steps = samplingsteps
if(debugmode==1):
steps="10"
cfg_scale = cfg
#size
if(ratio=='wide'):
width = "768"
height = "512"
elif(ratio=='portrait'):
width = "512"
height = "768"
elif(ratio=='ultrawide'):
width = "1280"
height = "360"
else:
width = "512"
height = "512"
#upscaler
enable_hr = upscale
if(debugmode==1):
enable_hr="False"
#defaults
hr_scale = hiresscale
denoising_strength = denoisestrength
hr_second_pass_steps = hiressteps
#hr_upscaler = "LDSR" # We have the time, why not use LDSR
if(upscaler != "automatic"):
hr_upscaler = upscaler
else:
upscalerlist = get_upscalers()
# on automatic, make some choices about what upscaler to use
# photos, prefer 4x ultrasharp
# anime, cartoon or drawing, go for R-ESRGAN 4x+ Anime6B
# else, R-ESRGAN 4x+"
if("hoto" in checkprompt and "4x-UltraSharp" in upscalerlist):
hr_upscaler = "4x-UltraSharp"
elif("anime" in checkprompt or "cartoon" in checkprompt or "draw" in checkprompt or "vector" in checkprompt or "cel shad" in checkprompt or "visual novel" in checkprompt):
hr_upscaler = "R-ESRGAN 4x+ Anime6B"
else:
hr_upscaler = "R-ESRGAN 4x+"
if(hiressteps==0):
hiressteps = samplingsteps
hr_second_pass_steps = int(hiressteps/2)
hr_scale = 2
if(hr_upscaler== "4x-UltraSharp"):
denoising_strength = "0.35"
if(hr_upscaler== "R-ESRGAN 4x+ Anime6B+"):
denoising_strength = "0.6" # 0.6 is fine for the anime upscaler
if(hr_upscaler== "R-ESRGAN 4x+"):
denoising_strength = "0.5" # default 0.6 is a lot and changes a lot of details
#params to stay the same
script_dir = os.path.dirname(os.path.abspath(__file__)) # Script directory
outputTXT2IMGfolder = os.path.join(script_dir, "./automated_outputs/txt2img/")
if(filename==""):
filename = str(uuid.uuid4())
outputTXT2IMGpng = '.png'
#outputTXT2IMGFull = '{}{}{}'.format(outputTXT2IMGfolder,filename,outputTXT2IMGpng)
outputTXT2IMGtxtfolder = os.path.join(script_dir, "./automated_outputs/prompts/")
outputTXT2IMGtxt = '.txt'
outputTXT2IMGtxtFull = '{}{}{}'.format(outputTXT2IMGtxtfolder,filename,outputTXT2IMGtxt)
# params for quality gate
isGoodNumber = float(quality)
foundgood = False
MaxRuns = int(runs)
Runs = 0
scorelist = []
scoredeclist = []
imagelist = []
pnginfolist = []
#call TXT2IMG
payload = {
"prompt": prompt,
"sampler_index": sampler_index,
"steps": steps,
"cfg_scale": cfg_scale,
"width": width,
"height": height,
"enable_hr": enable_hr,
"denoising_strength": denoising_strength,
"hr_scale": hr_scale,
"hr_upscaler": hr_upscaler,
"hr_second_pass_steps": hr_second_pass_steps
}
if(model != "currently selected model"):
payload.update({"sd_model": model})
if(negativeprompt != ""):
payload.update({"negative_prompt": negativeprompt})
while Runs < MaxRuns:
# make the filename unique for each run _0, _1, etc.
addrun = "_" + str(Runs)
filenamefull = filename + addrun
outputTXT2IMGFull = '{}{}{}'.format(outputTXT2IMGfolder,filenamefull,outputTXT2IMGpng)
response = requests.post(url=f'{url}/sdapi/v1/txt2img', json=payload)
r = response.json()
for i in r['images']:
image = Image.open(io.BytesIO(base64.b64decode(i.split(",",1)[0])))
png_payload = {
"image": "data:image/png;base64," + i
}
response2 = requests.post(url=f'{url}/sdapi/v1/png-info', json=png_payload)
pnginfo = PngImagePlugin.PngInfo()
pnginfo.add_text("parameters", response2.json().get("info"))
image.save(outputTXT2IMGFull, pnginfo=pnginfo)
if(qualitygate==True):
# check if the file exists in the parent directory
imagescorer_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'stable-diffusion-webui-aesthetic-image-scorer', 'scripts'))
#print(imagescorer_path)
if imagescorer_path not in sys.path:
sys.path.append(imagescorer_path)
try:
import image_scorer
print("Found aesthetic-image-scorer! Using this to measure the results...")
score = image_scorer.get_score(image)
scoredeclist.append(score)
score = round(score,1)
scorelist.append(score)
imagelist.append(outputTXT2IMGFull)
pnginfolist.append(pnginfo)
print("This image has scored: "+ str(score) + " out of " + str(isGoodNumber))
if(score >= isGoodNumber or debugmode == 1):
foundgood = True
print("Yay its good! Keeping this result.")
else:
runstodo = MaxRuns - Runs - 1
print("Not a good result. Retrying for another " + str(runstodo) + " times or until the image is good enough.")
except ImportError:
foundgood = True # just continue :)
# handle the case where the module doesn't exist
print("Could not find the stable-diffusion-webui-aesthetic-image-scorer extension.")
print("Install this extension via the WebUI to use Quality Gate")
pass
else:
foundgood = True # If there is no quality gate, then everything is good. So we escape this loop
Runs += 1
if(foundgood == True):
break #Break the loop if we found something good. Or if we set it to good :)
if(len(imagelist) > 0):
if(foundgood == True):
print("Removing any other images generated this run (if any).")
else:
print("Stopped trying, keeping the best image we had so far.")
# Get the index of the first occurrence of the maximum value in the list
indexofimagetokeep = scoredeclist.index(max(scoredeclist))
outputTXT2IMGFull = imagelist[indexofimagetokeep] #store the image to keep in here, so we can pass it along
pnginfo = pnginfolist[indexofimagetokeep]
imagelist.pop(indexofimagetokeep)
#remove all other images
for imagelocation in imagelist:
os.remove(imagelocation)
with open(outputTXT2IMGtxtFull,'w',encoding="utf8") as txt:
json_object = json.dumps(payload, indent = 4)
txt.write(json_object)
return [outputTXT2IMGFull,pnginfo]