Spaces:
Build error
Build error
| import cv2 | |
| import numpy as np | |
| import potrace | |
| import svgpathtools | |
| import ezdxf | |
| from ezdxf.addons.dxf2svg import make_svg | |
| import trimesh | |
| import io | |
| import base64 | |
| class SculptorEngine: | |
| def __init__(self): | |
| pass | |
| def preprocess_for_cnc(self, image): | |
| """ | |
| Sculptok style cleanup: Remove noise, sharpen edges, high contrast. | |
| """ | |
| # Grayscale | |
| gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) | |
| # Bilateral Filter: Noise remove karta hai but edges preserve rakhta hai | |
| # (Ye manual tracing jaisa clean look deta hai) | |
| clean = cv2.bilateralFilter(gray, 9, 75, 75) | |
| # Adaptive Threshold: Har jagah alag lighting ke hisab se lines nikalta hai | |
| thresh = cv2.adaptiveThreshold( | |
| clean, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, | |
| cv2.THRESH_BINARY, 11, 2 | |
| ) | |
| # Invert colors (Potrace ko black bg pe white lines chahiye) | |
| inverted = cv2.bitwise_not(thresh) | |
| return inverted | |
| def generate_vector(self, image_path): | |
| """ | |
| Potrace engine use karke High-Resolution SVG banata hai. | |
| """ | |
| img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE) | |
| processed = self.preprocess_for_cnc(cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)) | |
| # Potrace Bitmap object | |
| bmp = potrace.Bitmap(processed) | |
| path = bmp.trace() | |
| # SVG Header | |
| w, h = processed.shape[1], processed.shape[0] | |
| svg_header = f'<svg width="{w}" height="{h}" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 {w} {h}">' | |
| svg_paths = "" | |
| # Potrace se path data nikalna | |
| for curve in path: | |
| for segment in curve: | |
| # Start point | |
| start_node = segment.start_point | |
| d = f"M {start_node.x} {start_node.y} " | |
| # Cubic Bezier curves | |
| for c in segment: | |
| d += f"C {c.c1.x} {c.c1.y}, {c.c2.x} {c.c2.y}, {c.end_point.x} {c.end_point.y} " | |
| d += "Z " # Close path | |
| svg_paths += f'<path d="{d}" fill="none" stroke="black" stroke-width="1" vector-effect="non-scaling-stroke"/>' | |
| svg_output = svg_header + svg_paths + "</svg>" | |
| # SVG file save | |
| svg_file = "/tmp/result.svg" | |
| with open(svg_file, "w") as f: | |
| f.write(svg_output) | |
| return svg_file | |
| def generate_dxf(self, svg_file_path): | |
| """ | |
| SVG paths ko DXF (CAD format) mein convert karta hai. | |
| """ | |
| paths, _ = svgpathtools.svg2paths(svg_file_path) | |
| doc = ezdxf.new('R2010') | |
| msp = doc.modelspace() | |
| for path in paths: | |
| for segment in path: | |
| if isinstance(segment, svgpathtools.Line): | |
| start = segment.start.real, segment.start.imag | |
| end = segment.end.real, segment.end.imag | |
| msp.add_line(start, end) | |
| elif isinstance(segment, svgpathtools.CubicBezier): | |
| control1 = segment.control1.real, segment.control1.imag | |
| control2 = segment.control2.real, segment.control2.imag | |
| end = segment.end.real, segment.end.imag | |
| start = segment.start.real, segment.start.imag | |
| msp.add_spline( | |
| control_points=[(start[0], start[1]), (control1[0], control1[1]), (control2[0], control2[1]), (end[0], end[1])], | |
| degree=3 | |
| ) | |
| dxf_file = "/tmp/result.dxf" | |
| doc.saveas(dxf_file) | |
| return dxf_file | |
| def generate_3d_relief(self, image, model): | |
| """ | |
| Image ko 3D Depth Map mein convert karta hai (AI wala kaam). | |
| """ | |
| # AI Model se Depth Prediction | |
| depth_map = model(image) | |
| # Normalize depth map | |
| depth_map = np.array(depth_map) | |
| depth_map = (depth_map - depth_map.min()) / (depth_map.max() - depth_map.min()) | |
| # Mesh Generation (Basic logic for demo, production mein Marching Cubes use hota) | |
| # Simple plane mesh with displacement | |
| h, w = depth_map.shape | |
| vertices = [] | |
| faces = [] | |
| # Scale down for performance in demo | |
| scale = 0.1 | |
| for y in range(h): | |
| for x in range(w): | |
| z = depth_map[y, x] * 10 # Height multiplier | |
| vertices.append([x * scale, y * scale, z]) | |
| # Create faces (Grid mesh) | |
| for y in range(h - 1): | |
| for x in range(w - 1): | |
| v1 = y * w + x | |
| v2 = y * w + (x + 1) | |
| v3 = (y + 1) * w + x | |
| v4 = (y + 1) * w + (x + 1) | |
| faces.append([v1, v2, v3]) | |
| faces.append([v2, v4, v3]) | |
| mesh = trimesh.Trimesh(vertices=vertices, faces=faces) | |
| stl_file = "/tmp/result.stl" | |
| mesh.export(stl_file) | |
| return stl_file |