| import os |
| import sys |
| import cv2 |
| import torch |
| torch.set_num_threads(8) |
| |
| torch.backends.mkldnn.enabled = False |
| import yaml |
| import subprocess |
| import glob |
|
|
| import argparse |
|
|
| def main(): |
| parser = argparse.ArgumentParser(description="Train CodeFormer with custom parameters.") |
| parser.add_argument("--verify", action="store_true", help="Run 2 iterations for verification purposes.") |
| args = parser.parse_args() |
|
|
| project_dir = os.path.dirname(os.path.abspath(__file__)) |
| codeformer_dir = os.path.join(project_dir, "models", "CodeFormer") |
| |
| print("=== Custom CodeFormer Training Runner ===") |
| |
| |
| device = "cuda" if torch.cuda.is_available() else "cpu" |
| num_gpus = torch.cuda.device_count() if device == "cuda" else 0 |
| print(f"Device detected: {device.upper()}") |
| print(f"Number of GPUs available: {num_gpus}") |
| |
| |
| dataset_dir = os.path.join(codeformer_dir, "datasets", "ffhq", "ffhq_512") |
| if not os.path.exists(dataset_dir) or len(os.listdir(dataset_dir)) == 0: |
| print("Dataset directory is empty. Preparing dataset images...") |
| try: |
| import prepare_toy_training |
| prepare_toy_training.main() |
| print("Dataset preparation completed.") |
| except Exception as e: |
| print(f"Error preparing dataset: {e}") |
| sys.exit(1) |
| else: |
| print(f"Dataset found at {dataset_dir} ({len(os.listdir(dataset_dir))} images).") |
| |
| |
| config_path = os.path.join(codeformer_dir, "options", "CodeFormer_stage3_custom.yml") |
| if not os.path.exists(config_path): |
| print(f"Error: Config file not found at {config_path}") |
| sys.exit(1) |
| |
| print(f"Reading configuration from {config_path}...") |
| with open(config_path, "r", encoding="utf-8") as f: |
| config = yaml.safe_load(f) |
|
|
| |
| |
| |
| holdout_manifest = os.path.join(project_dir, "benchmarks", "holdout_paths.txt") |
| if os.path.isfile(holdout_manifest): |
| for dataset in config.get("datasets", {}).values(): |
| dataset["exclude_manifest"] = holdout_manifest |
| print(f"Excluding benchmark holdout from training: {holdout_manifest}") |
| else: |
| print("WARNING: benchmark holdout manifest not found; refusing quality claims for this run.") |
| |
| |
| |
| original_total_iter = config.get("train", {}).get("total_iter", 20000) |
| |
| |
| config["num_gpu"] = num_gpus |
| config["dist"] = False |
| config["dist_params"] = None |
| |
| |
| if "datasets" in config: |
| for phase in config["datasets"]: |
| dataset = config["datasets"][phase] |
| if device == "cpu": |
| dataset["num_worker_per_gpu"] = 0 |
| |
| |
| dataset["prefetch_mode"] = None |
| else: |
| dataset["num_worker_per_gpu"] = 4 |
| |
| |
| project_weights_path = os.path.join(project_dir, "weights", "CodeFormer", "codeformer.pth") |
| if os.path.exists(project_weights_path): |
| |
| config["path"]["pretrain_network_g"] = "../../weights/CodeFormer/codeformer.pth" |
| print(f"Configured pretrain generator path to: {config['path']['pretrain_network_g']}") |
| |
| |
| experiments_dir = os.path.join(codeformer_dir, "experiments") |
| latest_state = None |
| latest_state_iter = 0 |
| |
| |
| exp_pattern = os.path.join(experiments_dir, "*_CodeFormer_stage3_custom", "training_states", "*.state") |
| state_files = glob.glob(exp_pattern) |
| |
| for state_file in state_files: |
| basename = os.path.basename(state_file) |
| try: |
| iter_num = int(basename.replace(".state", "")) |
| if iter_num > latest_state_iter: |
| latest_state_iter = iter_num |
| latest_state = state_file |
| except ValueError: |
| continue |
| |
| if latest_state: |
| print(f"\n>>> RESUME MODE: Found checkpoint at iteration {latest_state_iter}") |
| print(f" State file: {latest_state}") |
| config["path"]["resume_state"] = latest_state |
| config["path"]["pretrain_network_g"] = None |
| if args.verify: |
| config["train"]["total_iter"] = latest_state_iter + 2 |
| print(f" Resuming training from iter {latest_state_iter} to {config['train']['total_iter']} (verification mode)...") |
| else: |
| if latest_state_iter >= config.get("train", {}).get("total_iter", 20000): |
| print(f"\n>>> Training already completed ({latest_state_iter} >= {config.get('train', {}).get('total_iter', 20000)} total_iter)") |
| sys.exit(0) |
| print(f" Resuming training from iter {latest_state_iter} to {config['train']['total_iter']}...") |
| else: |
| print("\n>>> FRESH START: No previous checkpoint found. Starting from pretrained weights.") |
| if args.verify: |
| config["train"]["total_iter"] = 2 |
| print(f" Training from scratch to {config['train']['total_iter']} (verification mode)...") |
| else: |
| print(f" Training from scratch to {config.get('train', {}).get('total_iter', 20000)}...") |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| import tempfile, shutil |
| tmp_fd, tmp_config_path = tempfile.mkstemp(suffix=".yml", prefix="cf_runtime_", |
| dir=os.path.join(codeformer_dir, "options")) |
| try: |
| with os.fdopen(tmp_fd, "w", encoding="utf-8") as f: |
| yaml.dump(config, f, default_flow_style=False, sort_keys=False) |
| print(f"Runtime config written to temp file: {os.path.basename(tmp_config_path)}") |
| print(f" device={device.upper()}, num_gpu={num_gpus}, total_iter={config['train']['total_iter']}") |
|
|
| |
| train_script = os.path.join("basicsr", "train.py") |
| cmd = [ |
| sys.executable, |
| train_script, |
| "-opt", |
| os.path.relpath(tmp_config_path, codeformer_dir), |
| "--launcher", |
| "none" |
| ] |
|
|
| |
| env = os.environ.copy() |
| for _k in ["OMP_NUM_THREADS", "MKL_NUM_THREADS", "OPENBLAS_NUM_THREADS", |
| "NUMEXPR_NUM_THREADS", "VECLIB_MAXIMUM_THREADS"]: |
| env[_k] = "8" |
| env["OPENCV_OPENCL_RUNTIME"] = "disabled" |
| env["OPENCV_THREAD_LIMIT"] = "1" |
| cv2.setNumThreads(0) |
| env["PYTHONPATH"] = os.path.pathsep.join([codeformer_dir, env.get("PYTHONPATH", "")]) |
|
|
| print("\nStarting training process. Command:") |
| print(" ".join(cmd)) |
| print(f"Working directory: {codeformer_dir}") |
| print("------------------------------------------") |
|
|
| try: |
| result = subprocess.run(cmd, cwd=codeformer_dir, env=env, check=True) |
| print("------------------------------------------") |
| print("Training execution completed successfully!") |
| except subprocess.CalledProcessError as e: |
| print("------------------------------------------") |
| print(f"Training failed with exit code: {e.returncode}") |
| sys.exit(e.returncode) |
| finally: |
| |
| if os.path.exists(tmp_config_path): |
| os.remove(tmp_config_path) |
|
|
| if __name__ == "__main__": |
| main() |
|
|