from image to SVG
Erstellt am: 31. Juli 2025
Erstellt am: 31. Juli 2025
pythonfrom PIL import Image import matplotlib.pyplot as plt img = Image.open('/mnt/data/image.png') print(img.size) plt.imshow(img) plt.axis('off') (-0.5, 979.5, 979.5, -0.5)
python# Load image grayscale import cv2, numpy as np img = cv2.imread('/mnt/data/image.png', cv2.IMREAD_GRAYSCALE) # threshold to binary _, thresh = cv2.threshold(img, 200, 255, cv2.THRESH_BINARY_INV) # invert to white shapes as 255 # find contours contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) len(contours) 1
python# draw contours to visualize vis = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR) cv2.drawContours(vis, contours, -1, (0,0,255), 2) plt.imshow(cv2.cvtColor(vis, cv2.COLOR_BGR2RGB)); plt.axis('off') (-0.5, 979.5, 979.5, -0.5)
python# outer contour outer = contours[0] (x, y), radius = cv2.minEnclosingCircle(outer) print(x, y, radius)
python# Create binary mask for white shapes inside circle rows, cols = img.shape binary = np.zeros_like(img) for i in range(rows): for j in range(cols): # pixel is white if bright enough in original if img[i,j] > 200: # check distance to center less than radius - maybe inside if (i - y)**2 + (j - x)**2 <= (radius-10)**2: binary[i,j] = 255 # find contours contours2, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) len(contours2) 3
pythonvis2 = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR) cv2.drawContours(vis2, contours2, -1, (255,0,0), 2) plt.imshow(cv2.cvtColor(vis2, cv2.COLOR_BGR2RGB)); plt.axis('off') (-0.5, 979.5, 979.5, -0.5)
python# get scaling factor to viewBox 1000 maybe svg_paths = [] for cnt in contours2: # approximate path pts = cnt.squeeze() # convert to path string path = "M {} {}".format(pts[0][0], pts[0][1]) for x,y in pts[1:]: path += " L {} {}".format(x, y) path += " Z" svg_paths.append(path) len(svg_paths) 3
pythonview_w, view_h = img.size svg_content = f'''<?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg xmlns="http://www.w3.org/2000/svg" width="{view_w}" height="{view_h}" viewBox="0 0 {view_w} {view_h}"> <circle cx="{x}" cy="{y}" r="{radius}" fill="#000000"/> ''' # add heart and hands as white for path in svg_paths: svg_content += f' <path d="{path}" fill="#ffffff"/>\n' svg_content += '</svg>' # save with open('/mnt/data/heart_hands.svg', 'w') as f: f.write(svg_content) print(svg_content[:500])
pythonview_w = img.shape[1] view_h = img.shape[0] svg_content = f'''<?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg xmlns="http://www.w3.org/2000/svg" width="{view_w}" height="{view_h}" viewBox="0 0 {view_w} {view_h}"> <circle cx="{x}" cy="{y}" r="{radius}" fill="#000000"/> ''' for path in svg_paths: svg_content += f' <path d="{path}" fill="#ffffff"/>\n' svg_content += '</svg>' with open('/mnt/data/heart_hands.svg', 'w') as f: f.write(svg_content) print(svg_content[:400])
pythonprint(x,y)
pythonprint(radius)
python(x2,y2),r2 = cv2.minEnclosingCircle(outer) print(x2,y2,r2)
pythonprint('x', x, 'y', y)
python# recompute center of outer again and assign new variables cx, cy (cx,cy),_ = cv2.minEnclosingCircle(outer) print(cx, cy)
pythonsvg_content = f'''<?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg xmlns="http://www.w3.org/2000/svg" width="{view_w}" height="{view_h}" viewBox="0 0 {view_w} {view_h}"> <circle cx="{x}" cy="{y}" r="{radius}" fill="#000000"/> ''' for path in svg_paths: svg_content += f' <path d="{path}" fill="#ffffff"/>\n' svg_content += '</svg>' with open('/mnt/data/heart_hands.svg', 'w') as f: f.write(svg_content) len(svg_content) 37078
Here’s the vector version of your icon, converted directly from the PNG you shared:
It preserves the solid black circle plus the white heart-and-hands cut-out as clean path geometry, so you can scale or recolor it without losing quality. Let me know if you’d like any tweaks—stroke added, colors changed, simplified paths, etc.