freevpn commited on
Commit
3123ccc
·
verified ·
1 Parent(s): 6905f3e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +77 -120
app.py CHANGED
@@ -1,4 +1,4 @@
1
- # app.py (Hugging Face Spaces အတွက် ပြင်ဆင်ပြီး)
2
 
3
  import os
4
  import gradio as gr
@@ -11,16 +11,13 @@ import shutil
11
  import time
12
 
13
  # --- Configuration (Hardcoded for Hugging Face Spaces) ---
14
- # Command-line arguments များကို ဖယ်ရှားပြီး လိုအပ်သော settings များကို တိုက်ရိုက်သတ်မှတ်ပါသည်
15
- NUM_FACES = 8 # တစ်ပြိုင်နက်တည်း ပြောင်းနိုင်မည့် မျက်နှာအရေအတွက်
16
- FORCE_CPU = True # Hugging Face free-tier hardware သည် CPU ဖြစ်သောကြောင့် True ဟု သတ်မှတ်ပါသည်
17
 
18
  # --- Initialize Refacer ---
19
- # Refacer ကို သတ်မှတ်ထားသော settings များဖြင့် စတင်ပါသည်
20
  refacer = Refacer(force_cpu=FORCE_CPU)
21
 
22
- # --- Functions (မူရင်းအတိုင်းနီးပါး၊ မလိုအပ်သော temp folder management ကို ဖယ်ရှားထား) ---
23
-
24
  def run_image(*vars):
25
  image_path = vars[0]
26
  origins = vars[1:(NUM_FACES + 1)]
@@ -28,22 +25,12 @@ def run_image(*vars):
28
  thresholds = vars[(NUM_FACES * 2) + 1:-2]
29
  face_mode = vars[-2]
30
  partial_reface_ratio = vars[-1]
31
-
32
  disable_similarity = (face_mode in ["Single Face", "Multiple Faces"])
33
  multiple_faces_mode = (face_mode == "Multiple Faces")
34
-
35
- faces = []
36
- for k in range(NUM_FACES):
37
- if destinations[k] is not None:
38
- faces.append({
39
- 'origin': origins[k] if not multiple_faces_mode else None,
40
- 'destination': destinations[k],
41
- 'threshold': thresholds[k] if not multiple_faces_mode else 0.0
42
- })
43
-
44
  return refacer.reface_image(image_path, faces, disable_similarity=disable_similarity, multiple_faces_mode=multiple_faces_mode, partial_reface_ratio=partial_reface_ratio)
45
 
46
- def run(*vars):
47
  video_path = vars[0]
48
  origins = vars[1:(NUM_FACES + 1)]
49
  destinations = vars[(NUM_FACES + 1):(NUM_FACES * 2) + 1]
@@ -51,37 +38,22 @@ def run(*vars):
51
  preview = vars[-3]
52
  face_mode = vars[-2]
53
  partial_reface_ratio = vars[-1]
54
-
55
  disable_similarity = (face_mode in ["Single Face", "Multiple Faces"])
56
  multiple_faces_mode = (face_mode == "Multiple Faces")
57
-
58
- faces = []
59
- for k in range(NUM_FACES):
60
- if destinations[k] is not None:
61
- faces.append({
62
- 'origin': origins[k] if not multiple_faces_mode else None,
63
- 'destination': destinations[k],
64
- 'threshold': thresholds[k] if not multiple_faces_mode else 0.0
65
- })
66
-
67
  mp4_path, gif_path = refacer.reface(video_path, faces, preview=preview, disable_similarity=disable_similarity, multiple_faces_mode=multiple_faces_mode, partial_reface_ratio=partial_reface_ratio)
68
- return mp4_path, gif_path if gif_path else None
69
 
70
  def load_first_frame(filepath):
71
- if filepath is None:
72
- return None
73
  with imageio.get_reader(filepath) as reader:
74
  return reader.get_data(0)
75
 
76
  def extract_faces_auto(filepath, max_faces=5, isvideo=False):
77
- if filepath is None:
78
- return [None] * max_faces
79
-
80
- # Video ဖိုင်ကြီးလျှင် performance မကျစေရန် auto-extract ကို ကျော်ပါသည်
81
- if isvideo and os.path.getsize(filepath) > 5 * 1024 * 1024:
82
- print("Video is too large for auto-extract, skipping face extraction.")
83
  return [None] * max_faces
84
-
85
  try:
86
  frame = load_first_frame(filepath)
87
  faces = refacer.extract_faces_from_image(frame, max_faces=max_faces)
@@ -92,96 +64,81 @@ def extract_faces_auto(filepath, max_faces=5, isvideo=False):
92
 
93
  def toggle_tabs_and_faces(mode):
94
  if mode == "Single Face":
95
- tab_updates = [gr.update(visible=(i == 0)) for i in range(NUM_FACES)]
96
- origin_updates = [gr.update(visible=False)] * NUM_FACES
97
  elif mode == "Multiple Faces":
98
- tab_updates = [gr.update(visible=True)] * NUM_FACES
99
- origin_updates = [gr.update(visible=False)] * NUM_FACES
100
  else: # Faces By Match
101
- tab_updates = [gr.update(visible=True)] * NUM_FACES
102
- origin_updates = [gr.update(visible=True)] * NUM_FACES
103
- return tab_updates + origin_updates
104
 
105
  def handle_tif_preview(filepath):
106
- if filepath is None:
107
- return None
108
-
109
- # tempfile ကိုအသုံးပြုခြင်းဖြင့် Gradio က temp files များကို သူ့အလိုလို စီမံခန့်ခွဲစေပါသည်
110
- with Image.open(filepath) as img:
111
- img_rgb = img.convert('RGB')
112
- with tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) as temp_file:
113
- img_rgb.save(temp_file.name)
114
- return temp_file.name
115
 
116
  # --- UI ---
117
  theme = gr.themes.Base(primary_hue="blue", secondary_hue="cyan")
118
 
119
  with gr.Blocks(theme=theme, title="NeoRefacer - AI Refacer") as demo:
120
- # Icon ကို base64 encode လုပ်ပြီး HTML ထဲမှာ တိုက်ရိုက်ထည့်သွင်းခြင်း
121
  with open("icon.png", "rb") as f:
122
  icon_data = base64.b64encode(f.read()).decode()
123
- icon_html = f'<img src="data:image/png;base64,{icon_data}" style="width:40px;height:40px;margin-right:10px;">'
124
-
125
- with gr.Row():
126
- gr.Markdown(f"""
127
- <div style="display: flex; align-items: center;">
128
- {icon_html}
129
- <span style="font-size: 2em; font-weight: bold; color:#2563eb;">NeoRefacer</span>
130
- </div>
131
- """)
132
-
133
- # --- IMAGE MODE ---
134
- with gr.Tab("Image Mode"):
135
- with gr.Row():
136
- image_input = gr.Image(label="Original image", type="filepath")
137
- image_output = gr.Image(label="Refaced image", interactive=False, type="filepath")
138
-
139
- with gr.Row():
140
- face_mode_image = gr.Radio(["Single Face", "Multiple Faces", "Faces By Match"], value="Single Face", label="Replacement Mode")
141
- partial_reface_ratio_image = gr.Slider(label="Reface Ratio (0 = Full Face, 0.5 = Half Face)", minimum=0.0, maximum=0.5, value=0.0, step=0.1)
142
- image_btn = gr.Button("Reface Image", variant="primary")
143
-
144
- origin_image, destination_image, thresholds_image, face_tabs_image = [], [], [], []
145
-
146
- for i in range(NUM_FACES):
147
- with gr.Tab(f"Face #{i+1}", visible=(i==0)) as tab:
148
- with gr.Row():
149
- origin = gr.Image(label="Face to replace", visible=True)
150
- destination = gr.Image(label="Destination face")
151
- threshold = gr.Slider(label="Threshold", minimum=0.0, maximum=1.0, value=0.2)
152
- origin_image.append(origin)
153
- destination_image.append(destination)
154
- thresholds_image.append(threshold)
155
- face_tabs_image.append(tab)
156
-
157
- face_mode_image.change(fn=toggle_tabs_and_faces, inputs=[face_mode_image], outputs=face_tabs_image + origin_image)
158
- demo.load(fn=lambda: toggle_tabs_and_faces("Single Face"), inputs=None, outputs=face_tabs_image + origin_image)
159
-
160
- image_btn.click(fn=run_image, inputs=[image_input] + origin_image + destination_image + thresholds_image + [face_mode_image, partial_reface_ratio_image], outputs=[image_output])
161
- image_input.change(fn=lambda filepath: extract_faces_auto(filepath, max_faces=NUM_FACES), inputs=image_input, outputs=destination_image) # Auto-fill destination faces
162
-
163
- # --- GIF MODE ---
164
- with gr.Tab("GIF Mode"):
165
- # (UI code is repetitive, so I'll omit it for brevity, assuming it's similar to the original)
166
- # The logic is identical to Image Mode, just with different input/output components.
167
- # Ensure all instances of `num_faces` are replaced with `NUM_FACES`.
168
- # ... (GIF UI Code Here) ...
169
- pass
170
-
171
- # --- TIF/TIFF MODE ---
172
- with gr.Tab("TIFF Mode"):
173
- # (UI code is repetitive, so I'll omit it for brevity)
174
- # Ensure all instances of `num_faces` are replaced with `NUM_FACES`.
175
- # ... (TIFF UI Code Here) ...
176
- pass
177
-
178
- # --- VIDEO MODE ---
179
- with gr.Tab("Video Mode"):
180
- # (UI code is repetitive, so I'll omit it for brevity)
181
- # Ensure all instances of `num_faces` are replaced with `NUM_FACES`.
182
- # ... (Video UI Code Here) ...
183
- pass
184
 
185
  # --- Launch app ---
186
- # Hugging Face Spaces အတွက် `launch()` ကို argument မထည့်ဘဲ ခေါ်ပါ
187
- demo.queue().launch()
 
1
+ # app.py (Complete Version for Hugging Face Spaces)
2
 
3
  import os
4
  import gradio as gr
 
11
  import time
12
 
13
  # --- Configuration (Hardcoded for Hugging Face Spaces) ---
14
+ NUM_FACES = 8
15
+ FORCE_CPU = True
 
16
 
17
  # --- Initialize Refacer ---
 
18
  refacer = Refacer(force_cpu=FORCE_CPU)
19
 
20
+ # --- Core Functions ---
 
21
  def run_image(*vars):
22
  image_path = vars[0]
23
  origins = vars[1:(NUM_FACES + 1)]
 
25
  thresholds = vars[(NUM_FACES * 2) + 1:-2]
26
  face_mode = vars[-2]
27
  partial_reface_ratio = vars[-1]
 
28
  disable_similarity = (face_mode in ["Single Face", "Multiple Faces"])
29
  multiple_faces_mode = (face_mode == "Multiple Faces")
30
+ faces = [{'origin': origins[k] if not multiple_faces_mode else None, 'destination': destinations[k], 'threshold': thresholds[k] if not multiple_faces_mode else 0.0} for k in range(NUM_FACES) if destinations[k] is not None]
 
 
 
 
 
 
 
 
 
31
  return refacer.reface_image(image_path, faces, disable_similarity=disable_similarity, multiple_faces_mode=multiple_faces_mode, partial_reface_ratio=partial_reface_ratio)
32
 
33
+ def run_video(*vars):
34
  video_path = vars[0]
35
  origins = vars[1:(NUM_FACES + 1)]
36
  destinations = vars[(NUM_FACES + 1):(NUM_FACES * 2) + 1]
 
38
  preview = vars[-3]
39
  face_mode = vars[-2]
40
  partial_reface_ratio = vars[-1]
 
41
  disable_similarity = (face_mode in ["Single Face", "Multiple Faces"])
42
  multiple_faces_mode = (face_mode == "Multiple Faces")
43
+ faces = [{'origin': origins[k] if not multiple_faces_mode else None, 'destination': destinations[k], 'threshold': thresholds[k] if not multiple_faces_mode else 0.0} for k in range(NUM_FACES) if destinations[k] is not None]
 
 
 
 
 
 
 
 
 
44
  mp4_path, gif_path = refacer.reface(video_path, faces, preview=preview, disable_similarity=disable_similarity, multiple_faces_mode=multiple_faces_mode, partial_reface_ratio=partial_reface_ratio)
45
+ return mp4_path, gif_path
46
 
47
  def load_first_frame(filepath):
48
+ if filepath is None: return None
 
49
  with imageio.get_reader(filepath) as reader:
50
  return reader.get_data(0)
51
 
52
  def extract_faces_auto(filepath, max_faces=5, isvideo=False):
53
+ if filepath is None: return [None] * max_faces
54
+ if isvideo and os.path.getsize(filepath) > 10 * 1024 * 1024:
55
+ print("Video too large for auto-extract.")
 
 
 
56
  return [None] * max_faces
 
57
  try:
58
  frame = load_first_frame(filepath)
59
  faces = refacer.extract_faces_from_image(frame, max_faces=max_faces)
 
64
 
65
  def toggle_tabs_and_faces(mode):
66
  if mode == "Single Face":
67
+ return [gr.update(visible=(i == 0)) for i in range(NUM_FACES)] + [gr.update(visible=False)] * NUM_FACES
 
68
  elif mode == "Multiple Faces":
69
+ return [gr.update(visible=True)] * NUM_FACES + [gr.update(visible=False)] * NUM_FACES
 
70
  else: # Faces By Match
71
+ return [gr.update(visible=True)] * NUM_FACES + [gr.update(visible=True)] * NUM_FACES
 
 
72
 
73
  def handle_tif_preview(filepath):
74
+ if filepath is None: return None
75
+ with Image.open(filepath) as img, tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) as temp_file:
76
+ img.convert('RGB').save(temp_file.name)
77
+ return temp_file.name
 
 
 
 
 
78
 
79
  # --- UI ---
80
  theme = gr.themes.Base(primary_hue="blue", secondary_hue="cyan")
81
 
82
  with gr.Blocks(theme=theme, title="NeoRefacer - AI Refacer") as demo:
 
83
  with open("icon.png", "rb") as f:
84
  icon_data = base64.b64encode(f.read()).decode()
85
+ gr.Markdown(f'<div style="display: flex; align-items: center;"><img src="data:image/png;base64,{icon_data}" style="width:40px;height:40px;margin-right:10px;"><span style="font-size: 2em; font-weight: bold; color:#2563eb;">NeoRefacer</span></div>')
86
+
87
+ for mode in ["Image", "GIF", "TIFF", "Video"]:
88
+ with gr.Tab(f"{mode} Mode"):
89
+ is_video_or_gif = mode in ["Video", "GIF"]
90
+
91
+ with gr.Row():
92
+ if is_video_or_gif:
93
+ input_component = gr.Video(label=f"Original {mode}")
94
+ if mode == "GIF":
95
+ output_main = gr.Video(label="Refaced GIF (MP4)", interactive=False, format="mp4")
96
+ output_secondary = gr.Image(label="Refaced GIF (GIF)", type="filepath")
97
+ else: # Video
98
+ output_main = gr.Video(label="Refaced Video", interactive=False, format="mp4")
99
+ output_secondary = gr.File(visible=False) # Dummy component
100
+ elif mode == "TIFF":
101
+ input_component = gr.File(label="Original TIF", file_types=[".tif", ".tiff"])
102
+ output_main = gr.Image(label="Refaced TIF Preview", type="filepath")
103
+ output_secondary = gr.File(label="Refaced TIF (Download)", interactive=False)
104
+ else: # Image
105
+ input_component = gr.Image(label="Original image", type="filepath")
106
+ output_main = gr.Image(label="Refaced image", interactive=False, type="filepath")
107
+
108
+ with gr.Row():
109
+ face_mode_radio = gr.Radio(["Single Face", "Multiple Faces", "Faces By Match"], value="Single Face", label="Replacement Mode")
110
+ partial_reface_slider = gr.Slider(label="Reface Ratio (0=Full, 0.5=Half)", minimum=0.0, maximum=0.5, value=0.0, step=0.1)
111
+ reface_btn = gr.Button(f"Reface {mode}", variant="primary")
112
+ if is_video_or_gif:
113
+ preview_checkbox = gr.Checkbox(label="Preview (fast)", value=False)
114
+
115
+ origins, destinations, thresholds, face_tabs = [], [], [], []
116
+ for i in range(NUM_FACES):
117
+ with gr.Tab(f"Face #{i+1}", visible=(i==0)) as tab:
118
+ with gr.Row():
119
+ origin_img = gr.Image(label="Face to replace (Match)", visible=False)
120
+ dest_img = gr.Image(label="Destination face (Target)")
121
+ thresh_slider = gr.Slider(label="Threshold (for Match mode)", minimum=0.0, maximum=1.0, value=0.2)
122
+ origins.append(origin_img); destinations.append(dest_img); thresholds.append(thresh_slider); face_tabs.append(tab)
123
+
124
+ # Event Handlers
125
+ face_mode_radio.change(toggle_tabs_and_faces, inputs=face_mode_radio, outputs=face_tabs + origins)
126
+
127
+ if mode == "TIFF":
128
+ tif_preview = gr.Image(label="TIF Preview", type="filepath") # Specific for TIFF
129
+ input_component.change(handle_tif_preview, inputs=input_component, outputs=tif_preview)
130
+ input_component.change(lambda fp: extract_faces_auto(fp, max_faces=NUM_FACES), inputs=input_component, outputs=destinations)
131
+ reface_btn.click(lambda fp, *args: (handle_tif_preview(run_image(fp, *args)), run_image(fp, *args)), inputs=[input_component] + origins + destinations + thresholds + [face_mode_radio, partial_reface_slider], outputs=[output_main, output_secondary])
132
+ elif is_video_or_gif:
133
+ input_component.change(lambda fp: extract_faces_auto(fp, max_faces=NUM_FACES, isvideo=True), inputs=input_component, outputs=destinations)
134
+ reface_btn.click(run_video, inputs=[input_component] + origins + destinations + thresholds + [preview_checkbox, face_mode_radio, partial_reface_slider], outputs=[output_main, output_secondary])
135
+ else: # Image
136
+ input_component.change(lambda fp: extract_faces_auto(fp, max_faces=NUM_FACES), inputs=input_component, outputs=destinations)
137
+ reface_btn.click(run_image, inputs=[input_component] + origins + destinations + thresholds + [face_mode_radio, partial_reface_slider], outputs=[output_main])
138
+
139
+ # Load initial state for all tabs
140
+ demo.load(lambda: toggle_tabs_and_faces("Single Face"), outputs=face_tabs + origins)
 
 
 
 
 
141
 
142
  # --- Launch app ---
143
+ demo.queue().launch()
144
+