mirror of
https://github.com/karl0ss/comfy_fm24_newgens.git
synced 2025-10-03 06:40:06 +01:00
initial commit with gui
This commit is contained in:
parent
2143847985
commit
14ae65eb57
@ -25,7 +25,9 @@ from lib.general import (
|
|||||||
from lib.logging import LOGGING_CONFIG
|
from lib.logging import LOGGING_CONFIG
|
||||||
|
|
||||||
# from simple_term_menu import TerminalMenu
|
# from simple_term_menu import TerminalMenu
|
||||||
from comfy_api_simplified import ComfyApiWrapper, ComfyWorkflowWrapper
|
from diffusers import StableDiffusionPipeline, DPMSolverMultistepScheduler
|
||||||
|
import torch
|
||||||
|
from PIL import Image
|
||||||
|
|
||||||
logging.config.dictConfig(LOGGING_CONFIG)
|
logging.config.dictConfig(LOGGING_CONFIG)
|
||||||
|
|
||||||
@ -51,31 +53,78 @@ p = inflect.engine()
|
|||||||
|
|
||||||
|
|
||||||
def generate_image(uid, comfy_prompt):
|
def generate_image(uid, comfy_prompt):
|
||||||
"""Generate an image using the Comfy API."""
|
"""Generate an image using local Stable Diffusion."""
|
||||||
try:
|
try:
|
||||||
# Initialize API and workflow
|
# Initialize the pipeline (do this once and reuse)
|
||||||
api = ComfyApiWrapper(user_config["comfyui"]["comfyui_url"])
|
if not hasattr(generate_image, 'pipeline'):
|
||||||
wf = ComfyWorkflowWrapper("./workflow_api.json")
|
logging.info("Loading Stable Diffusion model...")
|
||||||
|
|
||||||
# Set workflow parameters
|
# Get model configuration
|
||||||
wf.set_node_param("KSampler", "seed", random.getrandbits(32))
|
try:
|
||||||
# wf.set_node_param("KSampler", "steps", steps)
|
model_id = user_config["models"]["model_name"]
|
||||||
wf.set_node_param("positive", "text", comfy_prompt)
|
model_dir = user_config["models"].get("model_dir", None)
|
||||||
wf.set_node_param("Save Image", "filename_prefix", uid)
|
logging.info(f"Using model: {model_id}")
|
||||||
wf.set_node_param(
|
except KeyError:
|
||||||
"Load Checkpoint", "ckpt_name", user_config["comfyui"]["model"]
|
model_id = "SG161222/Realistic_Vision_V6.0_B1"
|
||||||
)
|
model_dir = None
|
||||||
# Queue your workflow for completion
|
logging.warning(f"Model configuration not found, using default: {model_id}")
|
||||||
|
|
||||||
|
# Check if CUDA is available
|
||||||
|
device = "cuda" if torch.cuda.is_available() else "cpu"
|
||||||
|
logging.info(f"Using device: {device}")
|
||||||
|
|
||||||
|
# Load the pipeline
|
||||||
|
if model_dir:
|
||||||
|
pipe = StableDiffusionPipeline.from_pretrained(
|
||||||
|
model_id,
|
||||||
|
cache_dir=model_dir,
|
||||||
|
torch_dtype=torch.float16 if device == "cuda" else torch.float32,
|
||||||
|
safety_checker=None,
|
||||||
|
requires_safety_checker=False
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
pipe = StableDiffusionPipeline.from_pretrained(
|
||||||
|
model_id,
|
||||||
|
torch_dtype=torch.float16 if device == "cuda" else torch.float32,
|
||||||
|
safety_checker=None,
|
||||||
|
requires_safety_checker=False
|
||||||
|
)
|
||||||
|
|
||||||
|
# Use DPMSolverMultistepScheduler for better quality/speed balance
|
||||||
|
pipe.scheduler = DPMSolverMultistepScheduler.from_config(pipe.scheduler.config)
|
||||||
|
|
||||||
|
if device == "cuda":
|
||||||
|
pipe = pipe.to("cuda")
|
||||||
|
pipe.enable_attention_slicing() # Reduce memory usage
|
||||||
|
|
||||||
|
generate_image.pipeline = pipe
|
||||||
|
logging.info("Model loaded successfully")
|
||||||
|
|
||||||
|
# Generate the image
|
||||||
logging.debug(f"Generating image for UID: {uid}")
|
logging.debug(f"Generating image for UID: {uid}")
|
||||||
results = api.queue_and_wait_images(wf, "Save Image")
|
|
||||||
for filename, image_data in results.items():
|
# Set random seed for reproducibility
|
||||||
with open(
|
generator = torch.Generator(device=generate_image.pipeline.device)
|
||||||
f"{user_config[selected_profile]['output_dir']}{uid}.png", "wb+"
|
generator.manual_seed(random.getrandbits(32))
|
||||||
) as f:
|
|
||||||
f.write(image_data)
|
# Generate image with parameters similar to ComfyUI workflow
|
||||||
|
image = generate_image.pipeline(
|
||||||
|
comfy_prompt,
|
||||||
|
num_inference_steps=6,
|
||||||
|
guidance_scale=1.5,
|
||||||
|
generator=generator,
|
||||||
|
width=512,
|
||||||
|
height=512
|
||||||
|
).images[0]
|
||||||
|
|
||||||
|
# Save the image
|
||||||
|
output_path = f"{user_config[selected_profile]['output_dir']}{uid}.png"
|
||||||
|
image.save(output_path)
|
||||||
logging.debug(f"Image generated successfully for UID: {uid}")
|
logging.debug(f"Image generated successfully for UID: {uid}")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"Failed to generate image for UID: {uid}. Error: {e}")
|
logging.error(f"Failed to generate image for UID: {uid}. Error: {e}")
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
def get_country_name(app_config, country_code):
|
def get_country_name(app_config, country_code):
|
||||||
|
500
gui.py
Normal file
500
gui.py
Normal file
@ -0,0 +1,500 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Standalone FM NewGens - GUI Interface
|
||||||
|
A user-friendly graphical interface for generating Football Manager faces
|
||||||
|
"""
|
||||||
|
|
||||||
|
import tkinter as tk
|
||||||
|
from tkinter import ttk, filedialog, messagebox, scrolledtext
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import json
|
||||||
|
import configparser
|
||||||
|
import threading
|
||||||
|
import queue
|
||||||
|
import time
|
||||||
|
from pathlib import Path
|
||||||
|
from PIL import Image, ImageTk
|
||||||
|
import logging
|
||||||
|
|
||||||
|
# Import the main generation logic
|
||||||
|
from comfy_fm_newgen import generate_image, get_country_name, generate_prompts_for_players
|
||||||
|
try:
|
||||||
|
from lib.rtf_parser import RTF_Parser
|
||||||
|
except ImportError:
|
||||||
|
# Fallback for when striprtf is not available
|
||||||
|
class RTF_Parser:
|
||||||
|
def parse_rtf(self, file_path):
|
||||||
|
print(f"Warning: RTF parsing not available. Please install striprtf: pip install striprtf==0.0.28")
|
||||||
|
return []
|
||||||
|
from lib.generate_xml import create_config_xml, append_to_config_xml
|
||||||
|
from lib.xml_reader import extract_from_values
|
||||||
|
from lib.general import choose_profile, create_or_update, process_player_or_file, get_player_input
|
||||||
|
|
||||||
|
class FMFaceGeneratorGUI:
|
||||||
|
def __init__(self, root):
|
||||||
|
self.root = root
|
||||||
|
self.root.title("FM Face Generator - Standalone Version")
|
||||||
|
self.root.geometry("1000x700")
|
||||||
|
self.root.minsize(800, 600)
|
||||||
|
|
||||||
|
# Initialize variables
|
||||||
|
self.config = None
|
||||||
|
self.app_config = None
|
||||||
|
self.rtf = RTF_Parser()
|
||||||
|
self.generation_thread = None
|
||||||
|
self.stop_generation = False
|
||||||
|
self.image_queue = queue.Queue()
|
||||||
|
|
||||||
|
# Set up the GUI
|
||||||
|
self.setup_gui()
|
||||||
|
self.load_config()
|
||||||
|
|
||||||
|
# Start image preview update loop
|
||||||
|
self.update_image_preview()
|
||||||
|
|
||||||
|
def setup_gui(self):
|
||||||
|
"""Set up the main GUI components"""
|
||||||
|
# Create main notebook (tabs)
|
||||||
|
self.notebook = ttk.Notebook(self.root)
|
||||||
|
self.notebook.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
|
||||||
|
|
||||||
|
# Configuration tab
|
||||||
|
self.config_frame = ttk.Frame(self.notebook)
|
||||||
|
self.notebook.add(self.config_frame, text="Configuration")
|
||||||
|
|
||||||
|
# Generation tab
|
||||||
|
self.generation_frame = ttk.Frame(self.notebook)
|
||||||
|
self.notebook.add(self.generation_frame, text="Generation")
|
||||||
|
|
||||||
|
# Preview tab
|
||||||
|
self.preview_frame = ttk.Frame(self.notebook)
|
||||||
|
self.notebook.add(self.preview_frame, text="Preview")
|
||||||
|
|
||||||
|
# Setup each tab
|
||||||
|
self.setup_config_tab()
|
||||||
|
self.setup_generation_tab()
|
||||||
|
self.setup_preview_tab()
|
||||||
|
|
||||||
|
# Status bar
|
||||||
|
self.status_var = tk.StringVar()
|
||||||
|
self.status_var.set("Ready")
|
||||||
|
self.status_bar = ttk.Label(self.root, textvariable=self.status_var, relief=tk.SUNKEN)
|
||||||
|
self.status_bar.pack(side=tk.BOTTOM, fill=tk.X)
|
||||||
|
|
||||||
|
# Progress bar
|
||||||
|
self.progress_var = tk.DoubleVar()
|
||||||
|
self.progress_bar = ttk.Progressbar(self.root, variable=self.progress_var, maximum=100)
|
||||||
|
self.progress_bar.pack(side=tk.BOTTOM, fill=tk.X)
|
||||||
|
|
||||||
|
def setup_config_tab(self):
|
||||||
|
"""Set up the configuration tab"""
|
||||||
|
# Model selection
|
||||||
|
model_frame = ttk.LabelFrame(self.config_frame, text="AI Model", padding=10)
|
||||||
|
model_frame.pack(fill=tk.X, padx=10, pady=5)
|
||||||
|
|
||||||
|
ttk.Label(model_frame, text="Model:").grid(row=0, column=0, sticky=tk.W, pady=5)
|
||||||
|
self.model_var = tk.StringVar()
|
||||||
|
model_combo = ttk.Combobox(model_frame, textvariable=self.model_var, width=50)
|
||||||
|
model_combo['values'] = [
|
||||||
|
'SG161222/Realistic_Vision_V6.0_B1',
|
||||||
|
'digiplay/AbsoluteReality',
|
||||||
|
'stabilityai/stable-diffusion-2-1',
|
||||||
|
'runwayml/stable-diffusion-v1-5'
|
||||||
|
]
|
||||||
|
model_combo.grid(row=0, column=1, sticky=tk.W, padx=5, pady=5)
|
||||||
|
model_combo.set('SG161222/Realistic_Vision_V6.0_B1')
|
||||||
|
|
||||||
|
# Model directory
|
||||||
|
ttk.Label(model_frame, text="Model Directory:").grid(row=1, column=0, sticky=tk.W, pady=5)
|
||||||
|
self.model_dir_var = tk.StringVar()
|
||||||
|
model_dir_entry = ttk.Entry(model_frame, textvariable=self.model_dir_var, width=50)
|
||||||
|
model_dir_entry.grid(row=1, column=1, sticky=tk.W, padx=5, pady=5)
|
||||||
|
ttk.Button(model_frame, text="Browse...", command=self.browse_model_dir).grid(row=1, column=2, padx=5, pady=5)
|
||||||
|
|
||||||
|
# FM Configuration
|
||||||
|
fm_frame = ttk.LabelFrame(self.config_frame, text="Football Manager", padding=10)
|
||||||
|
fm_frame.pack(fill=tk.X, padx=10, pady=5)
|
||||||
|
|
||||||
|
ttk.Label(fm_frame, text="FM Version:").grid(row=0, column=0, sticky=tk.W, pady=5)
|
||||||
|
self.fm_version_var = tk.StringVar(value="2024")
|
||||||
|
fm_version_entry = ttk.Entry(fm_frame, textvariable=self.fm_version_var, width=20)
|
||||||
|
fm_version_entry.grid(row=0, column=1, sticky=tk.W, padx=5, pady=5)
|
||||||
|
|
||||||
|
ttk.Label(fm_frame, text="RTF File:").grid(row=1, column=0, sticky=tk.W, pady=5)
|
||||||
|
self.rtf_file_var = tk.StringVar()
|
||||||
|
rtf_entry = ttk.Entry(fm_frame, textvariable=self.rtf_file_var, width=50)
|
||||||
|
rtf_entry.grid(row=1, column=1, sticky=tk.W, padx=5, pady=5)
|
||||||
|
ttk.Button(fm_frame, text="Browse...", command=self.browse_rtf_file).grid(row=1, column=2, padx=5, pady=5)
|
||||||
|
|
||||||
|
ttk.Label(fm_frame, text="Output Directory:").grid(row=2, column=0, sticky=tk.W, pady=5)
|
||||||
|
self.output_dir_var = tk.StringVar()
|
||||||
|
output_entry = ttk.Entry(fm_frame, textvariable=self.output_dir_var, width=50)
|
||||||
|
output_entry.grid(row=2, column=1, sticky=tk.W, padx=5, pady=5)
|
||||||
|
ttk.Button(fm_frame, text="Browse...", command=self.browse_output_dir).grid(row=2, column=2, padx=5, pady=5)
|
||||||
|
|
||||||
|
# Control buttons
|
||||||
|
button_frame = ttk.Frame(self.config_frame)
|
||||||
|
button_frame.pack(fill=tk.X, padx=10, pady=10)
|
||||||
|
|
||||||
|
ttk.Button(button_frame, text="Save Configuration", command=self.save_config).pack(side=tk.LEFT, padx=5)
|
||||||
|
ttk.Button(button_frame, text="Load Configuration", command=self.load_config).pack(side=tk.LEFT, padx=5)
|
||||||
|
ttk.Button(button_frame, text="Reset to Defaults", command=self.reset_config).pack(side=tk.LEFT, padx=5)
|
||||||
|
|
||||||
|
def setup_generation_tab(self):
|
||||||
|
"""Set up the generation tab"""
|
||||||
|
# Player selection
|
||||||
|
player_frame = ttk.LabelFrame(self.generation_frame, text="Player Selection", padding=10)
|
||||||
|
player_frame.pack(fill=tk.X, padx=10, pady=5)
|
||||||
|
|
||||||
|
self.player_mode_var = tk.StringVar(value="all")
|
||||||
|
ttk.Radiobutton(player_frame, text="Process all players", variable=self.player_mode_var, value="all", command=self.update_player_controls).grid(row=0, column=0, sticky=tk.W, pady=5)
|
||||||
|
ttk.Radiobutton(player_frame, text="Process specific player", variable=self.player_mode_var, value="specific", command=self.update_player_controls).grid(row=0, column=1, sticky=tk.W, pady=5)
|
||||||
|
|
||||||
|
ttk.Label(player_frame, text="Player UID:").grid(row=1, column=0, sticky=tk.W, pady=5)
|
||||||
|
self.player_uid_var = tk.StringVar()
|
||||||
|
self.player_uid_entry = ttk.Entry(player_frame, textvariable=self.player_uid_var, width=20, state=tk.DISABLED)
|
||||||
|
self.player_uid_entry.grid(row=1, column=1, sticky=tk.W, padx=5, pady=5)
|
||||||
|
|
||||||
|
# Generation options
|
||||||
|
gen_frame = ttk.LabelFrame(self.generation_frame, text="Generation Options", padding=10)
|
||||||
|
gen_frame.pack(fill=tk.X, padx=10, pady=5)
|
||||||
|
|
||||||
|
self.update_mode_var = tk.StringVar(value="false")
|
||||||
|
ttk.Checkbutton(gen_frame, text="Update existing (skip already processed)", variable=self.update_mode_var, onvalue="true", offvalue="false").grid(row=0, column=0, sticky=tk.W, pady=5)
|
||||||
|
|
||||||
|
# Progress display
|
||||||
|
progress_frame = ttk.LabelFrame(self.generation_frame, text="Progress", padding=10)
|
||||||
|
progress_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)
|
||||||
|
|
||||||
|
# Status text
|
||||||
|
self.status_text = scrolledtext.ScrolledText(progress_frame, height=10, wrap=tk.WORD)
|
||||||
|
self.status_text.pack(fill=tk.BOTH, expand=True, pady=5)
|
||||||
|
|
||||||
|
# Control buttons
|
||||||
|
control_frame = ttk.Frame(self.generation_frame)
|
||||||
|
control_frame.pack(fill=tk.X, padx=10, pady=10)
|
||||||
|
|
||||||
|
self.start_button = ttk.Button(control_frame, text="Start Generation", command=self.start_generation)
|
||||||
|
self.start_button.pack(side=tk.LEFT, padx=5)
|
||||||
|
|
||||||
|
self.stop_button = ttk.Button(control_frame, text="Stop Generation", command=self.stop_generation_thread, state=tk.DISABLED)
|
||||||
|
self.stop_button.pack(side=tk.LEFT, padx=5)
|
||||||
|
|
||||||
|
ttk.Button(control_frame, text="Clear Log", command=self.clear_log).pack(side=tk.RIGHT, padx=5)
|
||||||
|
|
||||||
|
def setup_preview_tab(self):
|
||||||
|
"""Set up the preview tab"""
|
||||||
|
# Image preview
|
||||||
|
preview_frame = ttk.LabelFrame(self.preview_frame, text="Generated Images", padding=10)
|
||||||
|
preview_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)
|
||||||
|
|
||||||
|
# Image display
|
||||||
|
self.image_label = ttk.Label(preview_frame, text="No images generated yet")
|
||||||
|
self.image_label.pack(pady=20)
|
||||||
|
|
||||||
|
# Image info
|
||||||
|
info_frame = ttk.Frame(preview_frame)
|
||||||
|
info_frame.pack(fill=tk.X, pady=10)
|
||||||
|
|
||||||
|
ttk.Label(info_frame, text="Current Image:").grid(row=0, column=0, sticky=tk.W)
|
||||||
|
self.current_image_var = tk.StringVar()
|
||||||
|
ttk.Label(info_frame, textvariable=self.current_image_var).grid(row=0, column=1, sticky=tk.W, padx=5)
|
||||||
|
|
||||||
|
ttk.Label(info_frame, text="Total Generated:").grid(row=1, column=0, sticky=tk.W)
|
||||||
|
self.total_generated_var = tk.StringVar(value="0")
|
||||||
|
ttk.Label(info_frame, textvariable=self.total_generated_var).grid(row=1, column=1, sticky=tk.W, padx=5)
|
||||||
|
|
||||||
|
# Navigation buttons
|
||||||
|
nav_frame = ttk.Frame(preview_frame)
|
||||||
|
nav_frame.pack(fill=tk.X, pady=10)
|
||||||
|
|
||||||
|
ttk.Button(nav_frame, text="Previous", command=self.show_previous_image).pack(side=tk.LEFT, padx=5)
|
||||||
|
ttk.Button(nav_frame, text="Next", command=self.show_next_image).pack(side=tk.LEFT, padx=5)
|
||||||
|
ttk.Button(nav_frame, text="Refresh", command=self.refresh_preview).pack(side=tk.RIGHT, padx=5)
|
||||||
|
|
||||||
|
def browse_model_dir(self):
|
||||||
|
"""Browse for model directory"""
|
||||||
|
directory = filedialog.askdirectory(title="Select Model Directory")
|
||||||
|
if directory:
|
||||||
|
self.model_dir_var.set(directory)
|
||||||
|
|
||||||
|
def browse_rtf_file(self):
|
||||||
|
"""Browse for RTF file"""
|
||||||
|
file_path = filedialog.askopenfilename(
|
||||||
|
title="Select RTF File",
|
||||||
|
filetypes=[("RTF files", "*.rtf"), ("All files", "*.*")]
|
||||||
|
)
|
||||||
|
if file_path:
|
||||||
|
self.rtf_file_var.set(file_path)
|
||||||
|
|
||||||
|
def browse_output_dir(self):
|
||||||
|
"""Browse for output directory"""
|
||||||
|
directory = filedialog.askdirectory(title="Select Output Directory")
|
||||||
|
if directory:
|
||||||
|
self.output_dir_var.set(directory)
|
||||||
|
|
||||||
|
def update_player_controls(self):
|
||||||
|
"""Update player selection controls based on mode"""
|
||||||
|
if self.player_mode_var.get() == "specific":
|
||||||
|
self.player_uid_entry.config(state=tk.NORMAL)
|
||||||
|
else:
|
||||||
|
self.player_uid_entry.config(state=tk.DISABLED)
|
||||||
|
self.player_uid_var.set("")
|
||||||
|
|
||||||
|
def save_config(self):
|
||||||
|
"""Save configuration to file"""
|
||||||
|
try:
|
||||||
|
# Update config object
|
||||||
|
if not self.config:
|
||||||
|
self.config = configparser.ConfigParser()
|
||||||
|
self.config.add_section('models')
|
||||||
|
self.config.add_section('profile:NewGens')
|
||||||
|
|
||||||
|
self.config.set('models', 'model_name', self.model_var.get())
|
||||||
|
if self.model_dir_var.get():
|
||||||
|
self.config.set('models', 'model_dir', self.model_dir_var.get())
|
||||||
|
|
||||||
|
self.config.set('profile:NewGens', 'football_manager_version', self.fm_version_var.get())
|
||||||
|
self.config.set('profile:NewGens', 'rtf_file', self.rtf_file_var.get())
|
||||||
|
self.config.set('profile:NewGens', 'output_dir', self.output_dir_var.get())
|
||||||
|
|
||||||
|
# Save to file
|
||||||
|
with open('user_config.cfg', 'w') as configfile:
|
||||||
|
self.config.write(configfile)
|
||||||
|
|
||||||
|
messagebox.showinfo("Success", "Configuration saved successfully!")
|
||||||
|
self.log_message("Configuration saved")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
messagebox.showerror("Error", f"Failed to save configuration: {str(e)}")
|
||||||
|
self.log_message(f"Error saving configuration: {str(e)}")
|
||||||
|
|
||||||
|
def load_config(self):
|
||||||
|
"""Load configuration from file"""
|
||||||
|
try:
|
||||||
|
if os.path.exists('user_config.cfg'):
|
||||||
|
self.config = configparser.ConfigParser()
|
||||||
|
self.config.read('user_config.cfg')
|
||||||
|
|
||||||
|
# Load model settings
|
||||||
|
if 'models' in self.config:
|
||||||
|
self.model_var.set(self.config.get('models', 'model_name', fallback='SG161222/Realistic_Vision_V6.0_B1'))
|
||||||
|
self.model_dir_var.set(self.config.get('models', 'model_dir', fallback=''))
|
||||||
|
|
||||||
|
# Load FM settings
|
||||||
|
if 'profile:NewGens' in self.config:
|
||||||
|
self.fm_version_var.set(self.config.get('profile:NewGens', 'football_manager_version', fallback='2024'))
|
||||||
|
self.rtf_file_var.set(self.config.get('profile:NewGens', 'rtf_file', fallback=''))
|
||||||
|
self.output_dir_var.set(self.config.get('profile:NewGens', 'output_dir', fallback=''))
|
||||||
|
|
||||||
|
self.log_message("Configuration loaded")
|
||||||
|
else:
|
||||||
|
self.log_message("No configuration file found, using defaults")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
messagebox.showerror("Error", f"Failed to load configuration: {str(e)}")
|
||||||
|
self.log_message(f"Error loading configuration: {str(e)}")
|
||||||
|
|
||||||
|
def reset_config(self):
|
||||||
|
"""Reset configuration to defaults"""
|
||||||
|
self.model_var.set('SG161222/Realistic_Vision_V6.0_B1')
|
||||||
|
self.model_dir_var.set('')
|
||||||
|
self.fm_version_var.set('2024')
|
||||||
|
self.rtf_file_var.set('')
|
||||||
|
self.output_dir_var.set('')
|
||||||
|
self.log_message("Configuration reset to defaults")
|
||||||
|
|
||||||
|
def log_message(self, message):
|
||||||
|
"""Add message to log"""
|
||||||
|
self.status_text.insert(tk.END, f"[{time.strftime('%H:%M:%S')}] {message}\n")
|
||||||
|
self.status_text.see(tk.END)
|
||||||
|
|
||||||
|
def clear_log(self):
|
||||||
|
"""Clear the log"""
|
||||||
|
self.status_text.delete(1.0, tk.END)
|
||||||
|
|
||||||
|
def start_generation(self):
|
||||||
|
"""Start the generation process"""
|
||||||
|
if not self.validate_config():
|
||||||
|
return
|
||||||
|
|
||||||
|
# Disable start button, enable stop button
|
||||||
|
self.start_button.config(state=tk.DISABLED)
|
||||||
|
self.stop_button.config(state=tk.NORMAL)
|
||||||
|
|
||||||
|
# Reset progress
|
||||||
|
self.progress_var.set(0)
|
||||||
|
self.stop_generation = False
|
||||||
|
|
||||||
|
# Start generation thread
|
||||||
|
self.generation_thread = threading.Thread(target=self.generation_worker)
|
||||||
|
self.generation_thread.daemon = True
|
||||||
|
self.generation_thread.start()
|
||||||
|
|
||||||
|
def stop_generation_thread(self):
|
||||||
|
"""Stop the generation process"""
|
||||||
|
self.stop_generation = True
|
||||||
|
self.stop_button.config(state=tk.DISABLED)
|
||||||
|
self.log_message("Stopping generation...")
|
||||||
|
|
||||||
|
def generation_worker(self):
|
||||||
|
"""Worker thread for generation process"""
|
||||||
|
try:
|
||||||
|
self.log_message("Starting generation process...")
|
||||||
|
|
||||||
|
# Load configurations
|
||||||
|
with open("app_config.json", "r") as f:
|
||||||
|
app_config = json.load(f)
|
||||||
|
|
||||||
|
# Parse RTF file
|
||||||
|
rtf_file = self.rtf.parse_rtf(self.rtf_file_var.get())
|
||||||
|
self.log_message(f"Parsed RTF file successfully. Found {len(rtf_file)} players.")
|
||||||
|
|
||||||
|
# Determine players to process
|
||||||
|
update = self.update_mode_var.get() == "true"
|
||||||
|
process_player = self.player_mode_var.get() == "specific"
|
||||||
|
|
||||||
|
if process_player:
|
||||||
|
player_uuid = int(self.player_uid_var.get())
|
||||||
|
players_to_process = [p for p in rtf_file if int(p[0]) == player_uuid]
|
||||||
|
elif update:
|
||||||
|
# Filter out already processed players
|
||||||
|
try:
|
||||||
|
values_from_config = extract_from_values(f"{self.output_dir_var.get()}/config.xml")
|
||||||
|
ids_in_b = [item for item in values_from_config]
|
||||||
|
players_to_process = [item for item in rtf_file if item[0] not in ids_in_b]
|
||||||
|
except FileNotFoundError:
|
||||||
|
players_to_process = rtf_file
|
||||||
|
else:
|
||||||
|
players_to_process = rtf_file
|
||||||
|
|
||||||
|
if len(players_to_process) == 0:
|
||||||
|
self.log_message("No players to process")
|
||||||
|
return
|
||||||
|
|
||||||
|
self.log_message(f"Processing {len(players_to_process)} players")
|
||||||
|
|
||||||
|
# Generate prompts
|
||||||
|
prompts = generate_prompts_for_players(players_to_process, app_config)
|
||||||
|
|
||||||
|
# Generate images
|
||||||
|
total_players = len(prompts)
|
||||||
|
for i, prompt in enumerate(prompts):
|
||||||
|
if self.stop_generation:
|
||||||
|
break
|
||||||
|
|
||||||
|
uid = prompt.split(":")[0]
|
||||||
|
comfy_prompt = prompt.split(":")[1]
|
||||||
|
|
||||||
|
self.log_message(f"Generating image for player {uid} ({i+1}/{total_players})")
|
||||||
|
generate_image(uid, comfy_prompt)
|
||||||
|
|
||||||
|
# Update progress
|
||||||
|
progress = (i + 1) / total_players * 100
|
||||||
|
self.progress_var.set(progress)
|
||||||
|
|
||||||
|
# Queue image for preview
|
||||||
|
self.image_queue.put(uid)
|
||||||
|
|
||||||
|
# Post-processing
|
||||||
|
if not self.stop_generation:
|
||||||
|
try:
|
||||||
|
if update:
|
||||||
|
append_to_config_xml(
|
||||||
|
self.output_dir_var.get(),
|
||||||
|
[item[0] for item in players_to_process],
|
||||||
|
self.fm_version_var.get()
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
create_config_xml(
|
||||||
|
self.output_dir_var.get(),
|
||||||
|
[item[0] for item in players_to_process],
|
||||||
|
self.fm_version_var.get()
|
||||||
|
)
|
||||||
|
self.log_message("Configuration XML updated")
|
||||||
|
except Exception as e:
|
||||||
|
self.log_message(f"Post-processing failed: {e}")
|
||||||
|
|
||||||
|
self.log_message("Generation complete!")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.log_message(f"Generation failed: {str(e)}")
|
||||||
|
import traceback
|
||||||
|
self.log_message(traceback.format_exc())
|
||||||
|
|
||||||
|
finally:
|
||||||
|
# Re-enable start button
|
||||||
|
self.start_button.config(state=tk.NORMAL)
|
||||||
|
self.stop_button.config(state=tk.DISABLED)
|
||||||
|
|
||||||
|
def validate_config(self):
|
||||||
|
"""Validate configuration before starting"""
|
||||||
|
if not self.rtf_file_var.get():
|
||||||
|
messagebox.showerror("Error", "Please select an RTF file")
|
||||||
|
return False
|
||||||
|
|
||||||
|
if not self.output_dir_var.get():
|
||||||
|
messagebox.showerror("Error", "Please select an output directory")
|
||||||
|
return False
|
||||||
|
|
||||||
|
if not os.path.exists(self.rtf_file_var.get()):
|
||||||
|
messagebox.showerror("Error", "RTF file does not exist")
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def update_image_preview(self):
|
||||||
|
"""Update image preview periodically"""
|
||||||
|
try:
|
||||||
|
while not self.image_queue.empty():
|
||||||
|
uid = self.image_queue.get()
|
||||||
|
self.show_image(uid)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Schedule next update
|
||||||
|
self.root.after(1000, self.update_image_preview)
|
||||||
|
|
||||||
|
def show_image(self, uid):
|
||||||
|
"""Show an image in the preview"""
|
||||||
|
try:
|
||||||
|
image_path = f"{self.output_dir_var.get()}/{uid}.png"
|
||||||
|
if os.path.exists(image_path):
|
||||||
|
# Load and resize image
|
||||||
|
image = Image.open(image_path)
|
||||||
|
image.thumbnail((300, 300), Image.Resampling.LANCZOS)
|
||||||
|
|
||||||
|
# Convert to PhotoImage
|
||||||
|
photo = ImageTk.PhotoImage(image)
|
||||||
|
|
||||||
|
# Update display
|
||||||
|
self.image_label.config(image=photo, text="")
|
||||||
|
self.image_label.image = photo # Keep reference
|
||||||
|
self.current_image_var.set(f"Player {uid}")
|
||||||
|
self.log_message(f"Preview updated: {uid}.png")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.log_message(f"Failed to load image {uid}: {str(e)}")
|
||||||
|
|
||||||
|
def show_previous_image(self):
|
||||||
|
"""Show previous image"""
|
||||||
|
self.log_message("Previous image functionality not implemented yet")
|
||||||
|
|
||||||
|
def show_next_image(self):
|
||||||
|
"""Show next image"""
|
||||||
|
self.log_message("Next image functionality not implemented yet")
|
||||||
|
|
||||||
|
def refresh_preview(self):
|
||||||
|
"""Refresh the preview"""
|
||||||
|
self.log_message("Refreshing preview...")
|
||||||
|
# This would scan the output directory and show available images
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Main function"""
|
||||||
|
root = tk.Tk()
|
||||||
|
app = FMFaceGeneratorGUI(root)
|
||||||
|
root.mainloop()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
218
readme.md
218
readme.md
@ -1,7 +1,9 @@
|
|||||||
|
|
||||||
# Comfy UI NewGens
|
# Standalone FM NewGens
|
||||||
|
|
||||||
Use ComfyUI to generate NewGen images for Football Manager 2024
|
Generate NewGen images for Football Manager using local Stable Diffusion
|
||||||
|
|
||||||
|
**🖥️ GUI Available!** - Now includes a user-friendly graphical interface
|
||||||
|
|
||||||
# Intro
|
# Intro
|
||||||
|
|
||||||
@ -13,68 +15,192 @@ Use ComfyUI to generate NewGen images for Football Manager 2024
|
|||||||
|
|
||||||
[Example video here](https://www.youtube.com/watch?v=mcGj3_nbV0A)
|
[Example video here](https://www.youtube.com/watch?v=mcGj3_nbV0A)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
These are some of the questions I think you are going to ask me, but I present to you somehting I have been working on, **Comfy FM24 NewGens**
|
|
||||||
|
These are some of the questions I think you are going to ask me, but I present to you something I have been working on, **Standalone FM NewGens**
|
||||||
|
|
||||||
# The Idea
|
# The Idea
|
||||||
|
|
||||||
Taking some inspiration from [fm-ai-face-generator](https://github.com/emilmirzayev/fm-ai-face-generator), but not wanting to pay for a hosted service (I already have AI _stuff_ setup on my home server) I started to rewrite chunks to make compatible with a hosted Comfy UI instance, after awhile, I had rewritten so much, that this is now a new beast in itself..
|
Taking inspiration from [fm-ai-face-generator](https://github.com/emilmirzayev/fm-ai-face-generator) and [NewGAN-Manager](https://github.com/franl08/NewGAN-Manager), this tool generates unique face images for Football Manager NewGens using local Stable Diffusion instead of requiring a separate ComfyUI server.
|
||||||
|
|
||||||
|
Thanks to both original projects for the inspiration!
|
||||||
|
|
||||||
Also taking inspiration from [NewGAN-Manager](https://github.com/franl08/NewGAN-Manager) and reworking some of thier code for my uses.
|
So what does this do? Why would you want to use it? (you probably won't but personally, I like a bit more personalization from my NewGens, some I get quite attached to :) )
|
||||||
|
|
||||||
|
- This will create images for your NewGens, based off of information provided from the FM database, making a player's image more unique to that player
|
||||||
|
- Generate images locally using Stable Diffusion (no external server required)
|
||||||
Thanks to both!
|
- Download the images to the specified output directory, all processed players images will be saved as their **uid** from the game
|
||||||
|
- Remove all the background from the generated faces
|
||||||
|
- Create the needed config file for FM to load the faces
|
||||||
|
- You can then rename the generated folder and place it in your **graphics** folder as you would normally and voila!
|
||||||
So what does this do? Why would you want to use it? (you probably wont but personally, I like a bit more personallisation from my NewGens, some, I get quite attached to :) )
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
- This will create images for your NewGens, based off of information provided from the FM database, making a players image more unique to that player
|
|
||||||
- download the images to the specified output directory, all processed players image will be saved as their **uid** from the game
|
|
||||||
- remove all the background from the generated faces
|
|
||||||
- create the needed config file for FM to load the faces,
|
|
||||||
- you can then rename the generated folder and place it in your **graphics** folder as you would noramlly and voila!
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Install Guide
|
# Install Guide
|
||||||
|
|
||||||
|
|
||||||
Things you will need that I will not be going over on how to setup.
|
Things you will need that I will not be going over on how to setup.
|
||||||
|
|
||||||
- Python installed
|
- Python 3.8+ installed
|
||||||
- Git installed
|
- Git installed
|
||||||
- A ComfyUI installation (On hosted server, or [portable](https://github.com/YanWenKun/ComfyUI-Windows-Portable))
|
- At least 4GB of RAM (8GB+ recommended for better performance)
|
||||||
- My suggestion it to use the [Realistic Vision 6](https://civitai.com/models/4201/realistic-vision-v60-b1) model
|
- CUDA-compatible GPU (optional, but highly recommended for faster generation)
|
||||||
|
|
||||||
If you have that, then carry on for Windows instructions
|
## Setup Instructions
|
||||||
- Use Git to checkout this repo
|
|
||||||
- You need to get a `rtf` file of the players you want to add images for, to do this you need the view and filter supplied with the project
|
|
||||||
- Copy the `filters` and `views` folder over to your `Football Manager 2024` data folder in `Documents`, this may create these folders, or may just add the contained files into your existing folders
|
|
||||||
- You can use `python INSTALL_VIEW_AND_FILTER.py` to do this automatically
|
|
||||||
- Included is the original `is newgen` filter created by the NewGAN-Manager team and a new view created by myself to get the needed data
|
|
||||||
- If you follow [this video](https://youtu.be/pmdIkhfmY6w?t=564) it will show you how to export the `rtf` file, you want to use our view, not the view in the video
|
|
||||||
- Once you have your `rtf` file add it to the root of the current repo
|
|
||||||
- Create a python virtual environment `python -m venv venv`
|
|
||||||
- Activate the venv `.\venv\Scripts\activate`
|
|
||||||
- Install the requirements `pip install -r requirements.txt`
|
|
||||||
- Copy the `user_config.cfg.sample` to `user_config.cfg` and make the needed changes
|
|
||||||
- football_manager_version - Version of FM to generate for. Defautls to `2024`
|
|
||||||
- output_dir - Where to save the generated set. Defaults to `./generated_images/`
|
|
||||||
- comfyui_url - HTTP location of your comfyui installation.
|
|
||||||
- model - Model to be used, by default `realisticVisionV60B1_v51HyperVAE.safetensors` is set, this is my suggested model at the moment.
|
|
||||||
- At this point you should be able to run and start to generate by running the command `python comfy_fm_newgen.py --rtf_file ExportedFile.rtf`
|
|
||||||
- ExportedFile is the name of the file that you exported and saved with your newgen list
|
|
||||||
|
|
||||||
|
- Use Git to checkout this repo
|
||||||
|
- You need to get a `rtf` file of the players you want to add images for, to do this you need the view and filter supplied with the project
|
||||||
|
- Copy the `filters` and `views` folder over to your `Football Manager 2024` data folder in `Documents`, this may create these folders, or may just add the contained files into your existing folders
|
||||||
|
- You can use `python INSTALL_VIEW_AND_FILTER.py` to do this automatically
|
||||||
|
- Included is the original `is newgen` filter created by the NewGAN-Manager team and a new view created by myself to get the needed data
|
||||||
|
- If you follow [this video](https://youtu.be/pmdIkhfmY6w?t=564) it will show you how to export the `rtf` file, you want to use our view, not the view in the video
|
||||||
|
- Once you have your `rtf` file add it to the root of the current repo
|
||||||
|
- Create a python virtual environment `python -m venv venv`
|
||||||
|
- Activate the venv `.\venv\Scripts\activate` (Windows) or `source venv/bin/activate` (Linux/Mac)
|
||||||
|
- Install the requirements `pip install -r requirements.txt`
|
||||||
|
- Copy the `user_config.cfg.sample` to `user_config.cfg` and make the needed changes
|
||||||
|
- football_manager_version - Version of FM to generate for. Defaults to `2024`
|
||||||
|
- output_dir - Where to save the generated set. Defaults to `./generated_images/`
|
||||||
|
- rtf_file - Path to your exported RTF file with player data
|
||||||
|
- model_name - Hugging Face model to use (see Model Selection section below)
|
||||||
|
- model_dir - Custom directory to store models (optional)
|
||||||
|
|
||||||
|
## Usage Options
|
||||||
|
|
||||||
|
### **🖥️ GUI Mode (Recommended)**
|
||||||
|
For the best user experience, use the graphical interface:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python run_gui.py
|
||||||
|
```
|
||||||
|
|
||||||
|
**GUI Features:**
|
||||||
|
- Easy configuration with file browsers
|
||||||
|
- Real-time progress monitoring
|
||||||
|
- Live image preview
|
||||||
|
- Start/stop controls
|
||||||
|
- Comprehensive logging
|
||||||
|
|
||||||
|
### **📝 Command Line Mode**
|
||||||
|
For advanced users or automation:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python comfy_fm_newgen.py
|
||||||
|
```
|
||||||
|
|
||||||
|
**Command Line Features:**
|
||||||
|
- Fast batch processing
|
||||||
|
- Resume capability
|
||||||
|
- Detailed logging
|
||||||
|
- Script automation
|
||||||
|
|
||||||
|
|
||||||
|
## Model Selection
|
||||||
|
|
||||||
|
The tool uses Hugging Face models for image generation. You can specify which model to use in your `user_config.cfg`:
|
||||||
|
|
||||||
|
### **Recommended Models for Face Generation:**
|
||||||
|
|
||||||
|
- `SG161222/Realistic_Vision_V6.0_B1` - **Best choice** for realistic faces (default)
|
||||||
|
- `digiplay/AbsoluteReality` - Photorealistic faces and people
|
||||||
|
- `stabilityai/stable-diffusion-2-1` - General purpose, good for faces
|
||||||
|
- `runwayml/stable-diffusion-v1-5` - Classic SD 1.5, widely supported
|
||||||
|
|
||||||
|
### **Model Storage:**
|
||||||
|
|
||||||
|
- **Default**: Models are stored in Hugging Face cache (`~/.cache/huggingface/`)
|
||||||
|
- **Custom Directory**: Set `model_dir` in config to store models in a specific folder
|
||||||
|
- **Model Size**: Most face models are 2-5GB, ensure you have sufficient disk space
|
||||||
|
- **First Run**: Model downloads automatically when you first run the tool
|
||||||
|
|
||||||
|
### **Changing Models:**
|
||||||
|
|
||||||
|
1. Edit `model_name` in your `user_config.cfg`
|
||||||
|
2. Delete the old model from your cache/directory if desired
|
||||||
|
3. Restart the tool - it will download the new model automatically
|
||||||
|
|
||||||
|
## System Requirements
|
||||||
|
|
||||||
|
- **CPU Mode**: Requires at least 8GB RAM, expect 2-5 minutes per image
|
||||||
|
- **GPU Mode**: Requires CUDA-compatible GPU with at least 4GB VRAM, expect 10-30 seconds per image
|
||||||
|
- First run will download the Stable Diffusion model (~5GB), so ensure you have sufficient disk space
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
### **Core Features**
|
||||||
|
- **Local Generation**: No external servers or API keys required
|
||||||
|
- **Model Selection**: Choose from various face generation models via configuration
|
||||||
|
- **Automatic Processing**: Batch process multiple players from your RTF file
|
||||||
|
- **Background Removal**: Automatically removes backgrounds from generated faces
|
||||||
|
- **XML Configuration**: Generates proper Football Manager configuration files
|
||||||
|
- **Resume Support**: Can resume from previous runs without regenerating existing images
|
||||||
|
- **Model Caching**: Downloads and caches models locally for faster subsequent runs
|
||||||
|
|
||||||
|
### **🖥️ GUI Features**
|
||||||
|
- **User-Friendly Interface**: Modern tabbed interface with intuitive controls
|
||||||
|
- **File Browsers**: Easy selection of RTF files and output directories
|
||||||
|
- **Real-Time Progress**: Live progress bars and status updates
|
||||||
|
- **Image Preview**: View generated images as they're created
|
||||||
|
- **Configuration Management**: Save and load different configurations
|
||||||
|
- **Error Handling**: Clear error messages and troubleshooting tips
|
||||||
|
- **Multi-threaded**: Non-blocking interface during generation
|
||||||
|
|
||||||
|
## GUI Troubleshooting
|
||||||
|
|
||||||
|
### **Common Issues:**
|
||||||
|
|
||||||
|
**GUI won't start:**
|
||||||
|
- Ensure Python 3.8+ is installed
|
||||||
|
- Install requirements: `pip install -r requirements.txt`
|
||||||
|
- Check for missing dependencies: `python -c "import tkinter"`
|
||||||
|
|
||||||
|
**Dependency installation fails:**
|
||||||
|
- Try installing packages individually: `pip install torch torchvision diffusers transformers`
|
||||||
|
- For Python 3.11+, use: `pip install rembg==2.0.59` (instead of 2.0.60)
|
||||||
|
- If `striprtf` fails, try: `pip install striprtf==0.0.28`
|
||||||
|
- Use alternative requirements: `pip install -r requirements-gui.txt` for GUI-only
|
||||||
|
|
||||||
|
**Alternative installation methods:**
|
||||||
|
- **Conda**: `conda install pytorch torchvision torchaudio cpuonly -c pytorch`
|
||||||
|
- **GPU Support**: Replace `cpuonly` with `cudatoolkit=11.8` for CUDA support
|
||||||
|
- **Individual packages**: Install problematic packages one by one to identify issues
|
||||||
|
|
||||||
|
**Model download fails:**
|
||||||
|
- Check internet connection
|
||||||
|
- Verify disk space (models are 2-5GB)
|
||||||
|
- Try a different model from the recommended list
|
||||||
|
|
||||||
|
**Images not appearing in preview:**
|
||||||
|
- Check output directory permissions
|
||||||
|
- Ensure images are being generated successfully
|
||||||
|
- Try refreshing the preview tab
|
||||||
|
|
||||||
|
**Configuration not saving:**
|
||||||
|
- Check file permissions in the project directory
|
||||||
|
- Ensure no other instances are running
|
||||||
|
- Try running as administrator
|
||||||
|
|
||||||
|
### **Performance Tips:**
|
||||||
|
|
||||||
|
- **First run** takes longer due to model download
|
||||||
|
- **Close other applications** during generation for better performance
|
||||||
|
- **Use SSD storage** for faster model loading
|
||||||
|
- **Monitor system resources** - generation is CPU/GPU intensive
|
||||||
|
|
||||||
|
## Command Line Usage
|
||||||
|
|
||||||
|
For advanced users or automation, you can still use the original command-line interface:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python comfy_fm_newgen.py
|
||||||
|
```
|
||||||
|
|
||||||
|
The GUI and command-line versions share the same configuration files and generated data.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
You should get some console output of the progress, good luck!
|
You should get some console output of the progress, good luck!
|
||||||
|
|
||||||
Open an issue here if your having problems
|
Open an issue here if you're having problems
|
||||||
|
|
||||||
Thanks
|
Thanks
|
4
requirements-gui.txt
Normal file
4
requirements-gui.txt
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
# Alternative requirements for GUI-only usage (without AI generation)
|
||||||
|
# Use this if you only want to run the GUI interface
|
||||||
|
tkinterdnd2==0.3.0
|
||||||
|
Pillow==10.4.0
|
BIN
requirements.txt
BIN
requirements.txt
Binary file not shown.
43
run_gui.py
Normal file
43
run_gui.py
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
FM Face Generator GUI Launcher
|
||||||
|
Simple launcher script for the GUI interface
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Launch the GUI application"""
|
||||||
|
try:
|
||||||
|
# Add current directory to path for imports
|
||||||
|
current_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
if current_dir not in sys.path:
|
||||||
|
sys.path.insert(0, current_dir)
|
||||||
|
|
||||||
|
# Import and run the GUI
|
||||||
|
from gui import main as gui_main
|
||||||
|
|
||||||
|
print("Starting FM Face Generator GUI...")
|
||||||
|
print("If you encounter any import errors, make sure to install requirements:")
|
||||||
|
print("pip install -r requirements.txt")
|
||||||
|
print()
|
||||||
|
|
||||||
|
gui_main()
|
||||||
|
|
||||||
|
except ImportError as e:
|
||||||
|
print(f"Import Error: {e}")
|
||||||
|
print("\nPlease install the required dependencies:")
|
||||||
|
print("pip install -r requirements.txt")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error starting GUI: {e}")
|
||||||
|
print("\nTroubleshooting:")
|
||||||
|
print("1. Make sure Python 3.8+ is installed")
|
||||||
|
print("2. Install requirements: pip install -r requirements.txt")
|
||||||
|
print("3. Check that all dependencies are available")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
@ -1,8 +1,16 @@
|
|||||||
[comfyui]
|
|
||||||
comfyui_url =
|
|
||||||
model = realisticVisionV60B1_v51HyperVAE.safetensors
|
|
||||||
|
|
||||||
[profile:NewGens]
|
[profile:NewGens]
|
||||||
football_manager_version = 2024
|
football_manager_version = 2024
|
||||||
rtf_file = ./NewGen.rtf
|
rtf_file = ./NewGen.rtf
|
||||||
output_dir = ./NewGens/
|
output_dir = ./NewGens/
|
||||||
|
|
||||||
|
[models]
|
||||||
|
# Hugging Face model repository (format: username/model-name)
|
||||||
|
# Popular face generation models:
|
||||||
|
# SG161222/Realistic_Vision_V6.0_B1 - Realistic faces (recommended)
|
||||||
|
# stabilityai/stable-diffusion-2-1 - General purpose
|
||||||
|
# runwayml/stable-diffusion-v1-5 - Classic SD 1.5
|
||||||
|
# digiplay/AbsoluteReality - Photorealistic
|
||||||
|
model_name = SG161222/Realistic_Vision_V6.0_B1
|
||||||
|
|
||||||
|
# Model storage directory (optional - defaults to Hugging Face cache)
|
||||||
|
# model_dir = ./models/
|
Loading…
x
Reference in New Issue
Block a user