Avanish11 commited on
Commit
d40e23c
·
verified ·
1 Parent(s): 5106185

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +199 -41
app.py CHANGED
@@ -1,5 +1,7 @@
1
  import os
2
  from io import BytesIO
 
 
3
 
4
  import cv2
5
  import numpy as np
@@ -21,6 +23,19 @@ app = FastAPI(
21
  version="1.0.0"
22
  )
23
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  # ====================================================
25
  # Load Model Once
26
  # ====================================================
@@ -66,10 +81,13 @@ face_helper = FaceRestoreHelper(
66
  # Face Enhancement Function
67
  # ====================================================
68
 
69
- def enhance_face(image_rgb):
70
-
71
  face_helper.clean_all()
72
-
 
 
 
73
  image_bgr = cv2.cvtColor(
74
  image_rgb,
75
  cv2.COLOR_RGB2BGR
@@ -77,15 +95,36 @@ def enhance_face(image_rgb):
77
 
78
  face_helper.read_image(image_bgr)
79
 
 
 
 
80
  face_helper.get_face_landmarks_5(
81
  only_center_face=False,
82
  resize=640,
83
  eye_dist_threshold=5
84
  )
85
 
 
 
 
86
  face_helper.align_warp_face()
87
-
88
- for cropped_face in face_helper.cropped_faces:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
 
90
  cropped_face_t = img2tensor(
91
  cropped_face / 255.0,
@@ -135,6 +174,9 @@ def enhance_face(image_rgb):
135
  cropped_face
136
  )
137
 
 
 
 
138
  face_helper.get_inverse_affine(None)
139
 
140
  restored_img = face_helper.paste_faces_to_input_image()
@@ -143,10 +185,46 @@ def enhance_face(image_rgb):
143
  restored_img,
144
  cv2.COLOR_BGR2RGB
145
  )
 
 
 
146
 
147
  return restored_img
148
 
149
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
  # ====================================================
151
  # UI
152
  # ====================================================
@@ -189,6 +267,22 @@ HTML_PAGE = """
189
  h1{
190
  text-align:center;
191
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
192
  </style>
193
 
194
  </head>
@@ -206,6 +300,10 @@ Enhance Face
206
 
207
  <p id="status"></p>
208
 
 
 
 
 
209
  <div class="container">
210
 
211
  <div class="card">
@@ -247,7 +345,10 @@ async function enhance(){
247
  }
248
 
249
  document.getElementById("status")
250
- .innerHTML = "Processing...";
 
 
 
251
 
252
  const formData = new FormData();
253
 
@@ -256,22 +357,61 @@ async function enhance(){
256
  file
257
  );
258
 
259
- const response = await fetch(
260
- "/convert",
261
- {
262
- method:"POST",
263
- body:formData
264
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
265
  );
266
-
267
- const blob =
268
- await response.blob();
269
-
270
- document.getElementById("outputPreview")
271
- .src = URL.createObjectURL(blob);
272
-
273
- document.getElementById("status")
274
- .innerHTML = "Done";
275
  }
276
 
277
  </script>
@@ -286,49 +426,67 @@ async def home():
286
 
287
 
288
  # ====================================================
289
- # API
290
  # ====================================================
291
 
292
  @app.post("/convert")
293
- async def convert(
294
- file: UploadFile = File(...)
295
- ):
296
-
297
  contents = await file.read()
298
-
299
  np_img = np.frombuffer(
300
  contents,
301
  np.uint8
302
  )
303
-
304
  image = cv2.imdecode(
305
  np_img,
306
  cv2.IMREAD_COLOR
307
  )
308
-
309
  image = cv2.cvtColor(
310
  image,
311
  cv2.COLOR_BGR2RGB
312
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
313
 
314
- result = enhance_face(image)
315
-
316
- result = cv2.cvtColor(
317
- result,
318
- cv2.COLOR_RGB2BGR
319
- )
320
-
321
- _, buffer = cv2.imencode(
322
- ".png",
323
- result
324
  )
325
 
 
 
 
 
 
 
 
326
  return StreamingResponse(
327
- BytesIO(buffer.tobytes()),
328
  media_type="image/png"
329
  )
330
 
331
-
332
  # ====================================================
333
  # Run
334
  # ====================================================
 
1
  import os
2
  from io import BytesIO
3
+ import uuid
4
+ import threading
5
 
6
  import cv2
7
  import numpy as np
 
23
  version="1.0.0"
24
  )
25
 
26
+ # ====================================================
27
+ # Job Storage
28
+ # ====================================================
29
+
30
+ jobs = {}
31
+ results = {}
32
+
33
+ def update_progress(job_id, value, message):
34
+ jobs[job_id] = {
35
+ "progress": value,
36
+ "message": message
37
+ }
38
+
39
  # ====================================================
40
  # Load Model Once
41
  # ====================================================
 
81
  # Face Enhancement Function
82
  # ====================================================
83
 
84
+ def enhance_face(image_rgb, job_id=None):
85
+
86
  face_helper.clean_all()
87
+
88
+ if job_id:
89
+ update_progress(job_id, 5, "Preparing image")
90
+
91
  image_bgr = cv2.cvtColor(
92
  image_rgb,
93
  cv2.COLOR_RGB2BGR
 
95
 
96
  face_helper.read_image(image_bgr)
97
 
98
+ if job_id:
99
+ update_progress(job_id, 20, "Detecting faces")
100
+
101
  face_helper.get_face_landmarks_5(
102
  only_center_face=False,
103
  resize=640,
104
  eye_dist_threshold=5
105
  )
106
 
107
+ if job_id:
108
+ update_progress(job_id, 35, "Aligning faces")
109
+
110
  face_helper.align_warp_face()
111
+
112
+ total_faces = len(face_helper.cropped_faces)
113
+
114
+ if total_faces == 0:
115
+ if job_id:
116
+ update_progress(job_id, 100, "No faces found")
117
+ return image_rgb
118
+
119
+ for idx, cropped_face in enumerate(face_helper.cropped_faces):
120
+
121
+ if job_id:
122
+ progress = 40 + int((idx / total_faces) * 50)
123
+ update_progress(
124
+ job_id,
125
+ progress,
126
+ f"Enhancing face {idx+1}/{total_faces}"
127
+ )
128
 
129
  cropped_face_t = img2tensor(
130
  cropped_face / 255.0,
 
174
  cropped_face
175
  )
176
 
177
+ if job_id:
178
+ update_progress(job_id, 95, "Finalizing image")
179
+
180
  face_helper.get_inverse_affine(None)
181
 
182
  restored_img = face_helper.paste_faces_to_input_image()
 
185
  restored_img,
186
  cv2.COLOR_BGR2RGB
187
  )
188
+
189
+ if job_id:
190
+ update_progress(job_id, 100, "Completed")
191
 
192
  return restored_img
193
 
194
 
195
+ # ====================================================
196
+ # Background Worker
197
+ # ====================================================
198
+
199
+ def process_job(job_id, image):
200
+ try:
201
+ result = enhance_face(image, job_id)
202
+
203
+ result = cv2.cvtColor(
204
+ result,
205
+ cv2.COLOR_RGB2BGR
206
+ )
207
+
208
+ _, buffer = cv2.imencode(
209
+ ".png",
210
+ result
211
+ )
212
+
213
+ results[job_id] = buffer.tobytes()
214
+
215
+ update_progress(
216
+ job_id,
217
+ 100,
218
+ "Completed"
219
+ )
220
+
221
+ except Exception as e:
222
+ update_progress(
223
+ job_id,
224
+ -1,
225
+ str(e)
226
+ )
227
+
228
  # ====================================================
229
  # UI
230
  # ====================================================
 
267
  h1{
268
  text-align:center;
269
  }
270
+
271
+ .progress-container {
272
+ width:100%;
273
+ border:1px solid #ccc;
274
+ height:30px;
275
+ margin:10px 0;
276
+ border-radius:4px;
277
+ overflow:hidden;
278
+ }
279
+
280
+ .progress-bar {
281
+ height:100%;
282
+ width:0%;
283
+ background:#4CAF50;
284
+ transition: width 0.3s ease;
285
+ }
286
  </style>
287
 
288
  </head>
 
300
 
301
  <p id="status"></p>
302
 
303
+ <div class="progress-container">
304
+ <div id="bar" class="progress-bar"></div>
305
+ </div>
306
+
307
  <div class="container">
308
 
309
  <div class="card">
 
345
  }
346
 
347
  document.getElementById("status")
348
+ .innerHTML = "Starting...";
349
+
350
+ document.getElementById("bar")
351
+ .style.width = "0%";
352
 
353
  const formData = new FormData();
354
 
 
357
  file
358
  );
359
 
360
+ const start =
361
+ await fetch("/convert", {
362
+ method: "POST",
363
+ body: formData
364
+ });
365
+
366
+ const data =
367
+ await start.json();
368
+
369
+ const jobId =
370
+ data.job_id;
371
+
372
+ const timer = setInterval(
373
+ async () => {
374
+
375
+ const res =
376
+ await fetch(
377
+ "/progress/" + jobId
378
+ );
379
+
380
+ const progress =
381
+ await res.json();
382
+
383
+ document.getElementById(
384
+ "status"
385
+ ).innerHTML =
386
+ progress.message;
387
+
388
+ document.getElementById(
389
+ "bar"
390
+ ).style.width =
391
+ progress.progress + "%";
392
+
393
+ if(progress.progress >= 100){
394
+
395
+ clearInterval(timer);
396
+
397
+ document
398
+ .getElementById("outputPreview")
399
+ .src =
400
+ "/result/" +
401
+ jobId +
402
+ "?t=" +
403
+ Date.now();
404
+ }
405
+
406
+ if(progress.progress < 0){
407
+ clearInterval(timer);
408
+ document.getElementById("status")
409
+ .innerHTML = "Error: " + progress.message;
410
+ }
411
+
412
+ },
413
+ 500
414
  );
 
 
 
 
 
 
 
 
 
415
  }
416
 
417
  </script>
 
426
 
427
 
428
  # ====================================================
429
+ # API Endpoints
430
  # ====================================================
431
 
432
  @app.post("/convert")
433
+ async def convert(file: UploadFile = File(...)):
 
 
 
434
  contents = await file.read()
435
+
436
  np_img = np.frombuffer(
437
  contents,
438
  np.uint8
439
  )
440
+
441
  image = cv2.imdecode(
442
  np_img,
443
  cv2.IMREAD_COLOR
444
  )
445
+
446
  image = cv2.cvtColor(
447
  image,
448
  cv2.COLOR_BGR2RGB
449
  )
450
+
451
+ job_id = str(uuid.uuid4())
452
+
453
+ jobs[job_id] = {
454
+ "progress": 0,
455
+ "message": "Queued"
456
+ }
457
+
458
+ threading.Thread(
459
+ target=process_job,
460
+ args=(job_id, image),
461
+ daemon=True
462
+ ).start()
463
+
464
+ return {
465
+ "job_id": job_id
466
+ }
467
 
468
+ @app.get("/progress/{job_id}")
469
+ async def progress(job_id: str):
470
+ return jobs.get(
471
+ job_id,
472
+ {
473
+ "progress": 0,
474
+ "message": "Unknown job"
475
+ }
 
 
476
  )
477
 
478
+ @app.get("/result/{job_id}")
479
+ async def result(job_id: str):
480
+ if job_id not in results:
481
+ return {
482
+ "status": "processing"
483
+ }
484
+
485
  return StreamingResponse(
486
+ BytesIO(results[job_id]),
487
  media_type="image/png"
488
  )
489
 
 
490
  # ====================================================
491
  # Run
492
  # ====================================================