Spaces:
Runtime error
Runtime error
| #!/usr/bin/env python | |
| # pylint: disable=no-member | |
| import os | |
| import re | |
| import json | |
| import time | |
| import logging | |
| import importlib | |
| import asyncio | |
| import argparse | |
| from pathlib import Path | |
| from util import Map, log | |
| from sdapi import get, post, close | |
| from generate import generate # pylint: disable=import-error | |
| grid = importlib.import_module('image-grid').grid | |
| options = Map({ | |
| # used by extra networks | |
| 'prompt': 'photo of <keyword> <embedding>, photograph, posing, pose, high detailed, intricate, elegant, sharp focus, skin texture, looking forward, facing camera, 135mm, shot on dslr, canon 5d, 4k, modelshoot style, cinematic lighting', | |
| # used by models | |
| 'prompts': [ | |
| ('photo citiscape', 'cityscape during night, photorealistic, high detailed, sharp focus, depth of field, 4k'), | |
| ('photo car', 'photo of a sports car, high detailed, sharp focus, dslr, cinematic lighting, realistic'), | |
| ('photo woman', 'portrait photo of beautiful woman, high detailed, dslr, 35mm'), | |
| ('photo naked', 'full body photo of beautiful sexy naked woman, high detailed, dslr, 35mm'), | |
| ('photo taylor', 'portrait photo of beautiful woman taylor swift, high detailed, sharp focus, depth of field, dslr, 35mm <lora:taylor-swift:1>'), | |
| ('photo ti-mia', 'portrait photo of beautiful woman "ti-mia", naked, high detailed, dslr, 35mm'), | |
| ('photo ti-vlado', 'portrait photo of man "ti-vlado", high detailed, dslr, 35mm'), | |
| ('photo lora-vlado', 'portrait photo of man vlado, high detailed, dslr, 35mm <lora:vlado-original:1>'), | |
| ('wlop', 'a stunning portrait of sexy teen girl in a wet t-shirt, vivid color palette, digital painting, octane render, highly detailed, particles, light effect, volumetric lighting, art by wlop'), | |
| ('greg rutkowski', 'beautiful woman, high detailed, sharp focus, depth of field, 4k, art by greg rutkowski'), | |
| ('carne griffiths', 'beautiful woman taylor swift, high detailed, sharp focus, depth of field, art by carne griffiths <lora:taylor-swift:1>'), | |
| ('carne griffiths', 'man vlado, high detailed, sharp focus, depth of field, art by carne griffiths <lora:vlado-full:1>'), | |
| ], | |
| # save format | |
| 'format': '.jpg', | |
| # used by generate script | |
| 'paths': { | |
| "root": "/mnt/c/Users/mandi/OneDrive/Generative/Generate", | |
| "generate": "image", | |
| "upscale": "upscale", | |
| "grid": "grid", | |
| }, | |
| # generate params | |
| 'generate': { | |
| 'restore_faces': True, | |
| 'prompt': '', | |
| 'negative_prompt': 'foggy, blurry, blurred, duplicate, ugly, mutilated, mutation, mutated, out of frame, bad anatomy, disfigured, deformed, censored, low res, low resolution, watermark, text, poorly drawn face, poorly drawn hands, signature', | |
| 'steps': 20, | |
| 'batch_size': 2, | |
| 'n_iter': 1, | |
| 'seed': -1, | |
| 'sampler_name': 'UniPC', | |
| 'cfg_scale': 6, | |
| 'width': 512, | |
| 'height': 512, | |
| }, | |
| 'lora': { | |
| 'strength': 1.0, | |
| }, | |
| 'hypernetwork': { | |
| 'keyword': '', | |
| 'strength': 1.0, | |
| }, | |
| }) | |
| def preview_exists(folder, model): | |
| model = os.path.splitext(model)[0] | |
| for suffix in ['', '.preview']: | |
| for ext in ['.jpg', '.png', '.webp']: | |
| fn = os.path.join(folder, f'{model}{suffix}{ext}') | |
| if os.path.exists(fn): | |
| return True | |
| return False | |
| async def preview_models(params): | |
| data = await get('/sdapi/v1/sd-models') | |
| allmodels = [m['title'] for m in data] | |
| models = [] | |
| excluded = [] | |
| for m in allmodels: # loop through all registered models | |
| ok = True | |
| for e in params.exclude: # check if model is excluded | |
| if e in m: | |
| excluded.append(m) | |
| ok = False | |
| break | |
| if ok: | |
| short = m.split(' [')[0] | |
| short = short.replace('.ckpt', '').replace('.safetensors', '') | |
| models.append(short) | |
| if len(params.input) > 0: # check if model is included in cmd line | |
| filtered = [] | |
| for m in params.input: | |
| if m in models: | |
| filtered.append(m) | |
| else: | |
| log.error({ 'model not found': m }) | |
| return | |
| models = filtered | |
| log.info({ 'models preview' }) | |
| log.info({ 'models': len(models), 'excluded': len(excluded) }) | |
| opt = await get('/sdapi/v1/options') | |
| log.info({ 'total jobs': len(models) * options.generate.batch_size, 'per-model': options.generate.batch_size }) | |
| log.info(json.dumps(options, indent=2)) | |
| for model in models: | |
| if preview_exists(opt['ckpt_dir'], model) and len(params.input) == 0: # if model preview exists and not manually included | |
| log.info({ 'model preview exists': model }) | |
| continue | |
| fn = os.path.join(opt['ckpt_dir'], os.path.splitext(model)[0] + options.format) | |
| log.info({ 'model load': model }) | |
| opt['sd_model_checkpoint'] = model | |
| del opt['sd_lora'] | |
| del opt['sd_lyco'] | |
| await post('/sdapi/v1/options', opt) | |
| opt = await get('/sdapi/v1/options') | |
| images = [] | |
| labels = [] | |
| t0 = time.time() | |
| for label, p in options.prompts: | |
| options.generate.prompt = p | |
| log.info({ 'model generating': model, 'label': label, 'prompt': options.generate.prompt }) | |
| data = await generate(options = options, quiet=True) | |
| if 'image' in data: | |
| for img in data['image']: | |
| images.append(img) | |
| labels.append(label) | |
| else: | |
| log.error({ 'model': model, 'error': data }) | |
| t1 = time.time() | |
| if len(images) == 0: | |
| log.error({ 'model': model, 'error': 'no images generated' }) | |
| continue | |
| image = grid(images = images, labels = labels, border = 8) | |
| log.info({ 'saving preview': fn, 'images': len(images), 'size': [image.width, image.height] }) | |
| image.save(fn) | |
| t = t1 - t0 | |
| its = 1.0 * options.generate.steps * len(images) / t | |
| log.info({ 'model preview created': model, 'image': fn, 'images': len(images), 'grid': [image.width, image.height], 'time': round(t, 2), 'its': round(its, 2) }) | |
| opt = await get('/sdapi/v1/options') | |
| if opt['sd_model_checkpoint'] != params.model: | |
| log.info({ 'model set default': params.model }) | |
| opt['sd_model_checkpoint'] = params.model | |
| del opt['sd_lora'] | |
| del opt['sd_lyco'] | |
| await post('/sdapi/v1/options', opt) | |
| async def lora(params): | |
| opt = await get('/sdapi/v1/options') | |
| folder = opt['lora_dir'] | |
| if not os.path.exists(folder): | |
| log.error({ 'lora directory not found': folder }) | |
| return | |
| models1 = list(Path(folder).glob('**/*.safetensors')) | |
| models2 = list(Path(folder).glob('**/*.ckpt')) | |
| models = [os.path.splitext(f)[0] for f in models1 + models2] | |
| log.info({ 'loras': len(models) }) | |
| for model in models: | |
| if preview_exists('', model) and len(params.input) == 0: # if model preview exists and not manually included | |
| log.info({ 'lora preview exists': model }) | |
| continue | |
| fn = model + options.format | |
| model = os.path.basename(model) | |
| images = [] | |
| labels = [] | |
| t0 = time.time() | |
| keywords = re.sub(r'\d', '', model) | |
| keywords = keywords.replace('-v', ' ').replace('-', ' ').strip().split(' ') | |
| keyword = '\"' + '\" \"'.join(keywords) + '\"' | |
| options.generate.prompt = options.prompt.replace('<keyword>', keyword) | |
| options.generate.prompt = options.generate.prompt.replace('<embedding>', '') | |
| options.generate.prompt += f' <lora:{model}:{options.lora.strength}>' | |
| log.info({ 'lora generating': model, 'keyword': keyword, 'prompt': options.generate.prompt }) | |
| data = await generate(options = options, quiet=True) | |
| if 'image' in data: | |
| for img in data['image']: | |
| images.append(img) | |
| labels.append(keyword) | |
| else: | |
| log.error({ 'lora': model, 'keyword': keyword, 'error': data }) | |
| t1 = time.time() | |
| if len(images) == 0: | |
| log.error({ 'model': model, 'error': 'no images generated' }) | |
| continue | |
| image = grid(images = images, labels = labels, border = 8) | |
| log.info({ 'saving preview': fn, 'images': len(images), 'size': [image.width, image.height] }) | |
| image.save(fn) | |
| t = t1 - t0 | |
| its = 1.0 * options.generate.steps * len(images) / t | |
| log.info({ 'lora preview created': model, 'image': fn, 'images': len(images), 'grid': [image.width, image.height], 'time': round(t, 2), 'its': round(its, 2) }) | |
| async def lyco(params): | |
| opt = await get('/sdapi/v1/options') | |
| folder = opt['lyco_dir'] | |
| if not os.path.exists(folder): | |
| log.error({ 'lyco directory not found': folder }) | |
| return | |
| models1 = list(Path(folder).glob('**/*.safetensors')) | |
| models2 = list(Path(folder).glob('**/*.ckpt')) | |
| models = [os.path.splitext(f)[0] for f in models1 + models2] | |
| log.info({ 'lycos': len(models) }) | |
| for model in models: | |
| if preview_exists('', model) and len(params.input) == 0: # if model preview exists and not manually included | |
| log.info({ 'lyco preview exists': model }) | |
| continue | |
| fn = model + options.format | |
| model = os.path.basename(model) | |
| images = [] | |
| labels = [] | |
| t0 = time.time() | |
| keywords = re.sub(r'\d', '', model) | |
| keywords = keywords.replace('-v', ' ').replace('-', ' ').strip().split(' ') | |
| keyword = '\"' + '\" \"'.join(keywords) + '\"' | |
| options.generate.prompt = options.prompt.replace('<keyword>', keyword) | |
| options.generate.prompt = options.generate.prompt.replace('<embedding>', '') | |
| options.generate.prompt += f' <lyco:{model}:{options.lora.strength}>' | |
| log.info({ 'lyco generating': model, 'keyword': keyword, 'prompt': options.generate.prompt }) | |
| data = await generate(options = options, quiet=True) | |
| if 'image' in data: | |
| for img in data['image']: | |
| images.append(img) | |
| labels.append(keyword) | |
| else: | |
| log.error({ 'lyco': model, 'keyword': keyword, 'error': data }) | |
| t1 = time.time() | |
| if len(images) == 0: | |
| log.error({ 'model': model, 'error': 'no images generated' }) | |
| continue | |
| image = grid(images = images, labels = labels, border = 8) | |
| log.info({ 'saving preview': fn, 'images': len(images), 'size': [image.width, image.height] }) | |
| image.save(fn) | |
| t = t1 - t0 | |
| its = 1.0 * options.generate.steps * len(images) / t | |
| log.info({ 'lyco preview created': model, 'image': fn, 'images': len(images), 'grid': [image.width, image.height], 'time': round(t, 2), 'its': round(its, 2) }) | |
| async def hypernetwork(params): | |
| opt = await get('/sdapi/v1/options') | |
| folder = opt['hypernetwork_dir'] | |
| if not os.path.exists(folder): | |
| log.error({ 'hypernetwork directory not found': folder }) | |
| return | |
| models = [os.path.splitext(f)[0] for f in Path(folder).glob('**/*.pt')] | |
| log.info({ 'hypernetworks': len(models) }) | |
| for model in models: | |
| if preview_exists(folder, model) and len(params.input) == 0: # if model preview exists and not manually included | |
| log.info({ 'hypernetwork preview exists': model }) | |
| continue | |
| fn = os.path.join(folder, model + options.format) | |
| images = [] | |
| labels = [] | |
| t0 = time.time() | |
| keyword = options.hypernetwork.keyword | |
| options.generate.prompt = options.prompt.replace('<keyword>', options.hypernetwork.keyword) | |
| options.generate.prompt = options.generate.prompt.replace('<embedding>', '') | |
| options.generate.prompt = f' <hypernet:{model}:{options.hypernetwork.strength}> ' + options.generate.prompt | |
| log.info({ 'hypernetwork generating': model, 'keyword': keyword, 'prompt': options.generate.prompt }) | |
| data = await generate(options = options, quiet=True) | |
| if 'image' in data: | |
| for img in data['image']: | |
| images.append(img) | |
| labels.append(keyword) | |
| else: | |
| log.error({ 'hypernetwork': model, 'keyword': keyword, 'error': data }) | |
| t1 = time.time() | |
| if len(images) == 0: | |
| log.error({ 'model': model, 'error': 'no images generated' }) | |
| continue | |
| image = grid(images = images, labels = labels, border = 8) | |
| log.info({ 'saving preview': fn, 'images': len(images), 'size': [image.width, image.height] }) | |
| image.save(fn) | |
| t = t1 - t0 | |
| its = 1.0 * options.generate.steps * len(images) / t | |
| log.info({ 'hypernetwork preview created': model, 'image': fn, 'images': len(images), 'grid': [image.width, image.height], 'time': round(t, 2), 'its': round(its, 2) }) | |
| async def embedding(params): | |
| opt = await get('/sdapi/v1/options') | |
| folder = opt['embeddings_dir'] | |
| if not os.path.exists(folder): | |
| log.error({ 'embeddings directory not found': folder }) | |
| return | |
| models = [os.path.splitext(f)[0] for f in Path(folder).glob('**/*.pt')] | |
| log.info({ 'embeddings': len(models) }) | |
| for model in models: | |
| if preview_exists(folder, model) and len(params.input) == 0: # if model preview exists and not manually included | |
| log.info({ 'embedding preview exists': model }) | |
| continue | |
| fn = os.path.join(folder, model + '.preview' + options.format) | |
| images = [] | |
| labels = [] | |
| t0 = time.time() | |
| keyword = '\"' + re.sub(r'\d', '', model) + '\"' | |
| options.generate.batch_size = 4 | |
| options.generate.prompt = options.prompt.replace('<keyword>', keyword) | |
| options.generate.prompt = options.generate.prompt.replace('<embedding>', '') | |
| log.info({ 'embedding generating': model, 'keyword': keyword, 'prompt': options.generate.prompt }) | |
| data = await generate(options = options, quiet=True) | |
| if 'image' in data: | |
| for img in data['image']: | |
| images.append(img) | |
| labels.append(keyword) | |
| else: | |
| log.error({ 'embeding': model, 'keyword': keyword, 'error': data }) | |
| t1 = time.time() | |
| if len(images) == 0: | |
| log.error({ 'model': model, 'error': 'no images generated' }) | |
| continue | |
| image = grid(images = images, labels = labels, border = 8) | |
| log.info({ 'saving preview': fn, 'images': len(images), 'size': [image.width, image.height] }) | |
| image.save(fn) | |
| t = t1 - t0 | |
| its = 1.0 * options.generate.steps * len(images) / t | |
| log.info({ 'embeding preview created': model, 'image': fn, 'images': len(images), 'grid': [image.width, image.height], 'time': round(t, 2), 'its': round(its, 2) }) | |
| async def create_previews(params): | |
| await preview_models(params) | |
| await lora(params) | |
| await lyco(params) | |
| await hypernetwork(params) | |
| await embedding(params) | |
| await close() | |
| if __name__ == '__main__': | |
| parser = argparse.ArgumentParser(description = 'generate model previews') | |
| parser.add_argument('--model', default='best/icbinp-icantbelieveIts-final.safetensors [73f48afbdc]', help="model used to create extra network previews") | |
| parser.add_argument('--exclude', default=['sd-v20', 'sd-v21', 'inpainting', 'pix2pix'], help="exclude models with keywords") | |
| parser.add_argument('--debug', default = False, action='store_true', help = 'print extra debug information') | |
| parser.add_argument('input', type = str, nargs = '*') | |
| args = parser.parse_args() | |
| if args.debug: | |
| log.setLevel(logging.DEBUG) | |
| log.debug({ 'debug': True }) | |
| log.debug({ 'args': args.__dict__ }) | |
| asyncio.run(create_previews(args)) | |