mirror of
https://github.com/vladmandic/automatic
synced 2026-09-19 09:14:35 +02:00
fix upscale api
This commit is contained in:
+4
-1
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
Executable
+90
@@ -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)
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user