Open ArchAngelAries opened 2 months ago
I went ahead and created a custom script to be saved in A1111 script folder that can do this, so I guess never mind? Or you can implement this if you want somehow.
import modules.scripts as scripts
import gradio as gr
import random
from modules import processing
from modules.processing import Processed
from modules.shared import opts, cmd_opts, state
class Script(scripts.Script):
def title(self):
return "Randomize Aspect Ratio and Layout"
def ui(self, is_img2img):
with gr.Group():
with gr.Row():
is_enabled = gr.Checkbox(label="Enable Randomize Aspect Ratio", value=False)
with gr.Row():
min_dim = gr.Slider(minimum=256, maximum=2048, step=64, label="Minimum Dimension", value=512)
max_dim = gr.Slider(minimum=256, maximum=2048, step=64, label="Maximum Dimension", value=1024)
return [is_enabled, min_dim, max_dim]
def run(self, p, is_enabled, min_dim, max_dim):
if not is_enabled:
return processing.process_images(p)
original_batch_size = p.batch_size
p.batch_size = 1 # Process one image at a time to allow different sizes
all_processed = []
for _ in range(original_batch_size):
aspect_ratios = [(1, 1), (4, 3), (3, 4), (16, 9), (9, 16)]
aspect_ratio = random.choice(aspect_ratios)
# Randomly choose between portrait and landscape
if random.choice([True, False]):
width_ratio, height_ratio = aspect_ratio
else:
height_ratio, width_ratio = aspect_ratio
# Calculate dimensions
max_width = int(max_dim * width_ratio / max(width_ratio, height_ratio))
max_height = int(max_dim * height_ratio / max(width_ratio, height_ratio))
min_width = int(min_dim * width_ratio / max(width_ratio, height_ratio))
min_height = int(min_dim * height_ratio / max(width_ratio, height_ratio))
p.width = random.randint(min_width, max_width)
p.height = random.randint(min_height, max_height)
p.width = max(64, min(p.width, 2048)) # Ensure width is within global limits
p.height = max(64, min(p.height, 2048)) # Ensure height is within global limits
p.init_latent = None # Reset latent to force recalculation with new dimensions
processed = processing.process_images(p)
# Add aspect ratio info to generation parameters
processed.infotexts[0] = f"{processed.infotexts[0]}, Aspect Ratio: {width_ratio}:{height_ratio}, Dimensions: {p.width}x{p.height}"
all_processed.append(processed)
# Combine all processed results
combined = Processed(p, [], p.seed, "")
for processed in all_processed:
combined.images.extend(processed.images)
combined.all_prompts.extend(processed.all_prompts)
combined.all_seeds.extend(processed.all_seeds)
combined.infotexts.extend(processed.infotexts)
return combined
def process(self, p):
# This method is called before processing begins; we can modify the processing object here
# This is useful for setting up any initial parameters or flags
p.extra_generation_params["Randomize Aspect Ratio"] = True
return p
Added prompt recognition and re-enforced User AR min/max values:
import modules.scripts as scripts
import gradio as gr
import random
import re
from modules import processing
from modules.processing import Processed
from modules.shared import opts, cmd_opts, state
class Script(scripts.Script):
def __init__(self):
self.keyword_orientations = {
'landscape': [
'aerial view', 'bird\'s-eye view', 'establishing shot', 'extreme long shot',
'long shot', 'fisheye-shot', 'hdri', 'panorama', 'wide angle'
],
'portrait': [
'close-up', 'extreme close-up', 'full shot', 'full body shot',
'medium close-up', 'medium shot', 'cowboy shot', 'from behind',
'from the side', 'over-the-shoulder shot', 'worm\'s eye shot',
'low-angle shot', 'macro shot'
],
'square': ['dutch angle', 'point-of-view shot', 'two-shot']
}
def title(self):
return "Randomize Aspect Ratio and Layout"
def ui(self, is_img2img):
with gr.Group():
with gr.Row():
is_enabled = gr.Checkbox(label="Enable Randomize Aspect Ratio", value=False)
with gr.Row():
use_prompt_recognition = gr.Checkbox(label="Use Prompt Recognition", value=False)
with gr.Row():
min_dim = gr.Slider(minimum=256, maximum=2048, step=64, label="Minimum Dimension", value=512)
max_dim = gr.Slider(minimum=256, maximum=2048, step=64, label="Maximum Dimension", value=1024)
return [is_enabled, use_prompt_recognition, min_dim, max_dim]
def recognize_orientation(self, prompt):
prompt = prompt.lower()
for orientation, keywords in self.keyword_orientations.items():
if any(keyword in prompt for keyword in keywords):
return orientation
return 'random'
def calculate_dimensions(self, width_ratio, height_ratio, min_dim, max_dim):
# Calculate the scaling factor to meet the minimum dimension
scale_factor = max(min_dim / width_ratio, min_dim / height_ratio)
# Calculate initial dimensions
width = width_ratio * scale_factor
height = height_ratio * scale_factor
# If either dimension exceeds max_dim, scale down
if width > max_dim or height > max_dim:
scale_factor = min(max_dim / width, max_dim / height)
width *= scale_factor
height *= scale_factor
# Ensure dimensions are integers
width = int(width)
height = int(height)
# Ensure dimensions are within global limits
width = max(64, min(width, 2048))
height = max(64, min(height, 2048))
return width, height
def run(self, p, is_enabled, use_prompt_recognition, min_dim, max_dim):
if not is_enabled:
return processing.process_images(p)
original_batch_size = p.batch_size
p.batch_size = 1 # Process one image at a time to allow different sizes
all_processed = []
for _ in range(original_batch_size):
aspect_ratios = {
'landscape': [(16, 9), (3, 2), (4, 3)],
'portrait': [(9, 16), (2, 3), (3, 4)],
'square': [(1, 1)],
'random': [(16, 9), (9, 16), (4, 3), (3, 4), (1, 1)]
}
if use_prompt_recognition:
orientation = self.recognize_orientation(p.prompt)
else:
orientation = 'random'
aspect_ratio = random.choice(aspect_ratios[orientation])
# For landscape and portrait, we don't need to flip
if orientation == 'random':
if random.choice([True, False]):
aspect_ratio = aspect_ratio[::-1] # Flip for random orientation
width_ratio, height_ratio = aspect_ratio
# Calculate dimensions using the new method
p.width, p.height = self.calculate_dimensions(width_ratio, height_ratio, min_dim, max_dim)
p.init_latent = None # Reset latent to force recalculation with new dimensions
processed = processing.process_images(p)
# Add aspect ratio info to generation parameters
processed.infotexts[0] = f"{processed.infotexts[0]}, Aspect Ratio: {width_ratio}:{height_ratio}, Dimensions: {p.width}x{p.height}, Orientation: {orientation}"
all_processed.append(processed)
# Combine all processed results
combined = Processed(p, [], p.seed, "")
for processed in all_processed:
combined.images.extend(processed.images)
combined.all_prompts.extend(processed.all_prompts)
combined.all_seeds.extend(processed.all_seeds)
combined.infotexts.extend(processed.infotexts)
return combined
def process(self, p):
p.extra_generation_params["Randomize Aspect Ratio"] = True
return p
I was wondering if it could be possible to add a feature where a user could select randomize Aspect Ratio to where a user could randomly generate images of varying dimensions without having to change the Width/Height/AR.
I'm kinda envisioning a tick box or two that allows:
Not sure if it is very difficult to implement, but thought it'd be a cool addition to AR Helper. Could be really useful for people who like to utilize Dynamic Prompts and run Generate Forever for a while. Could net really unique outputs.