### Setup Linux Virtual Environment Source: https://github.com/jeffersonqin/yuzumarker.fontdetection/blob/master/README.md Run this script to create a virtual environment and install dependencies, including libraqm, on a Linux cluster. Ensure python3-venv is installed. ```bash ./linux_venv_setup.sh ``` -------------------------------- ### Parallel Dataset Generation Source: https://github.com/jeffersonqin/yuzumarker.fontdetection/blob/master/README.md Example commands to run dataset generation in parallel across multiple partitions. Adjust the second parameter to match the desired number of parallel tasks. ```bash python font_ds_generate_script.py 1 4 python font_ds_generate_script.py 2 4 python font_ds_generate_script.py 3 4 python font_ds_generate_script.py 4 4 ``` -------------------------------- ### Start Demo Server with Arguments Source: https://github.com/jeffersonqin/yuzumarker.fontdetection/blob/master/README.md Launches the demo server. Use the provided arguments to configure device, checkpoint, model type, and other operational parameters. The '-h' flag displays all available options. ```bash python demo.py -h usage: demo.py [-h] [-d DEVICE] [-c CHECKPOINT] [-m {resnet18,resnet34,resnet50,resnet101,deepfont}] [-f] [-z SIZE] [-s] [-p PORT] [-a ADDRESS] optional arguments: -h, --help show this help message and exit -d DEVICE, --device DEVICE GPU devices to use (default: 0), -1 for CPU -c CHECKPOINT, --checkpoint CHECKPOINT Trainer checkpoint path (default: None). Use link as huggingface://// for huggingface.co models, currently only supports model file in the root directory. -m {resnet18,resnet34,resnet50,resnet101,deepfont}, --model {resnet18,resnet34,resnet50,resnet101,deepfont} Model to use (default: resnet18) -f, --font-classification-only Font classification only (default: False) -z SIZE, --size SIZE Model feature image input size (default: 512) -s, --share Get public link via Gradio (default: False) -p PORT, --port PORT Port to use for Gradio (default: 7860) -a ADDRESS, --address ADDRESS Address to use for Gradio (default: 127.0.0.1) ``` -------------------------------- ### Docker Deployment for Gradio Interface Source: https://context7.com/jeffersonqin/yuzumarker.fontdetection/llms.txt Commands to build a Docker image for the application and run it, mirroring the Hugging Face Space setup. ```bash docker build -t yuzumarker.fontdetection . docker run -it -p 7860:7860 yuzumarker.fontdetection ``` -------------------------------- ### Compile Task Schedulers for 4 Machines Source: https://github.com/jeffersonqin/yuzumarker.fontdetection/blob/master/README.md Example compilation commands for distributing a total of 64 partitions across 4 machines. Each machine compiles a specific range of missions. ```c # Machine 1 gcc -D MIN_MISSION=1 \ -D MAX_MISSION=16 \ -D TOTAL_MISSION=64 \ batch_generate_script_linux.c \ -o mission-1-16.out # Machine 2 gcc -D MIN_MISSION=17 \ -D MAX_MISSION=32 \ -D TOTAL_MISSION=64 \ batch_generate_script_linux.c \ -o mission-17-32.out # Machine 3 gcc -D MIN_MISSION=33 \ -D MAX_MISSION=48 \ -D TOTAL_MISSION=64 \ batch_generate_script_linux.c \ -o mission-33-48.out # Machine 4 gcc -D MIN_MISSION=49 \ -D MAX_MISSION=64 \ -D TOTAL_MISSION=64 \ batch_generate_script_linux.c \ -o mission-49-64.out ``` -------------------------------- ### Run Compiled Generation Tasks Source: https://github.com/jeffersonqin/yuzumarker.fontdetection/blob/master/README.md Execute the compiled object files on their respective machines to start the font generation tasks in parallel. ```bash ./mission-1-16.out # Machine 1 ./mission-17-32.out # Machine 2 ./mission-33-48.out # Machine 3 ./mission-49-64.out # Machine 4 ``` -------------------------------- ### Retrieve Current Git Commit Hash Source: https://context7.com/jeffersonqin/yuzumarker.fontdetection/llms.txt Get the short commit hash of the current HEAD using `get_current_tag()`. Raises `RuntimeError` if there are unstaged changes. Useful for default model naming in TensorBoard. ```python from utils import get_current_tag tag = get_current_tag() print(tag) # e.g., "a3f7c12" # Used in train.py as: # model_name = get_current_tag() if args.model_name is None else args.model_name ``` -------------------------------- ### Launch Gradio Web Interface Loading from Hugging Face Source: https://context7.com/jeffersonqin/yuzumarker.fontdetection/llms.txt Command to launch the Gradio web UI by loading the model directly from Hugging Face Hub. Uses CPU for inference. ```bash python demo.py \ --model resnet50 \ --checkpoint "huggingface://gyrojeff/YuzuMarker.FontDetection/resnet50.ckpt" \ --device -1 # use CPU ``` -------------------------------- ### Initialize FontDetector Training Module Source: https://context7.com/jeffersonqin/yuzumarker.fontdetection/llms.txt Set up the `FontDetector` training module, wrapping a backbone model with a combined loss function, accuracy metrics, and an LR scheduler. Configure loss weights, learning rate, optimizer betas, and warmup/total training steps. ```python from detector.model import FontDetector, ResNet50Regressor import torch import os backbone = ResNet50Regressor(pretrained=True) # Optional: compile with PyTorch 2.0 on Linux if torch.__version__ >= "2.0" and os.name == "posix": backbone = torch.compile(backbone) detector = FontDetector( model=backbone, lambda_font=2.0, # weight for font classification loss lambda_direction=0.5, # weight for direction classification loss lambda_regression=1.0, # weight for regression (MSE) loss font_classification_only=False, lr=1e-4, betas=(0.9, 0.999), num_warmup_iters=500, # linear warmup steps num_iters=50000, # total training steps for cosine decay num_epochs=100, ) # Forward pass x = torch.rand(2, 3, 512, 512) out = detector(x) print(out.shape) # torch.Size([2, 6162]) ``` -------------------------------- ### Generate Font Sample Images for Demo Source: https://context7.com/jeffersonqin/yuzumarker.fontdetection/llms.txt Script to pre-generate sample images for each font, used by the Gradio UI. Requires the dataset to be populated. ```bash # Requires ./dataset/fonts/ to be populated python generate_font_sample_image.py # Outputs: demo_fonts/0.jpg, demo_fonts/1.jpg, ..., demo_fonts/6149.jpg ``` -------------------------------- ### Training ResNet-50 with Augmentation and ROI Crop Source: https://context7.com/jeffersonqin/yuzumarker.fontdetection/llms.txt Command-line arguments for training a ResNet-50 model with specific configurations. Supports multi-GPU, augmentation strategies, and pretrained backbones. ```bash python train.py \ --model resnet50 \ --pretrained \ --devices 0 1 \ --single-batch-size 32 \ --augmentation v2 \ --crop-roi-bbox \ --lr 0.001 \ --size 512 \ --datasets ./dataset/font_img ./dataset/font_img2 \ --model-name my_experiment \ --tensor-core high ``` -------------------------------- ### Launch Gradio Web Interface with Local Checkpoint Source: https://context7.com/jeffersonqin/yuzumarker.fontdetection/llms.txt Command to launch the Gradio web UI using a local model checkpoint. Specifies model, checkpoint path, size, device, port, and address. ```bash python demo.py \ --model resnet50 \ --checkpoint ./checkpoints/resnet50.ckpt \ --size 512 \ --device 0 \ --port 7860 \ --address 0.0.0.0 ``` -------------------------------- ### Generate Font Sample Image Source: https://github.com/jeffersonqin/yuzumarker.fontdetection/blob/master/README.md Run this script to generate the demo font image if you have the font dataset. Ensure the dataset is located at './dataset/fonts'. ```bash python generate_font_sample_image.py ``` -------------------------------- ### Train Font Detection Model CLI Source: https://github.com/jeffersonqin/yuzumarker.fontdetection/blob/master/README.md Use this command to initiate model training. Customize training parameters like dataset paths, model architecture, batch size, and learning rate via command-line arguments. ```bash python train.py -h ``` -------------------------------- ### Build Docker Image Source: https://github.com/jeffersonqin/yuzumarker.fontdetection/blob/master/README.md Builds the Docker image for the YuzuMarker.FontDetection project. This command should be run from the directory containing the Dockerfile. ```bash docker build -t yuzumarker.fontdetection . ``` -------------------------------- ### Launch Gradio Web Interface with Public Sharing Source: https://context7.com/jeffersonqin/yuzumarker.fontdetection/llms.txt Command to launch the Gradio web UI and share it publicly via a Gradio tunnel. ```bash python demo.py --checkpoint ./model.ckpt --share ``` -------------------------------- ### Run Docker Image Source: https://github.com/jeffersonqin/yuzumarker.fontdetection/blob/master/README.md Runs the previously built Docker image. This command maps port 7860 from the container to the host machine, allowing access to the demo server. ```bash docker run -it -p 7860:7860 yuzumarker.fontdetection ``` -------------------------------- ### Resuming Training from a Checkpoint Source: https://context7.com/jeffersonqin/yuzumarker.fontdetection/llms.txt Command to resume training from a previously saved checkpoint. Specify the checkpoint path and desired devices. ```bash python train.py \ --model resnet50 \ --checkpoint lightning_logs/my_experiment/checkpoints/epoch=49-step=12500.ckpt \ --devices 0 ``` -------------------------------- ### Generate Scene Text Font Dataset Source: https://github.com/jeffersonqin/yuzumarker.fontdetection/blob/master/README.md Use this script to generate the dataset. The first parameter is the task index, and the second is the total number of partitions. This allows for parallel generation. ```bash python font_ds_generate_script.py 1 1 ``` -------------------------------- ### Initialize FontDataModule for Training Source: https://context7.com/jeffersonqin/yuzumarker.fontdetection/llms.txt Instantiate `FontDataModule` to manage multiple dataset directories for training, validation, and testing. Configure batch size, workers, shuffling, and transformations. ```python from detector.data import FontDataModule data_module = FontDataModule( train_paths=["./dataset/font_img/train", "./dataset/font_img2/train"], val_paths=["./dataset/font_img/val"], test_paths=["./dataset/font_img/test"], batch_size=64, num_workers=8, pin_memory=True, train_shuffle=True, train_transforms="v2", crop_roi_bbox=True, ) # Get training iterations per epoch for scheduler warmup calculation num_iters_per_epoch = data_module.get_train_num_iter(num_device=2) print(f"Iterations per epoch (2 GPUs): {num_iters_per_epoch}") ``` -------------------------------- ### Monitor Dataset Generation Progress Source: https://context7.com/jeffersonqin/yuzumarker.fontdetection/llms.txt Command to display per-split completion statistics for dataset generation, useful for tracking progress in parallel runs. ```bash python font_ds_stat.py # train: 412500 / 615000 (67.1%) # val: 20580 / 30750 (66.9%) # test: 123120 / 184500 (66.7%) ``` -------------------------------- ### Initialize DeepFontBaseline Model Source: https://context7.com/jeffersonqin/yuzumarker.fontdetection/llms.txt Instantiate the `DeepFontBaseline` model, a 5-layer CNN with BatchNorm, designed for font classification. It requires a 105x105 input size and outputs `FONT_COUNT` logits. ```python from detector.model import DeepFontBaseline import torch model = DeepFontBaseline() x = torch.rand(4, 3, 105, 105) out = model(x) print(out.shape) # torch.Size([4, 6150]) ``` -------------------------------- ### Parallel Dataset Generation Script Source: https://context7.com/jeffersonqin/yuzumarker.fontdetection/llms.txt Entry point for generating datasets in parallel. Splits font lists across multiple processes or machines using script_index and total_scripts arguments. Creates train/val/test splits with .jpg and .bin files. ```bash # Single process — all fonts python font_ds_generate_script.py 1 1 # 4-way parallel split (run each on a separate process/machine) python font_ds_generate_script.py 1 4 & python font_ds_generate_script.py 2 4 & python font_ds_generate_script.py 3 4 & python font_ds_generate_script.py 4 4 & # Dataset structure produced: # dataset/font_img/ # train/ font_0_img_0.jpg font_0_img_0.bin font_0_img_1.jpg ... # val/ font_0_img_0.jpg font_0_img_0.bin ... # test/ font_0_img_0.jpg font_0_img_0.bin ... ``` -------------------------------- ### Initialize FontDetectorLoss for Multi-Task Training Source: https://context7.com/jeffersonqin/yuzumarker.fontdetection/llms.txt Instantiate `FontDetectorLoss` to compute the weighted sum of losses for font classification (cross-entropy), text direction (cross-entropy), and regression targets (MSE). Configure the lambda weights for each loss component. ```python from detector.model import FontDetectorLoss import torch from detector import config loss_fn = FontDetectorLoss( lambda_font=2.0, lambda_direction=0.5, lambda_regression=1.0, font_classification_only=False, ) # y_hat: model output [B, FONT_COUNT+12] # y: label tensor [B, 12] where y[:,0]=font_idx, y[:,1]=direction_idx, y[:,2:]=regression y_hat = torch.randn(4, config.FONT_COUNT + 12) y = torch.zeros(4, 12) y[:, 0] = torch.randint(0, config.FONT_COUNT, (4,)).float() y[:, 1] = torch.randint(0, 2, (4,)).float() y[:, 2:] = torch.rand(4, 10) total_loss = loss_fn(y_hat, y) print(f"Loss: {total_loss.item():.4f}") ``` -------------------------------- ### Create FontDataset with v3 Augmentation Source: https://context7.com/jeffersonqin/yuzumarker.fontdetection/llms.txt Instantiate `FontDataset` with the 'v3' augmentation pipeline, which includes random color jitter, cropping, rotation, blur, noise, horizontal flip, and downsampling. Ensure `crop_roi_bbox` is set to `True` for v2/v3 augmentations. ```python from detector.data import FontDataset ds = FontDataset( path="./dataset/font_img/train", transforms="v3", crop_roi_bbox=True, # required for v2/v3 ) image, label = ds[0] print(image.shape) # torch.Size([3, 512, 512]) after resize ``` -------------------------------- ### Compile Batch Generation Task Scheduler Source: https://github.com/jeffersonqin/yuzumarker.fontdetection/blob/master/README.md Compile the C source file to create a task scheduler for parallel generation. Define MIN_MISSION, MAX_MISSION, and TOTAL_MISSION to partition the work. ```c gcc -D MIN_MISSION= \ -D MAX_MISSION= \ -D TOTAL_MISSION= \ batch_generate_script_linux.c \ -o .out ``` -------------------------------- ### CosineWarmupScheduler for Learning Rate Scheduling Source: https://context7.com/jeffersonqin/yuzumarker.fontdetection/llms.txt Implements a learning rate scheduler that combines linear warmup with cosine annealing. Use this to gradually increase the learning rate at the beginning of training and then smoothly decrease it. ```python from detector.model import CosineWarmupScheduler import torch optimizer = torch.optim.Adam([torch.nn.Parameter(torch.zeros(1))], lr=1e-4) scheduler = CosineWarmupScheduler(optimizer, warmup=500, max_iters=50000) # Step once per optimizer step for step in range(3): optimizer.step() scheduler.step() print(f"Step {step}: LR = {scheduler.get_last_lr()[0]:.6f}") # Step 0: LR = 0.000000 # Step 1: LR = 0.000000 # Step 2: LR = 0.000000 (still warming up) ``` -------------------------------- ### Recursively Walk Directory for Files Source: https://context7.com/jeffersonqin/yuzumarker.fontdetection/llms.txt Use `get_files(path)` to obtain a flat list of all file paths within a directory tree. This utility is employed by `load_fonts` to enumerate font files. ```python from font_dataset.utils import get_files files = get_files("./dataset/fonts/Adobe/CJK") print(len(files)) # e.g., 28 print(files[0]) # ./dataset/fonts/Adobe/CJK/SourceHanSans-Bold.ttc ``` -------------------------------- ### Clean Dataset Filenames Source: https://github.com/jeffersonqin/yuzumarker.fontdetection/blob/master/README.md Run this script after downloading CJK fonts and background images to clean up filenames before dataset generation. ```bash python dataset_filename_preprocess.py ``` -------------------------------- ### FontDetector Source: https://context7.com/jeffersonqin/yuzumarker.fontdetection/llms.txt A PyTorch Lightning training module that wraps a backbone model. It incorporates a combined loss function, accuracy metrics, a cosine warmup LR scheduler, and an Adam optimizer, supporting multi-task training or classification-only modes. ```APIDOC ## FontDetector ### Description Wraps any backbone model with a combined loss function, accuracy metrics, cosine warmup LR scheduler, and Adam optimizer. Supports both full multi-task training (font + direction + regression) and font-classification-only mode. ### Usage ```python from detector.model import FontDetector, ResNet50Regressor import torch backbone = ResNet50Regressor(pretrained=True) # Optional: compile with PyTorch 2.0 on Linux import torch, os if torch.__version__ >= "2.0" and os.name == "posix": backbone = torch.compile(backbone) detector = FontDetector( model=backbone, lambda_font=2.0, lambda_direction=0.5, lambda_regression=1.0, font_classification_only=False, lr=1e-4, betas=(0.9, 0.999), num_warmup_iters=500, num_iters=50000, num_epochs=100, ) # Forward pass x = torch.rand(2, 3, 512, 512) out = detector(x) print(out.shape) # torch.Size([2, 6162]) ``` ``` -------------------------------- ### Load Fonts with Exclusion and Caching Source: https://context7.com/jeffersonqin/yuzumarker.fontdetection/llms.txt Loads fonts, filters exclusions, and creates a font path to index dictionary. Caches the result for faster subsequent loads. ```python from font_dataset.font import load_font_with_exclusion # First call builds and caches the dict; subsequent calls load from cache font_index: dict = load_font_with_exclusion( config_path="configs/font.yml", cache_path="font_list_cache.bin" ) # font_index["./dataset/fonts/Adobe/CJK/SourceHanSans-Bold.ttc"] => 0 print(f"Number of classes: {len(font_index)}") # 6150 ``` -------------------------------- ### Render Scene Text onto Background Image Source: https://context7.com/jeffersonqin/yuzumarker.fontdetection/llms.txt Renders CJK text onto a background image with configurable text properties and returns the composite image and a FontLabel. Handles TextSizeTooSmallException by retrying. ```python from font_dataset.font import load_fonts from font_dataset.layout import generate_font_image, TextSizeTooSmallException from font_dataset.text import CorpusGeneratorManager from font_dataset.background import background_image_generator fonts, exclusion_rule = load_fonts("configs/font.yml") corpus_manager = CorpusGeneratorManager() bg_gen = background_image_generator("./dataset/pixivimages") font = next(f for f in fonts if not exclusion_rule(f)) while True: try: img_path = next(bg_gen) image, label = generate_font_image(img_path, font, corpus_manager) image.save("output_sample.jpg") print(f"Font: {label.font.path}") print(f"Text: {label.text}") print(f"Direction: {label.text_direction}") # 'ltr' or 'ttb' print(f"Text color RGB: {label.text_color}") print(f"Text size: {label.text_size}px") print(f"Stroke width: {label.stroke_width}px") print(f"Angle: {label.angle}°") print(f"BBox (left, top, w, h): {label.bbox}") break except TextSizeTooSmallException: continue # retry with a different crop/font size combination ``` -------------------------------- ### Initialize ResNet50Regressor Model Source: https://context7.com/jeffersonqin/yuzumarker.fontdetection/llms.txt Instantiate a `ResNet50Regressor` model, which is a modified ResNet architecture. The final fully-connected layer is replaced to output logits for font classes, direction, and regression targets. Set `pretrained=True` to load pre-trained weights. ```python from detector.model import ResNet50Regressor import torch model = ResNet50Regressor(pretrained=True, regression_use_tanh=False) # Input: batch of RGB images normalized [0,1] x = torch.rand(4, 3, 512, 512) out = model(x) print(out.shape) # torch.Size([4, 6162]) (6150 font + 2 direction + 10 regression) # Font class logits font_logits = out[:, :6150] # raw scores → apply softmax for probabilities direction_logits = out[:, 6150:6152] regression_targets = out[:, 6152:] # sigmoid-normalized: color, size, stroke... ``` -------------------------------- ### Check Generation Task Progress Source: https://github.com/jeffersonqin/yuzumarker.fontdetection/blob/master/README.md Use this Python script to monitor the progress of the font generation tasks. ```python python font_ds_stat.py ``` -------------------------------- ### Configure Model Input Size and Font Count Source: https://context7.com/jeffersonqin/yuzumarker.fontdetection/llms.txt Modify global configuration constants for input resolution and the number of font classes. These can be overridden at runtime before initializing datasets or models. ```python # detector/config.py — only two constants, both mutable at runtime INPUT_SIZE = 512 # spatial resolution fed to the backbone FONT_COUNT = 6150 # number of font classes (size of classification head) ``` ```python from detector import config config.INPUT_SIZE = 224 # use smaller input for faster experimentation config.FONT_COUNT = 100 # use a smaller subset for unit testing ``` -------------------------------- ### Load Font Images and Labels with PyTorch FontDataset Source: https://context7.com/jeffersonqin/yuzumarker.fontdetection/llms.txt PyTorch Dataset for loading font images and labels. Converts labels to a 12-dimensional float tensor and supports configurable augmentation pipelines. Requires dataset path and config file. ```python from detector.data import FontDataset from torch.utils.data import DataLoader # Label tensor layout (12 dims): # [0] font class index # [1] text direction (0=ltr, 1=ttb) # [2:5] text color RGB normalized [0,1] # [5] text size / image width # [6] stroke width / image width # [7:10] stroke color RGB normalized [0,1] # [10] line spacing / image width # [11] angle / 180 + 0.5 (normalized) dataset = FontDataset( path="./dataset/font_img/train", config_path="configs/font.yml", regression_use_tanh=False, # sigmoid normalization for [0,1] range transforms="v2", # augmentation: None | 'v1' | 'v2' | 'v3' crop_roi_bbox=True, # crop to text bounding box before resize preserve_aspect_ratio_by_random_crop=False, ) loader = DataLoader(dataset, batch_size=32, shuffle=True, num_workers=4) images, labels = next(iter(loader)) print(images.shape) # torch.Size([32, 3, 512, 512]) print(labels.shape) # torch.Size([32, 12]) print("Font class index sample:", labels[:4, 0].long()) ``` -------------------------------- ### Infinite Random Background Image Generator Source: https://context7.com/jeffersonqin/yuzumarker.fontdetection/llms.txt Generates an infinite stream of random image file paths from a specified directory. Useful for continuous dataset generation. ```python from font_dataset.background import background_image_generator gen = background_image_generator("./dataset/pixivimages") for _ in range(5): img_path = next(gen) print(img_path) # ./dataset/pixivimages/img_0042.jpg # ./dataset/pixivimages/img_1337.jpg # ... ``` -------------------------------- ### Project Citation Source: https://github.com/jeffersonqin/yuzumarker.fontdetection/blob/master/README.md This is the recommended citation format for the YuzuMarker.FontDetection project, including author, title, year, and URL. ```bibtex @misc{qin2023yuzumarkerfont, author = {Haoyun Qin}, title = {YuzuMarker.FontDetection}, year = {2023}, url = {https://github.com/JeffersonQin/YuzuMarker.FontDetection}, note = {GitHub repository} } ``` -------------------------------- ### generate_font_image Source: https://context7.com/jeffersonqin/yuzumarker.fontdetection/llms.txt Renders scene text onto a background image, returning the composite image and a FontLabel object with rendering parameters. ```APIDOC ## generate_font_image(img_path, font, corpus_manager) ### Description Opens a background image, randomly crops a region, selects text direction/length/color/stroke/rotation according to configurable ratios, renders the CJK text with PIL, and pastes it onto the crop. Returns the composite image and a `FontLabel` describing every rendering parameter. ### Parameters - **img_path** (string) - Path to the background image. - **font** (DSFont object) - The font object to use for rendering. - **corpus_manager** (CorpusGeneratorManager object) - Manager for text generation. ### Returns - **image** (PIL Image object) - The composite image with rendered text. - **label** (FontLabel object) - An object containing metadata about the rendered text. ``` -------------------------------- ### Generate Multi-language Text Corpora with CorpusGeneratorManager Source: https://context7.com/jeffersonqin/yuzumarker.fontdetection/llms.txt Manages per-language corpus generation for Japanese, Simplified Chinese, Traditional Chinese, and Korean. Configure generation parameters like line and character counts. Requires DSFont object and CJK language key. ```python from font_dataset.text import CorpusGeneratorManager, CorpusGenerationConfig from font_dataset.font import DSFont manager = CorpusGeneratorManager() # Supported language keys: 'ja', 'zh-Hans', 'zh-Hant', 'ko' # (zh-Hant-HK and zh-Hant-TW fall back to zh-Hant generator) config = CorpusGenerationConfig( min_num_line=1, max_num_line=3, min_num_char_per_line=5, max_num_char_per_line=15, ) mock_font = DSFont("./dataset/fonts/Adobe/CJK/SourceHanSans-Bold.ttc", "CJK") text_ja = manager.generate(config, mock_font, CJK_language="ja") text_zh = manager.generate(config, mock_font, CJK_language="zh-Hans") text_ko = manager.generate(config, mock_font, CJK_language="ko") print(text_ja) # Japanese lyrics excerpt, possibly mixed with English print(text_zh) # Simplified Chinese characters, possibly mixed with English print(text_ko) # Korean syllable block sequence ``` -------------------------------- ### Training for Font Classification Only Source: https://context7.com/jeffersonqin/yuzumarker.fontdetection/llms.txt Command to train a model focusing solely on font classification, disabling direction and regression heads. ```bash python train.py --model resnet18 --font-classification-only ``` -------------------------------- ### Define Font Dataset Specification in YAML Source: https://context7.com/jeffersonqin/yuzumarker.fontdetection/llms.txt Specify dataset root, per-language font directories, and filtering rules using a YAML configuration file. Supports exclusion lists and language-specific path mappings. ```yaml dataset: path: ./dataset/fonts exclusion: - ./Arphic(文鼎)/简体/文鼎习字体.TTF # unqualified font # ... hundreds of manually excluded fonts specs: - path: - ./Adobe/CJK rule: | lambda x: \ x.split('/')[-1].split('\')[-1].startswith('SourceHanSans-') \ or x.split('/')[-1].split('\')[-1].startswith('SourceHanSerif-') language: CJK # maps to ja/zh-Hans/zh-Hant/ko at generation time - path: - ./Arphic(文鼎)/简体 - ./Founder Type(方正)/简体 # ... language: zh-Hans # Simplified Chinese - path: - ./DynaFont(华康)/日文 - ./Morisawa(森泽)/日文/MorisawaAOTF/日文 # ... language: ja # Japanese ``` -------------------------------- ### Load Font List and Exclusion Rules Source: https://context7.com/jeffersonqin/yuzumarker.fontdetection/llms.txt Loads fonts from a YAML config, filters excluded fonts, and prints the total and valid font counts. Demonstrates accessing DSFont attributes. ```python from font_dataset.font import load_fonts, DSFont font_list, exclusion_rule = load_fonts("configs/font.yml") # Filter out excluded fonts valid_fonts = [f for f in font_list if not exclusion_rule(f)] print(f"Total fonts: {len(font_list)}, Valid: {len(valid_fonts)}") # DSFont attributes for font in valid_fonts[:3]: print(f"Path: {font.path}, Language: {font.language}") # Path: ./dataset/fonts/Adobe/CJK/SourceHanSans-Bold.ttc, Language: CJK # Path: ./dataset/fonts/Adobe/CJK/SourceHanSerif-Bold.ttc, Language: CJK ``` -------------------------------- ### Font Recognition Inference with PIL Image Source: https://context7.com/jeffersonqin/yuzumarker.fontdetection/llms.txt Python code for performing font recognition on a PIL image. Loads a model from Hugging Face, preprocesses the image, and outputs top font predictions. ```python from PIL import Image from torchvision import transforms import torch from detector.model import FontDetector, ResNet50Regressor from detector import config from font_dataset.font import load_fonts from huggingface_hub import hf_hub_download import pickle # Load model from Hugging Face ckpt_path = hf_hub_download("gyrojeff/YuzuMarker.FontDetection", "model.ckpt") backbone = ResNet50Regressor() detector = FontDetector.load_from_checkpoint( ckpt_path, model=backbone, lambda_font=1, lambda_direction=1, lambda_regression=1, font_classification_only=False, lr=1, betas=(1,1), num_warmup_iters=1, num_iters=int(1e9), num_epochs=int(1e9), ) detector.eval() transform = transforms.Compose([ transforms.Resize((512, 512)), transforms.ToTensor(), ]) font_list, exclusion_rule = load_fonts() font_list = sorted( [f for f in font_list if not exclusion_rule(f)], key=lambda x: x.path ) image = Image.open("sample_text.jpg").convert("RGB") tensor = transform(image).unsqueeze(0) with torch.no_grad(): output = detector(tensor) probs = output[0, :config.FONT_COUNT].softmax(dim=0) top9_indices = torch.topk(probs, 9).indices for i, idx in enumerate(top9_indices): print(f"Rank {i+1}: {font_list[idx].path} ({probs[idx]*100:.2f}%)") # Rank 1: ./dataset/fonts/Adobe/CJK/SourceHanSans-Bold.ttc (32.14%) # Rank 2: ./dataset/fonts/Google(谷歌)/CJK/NotoSansCJK-Bold.ttc (18.92%) # ... ``` -------------------------------- ### load_font_with_exclusion Source: https://context7.com/jeffersonqin/yuzumarker.fontdetection/llms.txt Loads fonts, filters exclusions, and creates an index dictionary mapping font paths to integer class labels, with caching. ```APIDOC ## load_font_with_exclusion(config_path, cache_path) ### Description Wraps `load_fonts`, filters exclusions, and builds a `{font_path: index}` dict used by the dataset loader to map font paths to integer class labels. Results are pickled for fast reuse. ### Parameters - **config_path** (string) - Path to the font configuration YAML file. - **cache_path** (string) - Path to the cache file for storing the font index. ### Returns - **font_index** (dict) - A dictionary mapping font file paths to their corresponding integer class labels. ``` -------------------------------- ### load_fonts Source: https://context7.com/jeffersonqin/yuzumarker.fontdetection/llms.txt Loads a list of fonts and their exclusion rules from a YAML configuration file. ```APIDOC ## load_fonts(config_path) ### Description Reads `configs/font.yml`, walks the specified font directories, applies optional per-spec filter lambdas, and returns a sorted list of `DSFont` objects and a callable `exclusion_rule` that returns `True` for fonts on the manual exclusion list. ### Parameters - **config_path** (string) - Path to the font configuration YAML file. ### Returns - **font_list** (list of DSFont objects) - A sorted list of available font objects. - **exclusion_rule** (callable) - A function that takes a DSFont object and returns `True` if the font should be excluded. ``` -------------------------------- ### background_image_generator Source: https://context7.com/jeffersonqin/yuzumarker.fontdetection/llms.txt An infinite generator that yields random image file paths from a specified directory. ```APIDOC ## background_image_generator(path) ### Description Yields random image file paths from the specified directory in an infinite loop. Used by the dataset generation script to continuously supply background photographs. ### Parameters - **path** (string) - The directory containing background images. ### Yields - **img_path** (string) - A path to a randomly selected background image. ``` -------------------------------- ### FontDataModule Source: https://context7.com/jeffersonqin/yuzumarker.fontdetection/llms.txt Wraps multiple FontDataset instances into a PyTorch Lightning DataModule, supporting concatenation of datasets from multiple directories. It handles data loading, batching, and augmentation strategies. ```APIDOC ## FontDataModule ### Description Wraps multiple `FontDataset` instances (train/val/test) into a `LightningDataModule`, supporting multiple dataset directories that are automatically concatenated. ### Usage ```python from detector.data import FontDataModule data_module = FontDataModule( train_paths=["./dataset/font_img/train", "./dataset/font_img2/train"], val_paths=["./dataset/font_img/val"], test_paths=["./dataset/font_img/test"], batch_size=64, num_workers=8, pin_memory=True, train_shuffle=True, train_transforms="v2", crop_roi_bbox=True, ) # Get training iterations per epoch for scheduler warmup calculation num_iters_per_epoch = data_module.get_train_num_iter(num_device=2) print(f"Iterations per epoch (2 GPUs): {num_iters_per_epoch}") ``` ### Augmentation Strategies - `None`: Resize to INPUT_SIZE × INPUT_SIZE, ToTensor - `v1`: RandomColorJitter, RandomCrop (10%), then resize - `v2`: RandomColorJitter, RandomCrop (54%), RandomRotate (±15°), GaussianBlur, RandomNoise; requires `crop_roi_bbox=True` - `v3`: All of v2 + RandomHorizontalFlip + RandomDownSample (up to 2×) ``` -------------------------------- ### Detect and Remove Corrupted Dataset Files Source: https://github.com/jeffersonqin/yuzumarker.fontdetection/blob/master/README.md Run this script after dataset generation to identify and remove any corrupted image or label files. You may need to re-run the generation script to fill the gaps. ```bash python font_ds_detect_broken.py ``` -------------------------------- ### FontDetectorLoss Source: https://context7.com/jeffersonqin/yuzumarker.fontdetection/llms.txt Computes the combined multi-task loss, which is a weighted sum of cross-entropy for font classes, cross-entropy for text direction, and MSE for regression targets. ```APIDOC ## FontDetectorLoss ### Description Computes weighted sum of cross-entropy for font classes, cross-entropy for text direction, and MSE for regression targets (color, size, stroke, spacing, angle). ### Usage ```python from detector.model import FontDetectorLoss import torch from detector import config loss_fn = FontDetectorLoss( lambda_font=2.0, lambda_direction=0.5, lambda_regression=1.0, font_classification_only=False, ) # y_hat: model output [B, FONT_COUNT+12] # y: label tensor [B, 12] where y[:,0]=font_idx, y[:,1]=direction_idx, y[:,2:]=regression y_hat = torch.randn(4, config.FONT_COUNT + 12) y = torch.zeros(4, 12) y[:, 0] = torch.randint(0, config.FONT_COUNT, (4,)).float() y[:, 1] = torch.randint(0, 2, (4,)).float() y[:, 2:] = torch.rand(4, 10) total_loss = loss_fn(y_hat, y) print(f"Loss: {total_loss.item():.4f}") ``` ``` -------------------------------- ### Check Font Character Support with char_in_font Source: https://context7.com/jeffersonqin/yuzumarker.fontdetection/llms.txt Verifies if a given Unicode character is supported by a font using fontTools. Essential for avoiding rendering errors by ensuring glyphs exist before generation. Takes character and font path as input. ```python from font_dataset.helper import char_in_font font_path = "./dataset/fonts/Adobe/CJK/SourceHanSans-Bold.ttc" print(char_in_font("一", font_path)) # True — common CJK ideograph print(char_in_font("A", font_path)) # True — Latin supported print(char_in_font("🦆", font_path)) # False — emoji likely absent ``` -------------------------------- ### DeepFontBaseline Source: https://context7.com/jeffersonqin/yuzumarker.fontdetection/llms.txt Implements the DeepFont CNN architecture. This model is suitable for font-classification-only tasks and requires a specific input size. ```APIDOC ## DeepFontBaseline ### Description Implements the DeepFont architecture from "DeepFont: Identify Your Font from An Image" (ECCV 2015). Uses a 5-layer CNN with BatchNorm and two fully-connected layers, outputting `FONT_COUNT` logits. Requires 105×105 input and font-classification-only mode. ### Usage ```python from detector.model import DeepFontBaseline import torch model = DeepFontBaseline() x = torch.rand(4, 3, 105, 105) out = model(x) print(out.shape) # torch.Size([4, 6150]) ``` ``` -------------------------------- ### ResNetRegressor Models Source: https://context7.com/jeffersonqin/yuzumarker.fontdetection/llms.txt These models are modified torchvision ResNets designed for font detection. They replace the final fully-connected layer to output font class logits, direction logits, and regression targets. ```APIDOC ## ResNet18Regressor / ResNet34Regressor / ResNet50Regressor / ResNet101Regressor ### Description Modifies a standard torchvision ResNet by replacing the final fully-connected layer with one that outputs `FONT_COUNT + 12` values: logits for 6,150 font classes followed by 2 direction logits and 10 regression targets. ### Usage ```python from detector.model import ResNet50Regressor import torch model = ResNet50Regressor(pretrained=True, regression_use_tanh=False) # Input: batch of RGB images normalized [0,1] x = torch.rand(4, 3, 512, 512) out = model(x) print(out.shape) # torch.Size([4, 6162]) (6150 font + 2 direction + 10 regression) # Font class logits font_logits = out[:, :6150] # raw scores → apply softmax for probabilities direction_logits = out[:, 6150:6152] regression_targets = out[:, 6152:] # sigmoid-normalized: color, size, stroke... ``` ``` -------------------------------- ### Detect and Remove Corrupted Dataset Entries Source: https://context7.com/jeffersonqin/yuzumarker.fontdetection/llms.txt Scans dataset image/label pairs for corruption and removes bad entries. Intended to be run before re-generating missing data. Operates on train, val, and test splits. ```bash python font_ds_detect_broken.py # Scans ./dataset/font_img/{train,val,test}/ # Removes corrupt image+label pairs # Then regenerate missing entries: python font_ds_generate_script.py 1 1 ``` -------------------------------- ### Sanitize Font Directory Filenames Source: https://context7.com/jeffersonqin/yuzumarker.fontdetection/llms.txt Renames font files in-place to remove or replace OS-problematic characters. Run this script once before dataset generation to ensure compatibility. ```bash python dataset_filename_preprocess.py # Processes ./dataset/fonts/ recursively # Renames files with problematic characters in-place ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.