| 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] |