So I am trying to write a code to covert img to svg with high accuracy so I am writing code if anyone could help that would be great
error:
libpng warning: pHYs: CRC error
Traceback (most recent call last):
File "C:UsersABDULLAHDesktoptestmain.py", line 144, in <module>
convert_image_to_svg('Input.png', 'output.svg')
File "C:UsersABDULLAHDesktoptestmain.py", line 135, in convert_image_to_svg
polygons = process_single_image(image_path)
File "C:UsersABDULLAHDesktoptestmain.py", line 127, in process_single_image
polygons = convert_contours_to_polygons(contours)
File "C:UsersABDULLAHDesktoptestmain.py", line 87, in convert_contours_to_polygons
polygon = merge_polygons(MultiPolygon(), 0, True)
File "C:UsersABDULLAHDesktoptestmain.py", line 71, in merge_polygons
new_poly = Polygon(contour)
File "C:UsersABDULLAHDesktoptest.venvlibsite-packagesshapelygeometrypolygon.py", line 230, in __new__
shell = LinearRing(shell)
File "C:UsersABDULLAHDesktoptest.venvlibsite-packagesshapelygeometrypolygon.py", line 104, in __new__
geom = shapely.linearrings(coordinates)
File "C:UsersABDULLAHDesktoptest.venvlibsite-packagesshapelydecorators.py", line 77, in wrapped
return func(*args, **kwargs)
File "C:UsersABDULLAHDesktoptest.venvlibsite-packagesshapelycreation.py", line 171, in linearrings
return lib.linearrings(coords, out=out, **kwargs)
ValueError: The ordinate (last) dimension should be 2 or 3, got 237
My code:
import cv2
import numpy as np
import svgwrite
import cc3d
from shapely.geometry import Polygon, MultiPolygon
def load_image(image_path):
"""
Loads an image and returns it in grayscale.
"""
try:
return cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
except Exception as e:
print(f"Error loading image {image_path}: {e}")
return None
def apply_thresholding(img):
"""
Applies adaptive thresholding to the image.
"""
if img is None:
return None
return cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)
def detect_edges(img):
"""
Detects edges in the image using Canny edge detection with a Gaussian kernel.
"""
if img is None:
return None
kernel_size = 5
kernel = cv2.getGaussianKernel(kernel_size, 0)
kernel = kernel * kernel.T # Make it a 2D kernel
blurred = cv2.filter2D(img, -1, kernel)
return cv2.Canny(blurred, 50, 150)
def find_contours(img):
"""
Finds contours in the image using cc3d for connected component analysis.
"""
if img is None:
return None, None
labels = cc3d.connected_components(img, out_dtype=np.uint64, connectivity=4)
contours = []
for blob_id, blob_shape in cc3d.each(labels, binary=True, in_place=True):
contours.append(blob_shape)
return contours, None
def convert_contours_to_polygons(contours, hierarchy=None):
"""
Converts OpenCV contours to Shapely polygons.
Parameters:
- contours: List of contours found by OpenCV.
- hierarchy: Optional. Hierarchy of contours.
Returns:
- A list of Shapely polygons representing the contours.
"""
polygons = []
if hierarchy is None:
hierarchy = np.array([])
# Function to merge individual contours into one MultiPolygon
def merge_polygons(polygon: MultiPolygon, idx: int, add: bool) -> MultiPolygon:
contour = np.squeeze(contours[idx])
if len(contour) > 2:
# Ensure the contour is a list of (x, y) tuples
if contour.ndim == 1:
contour = contour.reshape(-1, 2)
new_poly = Polygon(contour)
if not new_poly.is_valid:
new_poly = new_poly.buffer(0)
if add:
polygon = polygon.union(new_poly)
else:
polygon = polygon.difference(new_poly)
child_idx = hierarchy[idx][2]
if child_idx >= 0:
polygon = merge_polygons(polygon, child_idx, not add)
next_idx = hierarchy[idx][0]
if next_idx >= 0:
polygon = merge_polygons(polygon, next_idx, add)
return polygon
# Start merging from the first contour
polygon = merge_polygons(MultiPolygon(), 0, True)
polygons.append(polygon)
return polygons
def draw_polygons_to_svg(polygons, output_path):
"""
Creates an SVG file with the polygons using svgwrite.
"""
if polygons is None:
print("No polygons found. Check the input image.")
return
try:
# Create an SVG drawing
dwg = svgwrite.Drawing(output_path, profile='tiny')
# Iterate over each polygon and draw it
for polygon in polygons:
# Convert the polygon to a list of (x, y) tuples
points = [(int(point[0][0]), int(point[0][1])) for point in polygon]
# Add the polygon to the SVG drawing
dwg.add(dwg.polygon(points, fill='none', stroke='black'))
# Save the SVG file
dwg.save()
except Exception as e:
print(f"Error saving SVG file {output_path}: {e}")
def process_single_image(image_path):
"""
Processes a single image and returns the polygons.
"""
img = load_image(image_path)
if img is None:
return None
thresh = apply_thresholding(img)
edges = detect_edges(thresh)
contours, _ = find_contours(edges)
polygons = convert_contours_to_polygons(contours)
return polygons
def convert_image_to_svg(image_path, output_path):
"""
Converts an image to SVG format using optimized contour detection.
"""
# Simplified for a single image
polygons = process_single_image(image_path)
if polygons:
draw_polygons_to_svg(polygons, output_path)
else:
print("No polygons found. Check the input image.")
if __name__ == '__main__':
convert_image_to_svg('Input.png', 'output.svg')
read these for reference:
https://github.com/ValentinFrancois/pixels2svg/blob/main/pixels2svg/main.py
https://github.com/LizhengMathAi/pixel2SVG/blob/main/pixel2svg.py
for solving error I read:
https://www.reddit.com/r/computervision/comments/b0e4ql/converting_contours_to_polygons/
How to convert NumPy arrays obtained from cv2.findContours to Shapely polygons?
Abdullah Mirza is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.