Highlights:
- minimum mode: add min_true_black switch (default True = unchanged v1.6.1 behaviour).
True : true-black gate + CC denoise (best for black line work).
False : no gate, keeps colored regions, distance-transform thinning
(best for colorful posters).
- skeleton mode: replace hue-specific green-block smoothing with
saturation-based _color_zones; no hue or side-of-image assumptions.
- Move all comments, docstrings and messages to English.
- Remove built-in default paths; examples/demo.py now requires args.
- README: document both minimum variants, resolution guidance, parameters.
- tests: 18 cases covering I/O, both modes, both minimum variants.
94 lines
2.9 KiB
Python
94 lines
2.9 KiB
Python
"""
|
|
lineartization usage examples
|
|
=============================
|
|
Demonstrates the call styles: one-liner / custom config / raw ndarray.
|
|
|
|
Usage:
|
|
python demo.py <input_image> <output_dir>
|
|
|
|
There are no built-in default paths: both arguments are required.
|
|
|
|
Tip: extraction quality depends on the source resolution -- the higher the
|
|
resolution, the cleaner the result. For low-resolution inputs use the
|
|
``minimum`` method.
|
|
"""
|
|
import os
|
|
import sys
|
|
|
|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
|
|
from lineartization import (
|
|
LineArtConfig,
|
|
extract_lineart,
|
|
extract_lineart_file,
|
|
load_image,
|
|
save_image,
|
|
)
|
|
|
|
|
|
def demo_simple(src, out_dir):
|
|
"""Example 1: one-liner (skeleton mode)."""
|
|
print("=== Example 1: one-liner ===")
|
|
extract_lineart_file(src, os.path.join(out_dir, "simple.png"))
|
|
print(" wrote simple.png")
|
|
|
|
|
|
def demo_config(src, out_dir):
|
|
"""Example 2: custom config (minimum mode + protected region)."""
|
|
print("=== Example 2: custom config ===")
|
|
cfg = LineArtConfig(
|
|
method="minimum",
|
|
denoise="strong",
|
|
line_width=2, # uniform 2 px stroke
|
|
protect_areas=[(120, 220, 940, 1050)], # keep this region intact
|
|
)
|
|
extract_lineart_file(src, os.path.join(out_dir, "configured.png"),
|
|
cfg, verbose=True)
|
|
print(" wrote configured.png")
|
|
|
|
|
|
def demo_two_variants(src, out_dir):
|
|
"""Example 3: the two minimum variants (true-black on / off)."""
|
|
print("=== Example 3: minimum variants ===")
|
|
for flag, name in ((True, "true-black"), (False, "no-true-black")):
|
|
cfg = LineArtConfig(method="minimum", min_true_black=flag)
|
|
extract_lineart_file(src, os.path.join(out_dir, f"minimum_{name}.png"), cfg)
|
|
print(f" wrote minimum_{name}.png")
|
|
|
|
|
|
def demo_ndarray(src, out_dir):
|
|
"""Example 4: work directly on an ndarray (embeddable in your pipeline)."""
|
|
print("=== Example 4: ndarray processing ===")
|
|
img = load_image(src)
|
|
print(f" input size: {img.shape[1]}x{img.shape[0]}")
|
|
lineart = extract_lineart(img, LineArtConfig(line_width=2))
|
|
black_ratio = (lineart < 128).mean() * 100
|
|
print(f" black ratio: {black_ratio:.2f}%")
|
|
save_image(os.path.join(out_dir, "ndarray.png"), lineart)
|
|
print(" wrote ndarray.png")
|
|
|
|
|
|
def main(argv):
|
|
if len(argv) != 3:
|
|
print(__doc__.strip())
|
|
print("\nError: expected exactly 2 arguments "
|
|
"(<input_image> <output_dir>).")
|
|
return 2
|
|
|
|
src, out_dir = argv[1], argv[2]
|
|
if not os.path.exists(src):
|
|
print(f"Error: input image not found: {src}")
|
|
return 2
|
|
os.makedirs(out_dir, exist_ok=True)
|
|
|
|
demo_simple(src, out_dir)
|
|
demo_config(src, out_dir)
|
|
demo_two_variants(src, out_dir)
|
|
demo_ndarray(src, out_dir)
|
|
print("\nAll examples finished.")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main(sys.argv))
|