|
import json
|
|
import requests
|
|
import io
|
|
import base64
|
|
import uuid
|
|
import sys, os
|
|
from PIL import Image, PngImagePlugin
|
|
from model_lists import *
|
|
import time
|
|
import random
|
|
|
|
def call_txt2img(passingprompt,size,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="",qualityhiresfix = False, qualitymode = "highest", qualitykeep="keep used", basesize="512"):
|
|
|
|
|
|
|
|
|
|
prompt = passingprompt
|
|
checkprompt = passingprompt.lower()
|
|
|
|
|
|
|
|
|
|
url = apiurl
|
|
|
|
|
|
sampler_index = samplingmethod
|
|
steps = samplingsteps
|
|
if(debugmode==1):
|
|
steps="10"
|
|
cfg_scale = cfg
|
|
|
|
originalsize = size
|
|
|
|
sizes = setsize(size, basesize,originalsize)
|
|
width = sizes[0]
|
|
height = sizes[1]
|
|
|
|
|
|
|
|
|
|
|
|
enable_hr = upscale
|
|
if(debugmode==1 or qualityhiresfix == True):
|
|
enable_hr="False"
|
|
|
|
|
|
hr_scale = hiresscale
|
|
denoising_strength = denoisestrength
|
|
|
|
hr_second_pass_steps = hiressteps
|
|
|
|
|
|
if(upscaler != "automatic"):
|
|
hr_upscaler = upscaler
|
|
else:
|
|
upscalerlist = get_upscalers()
|
|
|
|
|
|
|
|
|
|
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"
|
|
if(hr_upscaler== "R-ESRGAN 4x+"):
|
|
denoising_strength = "0.5"
|
|
|
|
|
|
|
|
|
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
|
outputTXT2IMGfolder = os.path.join(script_dir, "./automated_outputs/txt2img/")
|
|
outputTXT2IMGfolder.replace("./", "/")
|
|
if(filename==""):
|
|
filename = str(uuid.uuid4())
|
|
|
|
outputTXT2IMGpng = '.png'
|
|
|
|
outputTXT2IMGtxtfolder = os.path.join(script_dir, "./automated_outputs/prompts/")
|
|
outputTXT2IMGtxtfolder.replace("./", "/")
|
|
outputTXT2IMGtxt = '.txt'
|
|
outputTXT2IMGtxtFull = '{}{}{}'.format(outputTXT2IMGtxtfolder,filename,outputTXT2IMGtxt)
|
|
|
|
|
|
isGoodNumber = float(quality)
|
|
foundgood = False
|
|
MaxRuns = int(runs)
|
|
Runs = 0
|
|
scorelist = []
|
|
scoredeclist = []
|
|
imagelist = []
|
|
pnginfolist = []
|
|
seedlist = []
|
|
widthlist = []
|
|
heightlist = []
|
|
usedwidht = width
|
|
usedheight = height
|
|
usedseed = -1
|
|
imagethatiskept = ""
|
|
|
|
|
|
continuewithnextpart = True
|
|
|
|
|
|
seed = -1
|
|
|
|
|
|
|
|
|
|
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,
|
|
"seed": seed,
|
|
"hr_prompt": prompt
|
|
}
|
|
|
|
if(model != "currently selected model"):
|
|
payload.update({"sd_model": model})
|
|
|
|
if(negativeprompt != ""):
|
|
payload.update({"negative_prompt": negativeprompt})
|
|
payload.update({"hr_negative_prompt": negativeprompt})
|
|
|
|
while Runs < MaxRuns:
|
|
|
|
|
|
addrun = "_" + str(Runs)
|
|
filenamefull = filename + addrun
|
|
outputTXT2IMGFull = '{}{}{}'.format(outputTXT2IMGfolder,filenamefull,outputTXT2IMGpng)
|
|
|
|
r = []
|
|
|
|
seed = random.randrange(1, 4294967295)
|
|
payload["seed"] = seed
|
|
|
|
|
|
if(originalsize=='all' or originalsize == 'wild'):
|
|
sizes = setsize(size, basesize, originalsize)
|
|
width = sizes[0]
|
|
height = sizes[1]
|
|
payload["width"] = width
|
|
payload["height"] = height
|
|
|
|
|
|
for i in range(4):
|
|
response = requests.post(url=f'{url}/sdapi/v1/txt2img', json=payload)
|
|
|
|
r = response.json()
|
|
if('images' in r):
|
|
break
|
|
else:
|
|
if(i == 3):
|
|
print("If this keeps happening: Is WebUI started with --api enabled?")
|
|
print("")
|
|
raise ValueError("API has not been responding after several retries. Stopped processing.")
|
|
print("")
|
|
print("We haven't received an image from the API. Maybe something went wrong. Will retry after waiting a bit.")
|
|
|
|
|
|
time.sleep(10 * (i+1) )
|
|
|
|
|
|
|
|
|
|
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):
|
|
|
|
imagescorer_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'stable-diffusion-webui-aesthetic-image-scorer', 'scripts'))
|
|
|
|
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)
|
|
seedlist.append(seed)
|
|
widthlist.append(width)
|
|
heightlist.append(height)
|
|
|
|
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
|
|
|
|
|
|
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
|
|
|
|
Runs += 1
|
|
if(foundgood == True):
|
|
break
|
|
|
|
if(len(imagelist) > 0):
|
|
|
|
if(foundgood == True):
|
|
if(qualitykeep == "keep used"):
|
|
print("Removing any other images generated this run (if any).")
|
|
else:
|
|
if(qualitymode == "highest"):
|
|
print("")
|
|
print("Stopped trying, keeping the best image we had so far.")
|
|
print("")
|
|
else:
|
|
print("")
|
|
print("Eh, its all pretty bad. Not going forward with any image.")
|
|
print("")
|
|
|
|
|
|
|
|
|
|
indexofimagetokeep = scoredeclist.index(max(scoredeclist))
|
|
outputTXT2IMGFull = imagelist[indexofimagetokeep]
|
|
pnginfo = pnginfolist[indexofimagetokeep]
|
|
usedseed = seedlist[indexofimagetokeep]
|
|
usedwidht = widthlist[indexofimagetokeep]
|
|
usedheight = heightlist[indexofimagetokeep]
|
|
imagethatiskept = imagelist[indexofimagetokeep]
|
|
imagelist.pop(indexofimagetokeep)
|
|
|
|
|
|
|
|
if(qualitykeep == "keep used"):
|
|
for imagelocation in imagelist:
|
|
os.remove(imagelocation)
|
|
|
|
if(foundgood == False and qualitymode != "highest"):
|
|
continuewithnextpart = False
|
|
if(imagethatiskept != "" and qualitykeep == "keep used"):
|
|
os.remove(imagethatiskept)
|
|
|
|
|
|
|
|
|
|
if(qualityhiresfix == True and upscale == False and continuewithnextpart == True):
|
|
print("Quality Gate hires fix was enabled, but no hires fix settings were given.")
|
|
if(qualityhiresfix == True and upscale == True and continuewithnextpart == True):
|
|
print("Going to run the chosen image with hiresfix")
|
|
|
|
payload["seed"] = usedseed
|
|
payload["width"] = usedwidht
|
|
payload["height"] = usedheight
|
|
payload["enable_hr"] = "True"
|
|
|
|
|
|
addrun = "_hiresfix"
|
|
filenamefull = filename + addrun
|
|
outputTXT2IMGFull = '{}{}{}'.format(outputTXT2IMGfolder,filenamefull,outputTXT2IMGpng)
|
|
|
|
|
|
for i in range(4):
|
|
response = requests.post(url=f'{url}/sdapi/v1/txt2img', json=payload)
|
|
|
|
r = response.json()
|
|
if('images' in r):
|
|
break
|
|
else:
|
|
if(i == 3):
|
|
print("If this keeps happening: Is WebUI started with --api enabled?")
|
|
print("")
|
|
raise ValueError("API has not been responding after several retries. Stopped processing.")
|
|
print("")
|
|
print("We haven't received an image from the API. Maybe something went wrong. Will retry after waiting a bit.")
|
|
|
|
|
|
time.sleep(10 * (i+1) )
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
|
|
|
with open(outputTXT2IMGtxtFull,'w',encoding="utf8") as txt:
|
|
json_object = json.dumps(payload, indent = 4)
|
|
txt.write(json_object)
|
|
|
|
return [outputTXT2IMGFull,pnginfo,continuewithnextpart]
|
|
|
|
def setsize(ratio,basesize, originalsize):
|
|
|
|
|
|
if(originalsize == "all"):
|
|
sizelist = ["portrait", "wide", "square"]
|
|
ratio = random.choice(sizelist)
|
|
|
|
if(ratio=='wide' and basesize != "1024"):
|
|
width = str(int(basesize) + 256)
|
|
height = basesize
|
|
elif(ratio=='wide' and basesize == "1024"):
|
|
width = "1152"
|
|
height = "896"
|
|
elif(ratio=='portrait' and basesize != "1024"):
|
|
width = basesize
|
|
height = str(int(basesize) + 256)
|
|
elif(ratio=='portrait' and basesize == "1024"):
|
|
width = "896"
|
|
height = "1152"
|
|
elif(ratio=='ultrawide'):
|
|
width = "1280"
|
|
height = "360"
|
|
elif(ratio=='ultraheight'):
|
|
width = "360"
|
|
height = "1280"
|
|
elif(ratio=='wild'):
|
|
width = str(round((random.randint(0,4) * 128) + (int(basesize) /2) ) )
|
|
height = str(round( (random.randint(0,4) * 128) + (int(basesize) /2) ) )
|
|
else:
|
|
width = basesize
|
|
height = basesize
|
|
|
|
return [width, height] |