TS447 commited on
Commit
ead23ff
Β·
verified Β·
1 Parent(s): 509d126

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +64 -66
app.py CHANGED
@@ -1,66 +1,75 @@
1
  import gradio as gr
2
  import cv2
3
  import numpy as np
4
- from PIL import Image
5
  import subprocess
6
 
7
- # --- 1. The Core Logic (CNC Brain) ---
8
- def process_vector(image, mode, thickness, noise_level, smooth_factor):
9
  if image is None: return None, None
10
 
11
  # A. Pre-processing (Convert to Grayscale)
12
- # Color se hamein matlab nahi, hamein sirf Light/Dark difference chahiye
13
  img_np = np.array(image.convert("RGB"))
14
  gray = cv2.cvtColor(img_np, cv2.COLOR_RGB2GRAY)
15
 
16
- # B. TRACING MODES
17
- if mode == "Standard (High Contrast)":
18
- # Simple Logic: Agar photo saaf hai (Black & White)
19
- _, binary = cv2.threshold(gray, 128, 255, cv2.THRESH_BINARY_INV)
20
-
21
- elif mode == "Scanner Mode (Colored/Light Lights)":
22
- # ADVANCED: Adaptive Thresholding
23
- # Ye local areas dekhta hai. Colored lights ya shadows ko ignore karta hai.
24
- # Block Size 11, C 2 (Standard scanner settings)
25
- binary = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
26
- cv2.THRESH_BINARY_INV, 15, 4)
27
 
28
- elif mode == "Silhouette (Dark Object)":
29
- # Agar Jali kaali hai aur peeche light hai
30
- _, binary = cv2.threshold(gray, 100, 255, cv2.THRESH_BINARY)
 
 
 
 
 
31
 
32
- # C. CLEANING & THICKNESS (Thickness Slider Logic)
33
- # Morphological Operations - Jali ko mota/patla karne ke liye
34
  kernel = np.ones((3,3), np.uint8)
35
-
36
- # Noise Removal (Chote daane hatana)
37
- if noise_level > 0:
38
- # Opening: Removes small noise (white dots)
39
- binary = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel, iterations=int(noise_level))
40
 
41
- # Thickness (Erosion/Dilation)
 
 
 
 
 
 
 
42
  if thickness > 0:
43
- # Dilate: Makes white lines thicker (Jali moti hogi)
44
  binary = cv2.dilate(binary, kernel, iterations=int(thickness))
45
  elif thickness < 0:
46
- # Erode: Makes lines thinner
47
  binary = cv2.erode(binary, kernel, iterations=abs(int(thickness)))
48
 
49
  # D. Save Temp BMP for Potrace
50
  temp_bmp = "temp_trace.bmp"
51
- cv2.imwrite(temp_bmp, binary)
 
 
52
 
53
  # E. Vectorize using Potrace
54
  output_svg = "ts_vector_design.svg"
55
 
56
  # Potrace Commands
 
 
57
  cmd = [
58
  "potrace", temp_bmp,
59
- "-s", # Output SVG
60
- "-o", output_svg,
61
- "-t", "2", # Remove Speckles
62
- "-a", str(smooth_factor), # Corner Smoothness
63
- "--opaque" # Solid Fill
64
  ]
65
 
66
  try:
@@ -69,57 +78,46 @@ def process_vector(image, mode, thickness, noise_level, smooth_factor):
69
  print(f"Error: {e}")
70
  return None, None
71
 
72
- # Return SVG and the B&W Preview
73
- return output_svg, Image.fromarray(binary)
74
 
75
  # --- 2. Interface Design ---
76
  custom_css = """
77
  @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600;900&display=swap');
78
  body, .gradio-container { font-family: 'Inter', sans-serif !important; background: #1e1e2e !important; color: white !important; }
79
-
80
- #main_card {
81
- background: rgba(255, 255, 255, 0.05);
82
- border: 1px solid rgba(255, 255, 255, 0.1);
83
- border-radius: 20px;
84
- padding: 30px;
85
- }
86
- .primary-btn {
87
- background: linear-gradient(90deg, #FF9966, #FF5E62) !important;
88
- color: white !important;
89
- border: none !important;
90
- font-size: 1.2rem !important;
91
- font-weight: bold !important;
92
- }
93
  """
94
 
95
  with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as app:
96
  with gr.Column(elem_id="main_card"):
97
- gr.Markdown("# πŸ“ TS VECTOR PRO", elem_id="logo_text")
98
- gr.Markdown("### Advanced CNC Tracer (Color/Light Proof)")
 
 
99
 
100
  with gr.Row():
101
  with gr.Column():
102
- inp_img = gr.Image(type="pil", label="Upload Jali Image", height=300)
103
-
104
- # --- NEW CONTROLS ---
105
- gr.Markdown("### πŸŽ›οΈ Trace Settings")
106
 
 
107
  mode_drp = gr.Dropdown(
108
- ["Scanner Mode (Colored/Light Lights)", "Standard (High Contrast)", "Silhouette (Dark Object)"],
109
- value="Scanner Mode (Colored/Light Lights)",
110
- label="1. Tracing Mode (Best for Colored Lights)"
111
  )
112
 
113
- thick_sld = gr.Slider(-2, 5, value=0, step=1, label="2. Thickness (Mota/Patla)")
114
- noise_sld = gr.Slider(0, 3, value=1, step=1, label="3. Clean Noise (Daane Hataye)")
115
- smooth_sld = gr.Slider(0, 1.4, value=1.0, label="4. Smoothing")
116
 
117
- btn = gr.Button("πŸš€ CONVERT TO VECTOR", variant="primary", elem_classes=["primary-btn"])
118
 
119
  with gr.Column():
120
- preview_img = gr.Image(label="AI Vision (B&W)", interactive=False)
121
- out_file = gr.File(label="Download SVG")
122
 
123
- btn.click(process_vector, inputs=[inp_img, mode_drp, thick_sld, noise_sld, smooth_sld], outputs=[out_file, preview_img])
124
 
125
  app.launch()
 
1
  import gradio as gr
2
  import cv2
3
  import numpy as np
4
+ from PIL import Image, ImageOps
5
  import subprocess
6
 
7
+ # --- 1. The Core Logic (CNC Brain V3 - Final Polish) ---
8
+ def process_vector(image, mode, fill_gaps, thickness, smooth_factor):
9
  if image is None: return None, None
10
 
11
  # A. Pre-processing (Convert to Grayscale)
 
12
  img_np = np.array(image.convert("RGB"))
13
  gray = cv2.cvtColor(img_np, cv2.COLOR_RGB2GRAY)
14
 
15
+ # --- THE NEW MAGIC STEP: Smart Smoothing ---
16
+ # Bilateral Filter: Ye noise hatata hai par edges ko sharp rakhta hai.
17
+ # Real photos ke liye ye sabse zaroori hai.
18
+ gray_blurred = cv2.bilateralFilter(gray, 9, 75, 75)
19
+
20
+ # B. TRACING MODES (Improved)
21
+ if mode == "1. Adaptive Scanner (Best for most photos)":
22
+ # Ye lighting variations ko handle karta hai.
23
+ # Block size 11, C 2 (Standard settings for clean scan)
24
+ binary = cv2.adaptiveThreshold(gray_blurred, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
25
+ cv2.THRESH_BINARY_INV, 11, 2)
26
 
27
+ elif mode == "2. Silhouette / Backlit (Dark Jali, Bright Back)":
28
+ # Agar jali kaali dikh rahi hai aur peeche light hai.
29
+ # Simple hard threshold. Value 100 se neeche sab black.
30
+ _, binary = cv2.threshold(gray_blurred, 100, 255, cv2.THRESH_BINARY_INV)
31
+
32
+ elif mode == "3. Solid Graphic (Perfect B&W Image)":
33
+ # Agar pehle se hi saaf graphic image hai.
34
+ _, binary = cv2.threshold(gray_blurred, 128, 255, cv2.THRESH_BINARY_INV)
35
 
36
+ # C. POST-PROCESSING (Filling and Cleaning)
 
37
  kernel = np.ones((3,3), np.uint8)
 
 
 
 
 
38
 
39
+ # Step C1: Fill Gaps (Agar Jali toot rahi hai ya khokhli aa rahi hai)
40
+ if fill_gaps:
41
+ # Morphological CLOSE: Dilate then Erode. Fills small holes inside black areas.
42
+ binary = cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel, iterations=1)
43
+ # Thoda sa aur bharo taaki solid lage
44
+ binary = cv2.dilate(binary, kernel, iterations=1)
45
+
46
+ # Step C2: Thickness Adjustment (User Controlled)
47
  if thickness > 0:
48
+ # Dilate: Makes design thicker
49
  binary = cv2.dilate(binary, kernel, iterations=int(thickness))
50
  elif thickness < 0:
51
+ # Erode: Makes design thinner
52
  binary = cv2.erode(binary, kernel, iterations=abs(int(thickness)))
53
 
54
  # D. Save Temp BMP for Potrace
55
  temp_bmp = "temp_trace.bmp"
56
+ # Ensure it's pure black and white for Potrace
57
+ (thresh, binary_final) = cv2.threshold(binary, 128, 255, cv2.THRESH_BINARY)
58
+ cv2.imwrite(temp_bmp, binary_final)
59
 
60
  # E. Vectorize using Potrace
61
  output_svg = "ts_vector_design.svg"
62
 
63
  # Potrace Commands
64
+ # -t 5: Thoda noise ignore karega
65
+ # --longcurve: CNC ke liye lambi smooth lines banane ki koshish karega
66
  cmd = [
67
  "potrace", temp_bmp,
68
+ "-s", "-o", output_svg,
69
+ "-t", "5",
70
+ "-a", str(smooth_factor),
71
+ "--longcurve",
72
+ "--opaque"
73
  ]
74
 
75
  try:
 
78
  print(f"Error: {e}")
79
  return None, None
80
 
81
+ # Return SVG and the B&W Preview (Invert preview for better visualization if needed)
82
+ return output_svg, Image.fromarray(binary_final)
83
 
84
  # --- 2. Interface Design ---
85
  custom_css = """
86
  @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600;900&display=swap');
87
  body, .gradio-container { font-family: 'Inter', sans-serif !important; background: #1e1e2e !important; color: white !important; }
88
+ #main_card { background: rgba(255, 255, 255, 0.05); border: 1px solid rgba(255, 255, 255, 0.1); border-radius: 20px; padding: 30px; }
89
+ .primary-btn { background: linear-gradient(90deg, #FF9966, #FF5E62) !important; color: white !important; border: none !important; font-size: 1.2rem !important; font-weight: bold !important; }
90
+ .svelte-1g805jl img { border: 1px solid #FF9966; } /* Orange border on preview */
 
 
 
 
 
 
 
 
 
 
 
91
  """
92
 
93
  with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as app:
94
  with gr.Column(elem_id="main_card"):
95
+ gr.Markdown("# πŸ“ TS VECTOR MASTER", elem_id="logo_text")
96
+ gr.Markdown("### Professional CNC Tracer for Real Photos")
97
+
98
+ gr.Markdown("ℹ️ **Pro Tip:** Best results come from photos taken straight-on (flat), not at an angle.")
99
 
100
  with gr.Row():
101
  with gr.Column():
102
+ inp_img = gr.Image(type="pil", label="Upload Jali Photo", height=300)
 
 
 
103
 
104
+ gr.Markdown("### πŸŽ›οΈ Fine-Tune Result")
105
  mode_drp = gr.Dropdown(
106
+ ["1. Adaptive Scanner (Best for most photos)", "2. Silhouette / Backlit (Dark Jali, Bright Back)", "3. Solid Graphic (Perfect B&W Image)"],
107
+ value="1. Adaptive Scanner (Best for most photos)",
108
+ label="Tracing Mode"
109
  )
110
 
111
+ fill_chk = gr.Checkbox(label="Fill Gaps & Holes (Agar design toot raha ho)", value=True)
112
+ thick_sld = gr.Slider(-2, 4, value=0, step=1, label="Thickness Adjustment")
113
+ smooth_sld = gr.Slider(0, 1.3, value=1.0, label="Corner Smoothing")
114
 
115
+ btn = gr.Button("πŸš€ TRACE IT!", variant="primary", elem_classes=["primary-btn"])
116
 
117
  with gr.Column():
118
+ preview_img = gr.Image(label="AI Vision Preview (Check quality here)", interactive=False)
119
+ out_file = gr.File(label="Download Finished Vector (.SVG)")
120
 
121
+ btn.click(process_vector, inputs=[inp_img, mode_drp, fill_chk, thick_sld, smooth_sld], outputs=[out_file, preview_img])
122
 
123
  app.launch()