import cv2
import numpy as np
from PIL import Image
import subprocess
import os
import sys
def vectorize_png(
input_png,
output_svg,
blur_strength=15,
threshold=180
):
if not os.path.exists(input_png):
raise FileNotFoundError(input_png)
# Load image
img = cv2.imread(input_png, cv2.IMREAD_COLOR)
# Convert to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Edge-preserving smoothing (strong but clean)
smooth = cv2.bilateralFilter(
gray,
d=blur_strength,
sigmaColor=75,
sigmaSpace=75
)
# Optional extra smoothing
smooth = cv2.GaussianBlur(smooth, (7, 7), 0)
# High-contrast threshold
_, bw = cv2.threshold(
smooth,
threshold,
255,
cv2.THRESH_BINARY
)
# Invert for Potrace (expects black foreground)
bw = 255 - bw
# Save temporary PBM
temp_pbm = "temp.pbm"
Image.fromarray(bw).save(temp_pbm)
# Run Potrace
subprocess.run([
"potrace",
temp_pbm,
"-s", # SVG output
"-o", output_svg,
"--turdsize", "2",
"--alphamax", "1.0",
"--opttolerance", "0.2"
], check=True)
os.remove(temp_pbm)
print(f"Vectorized SVG saved to: {output_svg}")
if __name__ == "__main__":
if len(sys.argv) != 3:
print("Usage: python vectorize.py input.png output.svg")
sys.exit(1)
vectorize_png(sys.argv[1], sys.argv[2])