zgrafic commited on
Commit
1fee61f
·
verified ·
1 Parent(s): 106f568

Upload 4 files

Browse files
Files changed (4) hide show
  1. Dockerfile +1 -1
  2. app.py +0 -113
  3. bot.py +1 -1
  4. requirements.txt +0 -1
Dockerfile CHANGED
@@ -21,7 +21,7 @@ FROM python:3.10-slim
21
 
22
  WORKDIR /app
23
 
24
- RUN apt-get update && apt-get install -y --no-install-recommends libgl1 libglib2.0-0 wget git \
25
  && rm -rf /var/lib/apt/lists/*
26
 
27
  COPY --from=tgbotapi-builder /usr/local/bin/telegram-bot-api /usr/local/bin/telegram-bot-api
 
21
 
22
  WORKDIR /app
23
 
24
+ RUN apt-get update && apt-get install -y --no-install-recommends libgl1 libglib2.0-0 wget \
25
  && rm -rf /var/lib/apt/lists/*
26
 
27
  COPY --from=tgbotapi-builder /usr/local/bin/telegram-bot-api /usr/local/bin/telegram-bot-api
app.py CHANGED
@@ -9,7 +9,6 @@ import easyocr
9
  import torch
10
  import requests
11
  import vtracer
12
- import pydiffvg
13
  from PIL import Image
14
  from fastapi import FastAPI, File, UploadFile, HTTPException, Form
15
  from fastapi.middleware.cors import CORSMiddleware
@@ -21,8 +20,6 @@ from basicsr.archs.rrdbnet_arch import RRDBNet
21
  from realesrgan import RealESRGANer
22
  from gfpgan import GFPGANer
23
 
24
- pydiffvg.set_use_gpu(False)
25
-
26
  app = FastAPI(title="ZGrafic API")
27
 
28
  # Permite que tu página en GitHub Pages (u otro origen) llame a este servidor.
@@ -711,113 +708,3 @@ async def vectorize(file: UploadFile = File(...)):
711
  "X-Vectorize-Type": "ilustracion" if is_flat_illustration else "foto-detallada",
712
  },
713
  )
714
-
715
-
716
- # ---- /vectorize-ai (experimental: optimización tipo LIVE con pydiffvg) ----
717
-
718
- def random_path(num_segments, canvas_w, canvas_h, seed_point=None):
719
- """Una forma cerrada de curvas Bézier, arrancando en un punto al
720
- azar (o uno dado) — la optimización después la va a ir moviendo y
721
- deformando hasta que se parezca a una región real de la imagen."""
722
- num_control_points = torch.zeros(num_segments, dtype=torch.int32) + 2
723
- points = []
724
- p0 = seed_point if seed_point is not None else torch.rand(2) * torch.tensor([canvas_w, canvas_h])
725
- points.append(p0)
726
- radius = max(canvas_w, canvas_h) * 0.08
727
- for _ in range(num_segments):
728
- p1 = p0 + (torch.rand(2) - 0.5) * radius
729
- p2 = p1 + (torch.rand(2) - 0.5) * radius
730
- p3 = p2 + (torch.rand(2) - 0.5) * radius
731
- points += [p1, p2, p3]
732
- p0 = p3
733
- points_t = torch.stack(points)
734
- return pydiffvg.Path(
735
- num_control_points=num_control_points,
736
- points=points_t,
737
- is_closed=True,
738
- stroke_width=torch.tensor(0.0),
739
- )
740
-
741
-
742
- def vectorize_with_live(pil_img, num_paths=80, num_iter=250):
743
- """Versión simplificada del enfoque de LIVE: arranca con formas al
744
- azar y las va ajustando con descenso de gradiente hasta que, todas
745
- juntas, se parezcan a la imagen original."""
746
- canvas_w, canvas_h = pil_img.size
747
- target = torch.from_numpy(np.array(pil_img).astype(np.float32) / 255.0)
748
- if target.shape[2] == 3:
749
- alpha = torch.ones((canvas_h, canvas_w, 1))
750
- target = torch.cat([target, alpha], dim=2)
751
-
752
- # Colores de partida: tomamos colores reales de la imagen (en vez de
753
- # colores al azar), para que arranque más cerca del resultado final.
754
- small = pil_img.copy()
755
- small.thumbnail((64, 64))
756
- palette_source = np.array(small).reshape(-1, 3)
757
-
758
- shapes, shape_groups = [], []
759
- for i in range(num_paths):
760
- seed_point = torch.rand(2) * torch.tensor([canvas_w, canvas_h])
761
- path = random_path(num_segments=3, canvas_w=canvas_w, canvas_h=canvas_h, seed_point=seed_point)
762
- shapes.append(path)
763
-
764
- color_rgb = palette_source[np.random.randint(0, len(palette_source))] / 255.0
765
- fill_color = torch.tensor([color_rgb[0], color_rgb[1], color_rgb[2], 1.0], requires_grad=True)
766
- group = pydiffvg.ShapeGroup(
767
- shape_ids=torch.tensor([i]),
768
- fill_color=fill_color,
769
- )
770
- shape_groups.append(group)
771
-
772
- points_vars = [s.points.requires_grad_() for s in shapes]
773
- color_vars = [g.fill_color.requires_grad_() for g in shape_groups]
774
-
775
- points_optim = torch.optim.Adam(points_vars, lr=1.0)
776
- color_optim = torch.optim.Adam(color_vars, lr=0.02)
777
-
778
- for _ in range(num_iter):
779
- points_optim.zero_grad()
780
- color_optim.zero_grad()
781
-
782
- scene_args = pydiffvg.RenderFunction.serialize_scene(canvas_w, canvas_h, shapes, shape_groups)
783
- img = pydiffvg.RenderFunction.apply(canvas_w, canvas_h, 2, 2, 0, None, *scene_args)
784
-
785
- loss = (img - target).pow(2).mean()
786
- loss.backward()
787
-
788
- points_optim.step()
789
- color_optim.step()
790
-
791
- for g in shape_groups:
792
- g.fill_color.data.clamp_(0.0, 1.0)
793
-
794
- svg_path = tempfile.NamedTemporaryFile(suffix=".svg", delete=False).name
795
- pydiffvg.save_svg(svg_path, canvas_w, canvas_h, shapes, shape_groups)
796
- with open(svg_path, "r") as f:
797
- return f.read()
798
-
799
-
800
- @app.post("/vectorize-ai")
801
- async def vectorize_ai(file: UploadFile = File(...)):
802
- if not file.content_type or not file.content_type.startswith("image/"):
803
- raise HTTPException(status_code=400, detail="El archivo debe ser una imagen.")
804
-
805
- input_bytes = await file.read()
806
-
807
- try:
808
- pil_img = Image.open(io.BytesIO(input_bytes)).convert("RGB")
809
-
810
- # Achicamos bastante: esto optimiza pixel por pixel en CPU, una
811
- # imagen grande sería demasiado lenta.
812
- MAX_SIDE = 200
813
- w, h = pil_img.size
814
- if max(w, h) > MAX_SIDE:
815
- ratio = MAX_SIDE / max(w, h)
816
- pil_img = pil_img.resize((int(w * ratio), int(h * ratio)), Image.LANCZOS)
817
-
818
- svg_content = vectorize_with_live(pil_img)
819
-
820
- except Exception as e:
821
- raise HTTPException(status_code=500, detail=f"No se pudo vectorizar la imagen: {e}")
822
-
823
- return Response(content=svg_content, media_type="image/svg+xml")
 
9
  import torch
10
  import requests
11
  import vtracer
 
12
  from PIL import Image
13
  from fastapi import FastAPI, File, UploadFile, HTTPException, Form
14
  from fastapi.middleware.cors import CORSMiddleware
 
20
  from realesrgan import RealESRGANer
21
  from gfpgan import GFPGANer
22
 
 
 
23
  app = FastAPI(title="ZGrafic API")
24
 
25
  # Permite que tu página en GitHub Pages (u otro origen) llame a este servidor.
 
708
  "X-Vectorize-Type": "ilustracion" if is_flat_illustration else "foto-detallada",
709
  },
710
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bot.py CHANGED
@@ -27,7 +27,7 @@ BOT_TOKEN = os.environ.get("TELEGRAM_BOT_TOKEN", "")
27
  REMOVE_BG_URL = "https://zgrafic-remove-bg-api.hf.space/remove-bg"
28
  ENHANCE_URL = "https://zgrafic-remove-bg-api.hf.space/enhance"
29
  VECTORIZE_URL = "https://zgrafic-remove-bg-api.hf.space/vectorize"
30
- VECTORIZE_AI_URL = "https://zgrafic-remove-bg-api.hf.space/vectorize-ai"
31
 
32
  FREE_USES_PER_DAY = 10
33
  STARS_PER_IMAGE = 10
 
27
  REMOVE_BG_URL = "https://zgrafic-remove-bg-api.hf.space/remove-bg"
28
  ENHANCE_URL = "https://zgrafic-remove-bg-api.hf.space/enhance"
29
  VECTORIZE_URL = "https://zgrafic-remove-bg-api.hf.space/vectorize"
30
+ VECTORIZE_AI_URL = "https://zgrafic-enhance-photo-api.hf.space/vectorize-ai"
31
 
32
  FREE_USES_PER_DAY = 10
33
  STARS_PER_IMAGE = 10
requirements.txt CHANGED
@@ -18,4 +18,3 @@ realesrgan==0.3.0
18
  gfpgan==1.3.8
19
  firebase-admin==6.5.0
20
  vtracer==0.6.15
21
- git+https://github.com/ANaka/easydiffvg.git
 
18
  gfpgan==1.3.8
19
  firebase-admin==6.5.0
20
  vtracer==0.6.15