|
|
from io import BytesIO |
|
|
import random |
|
|
import requests |
|
|
import modules.scripts as scripts |
|
|
import gradio as gr |
|
|
import os |
|
|
from PIL import Image |
|
|
import numpy as np |
|
|
import importlib |
|
|
import requests_cache |
|
|
|
|
|
from modules.processing import process_images, StableDiffusionProcessingImg2Img |
|
|
from modules import shared |
|
|
from modules.sd_hijack import model_hijack |
|
|
from modules import deepbooru |
|
|
from modules.ui_components import InputAccordion |
|
|
|
|
|
extension_root = scripts.basedir() |
|
|
user_data_dir = os.path.join(extension_root, 'user') |
|
|
user_search_dir = os.path.join(user_data_dir, 'search') |
|
|
user_remove_dir = os.path.join(user_data_dir, 'remove') |
|
|
os.makedirs(user_search_dir, exist_ok=True) |
|
|
os.makedirs(user_remove_dir, exist_ok=True) |
|
|
|
|
|
if not os.path.isfile(os.path.join(user_search_dir, 'tags_search.txt')): |
|
|
with open(os.path.join(user_search_dir, 'tags_search.txt'), 'w'): |
|
|
pass |
|
|
if not os.path.isfile(os.path.join(user_remove_dir, 'tags_remove.txt')): |
|
|
with open(os.path.join(user_remove_dir, 'tags_remove.txt'), 'w'): |
|
|
pass |
|
|
|
|
|
COLORED_BG = ['black_background', 'aqua_background', 'white_background', 'colored_background', 'gray_background', 'blue_background', 'green_background', 'red_background', 'brown_background', 'purple_background', 'yellow_background', 'orange_background', 'pink_background', 'plain', 'transparent_background', 'simple_background', 'two-tone_background', 'grey_background'] |
|
|
ADD_BG = ['outdoors', 'indoors'] |
|
|
BW_BG = ['monochrome', 'greyscale', 'grayscale'] |
|
|
POST_AMOUNT = 100 |
|
|
COUNT = 100 |
|
|
DEBUG = False |
|
|
RATING_TYPES = { |
|
|
"none": { |
|
|
"All": "All" |
|
|
}, |
|
|
"full": { |
|
|
"All": "All", |
|
|
"Safe": "safe", |
|
|
"Questionable": "questionable", |
|
|
"Explicit": "explicit" |
|
|
}, |
|
|
"single": { |
|
|
"All": "All", |
|
|
"Safe": "g", |
|
|
"Sensitive": "s", |
|
|
"Questionable": "q", |
|
|
"Explicit": "e" |
|
|
} |
|
|
} |
|
|
RATINGS = { |
|
|
"e621": RATING_TYPES['full'], |
|
|
"danbooru": RATING_TYPES['single'], |
|
|
"aibooru": RATING_TYPES['full'], |
|
|
"yande.re": RATING_TYPES['full'], |
|
|
"konachan": RATING_TYPES['full'], |
|
|
"safebooru": RATING_TYPES['none'], |
|
|
"rule34": RATING_TYPES['full'], |
|
|
"xbooru": RATING_TYPES['full'], |
|
|
"gelbooru": RATING_TYPES['single'] |
|
|
} |
|
|
|
|
|
|
|
|
def get_available_ratings(booru): |
|
|
mature_ratings = gr.Radio.update(choices=RATINGS[booru].keys(), value="All") |
|
|
return mature_ratings |
|
|
|
|
|
|
|
|
def show_fringe_benefits(booru): |
|
|
if booru == 'gelbooru': |
|
|
return gr.Checkbox.update(visible=True) |
|
|
else: |
|
|
return gr.Checkbox.update(visible=False) |
|
|
|
|
|
|
|
|
def check_exception(booru, parameters): |
|
|
post_id = parameters.get('post_id') |
|
|
tags = parameters.get('tags') |
|
|
if booru == 'konachan' and post_id: |
|
|
raise Exception("Konachan does not support post IDs") |
|
|
if booru == 'yande.re' and post_id: |
|
|
raise Exception("Yande.re does not support post IDs") |
|
|
if booru == 'e621' and post_id: |
|
|
raise Exception("e621 does not support post IDs") |
|
|
if booru == 'danbooru' and len(tags.split(',')) > 1: |
|
|
raise Exception("Danbooru does not support multiple tags. You can have only one tag.") |
|
|
|
|
|
|
|
|
class Booru(): |
|
|
|
|
|
def __init__(self, booru, booru_url): |
|
|
self.booru = booru |
|
|
self.booru_url = booru_url |
|
|
self.headers = {'user-agent': 'my-app/0.0.1'} |
|
|
|
|
|
def get_data(self, add_tags, max_pages=10, id=''): |
|
|
pass |
|
|
|
|
|
def get_post(self, add_tags, max_pages=10, id=''): |
|
|
pass |
|
|
|
|
|
|
|
|
class Gelbooru(Booru): |
|
|
|
|
|
def __init__(self, fringe_benefits): |
|
|
super().__init__('gelbooru', f'https://gelbooru.com/index.php?page=dapi&s=post&q=index&json=1&limit={POST_AMOUNT}') |
|
|
self.fringeBenefits = fringe_benefits |
|
|
|
|
|
def get_data(self, add_tags, max_pages=10, id=''): |
|
|
global COUNT |
|
|
loop_msg = True |
|
|
for loop in range(2): |
|
|
if id: |
|
|
add_tags = '' |
|
|
self.booru_url = f"{self.booru_url}&pid={random.randint(0, max_pages-1)}{id}{add_tags}" |
|
|
|
|
|
if self.fringeBenefits: |
|
|
res = requests.get(self.booru_url, cookies={'fringeBenefits': 'yup'}) |
|
|
else: |
|
|
res = requests.get(self.booru_url) |
|
|
data = res.json() |
|
|
COUNT = data['@attributes']['count'] |
|
|
if COUNT <= max_pages*POST_AMOUNT: |
|
|
max_pages = COUNT // POST_AMOUNT+1 |
|
|
|
|
|
while loop_msg: |
|
|
print(f" Processing {COUNT} results.") |
|
|
loop_msg = False |
|
|
|
|
|
continue |
|
|
else: |
|
|
print(f" Processing {max_pages*POST_AMOUNT} out of {COUNT} results.") |
|
|
break |
|
|
return data |
|
|
|
|
|
def get_post(self, add_tags, max_pages=10, id=''): |
|
|
return self.get_data(add_tags, max_pages, "&id=" + id) |
|
|
|
|
|
|
|
|
class XBooru(Booru): |
|
|
|
|
|
def __init__(self): |
|
|
super().__init__('xbooru', f'https://xbooru.com/index.php?page=dapi&s=post&q=index&json=1&limit={POST_AMOUNT}') |
|
|
|
|
|
def get_data(self, add_tags, max_pages=10, id=''): |
|
|
global COUNT |
|
|
loop_msg = True |
|
|
for loop in range(2): |
|
|
if id: |
|
|
add_tags = '' |
|
|
self.booru_url = f"{self.booru_url}&pid={random.randint(0, max_pages-1)}{id}{add_tags}" |
|
|
print(self.booru_url) |
|
|
res = requests.get(self.booru_url) |
|
|
data = res.json() |
|
|
COUNT = 0 |
|
|
for post in data: |
|
|
post['file_url'] = f"https://xbooru.com/images/{post['directory']}/{post['image']}" |
|
|
COUNT += 1 |
|
|
if COUNT <= max_pages*POST_AMOUNT: |
|
|
max_pages = COUNT // POST_AMOUNT+1 |
|
|
|
|
|
while loop_msg: |
|
|
print(f" Processing {COUNT} results.") |
|
|
loop_msg = False |
|
|
|
|
|
continue |
|
|
else: |
|
|
print(f" Processing {max_pages*POST_AMOUNT} out of {COUNT} results.") |
|
|
break |
|
|
return {'post': data} |
|
|
|
|
|
def get_post(self, add_tags, max_pages=10, id=''): |
|
|
return self.get_data(add_tags, max_pages, "&id=" + id) |
|
|
|
|
|
|
|
|
class Rule34(Booru): |
|
|
|
|
|
def __init__(self): |
|
|
super().__init__('rule34', f'https://api.rule34.xxx/index.php?page=dapi&s=post&q=index&json=1&limit={POST_AMOUNT}') |
|
|
|
|
|
def get_data(self, add_tags, max_pages=10, id=''): |
|
|
global COUNT |
|
|
loop_msg = True |
|
|
for loop in range(2): |
|
|
if id: |
|
|
add_tags = '' |
|
|
self.booru_url = f"{self.booru_url}&pid={random.randint(0, max_pages-1)}{id}{add_tags}" |
|
|
res = requests.get(self.booru_url) |
|
|
data = res.json() |
|
|
COUNT = len(data) |
|
|
if COUNT == 0: |
|
|
max_pages = 2 |
|
|
|
|
|
while loop_msg: |
|
|
print(f" Processing {COUNT} results.") |
|
|
loop_msg = False |
|
|
|
|
|
continue |
|
|
else: |
|
|
print(f"Found enough results") |
|
|
break |
|
|
return {'post': data} |
|
|
|
|
|
def get_post(self, add_tags, max_pages=10, id=''): |
|
|
return self.get_data(add_tags, max_pages, "&id=" + id) |
|
|
|
|
|
|
|
|
class Safebooru(Booru): |
|
|
|
|
|
def __init__(self): |
|
|
super().__init__('safebooru', f'https://safebooru.org/index.php?page=dapi&s=post&q=index&json=1&limit={POST_AMOUNT}') |
|
|
|
|
|
def get_data(self, add_tags, max_pages=10, id=''): |
|
|
global COUNT |
|
|
loop_msg = True |
|
|
for loop in range(2): |
|
|
if id: |
|
|
add_tags = '' |
|
|
self.booru_url = f"{self.booru_url}&pid={random.randint(0, max_pages-1)}{id}{add_tags}" |
|
|
res = requests.get(self.booru_url) |
|
|
data = res.json() |
|
|
COUNT = 0 |
|
|
for post in data: |
|
|
post['file_url'] = f"https://safebooru.org/images/{post['directory']}/{post['image']}" |
|
|
COUNT += 1 |
|
|
if COUNT <= max_pages*POST_AMOUNT: |
|
|
max_pages = COUNT // POST_AMOUNT+1 |
|
|
|
|
|
while loop_msg: |
|
|
print(f" Processing {COUNT} results.") |
|
|
loop_msg = False |
|
|
|
|
|
continue |
|
|
else: |
|
|
print(f" Processing {max_pages*POST_AMOUNT} out of {COUNT} results.") |
|
|
break |
|
|
return {'post': data} |
|
|
|
|
|
def get_post(self, add_tags, max_pages=10, id=''): |
|
|
return self.get_data(add_tags, max_pages, "&id=" + id) |
|
|
|
|
|
|
|
|
class Konachan(Booru): |
|
|
|
|
|
def __init__(self): |
|
|
super().__init__('konachan', f'https://konachan.com/post.json?limit={POST_AMOUNT}') |
|
|
|
|
|
def get_data(self, add_tags, max_pages=10, id=''): |
|
|
global COUNT |
|
|
loop_msg = True |
|
|
for loop in range(2): |
|
|
if id: |
|
|
add_tags = '' |
|
|
self.booru_url = f"{self.booru_url}&page={random.randint(0, max_pages-1)}{id}{add_tags}" |
|
|
res = requests.get(self.booru_url) |
|
|
data = res.json() |
|
|
COUNT = len(data) |
|
|
if COUNT == 0: |
|
|
max_pages = 2 |
|
|
|
|
|
while loop_msg: |
|
|
print(f" Processing {COUNT} results.") |
|
|
loop_msg = False |
|
|
|
|
|
continue |
|
|
else: |
|
|
print(f"Found enough results") |
|
|
break |
|
|
return {'post': data} |
|
|
|
|
|
def get_post(self, add_tags, max_pages=10, id=''): |
|
|
raise Exception("Konachan does not support post IDs") |
|
|
|
|
|
|
|
|
class Yandere(Booru): |
|
|
|
|
|
def __init__(self): |
|
|
super().__init__('yande.re', f'https://yande.re/post.json?limit={POST_AMOUNT}') |
|
|
|
|
|
def get_data(self, add_tags, max_pages=10, id=''): |
|
|
global COUNT |
|
|
loop_msg = True |
|
|
for loop in range(2): |
|
|
if id: |
|
|
add_tags = '' |
|
|
self.booru_url = f"{self.booru_url}&page={random.randint(0, max_pages-1)}{id}{add_tags}" |
|
|
res = requests.get(self.booru_url) |
|
|
data = res.json() |
|
|
COUNT = len(data) |
|
|
COUNT = len(data) |
|
|
if COUNT == 0: |
|
|
max_pages = 2 |
|
|
|
|
|
while loop_msg: |
|
|
print(f" Processing {COUNT} results.") |
|
|
loop_msg = False |
|
|
|
|
|
continue |
|
|
else: |
|
|
print(f"Found enough results") |
|
|
break |
|
|
return {'post': data} |
|
|
|
|
|
def get_post(self, add_tags, max_pages=10, id=''): |
|
|
raise Exception("Yande.re does not support post IDs") |
|
|
|
|
|
|
|
|
class AIBooru(Booru): |
|
|
|
|
|
def __init__(self): |
|
|
super().__init__('AIBooru', f'https://aibooru.online/posts.json?limit={POST_AMOUNT}') |
|
|
|
|
|
def get_data(self, add_tags, max_pages=10, id=''): |
|
|
global COUNT |
|
|
loop_msg = True |
|
|
for loop in range(2): |
|
|
if id: |
|
|
add_tags = '' |
|
|
self.booru_url = f"{self.booru_url}&page={random.randint(0, max_pages-1)}{id}{add_tags}" |
|
|
res = requests.get(self.booru_url) |
|
|
data = res.json() |
|
|
for post in data: |
|
|
post['tags'] = post['tag_string'] |
|
|
COUNT = len(data) |
|
|
if COUNT == 0: |
|
|
max_pages = 2 |
|
|
|
|
|
while loop_msg: |
|
|
print(f" Processing {COUNT} results.") |
|
|
loop_msg = False |
|
|
|
|
|
continue |
|
|
else: |
|
|
print(f"Found enough results") |
|
|
break |
|
|
return {'post': data} |
|
|
|
|
|
def get_post(self, add_tags, max_pages=10, id=''): |
|
|
raise Exception("AIBooru does not support post IDs") |
|
|
|
|
|
|
|
|
class Danbooru(Booru): |
|
|
|
|
|
def __init__(self): |
|
|
super().__init__('danbooru', f'https://danbooru.donmai.us/posts.json?limit={POST_AMOUNT}') |
|
|
|
|
|
def get_data(self, add_tags, max_pages=10, id=''): |
|
|
global COUNT |
|
|
loop_msg = True |
|
|
for loop in range(2): |
|
|
if id: |
|
|
add_tags = '' |
|
|
self.booru_url = f"{self.booru_url}&page={random.randint(0, max_pages-1)}{id}{add_tags}" |
|
|
res = requests.get(self.booru_url, headers=self.headers) |
|
|
data = res.json() |
|
|
for post in data: |
|
|
post['tags'] = post['tag_string'] |
|
|
COUNT = len(data) |
|
|
if COUNT == 0: |
|
|
max_pages = 2 |
|
|
|
|
|
while loop_msg: |
|
|
print(f" Processing {COUNT} results.") |
|
|
loop_msg = False |
|
|
|
|
|
continue |
|
|
else: |
|
|
print(f"Found enough results") |
|
|
break |
|
|
return {'post': data} |
|
|
|
|
|
def get_post(self, add_tags, max_pages=10, id=''): |
|
|
self.booru_url = f"https://danbooru.donmai.us/posts/{id}.json" |
|
|
res = requests.get(self.booru_url, headers=self.headers) |
|
|
data = res.json() |
|
|
data['tags'] = data['tag_string'] |
|
|
data = {'post': [data]} |
|
|
return data |
|
|
|
|
|
|
|
|
class e621(Booru): |
|
|
|
|
|
def __init__(self): |
|
|
super().__init__('danbooru', f'https://e621.net/posts.json?limit={POST_AMOUNT}') |
|
|
|
|
|
def get_data(self, add_tags, max_pages=10, id=''): |
|
|
global COUNT |
|
|
loop_msg = True |
|
|
for loop in range(2): |
|
|
if id: |
|
|
add_tags = '' |
|
|
self.booru_url = f"{self.booru_url}&page={random.randint(0, max_pages-1)}{id}{add_tags}" |
|
|
res = requests.get(self.booru_url, headers=self.headers) |
|
|
data = res.json()['posts'] |
|
|
COUNT = len(data) |
|
|
for post in data: |
|
|
temp_tags = [] |
|
|
sublevels = ['general', 'artist', 'copyright', 'character', 'species'] |
|
|
for sublevel in sublevels: |
|
|
temp_tags.extend(post['tags'][sublevel]) |
|
|
post['tags'] = ' '.join(temp_tags) |
|
|
post['score'] = post['score']['total'] |
|
|
if COUNT <= max_pages*POST_AMOUNT: |
|
|
max_pages = COUNT // POST_AMOUNT+1 |
|
|
|
|
|
while loop_msg: |
|
|
print(f" Processing {COUNT} results.") |
|
|
loop_msg = False |
|
|
|
|
|
continue |
|
|
else: |
|
|
print(f" Processing {max_pages*POST_AMOUNT} out of {COUNT} results.") |
|
|
break |
|
|
return {'post': data} |
|
|
|
|
|
def get_post(self, add_tags, max_pages=10, id=''): |
|
|
self.get_data(add_tags, max_pages, "&id=" + id) |
|
|
|
|
|
|
|
|
def generate_chaos(pos_tags, neg_tags, chaos_amount): |
|
|
"""Generates chaos in the prompt by adding random tags from the prompt to the positive and negative prompts |
|
|
|
|
|
Args: |
|
|
pos_tags (str): the positive prompt |
|
|
neg_tags (str): the negative prompt |
|
|
chaos_amount (float): the percentage of tags to put in the positive prompt |
|
|
|
|
|
Returns: |
|
|
str: the positive prompt |
|
|
str: the negative prompt |
|
|
""" |
|
|
|
|
|
chaos_list = [tag for tag in pos_tags.split(',') + neg_tags.split(',') if tag.strip() != ''] |
|
|
|
|
|
chaos_list = list(set(chaos_list)) |
|
|
random.shuffle(chaos_list) |
|
|
|
|
|
len_list = round(len(chaos_list) * chaos_amount) |
|
|
pos_list = chaos_list[len_list:] |
|
|
pos_prompt = ','.join(pos_list) |
|
|
neg_list = chaos_list[:len_list] |
|
|
random.shuffle(neg_list) |
|
|
neg_prompt = ','.join(neg_list) |
|
|
return pos_prompt, neg_prompt |
|
|
|
|
|
|
|
|
def resize_image(img, width, height, cropping=True): |
|
|
"""Resize image to specified width and height |
|
|
|
|
|
Args: |
|
|
img (PIL.Image): the image |
|
|
width (int): the width in pixels |
|
|
height (int): the height in pixels |
|
|
cropping (bool): whether to crop the image or not |
|
|
|
|
|
Returns: |
|
|
PIL.Image: the resized image |
|
|
""" |
|
|
if cropping: |
|
|
|
|
|
|
|
|
|
|
|
x, y = img.size |
|
|
if x < y: |
|
|
|
|
|
wpercent = (width / float(img.size[0])) |
|
|
hsize = int((float(img.size[1]) * float(wpercent))) |
|
|
img_new = img.resize((width, hsize)) |
|
|
if img_new.size[1] < height: |
|
|
|
|
|
hpercent = (height / float(img.size[1])) |
|
|
wsize = int((float(img.size[0]) * float(hpercent))) |
|
|
img_new = img.resize((wsize, height)) |
|
|
else: |
|
|
ypercent = (height / float(img.size[1])) |
|
|
wsize = int((float(img.size[0]) * float(ypercent))) |
|
|
img_new = img.resize((wsize, height)) |
|
|
if img_new.size[0] < width: |
|
|
xpercent = (width / float(img.size[0])) |
|
|
hsize = int((float(img.size[1]) * float(xpercent))) |
|
|
img_new = img.resize((width, hsize)) |
|
|
|
|
|
|
|
|
x, y = img_new.size |
|
|
left = (x - width) / 2 |
|
|
top = (y - height) / 2 |
|
|
right = (x + width) / 2 |
|
|
bottom = (y + height) / 2 |
|
|
img = img_new.crop((left, top, right, bottom)) |
|
|
else: |
|
|
img = img.resize((width, height)) |
|
|
return img |
|
|
|
|
|
def modify_prompt(prompt, tagged_prompt, type_deepbooru): |
|
|
"""Modifies the prompt based on the type_deepbooru selected |
|
|
|
|
|
Args: |
|
|
prompt (str): the prompt |
|
|
tagged_prompt (str): the prompt tagged by deepbooru |
|
|
type_deepbooru (str): the type of modification |
|
|
|
|
|
Returns: |
|
|
str: the modified prompt |
|
|
""" |
|
|
if type_deepbooru == 'Add Before': |
|
|
return tagged_prompt + ',' + prompt |
|
|
elif type_deepbooru == 'Add After': |
|
|
return prompt + ',' + tagged_prompt |
|
|
elif type_deepbooru == 'Replace': |
|
|
return tagged_prompt |
|
|
return prompt |
|
|
|
|
|
def remove_repeated_tags(prompt): |
|
|
"""Removes the repeated tags keeping the same order |
|
|
|
|
|
Args: |
|
|
prompt (str): the prompt |
|
|
|
|
|
Returns: |
|
|
str: the prompt without repeated tags |
|
|
""" |
|
|
prompt = prompt.split(',') |
|
|
new_prompt = [] |
|
|
for tag in prompt: |
|
|
if tag not in new_prompt: |
|
|
new_prompt.append(tag) |
|
|
return ','.join(new_prompt) |
|
|
|
|
|
def limit_prompt_tags(prompt, limit_tags, mode): |
|
|
"""Limits the amount of tags in the prompt. It can be done by percentage or by a fixed amount. |
|
|
|
|
|
Args: |
|
|
prompt (str): the prompt |
|
|
limit_tags (float): the percentage of tags to keep |
|
|
mode (str): 'Limit' or 'Max' |
|
|
|
|
|
Returns: |
|
|
str: the prompt with the limited amount of tags |
|
|
""" |
|
|
clean_prompt = prompt.split(',') |
|
|
if mode == 'Limit': |
|
|
clean_prompt = clean_prompt[:int(len(clean_prompt) * limit_tags)] |
|
|
elif mode == 'Max': |
|
|
clean_prompt = clean_prompt[:limit_tags] |
|
|
return ','.join(clean_prompt) |
|
|
|
|
|
class Script(scripts.Script): |
|
|
previous_loras = '' |
|
|
last_img = [] |
|
|
real_steps = 0 |
|
|
version = "1.2" |
|
|
original_prompt = '' |
|
|
|
|
|
def get_files(self, path): |
|
|
files = [] |
|
|
for file in os.listdir(path): |
|
|
if file.endswith('.txt'): |
|
|
files.append(file) |
|
|
return files |
|
|
|
|
|
def hide_object(self, obj, booru): |
|
|
print(f'hide_object: {obj}, {booru.value}') |
|
|
if booru.value == 'konachan' or booru.value == 'yande.re': |
|
|
obj.interactive = False |
|
|
else: |
|
|
obj.interactive = True |
|
|
|
|
|
def title(self): |
|
|
return "Ranbooru" |
|
|
|
|
|
def show(self, is_img2img): |
|
|
return scripts.AlwaysVisible |
|
|
|
|
|
def refresh_ser(self): |
|
|
return gr.update(choices=self.get_files(user_search_dir)) |
|
|
def refresh_rem(self): |
|
|
return gr.update(choices=self.get_files(user_remove_dir)) |
|
|
|
|
|
def ui(self, is_img2img): |
|
|
with gr.Group(): |
|
|
with InputAccordion(False, label="Ranbooru", elem_id=self.elem_id("ra_enable")) as enabled: |
|
|
booru = gr.Dropdown( |
|
|
["gelbooru", "rule34", "safebooru", "danbooru", "konachan", 'yande.re', 'aibooru', 'xbooru', 'e621'], label="Booru", value="gelbooru") |
|
|
max_pages = gr.Slider(label="Max Pages", minimum=1, maximum=100, value=100, step=1) |
|
|
gr.Markdown("""## Post""") |
|
|
post_id = gr.Textbox(lines=1, label="Post ID") |
|
|
gr.Markdown("""## Tags""") |
|
|
tags = gr.Textbox(lines=1, label="Tags to Search (Pre)") |
|
|
remove_tags = gr.Textbox(lines=1, label="Tags to Remove (Post)") |
|
|
mature_rating = gr.Radio(list(RATINGS['gelbooru']), label="Mature Rating", value="All") |
|
|
remove_bad_tags = gr.Checkbox(label="Remove bad tags", value=True) |
|
|
shuffle_tags = gr.Checkbox(label="Shuffle tags", value=True) |
|
|
change_dash = gr.Checkbox(label='Convert "_" to spaces', value=False) |
|
|
same_prompt = gr.Checkbox(label="Use same prompt for all images", value=False) |
|
|
fringe_benefits = gr.Checkbox(label="Fringe Benefits", value=True) |
|
|
limit_tags = gr.Slider(value=1.0, label="Limit tags", minimum=0.05, maximum=1.0, step=0.05) |
|
|
max_tags = gr.Slider(value=100, label="Max tags", minimum=1, maximum=100, step=1) |
|
|
change_background = gr.Radio(["Don't Change", "Add Background", "Remove Background", "Remove All"], label="Change Background", value="Don't Change") |
|
|
change_color = gr.Radio(["Don't Change", "Colored", "Limited Palette", "Monochrome"], label="Change Color", value="Don't Change") |
|
|
sorting_order = gr.Radio(["Random", "High Score", "Low Score"], label="Sorting Order", value="Random") |
|
|
|
|
|
booru.change(get_available_ratings, booru, mature_rating) |
|
|
booru.change(show_fringe_benefits, booru, fringe_benefits) |
|
|
|
|
|
gr.Markdown("""\n---\n""") |
|
|
with gr.Group(): |
|
|
with gr.Accordion("Img2Img", open=False): |
|
|
use_img2img = gr.Checkbox(label="Use img2img", value=False) |
|
|
use_ip = gr.Checkbox(label="Send to Controlnet", value=False) |
|
|
denoising = gr.Slider(value=0.75, label="Denoising", minimum=0.05, maximum=1.0, step=0.05) |
|
|
use_last_img = gr.Checkbox(label="Use last image as img2img", value=False) |
|
|
crop_center = gr.Checkbox(label="Crop Center", value=False) |
|
|
use_deepbooru = gr.Checkbox(label="Use Deepbooru", value=False) |
|
|
type_deepbooru = gr.Radio(["Add Before", "Add After", "Replace"], label="Deepbooru Tags Position", value="Add Before") |
|
|
with gr.Group(): |
|
|
with gr.Accordion("File", open=False): |
|
|
use_search_txt = gr.Checkbox(label="Use tags_search.txt", value=False) |
|
|
choose_search_txt = gr.Dropdown(self.get_files(user_search_dir), label="Choose tags_search.txt", value="") |
|
|
search_refresh_btn = gr.Button("Refresh") |
|
|
use_remove_txt = gr.Checkbox(label="Use tags_remove.txt", value=False) |
|
|
choose_remove_txt = gr.Dropdown(self.get_files(user_remove_dir), label="Choose tags_remove.txt", value="") |
|
|
remove_refresh_btn = gr.Button("Refresh") |
|
|
with gr.Group(): |
|
|
with gr.Accordion("Extra", open=False): |
|
|
with gr.Box(): |
|
|
mix_prompt = gr.Checkbox(label="Mix prompts", value=False) |
|
|
mix_amount = gr.Slider(value=2, label="Mix amount", minimum=2, maximum=10, step=1) |
|
|
with gr.Box(): |
|
|
chaos_mode = gr.Radio(["None", "Chaos", "Less Chaos"], label="Chaos Mode", value="None") |
|
|
chaos_amount = gr.Slider(value=0.5, label="Chaos Amount %", minimum=0.1, maximum=1, step=0.05) |
|
|
with gr.Box(): |
|
|
negative_mode = gr.Radio(["None", "Negative"], label="Negative Mode", value="None") |
|
|
use_same_seed = gr.Checkbox(label="Use same seed for all pictures", value=False) |
|
|
with gr.Box(): |
|
|
use_cache = gr.Checkbox(label="Use cache", value=True) |
|
|
with gr.Group(): |
|
|
with InputAccordion(False, label="LoRAnado", elem_id=self.elem_id("lo_enable")) as lora_enabled: |
|
|
with gr.Box(): |
|
|
lora_lock_prev = gr.Checkbox(label="Lock previous LoRAs", value=False) |
|
|
lora_folder = gr.Textbox(lines=1, label="LoRAs Subfolder") |
|
|
lora_amount = gr.Slider(default=1, label="LoRAs Amount", minimum=1, maximum=10, step=1) |
|
|
with gr.Box(): |
|
|
lora_min = gr.Slider(value=-1.0, label="Min LoRAs Weight", minimum=-1.0, maximum=1, step=0.1) |
|
|
lora_max = gr.Slider(value=1.0, label="Max LoRAs Weight", minimum=-1.0, maximum=1.0, step=0.1) |
|
|
lora_custom_weights = gr.Textbox(lines=1, label="LoRAs Custom Weights") |
|
|
|
|
|
search_refresh_btn.click( |
|
|
fn=self.refresh_ser, |
|
|
inputs=[], |
|
|
outputs=[choose_search_txt] |
|
|
) |
|
|
|
|
|
remove_refresh_btn.click( |
|
|
fn=self.refresh_rem, |
|
|
inputs=[], |
|
|
outputs=[choose_remove_txt] |
|
|
) |
|
|
|
|
|
return [enabled, tags, booru, remove_bad_tags, max_pages, change_dash, same_prompt, fringe_benefits, remove_tags, use_img2img, denoising, use_last_img, change_background, change_color, shuffle_tags, post_id, mix_prompt, mix_amount, chaos_mode, negative_mode, chaos_amount, limit_tags, max_tags, sorting_order, mature_rating, lora_folder, lora_amount, lora_min, lora_max, lora_enabled, lora_custom_weights, lora_lock_prev, use_ip, use_search_txt, use_remove_txt, choose_search_txt, choose_remove_txt, search_refresh_btn, remove_refresh_btn, crop_center, use_deepbooru, type_deepbooru, use_same_seed, use_cache] |
|
|
|
|
|
def check_orientation(self, img): |
|
|
"""Check if image is portrait, landscape or square""" |
|
|
x, y = img.size |
|
|
if x / y > 1.2: |
|
|
return [768, 512] |
|
|
elif y / x > 1.2: |
|
|
return [512, 768] |
|
|
else: |
|
|
return [768, 768] |
|
|
|
|
|
def loranado(self, lora_enabled, lora_folder, lora_amount, lora_min, lora_max, lora_custom_weights, p, lora_lock_prev): |
|
|
lora_prompt = '' |
|
|
if lora_enabled: |
|
|
if lora_lock_prev: |
|
|
lora_prompt = self.previous_loras |
|
|
else: |
|
|
loras = [] |
|
|
loras = os.listdir(f'{lora_folder}') |
|
|
|
|
|
loras = [lora.replace('.safetensors', '') for lora in loras if lora.endswith('.safetensors')] |
|
|
for l in range(0, lora_amount): |
|
|
lora_weight = 0 |
|
|
if lora_custom_weights != '': |
|
|
lora_weight = float(lora_custom_weights.split(',')[l]) |
|
|
while lora_weight == 0: |
|
|
lora_weight = round(random.uniform(lora_min, lora_max), 1) |
|
|
lora_prompt += f'<lora:{random.choice(loras)}:{lora_weight}>' |
|
|
self.previous_loras = lora_prompt |
|
|
if lora_prompt: |
|
|
if isinstance(p.prompt, list): |
|
|
for num, pr in enumerate(p.prompt): |
|
|
p.prompt[num] = f'{lora_prompt} {pr}' |
|
|
else: |
|
|
p.prompt = f'{lora_prompt} {p.prompt}' |
|
|
return p |
|
|
|
|
|
def before_process(self, p, enabled, tags, booru, remove_bad_tags, max_pages, change_dash, same_prompt, fringe_benefits, remove_tags, use_img2img, denoising, use_last_img, change_background, change_color, shuffle_tags, post_id, mix_prompt, mix_amount, chaos_mode, negative_mode, chaos_amount, limit_tags, max_tags, sorting_order, mature_rating, lora_folder, lora_amount, lora_min, lora_max, lora_enabled, lora_custom_weights, lora_lock_prev, use_ip, use_search_txt, use_remove_txt, choose_search_txt, choose_remove_txt, search_refresh_btn, remove_refresh_btn, crop_center, use_deepbooru, type_deepbooru, use_same_seed, use_cache): |
|
|
|
|
|
if use_cache and not requests_cache.patcher.is_installed(): |
|
|
requests_cache.install_cache('ranbooru_cache', backend='sqlite', expire_after=3600) |
|
|
elif not use_cache and requests_cache.patcher.is_installed(): |
|
|
requests_cache.uninstall_cache() |
|
|
if enabled: |
|
|
|
|
|
booru_apis = { |
|
|
'gelbooru': Gelbooru(fringe_benefits), |
|
|
'rule34': Rule34(), |
|
|
'safebooru': Safebooru(), |
|
|
'danbooru': Danbooru(), |
|
|
'konachan': Konachan(), |
|
|
'yande.re': Yandere(), |
|
|
'aibooru': AIBooru(), |
|
|
'xbooru': XBooru(), |
|
|
'e621': e621(), |
|
|
} |
|
|
self.original_prompt = p.prompt |
|
|
|
|
|
check_exception(booru, {'tags': tags, 'post_id': post_id}) |
|
|
|
|
|
|
|
|
bad_tags = [] |
|
|
if remove_bad_tags: |
|
|
bad_tags = ['mixed-language_text', 'watermark', 'text', 'english_text', 'speech_bubble', 'signature', 'artist_name', 'censored', 'bar_censor', 'translation', 'twitter_username', "twitter_logo", 'patreon_username', 'commentary_request', 'tagme', 'commentary', 'character_name', 'mosaic_censoring', 'instagram_username', 'text_focus', 'english_commentary', 'comic', 'translation_request', 'fake_text', 'translated', 'paid_reward_available', 'thought_bubble', 'multiple_views', 'silent_comic', 'out-of-frame_censoring', 'symbol-only_commentary', '3koma', '2koma', 'character_watermark', 'spoken_question_mark', 'japanese_text', 'spanish_text', 'language_text', 'fanbox_username', 'commission', 'original', 'ai_generated', 'stable_diffusion', 'tagme_(artist)', 'text_bubble', 'qr_code', 'chinese_commentary', 'korean_text', 'partial_commentary', 'chinese_text', 'copyright_request', 'heart_censor', 'censored_nipples', 'page_number', 'scan', 'fake_magazine_cover', 'korean_commentary'] |
|
|
|
|
|
if ',' in remove_tags: |
|
|
bad_tags.extend(remove_tags.split(',')) |
|
|
else: |
|
|
bad_tags.append(remove_tags) |
|
|
|
|
|
if use_remove_txt: |
|
|
bad_tags.extend(open(os.path.join(user_remove_dir, choose_remove_txt), 'r').read().split(',')) |
|
|
|
|
|
|
|
|
background_options = { |
|
|
'Add Background': ('detailed_background,' + random.choice(["outdoors", "indoors"]), COLORED_BG), |
|
|
'Remove Background': ('plain_background,simple_background,' + random.choice(COLORED_BG), ADD_BG), |
|
|
'Remove All': ('', COLORED_BG + ADD_BG) |
|
|
} |
|
|
|
|
|
if change_background in background_options: |
|
|
prompt_addition, tags_to_remove = background_options[change_background] |
|
|
bad_tags.extend(tags_to_remove) |
|
|
p.prompt = f'{p.prompt},{prompt_addition}' if p.prompt else prompt_addition |
|
|
|
|
|
|
|
|
color_options = { |
|
|
'Colored': BW_BG, |
|
|
'Limited Palette': '(limited_palette:1.3)', |
|
|
'Monochrome': ','.join(BW_BG) |
|
|
} |
|
|
|
|
|
if change_color in color_options: |
|
|
color_option = color_options[change_color] |
|
|
if isinstance(color_option, list): |
|
|
bad_tags.extend(color_option) |
|
|
else: |
|
|
p.prompt = f'{p.prompt},{color_option}' if p.prompt else color_option |
|
|
|
|
|
if use_search_txt: |
|
|
search_tags = open(os.path.join(user_search_dir, choose_search_txt), 'r').read() |
|
|
search_tags_r = search_tags.replace(" ", "") |
|
|
split_tags = search_tags_r.splitlines() |
|
|
filtered_tags = [line for line in split_tags if line.strip()] |
|
|
rand_selected = random.randint(0, len(filtered_tags) - 1) |
|
|
selected_tags = filtered_tags[rand_selected] |
|
|
tags = f'{tags},{selected_tags}' if tags else selected_tags |
|
|
|
|
|
add_tags = '&tags=-animated' |
|
|
if tags: |
|
|
add_tags += f'+{tags.replace(",", "+")}' |
|
|
if mature_rating != 'All': |
|
|
add_tags += f'+rating:{RATINGS[booru][mature_rating]}' |
|
|
|
|
|
|
|
|
random_post = {'preview_url': ''} |
|
|
prompts = [] |
|
|
last_img = [] |
|
|
preview_urls = [] |
|
|
api_url = booru_apis.get(booru, Gelbooru(fringe_benefits)) |
|
|
print(f'Using {booru}') |
|
|
|
|
|
|
|
|
if post_id: |
|
|
data = api_url.get_post(add_tags, max_pages, post_id) |
|
|
else: |
|
|
data = api_url.get_data(add_tags, max_pages) |
|
|
|
|
|
print(api_url.booru_url) |
|
|
|
|
|
for post in data['post']: |
|
|
post['score'] = post.get('score', 0) |
|
|
|
|
|
if sorting_order == 'High Score': |
|
|
data['post'] = sorted(data['post'], key=lambda k: k.get('score', 0), reverse=True) |
|
|
elif sorting_order == 'Low Score': |
|
|
data['post'] = sorted(data['post'], key=lambda k: k.get('score', 0)) |
|
|
if post_id: |
|
|
print(f'Using post ID: {post_id}') |
|
|
random_numbers = [0 for _ in range(0, p.batch_size * p.n_iter)] |
|
|
else: |
|
|
random_numbers = self.random_number(sorting_order, p.batch_size * p.n_iter) |
|
|
for random_number in random_numbers: |
|
|
if same_prompt: |
|
|
random_post = data['post'][random_numbers[0]] |
|
|
else: |
|
|
if mix_prompt: |
|
|
temp_tags = [] |
|
|
max_tags = 0 |
|
|
for _ in range(0, mix_amount): |
|
|
if not post_id: |
|
|
random_mix_number = self.random_number(sorting_order, 1)[0] |
|
|
temp_tags.extend(data['post'][random_mix_number]['tags'].split(' ')) |
|
|
max_tags = max(max_tags, len(data['post'][random_mix_number]['tags'].split(' '))) |
|
|
|
|
|
temp_tags = list(set(temp_tags)) |
|
|
random_post = data['post'][random_number] |
|
|
max_tags = min(max(len(temp_tags), 20), max_tags) |
|
|
random_post['tags'] = ' '.join(random.sample(temp_tags, max_tags)) |
|
|
else: |
|
|
try: |
|
|
random_post = data['post'][random_number] |
|
|
except IndexError: |
|
|
raise Exception( |
|
|
"No posts found with those tags. Try lowering the pages or changing the tags.") |
|
|
clean_tags = random_post['tags'].replace('(', r'\(').replace(')', r'\)') |
|
|
temp_tags = random.sample(clean_tags.split(' '), len(clean_tags.split(' '))) if shuffle_tags else clean_tags.split(' ') |
|
|
prompts.append(','.join(temp_tags)) |
|
|
preview_urls.append(random_post.get('file_url', 'https://pic.re/image')) |
|
|
|
|
|
if DEBUG: |
|
|
print(random_post) |
|
|
|
|
|
if use_img2img or use_deepbooru: |
|
|
image_urls = [random_post['file_url']] if use_last_img else preview_urls |
|
|
|
|
|
for img in image_urls: |
|
|
response = requests.get(img, headers=api_url.headers) |
|
|
last_img.append(Image.open(BytesIO(response.content))) |
|
|
new_prompts = [] |
|
|
|
|
|
for prompt in prompts: |
|
|
prompt_tags = [tag for tag in prompt.split(',') if tag.strip() not in bad_tags] |
|
|
for bad_tag in bad_tags: |
|
|
if '*' in bad_tag: |
|
|
prompt_tags = [tag for tag in prompt_tags if bad_tag.replace('*', '') not in tag] |
|
|
new_prompt = ','.join(prompt_tags) |
|
|
if change_dash: |
|
|
new_prompt = new_prompt.replace("_", " ") |
|
|
new_prompts.append(new_prompt) |
|
|
prompts = new_prompts |
|
|
if len(prompts) == 1: |
|
|
print('Processing Single Prompt') |
|
|
p.prompt = f"{p.prompt},{prompts[-1]}" if p.prompt else prompts[-1] |
|
|
if chaos_mode in ['Chaos', 'Less Chaos']: |
|
|
negative_prompt = '' if chaos_mode == 'Less Chaos' else p.negative_prompt |
|
|
p.prompt, negative_prompt = generate_chaos(p.prompt, negative_prompt, chaos_amount) |
|
|
p.negative_prompt = f"{p.negative_prompt},{negative_prompt}" if p.negative_prompt else negative_prompt |
|
|
else: |
|
|
print('Processing Multiple Prompts') |
|
|
negative_prompts = [] |
|
|
new_prompts = [] |
|
|
if chaos_mode == 'Chaos': |
|
|
for prompt in prompts: |
|
|
tmp_prompt, negative_prompt = generate_chaos(prompt, p.negative_prompt, chaos_amount) |
|
|
new_prompts.append(tmp_prompt) |
|
|
negative_prompts.append(negative_prompt) |
|
|
prompts = new_prompts |
|
|
p.negative_prompt = negative_prompts |
|
|
elif chaos_mode == 'Less Chaos': |
|
|
for prompt in prompts: |
|
|
tmp_prompt, negative_prompt = generate_chaos(prompt, '', chaos_amount) |
|
|
new_prompts.append(tmp_prompt) |
|
|
negative_prompts.append(negative_prompt) |
|
|
prompts = new_prompts |
|
|
p.negative_prompt = [p.negative_prompt + ',' + negative_prompt for negative_prompt in negative_prompts] |
|
|
else: |
|
|
p.negative_prompt = [p.negative_prompt for _ in range(0, p.batch_size * p.n_iter)] |
|
|
p.prompt = prompts if not p.prompt else [f"{p.prompt},{prompt}" for prompt in prompts] |
|
|
if use_img2img: |
|
|
if len(last_img) < p.batch_size * p.n_iter: |
|
|
last_img = [last_img[0] for _ in range(0, p.batch_size * p.n_iter)] |
|
|
if negative_mode == 'Negative': |
|
|
|
|
|
orig_list = self.original_prompt.split(',') |
|
|
if isinstance(p.prompt, list): |
|
|
new_positive_prompts = [] |
|
|
new_negative_prompts = [] |
|
|
for pr, npp in zip(p.prompt, p.negative_prompt): |
|
|
clean_prompt = pr.split(',') |
|
|
clean_prompt = [tag for tag in clean_prompt if tag not in orig_list] |
|
|
clean_prompt = ','.join(clean_prompt) |
|
|
new_positive_prompts.append(self.original_prompt) |
|
|
new_negative_prompts.append(f'{npp},{clean_prompt}') |
|
|
p.prompt = new_positive_prompts |
|
|
p.negative_prompt = new_negative_prompts |
|
|
else: |
|
|
clean_prompt = p.prompt.split(',') |
|
|
clean_prompt = [tag for tag in clean_prompt if tag not in orig_list] |
|
|
clean_prompt = ','.join(clean_prompt) |
|
|
p.negative_prompt = f'{p.negative_prompt},{clean_prompt}' |
|
|
p.prompt = self.original_prompt |
|
|
if negative_mode == 'Negative' or chaos_mode in ['Chaos', 'Less Chaos']: |
|
|
|
|
|
neg_prompt_tokens = [] |
|
|
for pr in p.negative_prompt: |
|
|
neg_prompt_tokens.append(model_hijack.get_prompt_lengths(pr)[1]) |
|
|
if len(set(neg_prompt_tokens)) != 1: |
|
|
print('Padding negative prompts') |
|
|
max_tokens = max(neg_prompt_tokens) |
|
|
for num, neg in enumerate(neg_prompt_tokens): |
|
|
while neg < max_tokens: |
|
|
p.negative_prompt[num] += random.choice(p.negative_prompt[num].split(',')) |
|
|
|
|
|
neg = model_hijack.get_prompt_lengths(p.negative_prompt[num])[1] |
|
|
|
|
|
if limit_tags < 1: |
|
|
if isinstance(p.prompt, list): |
|
|
p.prompt = [limit_prompt_tags(pr, limit_tags, 'Limit') for pr in p.prompt] |
|
|
else: |
|
|
p.prompt = limit_prompt_tags(p.prompt, limit_tags, 'Limit') |
|
|
|
|
|
if max_tags > 0: |
|
|
if isinstance(p.prompt, list): |
|
|
p.prompt = [limit_prompt_tags(pr, max_tags, 'Max') for pr in p.prompt] |
|
|
else: |
|
|
p.prompt = limit_prompt_tags(p.prompt, max_tags, 'Max') |
|
|
|
|
|
if use_same_seed: |
|
|
p.seed = random.randint(0, 2 ** 32 - 1) if p.seed == -1 else p.seed |
|
|
p.seed = [p.seed] * p.batch_size |
|
|
|
|
|
|
|
|
p = self.loranado(lora_enabled, lora_folder, lora_amount, lora_min, lora_max, lora_custom_weights, p, lora_lock_prev) |
|
|
if use_deepbooru and not use_img2img: |
|
|
self.last_img = last_img |
|
|
tagged_prompts = self.use_autotagger('deepbooru') |
|
|
|
|
|
if isinstance(p.prompt, list): |
|
|
p.prompt = [modify_prompt(pr, tagged_prompts[num], type_deepbooru) for num, pr in enumerate(p.prompt)] |
|
|
p.prompt = [remove_repeated_tags(pr) for pr in p.prompt] |
|
|
else: |
|
|
p.prompt = modify_prompt(p.prompt, tagged_prompts, type_deepbooru) |
|
|
p.prompt = remove_repeated_tags(p.prompt[0]) |
|
|
|
|
|
if use_img2img: |
|
|
if not use_ip: |
|
|
self.real_steps = p.steps |
|
|
p.steps = 1 |
|
|
self.last_img = last_img |
|
|
if use_ip: |
|
|
controlNetModule = importlib.import_module('extensions.sd-webui-controlnet.scripts.external_code', 'external_code') |
|
|
controlNetList = controlNetModule.get_all_units_in_processing(p) |
|
|
copied_network = controlNetList[0].__dict__.copy() |
|
|
copied_network['enabled'] = True |
|
|
copied_network['weight'] = denoising |
|
|
array_img = np.array(last_img[0]) |
|
|
copied_network['image']['image'] = array_img |
|
|
copied_networks = [copied_network] + controlNetList[1:] |
|
|
controlNetModule.update_cn_script_in_processing(p, copied_networks) |
|
|
|
|
|
elif lora_enabled: |
|
|
p = self.loranado(lora_enabled, lora_folder, lora_amount, lora_min, lora_max, lora_custom_weights, p, lora_lock_prev) |
|
|
|
|
|
def postprocess(self, p, processed, enabled, tags, booru, remove_bad_tags, max_pages, change_dash, same_prompt, fringe_benefits, remove_tags, use_img2img, denoising, use_last_img, change_background, change_color, shuffle_tags, post_id, mix_prompt, mix_amount, chaos_mode, negative_mode, chaos_amount, limit_tags, max_tags, sorting_order, mature_rating, lora_folder, lora_amount, lora_min, lora_max, lora_enabled, lora_custom_weights, lora_lock_prev, use_ip, use_search_txt, use_remove_txt, choose_search_txt, choose_remove_txt, search_refresh_btn, remove_refresh_btn, crop_center, use_deepbooru, type_deepbooru, use_same_seed, use_cache): |
|
|
if use_img2img and not use_ip and enabled: |
|
|
print('Using pictures') |
|
|
if crop_center: |
|
|
width, height = p.width, p.height |
|
|
self.last_img = [resize_image(img, width, height, cropping=True) for img in self.last_img] |
|
|
else: |
|
|
width, height = self.check_orientation(self.last_img[0]) |
|
|
final_prompts = p.prompt |
|
|
if use_deepbooru: |
|
|
tagged_prompts = self.use_autotagger('deepbooru') |
|
|
if isinstance(p.prompt, list): |
|
|
final_prompts = [modify_prompt(pr, tagged_prompts[num], type_deepbooru) for num, pr in enumerate(p.prompt)] |
|
|
final_prompts = [remove_repeated_tags(pr) for pr in final_prompts] |
|
|
else: |
|
|
final_prompts = modify_prompt(p.prompt, tagged_prompts, type_deepbooru) |
|
|
final_prompts = remove_repeated_tags(final_prompts) |
|
|
p = StableDiffusionProcessingImg2Img( |
|
|
sd_model=shared.sd_model, |
|
|
outpath_samples=shared.opts.outdir_samples or shared.opts.outdir_img2img_samples, |
|
|
outpath_grids=shared.opts.outdir_grids or shared.opts.outdir_img2img_grids, |
|
|
prompt=final_prompts, |
|
|
negative_prompt=p.negative_prompt, |
|
|
seed=p.seed, |
|
|
sampler_name=p.sampler_name, |
|
|
scheduler=p.scheduler, |
|
|
batch_size=p.batch_size, |
|
|
n_iter=p.n_iter, |
|
|
steps=self.real_steps, |
|
|
cfg_scale=p.cfg_scale, |
|
|
width=width, |
|
|
height=height, |
|
|
init_images=self.last_img, |
|
|
denoising_strength=denoising, |
|
|
) |
|
|
proc = process_images(p) |
|
|
processed.images = proc.images |
|
|
processed.infotexts = proc.infotexts |
|
|
if use_last_img: |
|
|
processed.images.append(self.last_img[0]) |
|
|
else: |
|
|
for num, img in enumerate(self.last_img): |
|
|
processed.images.append(img) |
|
|
processed.infotexts.append(proc.infotexts[num + 1]) |
|
|
|
|
|
def random_number(self, sorting_order, size): |
|
|
"""Generates random numbers based on the sorting_order |
|
|
|
|
|
Args: |
|
|
sorting_order (str): the sorting order. It can be 'Random', 'High Score' or 'Low Score' |
|
|
size (int): the amount of random numbers to generate |
|
|
|
|
|
Returns: |
|
|
list: the random numbers |
|
|
""" |
|
|
global COUNT |
|
|
if COUNT > POST_AMOUNT: |
|
|
COUNT = POST_AMOUNT |
|
|
weights = np.arange(COUNT, 0, -1) |
|
|
weights = weights / weights.sum() |
|
|
if sorting_order in ('High Score', 'Low Score'): |
|
|
random_numbers = np.random.choice(np.arange(COUNT), size=size, p=weights, replace=False) |
|
|
else: |
|
|
random_numbers = random.sample(range(COUNT), size) |
|
|
return random_numbers |
|
|
|
|
|
def use_autotagger(self, model): |
|
|
"""Use the autotagger to tag the images |
|
|
|
|
|
Args: |
|
|
model (str): the model to use. Right now only 'deepbooru' is supported |
|
|
|
|
|
Returns: |
|
|
list: the tagged prompts |
|
|
""" |
|
|
if model == 'deepbooru': |
|
|
if isinstance(self.original_prompt, str): |
|
|
orig_prompt = [self.original_prompt] |
|
|
else: |
|
|
orig_prompt = self.original_prompt |
|
|
deepbooru.model.start() |
|
|
for img, prompt in zip(self.last_img, orig_prompt): |
|
|
final_prompts = [prompt + ',' + deepbooru.model.tag_multi(img) for img in self.last_img] |
|
|
deepbooru.model.stop() |
|
|
return final_prompts |
|
|
|