Skip to content

Zerrant2/SeamlessFix

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SeamlessFix

Language: English | Русский

SeamlessFix is a Python pipeline for converting material photos into tileable textures. The project validates every generated image automatically, writes a 3x3 tiled preview, and can optionally generate a compact PBR material set from the selected seamless albedo texture.

The acceptance set is the four PNG images in Test_Image.

Final Results

The final output directory is results. Each material contains:

  • seamless_algorithm.png - selected seamless albedo texture;
  • tile_3x3.png - 3x3 preview for visual seam inspection;
  • metrics.json - validator report and selected candidate metadata;
  • pbr/ - optional PBR maps generated with the --pbr flag.
Input Selected method Passed Border max Low-frequency seam Artifact score Detail ratio
84953235_01.png delight-0.55-best-tonal-crop yes 0.0000 0.0000 0.1260 0.7949
85346059.png edge-cut yes 0.1062 0.0000 0.1118 0.9964
89436101_02.png delight-0.75-structured-grid-crop-narrow yes 0.0000 2.7482 0.1607 1.3111
89438339.png edge-equalized-narrow-detail yes 1.5677 0.0000 0.0416 1.1618

Output Previews

Material Seamless texture 3x3 tiled preview
84953235_01
85346059
89436101_02
89438339

Chosen Approach

The primary method is a local algorithmic candidate search with automatic validation. For each input image the generator creates several candidate seamless textures, evaluates them with the local validator, and selects the best passing candidate. If no candidate passes, it falls back to the least bad candidate by rank.

This method was chosen as the main path because it is deterministic, runs offline, preserves the source material identity, and is not blocked by API quota or model behavior. Image-generation APIs were tested as optional repair branches, but their outputs often changed the material too much or failed strict tileability checks.

The selected algorithmic candidates are built from these techniques:

  • narrow opposite-edge equalization;
  • low-error edge cuts inside a small overlap band;
  • Moisan-style periodic-plus-smooth decomposition;
  • tonal crop search that minimizes broad color bands near tile boundaries;
  • Retinex-style de-lighting for albedo-like correction;
  • structured grid crop for orthogonal plank/tile textures;
  • high-frequency edge detail restoration to reduce soft blend zones.

The final selection is not a single fixed operation for every input. It is a ranked candidate system. This is important because the four test images have different failure modes: diagonal parquet, plank floors, broad lighting gradients, and visible local seams.

Methods Considered

Simple edge equalization

The earliest baseline directly averaged opposite borders and feathered the edit into the image. It makes pixel borders tileable quickly, but wider bands can create visible soft strips in the 3x3 preview. It remains useful as a fallback and as a building block.

Periodic-plus-smooth

The project implements a Moisan-style periodic component. This can remove hard boundary discontinuities while preserving much of the texture. On structured wood textures it can introduce visible repeated cross/band artifacts, so the ranker penalizes periodic candidates when the structured-texture artifact score is high.

Tonal crop search

The crop search tries many candidate crops and prefers borders whose low-frequency tones match internal bands. It helps when the source image has broad lighting or color drift near the edges. The downside is that cropping can reduce source coverage and can cut through logical board patterns if geometry is not also considered.

De-lighting

The Retinex-style de-lighting pass estimates broad illumination from luminance and divides it out while preserving average color. It improved albedo consistency for lighter wood textures, especially 89436101_02.png. It is intentionally conservative because aggressive de-lighting can shift color identity.

Structured grid crop

For orthogonal plank or tile textures, the generator detects projected line positions and crops to a repeatable grid span. This is the best local strategy for preserving board logic. It is still a simple projection-based method, so it does not fully solve arbitrary parquet or herringbone reconstruction.

API image repair

Two API branches were implemented and tested:

  • OpenAI image edit with a planning step;
  • OpenRouter image generation with a reference image.

Both branches are optional. The local validator remains the first gate, and an optional API judge can review rejected API candidates. Live OpenAI testing reached the API but was blocked by platform quota/billing. OpenRouter returned images, but the tested candidates were rejected by the validator because they changed detail or failed tileability. For this reason the API path is not the main acceptance path.

Strengths And Weaknesses

Strengths:

  • fully local algorithmic path;
  • deterministic command-line runs with seed control;
  • automatic validation on border mismatch, gradient mismatch, seam artifacts, low-frequency color seams, source distance, detail preservation, and structured boundary metrics;
  • preserves the original material better than tested image-generation API outputs;
  • writes visual 3x3 previews for human inspection;
  • optional PBR generation from the final selected seamless texture.

Weaknesses:

  • structured geometry is still heuristic, not a full board/plank synthesis engine;
  • some accepted outputs still show soft blend zones when the source image has difficult lighting or incomplete repeat structure;
  • diagonal parquet/herringbone textures need a stronger 2D phase-aware validator;
  • PBR maps are derived from a single albedo image and should be treated as generated approximations, not scanned ground truth;
  • API branches depend on external services, quota, and model behavior.

PBR Output

PBR generation is enabled with --pbr. It uses the bundled DeepBump ONNX models to infer normal maps, then derives height, curvature, roughness, and ambient occlusion maps from the selected seamless albedo.

For each material:

  • pbr/albedo.png
  • pbr/normal.png
  • pbr/height.png
  • pbr/curvature.png
  • pbr/roughness.png
  • pbr/ambient_occlusion.png
  • pbr/<map>_tile_3x3.png

Example PBR previews:

Material Normal 3x3 Height 3x3 Roughness 3x3
84953235_01
85346059
89436101_02
89438339

DeepBump is GPL-3.0 licensed. The bundled runtime license is kept at seamlessfix/deepbump_backend/LICENSE.DeepBump-GPL-3.0.

Repository Structure

seamlessfix/
  cli.py                  Command-line interface
  generator.py            Local algorithmic candidate generation and selection
  metrics.py              Tileability validator and candidate ranking
  delight.py              Conservative de-lighting / albedo approximation
  pbr.py                  DeepBump-backed PBR map generation
  openai_branch.py        Optional OpenAI repair branch
  openrouter_branch.py    Optional OpenRouter repair branch
  api_judge.py            Optional multimodal judge for API candidates
  deepbump_backend/       Bundled DeepBump runtime and ONNX models
tests/                    Regression and integration tests
Test_Image/               Acceptance input images
results/                  Final generated textures, previews, metrics, and PBR maps

Installation

Create and activate a virtual environment, then install dependencies:

py -m venv .venv
.\.venv\Scripts\python.exe -m pip install -r requirements.txt

The project was verified with Python 3.14 on Windows.

Usage

Common Commands

Validate existing images:

.\.venv\Scripts\python.exe -m seamlessfix validate --input Test_Image --output results\validation

Generate seamless textures only:

.\.venv\Scripts\python.exe -m seamlessfix generate --input Test_Image --output results --method algorithm --preview 3 --max-candidates 8 --seed 7

Generate seamless textures and PBR maps:

.\.venv\Scripts\python.exe -m seamlessfix generate --input Test_Image --output results --method algorithm --preview 3 --max-candidates 8 --seed 7 --pbr

Optional API branches:

.\.venv\Scripts\python.exe -m seamlessfix generate --input Test_Image --output results --method openai --api-judge
.\.venv\Scripts\python.exe -m seamlessfix generate --input Test_Image --output results --method openrouter --api-judge

API generation receives the full selected algorithmic texture as a reference. By default --api-edit-scope full allows the API model to redraw the whole texture if that produces a better seamless material. Use --api-edit-scope border for the older conservative behavior where OpenAI edits only tile-boundary bands and OpenRouter is prompted to preserve the interior as much as possible.

Final output selection is controlled by --output-selection:

  • validated - default behavior. API output is used only if it passes the validator or API judge;
  • algorithm - always build tile_3x3.png and PBR maps from the algorithmic candidate;
  • api - force the best generated API image for tile_3x3.png and PBR maps, even if the validator rejected it.

Force an OpenRouter result as the final texture:

.\.venv\Scripts\python.exe -m seamlessfix generate --input "E:\SeamlessFix\Test_Image\84953235_01.png" --output results --method openrouter --preview 3 --output-selection api --pbr

Conservative API edge repair:

.\.venv\Scripts\python.exe -m seamlessfix generate --input "E:\SeamlessFix\Test_Image\84953235_01.png" --output results --method openrouter --preview 3 --api-edit-scope border --output-selection validated

The forced API texture is also saved as seamless_openrouter_forced.png or seamless_openai_forced.png.

API keys are loaded from .env, which is ignored by git. Use .env.example as the template.

CLI Flags

General flags:

Flag Values / default What it does When to use
--input required Path to one image file or a directory with images. Supported extensions include PNG, JPG, WebP, BMP, TIFF. Always required for validate and generate.
--output required Directory where result folders and reports are written. Usually results.
--preview default 3 Repeat count for the tiled preview. 3 writes tile_3x3.png. Keep 3 for the assignment report.
--seed default 7 Seed for random crop candidates. Use the same seed for reproducible algorithmic results.

Generation method flags:

Flag Values / default What it does Notes
--method auto, algorithm, openai, openrouter; default auto Chooses which generation branches run. algorithm is local and reliable. openai and openrouter still run the algorithm first as a fallback/reference.
--max-candidates default 8 Controls random algorithmic crop candidates. Deterministic candidates are always included. Higher values may improve search but cost more time.
--output-selection / --select-output validated, algorithm, api; default validated Chooses what image becomes final tile_3x3.png and PBR source. This is the key switch when API output looks better than the validator thinks.

--output-selection behavior:

Value Final output source Behavior
validated Best accepted API result if accepted, otherwise algorithm Default safe mode. API output must pass the validator or API judge.
algorithm Algorithmic candidate Strictly ignores API output for final tile_3x3.png and PBR, even if API succeeds.
api Best generated API image Forces API output even when rejected by the validator. If the API produced no decodable image, the command fails instead of silently falling back.

API control flags:

Flag Values / default What it does Notes
--api-edit-scope full, border; default full Controls how much freedom the API prompt/edit has. full lets the model redraw the whole texture. border keeps the older conservative seam-repair behavior.
--api-judge off by default Lets an OpenAI vision model approve rejected API candidates. Costs an extra OpenAI API call and needs OpenAI quota.
--api-judge-model env/default Model used by the visual judge. Optional.
--api-judge-threshold env/default Minimum judge confidence for override. Higher is stricter.

OpenAI-specific flags:

Flag Default What it does
--openai-model gpt-image-2 Image edit model.
--openai-analysis-model gpt-5.4-mini Planning model that analyzes the source and current tiled preview before image edit.
--openai-variants 2 Number of image edit variants to request, clamped to 1..4.

OpenRouter-specific flags:

Flag Default What it does
--openrouter-model env OPENROUTER_MODEL / sourceful/riverflow-v2.5-pro:free OpenRouter image model. Can also use a comma-separated model list through OPENROUTER_MODELS.
--openrouter-variants 1 Number of variants per selected model, clamped to 1..4.
--openrouter-image-size 1K Value passed to OpenRouter image_config.image_size.
--openrouter-reference-max-dim 1024 Max dimension of the reference image sent to OpenRouter.
--openrouter-timeout 180 Seconds to wait for each OpenRouter request.

PBR flags:

Flag Values / default What it does
--pbr off by default Generates pbr/albedo, normal, height, curvature, roughness, ambient_occlusion, plus tiled previews.
--pbr-overlap SMALL, MEDIUM, LARGE; default LARGE DeepBump color-to-normal overlap. Larger overlap is slower but smoother.
--pbr-curvature-blur SMALLEST..LARGEST; default MEDIUM Blur radius for DeepBump normals-to-curvature.
--pbr-verbose off by default Prints DeepBump tile inference progress.

Typical Recipes

Local algorithm only:

.\.venv\Scripts\python.exe -m seamlessfix generate --input "E:\SeamlessFix\Test_Image\84953235_01.png" --output results --method algorithm --preview 3 --pbr

Try OpenRouter, but keep the algorithm unless API passes validation:

.\.venv\Scripts\python.exe -m seamlessfix generate --input "E:\SeamlessFix\Test_Image\84953235_01.png" --output results --method openrouter --preview 3 --output-selection validated --pbr

Force OpenRouter output even if the validator rejects it:

.\.venv\Scripts\python.exe -m seamlessfix generate --input "E:\SeamlessFix\Test_Image\84953235_01.png" --output results --method openrouter --preview 3 --api-edit-scope full --output-selection api --pbr

Use conservative API seam repair:

.\.venv\Scripts\python.exe -m seamlessfix generate --input "E:\SeamlessFix\Test_Image\84953235_01.png" --output results --method openrouter --preview 3 --api-edit-scope border --output-selection validated

Force OpenAI output:

.\.venv\Scripts\python.exe -m seamlessfix generate --input "E:\SeamlessFix\Test_Image\84953235_01.png" --output results --method openai --preview 3 --api-edit-scope full --output-selection api --pbr

Run on a whole folder:

.\.venv\Scripts\python.exe -m seamlessfix generate --input "E:\SeamlessFix\Test_Image" --output results --method algorithm --preview 3 --pbr

Verification

Final test run:

.\.venv\Scripts\python.exe -m pytest -q
34 passed in 166.62s

Final generation run:

.\.venv\Scripts\python.exe -m seamlessfix generate --input Test_Image --output results --method algorithm --preview 3 --max-candidates 8 --seed 7 --pbr
ALG 84953235_01.png: delight-0.55-best-tonal-crop, pass=True, border=0.0
PBR 84953235_01.png: generated 6 maps in results\84953235_01\pbr
ALG 85346059.png: edge-cut, pass=True, border=0.1062
PBR 85346059.png: generated 6 maps in results\85346059\pbr
ALG 89436101_02.png: delight-0.75-structured-grid-crop-narrow, pass=True, border=0.0
PBR 89436101_02.png: generated 6 maps in results\89436101_02\pbr
ALG 89438339.png: edge-equalized-narrow-detail, pass=True, border=1.5677
PBR 89438339.png: generated 6 maps in results\89438339\pbr

Notes For GitHub Upload

The final result set is intentionally kept in the repository because the task asks to include output seamless textures, 3x3 previews, and PBR maps. Diagnostic experiments and API smoke outputs are not needed for the report and should not be committed.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages