#!/usr/bin/env python3 import numpy as np import cv2 import argparse import os def compute_sdf(img, scale_factor): # Convert to binary image if not already _, binary = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY) # Compute distance transform for both foreground and background dist_transform_fg = cv2.distanceTransform(binary, cv2.DIST_L2, 5) dist_transform_bg = cv2.distanceTransform(255 - binary, cv2.DIST_L2, 5) # Combine the distance fields and scale by factor sdf = (dist_transform_fg - dist_transform_bg) / scale_factor # Normalize values to [0, 255] range sdf_min = np.min(sdf) sdf_max = np.max(sdf) sdf = ((sdf - sdf_min) * 255 / (sdf_max - sdf_min)) return sdf.astype(np.uint8) def main(): parser = argparse.ArgumentParser(description='Generate SDF from black and white image') parser.add_argument('input_images', nargs='+', help='Path to input image(s)') parser.add_argument('--scale', type=float, default=1.0, help='Scale factor for distance (in texels)') args = parser.parse_args() # Process each input image for input_path in args.input_images: # Get input and output paths filename, ext = os.path.splitext(input_path) output_path = f"{filename}-sdf{ext}" # Read input image img = cv2.imread(input_path, cv2.IMREAD_GRAYSCALE) if img is None: print(f"Error: Could not read image {input_path}") continue # Compute SDF with scale factor sdf = compute_sdf(img, args.scale) # Save result cv2.imwrite(output_path, sdf) print(f"SDF generated and saved to {output_path}") if __name__ == "__main__": main()