zgrafic commited on
Commit
d015dae
·
verified ·
1 Parent(s): 23d45d7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +29 -9
app.py CHANGED
@@ -589,7 +589,7 @@ def analyze_for_vectorization(pil_img):
589
  return params, is_flat_illustration, n_colors
590
 
591
 
592
- def detect_primitive_circles(pil_img):
593
  """Detecta círculos grandes y bien definidos (por ejemplo, un fondo
594
  circular detrás de un logo) con la transformada de Hough — no hace
595
  falta ningún modelo de IA para esto, es un problema ya resuelto por
@@ -605,6 +605,18 @@ def detect_primitive_circles(pil_img):
605
  minRadius=int(min(h, w) * 0.15), maxRadius=int(min(h, w) * 0.6),
606
  )
607
 
 
 
 
 
 
 
 
 
 
 
 
 
608
  detected = []
609
  if circles is not None:
610
  for x, y, r in circles[0]:
@@ -613,9 +625,13 @@ def detect_primitive_circles(pil_img):
613
  sample_x = int(min(w - 1, max(0, x)))
614
  sample_y = int(min(h - 1, max(0, y - r * 0.85)))
615
  color = arr[sample_y, sample_x]
 
 
 
 
616
  detected.append({
617
  "cx": float(x), "cy": float(y), "r": float(r),
618
- "color": "#{:02x}{:02x}{:02x}".format(*color),
619
  })
620
  return detected
621
 
@@ -710,12 +726,14 @@ def consolidate_svg_colors(svg_content, max_colors=10):
710
  """VTracer puede volver a generar variaciones de color al trazar
711
  los bordes, aunque la imagen de entrada ya viniera con pocos
712
  colores. Esto agarra el SVG ya generado y fuerza que use como
713
- máximo max_colors colores de verdad, agrupando los parecidos."""
 
 
714
  try:
715
  ET.register_namespace("", "http://www.w3.org/2000/svg")
716
  root = ET.fromstring(svg_content)
717
  except ET.ParseError:
718
- return svg_content
719
 
720
  paths = root.findall(".//{http://www.w3.org/2000/svg}path") or root.findall(".//path")
721
 
@@ -730,7 +748,8 @@ def consolidate_svg_colors(svg_content, max_colors=10):
730
  continue
731
 
732
  if len(colors) < max_colors:
733
- return svg_content
 
734
 
735
  pixels = np.array(colors, dtype=np.float32)
736
  k = min(max_colors, len(np.unique(pixels.astype(np.uint8), axis=0)))
@@ -748,7 +767,8 @@ def consolidate_svg_colors(svg_content, max_colors=10):
748
  path.set("fill", "#{:02x}{:02x}{:02x}".format(*center))
749
  i += 1
750
 
751
- return ET.tostring(root, encoding="unicode")
 
752
 
753
 
754
  @app.post("/vectorize")
@@ -783,9 +803,9 @@ async def vectorize(file: UploadFile = File(...)):
783
  with open(out_file.name, "r") as f:
784
  svg_content = f.read()
785
 
786
- svg_content = consolidate_svg_colors(svg_content, max_colors=10)
787
 
788
- detected_circles = detect_primitive_circles(vtracer_input)
789
  svg_content = inject_primitive_shapes(svg_content, detected_circles)
790
 
791
  except Exception as e:
@@ -798,4 +818,4 @@ async def vectorize(file: UploadFile = File(...)):
798
  "X-Vectorize-Colors-Detected": str(n_colors),
799
  "X-Vectorize-Type": "ilustracion" if is_flat_illustration else "foto-detallada",
800
  },
801
- )
 
589
  return params, is_flat_illustration, n_colors
590
 
591
 
592
+ def detect_primitive_circles(pil_img, palette=None):
593
  """Detecta círculos grandes y bien definidos (por ejemplo, un fondo
594
  circular detrás de un logo) con la transformada de Hough — no hace
595
  falta ningún modelo de IA para esto, es un problema ya resuelto por
 
605
  minRadius=int(min(h, w) * 0.15), maxRadius=int(min(h, w) * 0.6),
606
  )
607
 
608
+ def closest_palette_color(hex_color, palette):
609
+ if not palette:
610
+ return hex_color
611
+ target = tuple(int(hex_color.lstrip("#")[i:i + 2], 16) for i in (0, 2, 4))
612
+ best, best_dist = hex_color, None
613
+ for p in palette:
614
+ c = tuple(int(p.lstrip("#")[i:i + 2], 16) for i in (0, 2, 4))
615
+ dist = sum((a - b) ** 2 for a, b in zip(target, c))
616
+ if best_dist is None or dist < best_dist:
617
+ best, best_dist = p, dist
618
+ return best
619
+
620
  detected = []
621
  if circles is not None:
622
  for x, y, r in circles[0]:
 
625
  sample_x = int(min(w - 1, max(0, x)))
626
  sample_y = int(min(h - 1, max(0, y - r * 0.85)))
627
  color = arr[sample_y, sample_x]
628
+ hex_color = "#{:02x}{:02x}{:02x}".format(*color)
629
+ # Lo ajustamos al color más parecido de la paleta final del
630
+ # SVG, para que coincida exacto con lo que quedó ahí.
631
+ hex_color = closest_palette_color(hex_color, palette)
632
  detected.append({
633
  "cx": float(x), "cy": float(y), "r": float(r),
634
+ "color": hex_color,
635
  })
636
  return detected
637
 
 
726
  """VTracer puede volver a generar variaciones de color al trazar
727
  los bordes, aunque la imagen de entrada ya viniera con pocos
728
  colores. Esto agarra el SVG ya generado y fuerza que use como
729
+ máximo max_colors colores de verdad, agrupando los parecidos.
730
+ Devuelve también esa paleta final, para poder buscar formas
731
+ geométricas (círculos, etc.) usando esos mismos colores exactos."""
732
  try:
733
  ET.register_namespace("", "http://www.w3.org/2000/svg")
734
  root = ET.fromstring(svg_content)
735
  except ET.ParseError:
736
+ return svg_content, []
737
 
738
  paths = root.findall(".//{http://www.w3.org/2000/svg}path") or root.findall(".//path")
739
 
 
748
  continue
749
 
750
  if len(colors) < max_colors:
751
+ palette = ["#{:02x}{:02x}{:02x}".format(*c) for c in {tuple(c) for c in colors}]
752
+ return svg_content, palette
753
 
754
  pixels = np.array(colors, dtype=np.float32)
755
  k = min(max_colors, len(np.unique(pixels.astype(np.uint8), axis=0)))
 
767
  path.set("fill", "#{:02x}{:02x}{:02x}".format(*center))
768
  i += 1
769
 
770
+ palette = ["#{:02x}{:02x}{:02x}".format(*c) for c in centers]
771
+ return ET.tostring(root, encoding="unicode"), palette
772
 
773
 
774
  @app.post("/vectorize")
 
803
  with open(out_file.name, "r") as f:
804
  svg_content = f.read()
805
 
806
+ svg_content, final_palette = consolidate_svg_colors(svg_content, max_colors=10)
807
 
808
+ detected_circles = detect_primitive_circles(vtracer_input, palette=final_palette)
809
  svg_content = inject_primitive_shapes(svg_content, detected_circles)
810
 
811
  except Exception as e:
 
818
  "X-Vectorize-Colors-Detected": str(n_colors),
819
  "X-Vectorize-Type": "ilustracion" if is_flat_illustration else "foto-detallada",
820
  },
821
+ )