fix upscale api

This commit is contained in:
Vladimir Mandic
2024-02-04 10:14:10 -05:00
parent a93c8160d7
commit 0a0efa3fc1
9 changed files with 147 additions and 54 deletions
+4 -1
View File
@@ -8,6 +8,7 @@
- image2video: pia and vgen pipelines
- wuerstchen v3 [pr](https://github.com/huggingface/diffusers/pull/6487)
- more pipelines: <https://github.com/huggingface/diffusers/blob/main/examples/community/README.md>
- segmoe: <https://github.com/segmind/segmoe>
- control api
- masking api
- preprocess api
@@ -277,11 +278,14 @@ As of this release, default backend is set to **diffusers** as its more feature
- img2img: clip and blip interrogate
- img2img: sampler selection offset
- img2img: support variable aspect ratio without explicit resize
- cli: add `simple-upscale.py` script
- cli: fix cmd args parsing
- api: return current image in progress api if requested
- api: sanitize response object
- api: cleanup error logging
- api: fix api-only errors
- api: fix image to base64
- api: fix upscale
- refiner: fix use of sd15 model as refiners in second pass
- refiner: enable none as option in xyz grid
- sampler: add sampler options info to metadata
@@ -297,7 +301,6 @@ As of this release, default backend is set to **diffusers** as its more feature
- reference: fix links to models and use safetensors where possible
- model merge: unbalanced models where not all keys are present, thanks @AI-Casanova
- better sdxl model detection
- cli: fix cmd args parsing
- global crlf->lf switch
- model type switch if there is loaded submodels
- cleanup samplers use of compute devices, thanks @Disty0
+2
View File
@@ -37,6 +37,7 @@ def post(endpoint: str, dct: dict = None):
else:
return req.json()
def encode(f):
image = Image.open(f)
if image.mode == 'RGBA':
@@ -48,6 +49,7 @@ def encode(f):
encoded = base64.b64encode(values).decode()
return encoded
def generate(args): # pylint: disable=redefined-outer-name
t0 = time.time()
if args.model is not None:
+90
View File
@@ -0,0 +1,90 @@
#!/usr/bin/env python
import os
import io
import time
import base64
import logging
import argparse
import requests
import urllib3
from PIL import Image
sd_url = os.environ.get('SDAPI_URL', "http://127.0.0.1:7860")
sd_username = os.environ.get('SDAPI_USR', None)
sd_password = os.environ.get('SDAPI_PWD', None)
logging.basicConfig(level = logging.INFO, format = '%(asctime)s %(levelname)s: %(message)s')
log = logging.getLogger(__name__)
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
def auth():
if sd_username is not None and sd_password is not None:
return requests.auth.HTTPBasicAuth(sd_username, sd_password)
return None
def get(endpoint: str, dct: dict = None):
req = requests.get(f'{sd_url}{endpoint}', json=dct, timeout=300, verify=False, auth=auth())
if req.status_code != 200:
return { 'error': req.status_code, 'reason': req.reason, 'url': req.url }
else:
return req.json()
def post(endpoint: str, dct: dict = None):
req = requests.post(f'{sd_url}{endpoint}', json = dct, timeout=300, verify=False, auth=auth())
if req.status_code != 200:
return { 'error': req.status_code, 'reason': req.reason, 'url': req.url }
else:
return req.json()
def encode(f):
image = Image.open(f)
if image.mode == 'RGBA':
image = image.convert('RGB')
log.info(f'encoding image: {image}')
with io.BytesIO() as stream:
image.save(stream, 'JPEG')
image.close()
values = stream.getvalue()
encoded = base64.b64encode(values).decode()
return encoded
def upscale(args): # pylint: disable=redefined-outer-name
t0 = time.time()
# options['mask'] = encode(args.mask)
upscalers = get('/sdapi/v1/upscalers')
upscalers = [u['name'] for u in upscalers]
log.info(f'upscalers: {upscalers}')
options = {
"save_images": False,
"send_images": True,
'image': encode(args.input),
'upscaler_1': args.upscaler,
'resize_mode': 0, # rescale_by
'upscaling_resize': args.scale,
}
data = post('/sdapi/v1/extra-single-image', options)
t1 = time.time()
if 'image' in data:
b64 = data['image'].split(',',1)[0]
image = Image.open(io.BytesIO(base64.b64decode(b64)))
image.save(args.output)
log.info(f'received: image={image} file={args.output} time={t1-t0:.2f}')
else:
log.warning(f'no images received: {data}')
if __name__ == "__main__":
parser = argparse.ArgumentParser(description = 'simple-upscale')
parser.add_argument('--input', required=True, help='input image')
parser.add_argument('--output', required=True, help='output image')
parser.add_argument('--upscaler', required=False, default='Nearest', help='upscaler name')
parser.add_argument('--scale', required=False, default=2, help='upscaler scale')
args = parser.parse_args()
log.info(f'upscale: {args}')
upscale(args)
-1
View File
@@ -23,7 +23,6 @@ class NetworkOnDisk:
self.filename = filename
self.metadata = {}
self.is_safetensors = os.path.splitext(filename)[1].lower() == ".safetensors"
if self.is_safetensors:
self.metadata = sd_models.read_metadata_from_safetensors(filename)
if self.metadata:
+2 -1
View File
@@ -448,8 +448,9 @@ def list_available_networks():
shared.log.warning('LoRA directory not found: path="{shared.cmd_opts.lora_dir}"')
if os.path.exists(shared.cmd_opts.lyco_dir) and shared.cmd_opts.lyco_dir != shared.cmd_opts.lora_dir:
directories.append(shared.cmd_opts.lyco_dir)
def add_network(filename):
if os.path.isdir(filename):
if not os.path.isfile(filename):
return
name = os.path.splitext(os.path.basename(filename))[0]
try:
+1 -1
View File
@@ -58,13 +58,13 @@ def instant_id(p: processing.StableDiffusionProcessing, app, source_image, stren
shared.sd_model.load_ip_adapter_instantid(face_adapter, scale=strength)
shared.sd_model.set_ip_adapter_scale(strength)
if not ((shared.opts.diffusers_model_cpu_offload or shared.cmd_opts.medvram) or (shared.opts.diffusers_seq_cpu_offload or shared.cmd_opts.lowvram)):
print('HERE1')
shared.sd_model.to(shared.device, devices.dtype) # move pipeline if needed, but don't touch if its under automatic managment
# pipeline specific args
orig_prompt_attention = shared.opts.prompt_attention
shared.opts.data['prompt_attention'] = 'Fixed attention' # otherwise need to deal with class_tokens_mask
p.task_args['prompt'] = p.all_prompts[0] # override all logic
p.task_args['negative_prompt'] = p.all_negative_prompts[0]
p.task_args['image_embeds'] = face_emb
p.task_args['image'] = face_kps
p.task_args['controlnet_conditioning_scale'] = float(conditioning)
+4 -3
View File
@@ -7,6 +7,7 @@ TODO ipadapter items:
- SD/SDXL autodetect
"""
import os
import time
from modules import processing, shared, devices
@@ -110,12 +111,12 @@ def apply(pipe, p: processing.StableDiffusionProcessing, adapter_name='None', sc
pipe.load_ip_adapter(base_repo, subfolder=ip_subfolder, weight_name=adapter)
pipe.set_ip_adapter_scale(scale)
t1 = time.time()
shared.log.info(f'IP adapter: adapter="{adapter}" scale={scale} image={image} time={t1-t0:.2f}')
shared.log.info(f'IP adapter: adapter="{ip_subfolder}/{adapter}" scale={scale} image={image} time={t1-t0:.2f}')
if isinstance(image, str):
from modules.api.api import decode_base64_to_image
image = decode_base64_to_image(image).convert("RGB")
p.task_args['ip_adapter_image'] = p.batch_size * [image]
p.extra_generation_params["IP Adapter"] = f'{adapter}:{scale}'
p.task_args['ip_adapter_image'] = [image]
p.extra_generation_params["IP Adapter"] = f'{os.path.splitext(adapter)[0]}:{scale}'
return True
+43 -46
View File
@@ -305,10 +305,7 @@ def scrub_dict(dict_obj, keys):
def read_metadata_from_safetensors(filename):
global sd_metadata # pylint: disable=global-statement
if sd_metadata is None:
if not os.path.isfile(sd_metadata_file):
sd_metadata = {}
else:
sd_metadata = shared.readfile(sd_metadata_file, lock=True)
sd_metadata = shared.readfile(sd_metadata_file, lock=True) if os.path.isfile(sd_metadata_file) else {}
res = sd_metadata.get(filename, None)
if res is not None:
return res
@@ -317,48 +314,48 @@ def read_metadata_from_safetensors(filename):
if shared.cmd_opts.no_metadata:
return {}
res = {}
try:
t0 = time.time()
with open(filename, mode="rb") as file:
metadata_len = file.read(8)
metadata_len = int.from_bytes(metadata_len, "little")
json_start = file.read(2)
if metadata_len <= 2 or json_start not in (b'{"', b"{'"):
shared.log.error(f"Not a valid safetensors file: {filename}")
json_data = json_start + file.read(metadata_len-2)
json_obj = json.loads(json_data)
for k, v in json_obj.get("__metadata__", {}).items():
if v.startswith("data:"):
v = 'data'
if k == 'format' and v == 'pt':
continue
large = True if len(v) > 2048 else False
if large and k == 'ss_datasets':
continue
if large and k == 'workflow':
continue
if large and k == 'prompt':
continue
if large and k == 'ss_bucket_info':
continue
if v[0:1] == '{':
try:
v = json.loads(v)
if large and k == 'ss_tag_frequency':
v = { i: len(j) for i, j in v.items() }
if large and k == 'sd_merge_models':
scrub_dict(v, ['sd_merge_recipe'])
except Exception:
pass
res[k] = v
sd_metadata[filename] = res
global sd_metadata_pending # pylint: disable=global-statement
sd_metadata_pending += 1
t1 = time.time()
global sd_metadata_timer # pylint: disable=global-statement
sd_metadata_timer += (t1 - t0)
except Exception as e:
shared.log.error(f"Error reading metadata from: {filename} {e}")
# try:
t0 = time.time()
with open(filename, mode="rb") as file:
metadata_len = file.read(8)
metadata_len = int.from_bytes(metadata_len, "little")
json_start = file.read(2)
if metadata_len <= 2 or json_start not in (b'{"', b"{'"):
shared.log.error(f"Not a valid safetensors file: {filename}")
json_data = json_start + file.read(metadata_len-2)
json_obj = json.loads(json_data)
for k, v in json_obj.get("__metadata__", {}).items():
if v.startswith("data:"):
v = 'data'
if k == 'format' and v == 'pt':
continue
large = True if len(v) > 2048 else False
if large and k == 'ss_datasets':
continue
if large and k == 'workflow':
continue
if large and k == 'prompt':
continue
if large and k == 'ss_bucket_info':
continue
if v[0:1] == '{':
try:
v = json.loads(v)
if large and k == 'ss_tag_frequency':
v = { i: len(j) for i, j in v.items() }
if large and k == 'sd_merge_models':
scrub_dict(v, ['sd_merge_recipe'])
except Exception:
pass
res[k] = v
sd_metadata[filename] = res
global sd_metadata_pending # pylint: disable=global-statement
sd_metadata_pending += 1
t1 = time.time()
global sd_metadata_timer # pylint: disable=global-statement
sd_metadata_timer += (t1 - t0)
# except Exception as e:
# shared.log.error(f"Error reading metadata from: {filename} {e}")
return res
+1 -1
View File
@@ -41,7 +41,7 @@ class ScriptPostprocessingUpscale(scripts_postprocessing.ScriptPostprocessing):
}
def postprocess(self, images, filename, video_type, duration, loop, pad, interpolate, scale, change): # pylint: disable=arguments-differ
filename = filename.strip()
filename = filename.strip() if filename is not None else ''
if video_type == 'None' or len(filename) == 0 or images is None or len(images) < 2:
return
modules.images.save_video(p=None, filename=filename, images=images, video_type=video_type, duration=duration, loop=loop, pad=pad, interpolate=interpolate, scale=scale, change=change)