yusiff commited on
Commit
123fe15
·
verified ·
1 Parent(s): 67dcc53

Upload 7 files

Browse files
Files changed (7) hide show
  1. .gitattributes +35 -35
  2. README.md +11 -0
  3. app.py +134 -0
  4. gfpgan/weights/GFPGANv1.4.pth +3 -0
  5. mask.py +93 -0
  6. models/inswapper_128.onnx +3 -0
  7. requirements.txt +0 -0
.gitattributes CHANGED
@@ -1,35 +1,35 @@
1
- *.7z filter=lfs diff=lfs merge=lfs -text
2
- *.arrow filter=lfs diff=lfs merge=lfs -text
3
- *.bin filter=lfs diff=lfs merge=lfs -text
4
- *.bz2 filter=lfs diff=lfs merge=lfs -text
5
- *.ckpt filter=lfs diff=lfs merge=lfs -text
6
- *.ftz filter=lfs diff=lfs merge=lfs -text
7
- *.gz filter=lfs diff=lfs merge=lfs -text
8
- *.h5 filter=lfs diff=lfs merge=lfs -text
9
- *.joblib filter=lfs diff=lfs merge=lfs -text
10
- *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
- *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
- *.model filter=lfs diff=lfs merge=lfs -text
13
- *.msgpack filter=lfs diff=lfs merge=lfs -text
14
- *.npy filter=lfs diff=lfs merge=lfs -text
15
- *.npz filter=lfs diff=lfs merge=lfs -text
16
- *.onnx filter=lfs diff=lfs merge=lfs -text
17
- *.ot filter=lfs diff=lfs merge=lfs -text
18
- *.parquet filter=lfs diff=lfs merge=lfs -text
19
- *.pb filter=lfs diff=lfs merge=lfs -text
20
- *.pickle filter=lfs diff=lfs merge=lfs -text
21
- *.pkl filter=lfs diff=lfs merge=lfs -text
22
- *.pt filter=lfs diff=lfs merge=lfs -text
23
- *.pth filter=lfs diff=lfs merge=lfs -text
24
- *.rar filter=lfs diff=lfs merge=lfs -text
25
- *.safetensors filter=lfs diff=lfs merge=lfs -text
26
- saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
- *.tar.* filter=lfs diff=lfs merge=lfs -text
28
- *.tar filter=lfs diff=lfs merge=lfs -text
29
- *.tflite filter=lfs diff=lfs merge=lfs -text
30
- *.tgz filter=lfs diff=lfs merge=lfs -text
31
- *.wasm filter=lfs diff=lfs merge=lfs -text
32
- *.xz filter=lfs diff=lfs merge=lfs -text
33
- *.zip filter=lfs diff=lfs merge=lfs -text
34
- *.zst filter=lfs diff=lfs merge=lfs -text
35
- *tfevents* filter=lfs diff=lfs merge=lfs -text
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
README.md CHANGED
@@ -1,3 +1,14 @@
1
  ---
 
 
 
 
 
 
 
 
2
  license: apache-2.0
 
3
  ---
 
 
 
1
  ---
2
+ title: Face Swap
3
+ emoji: 📊
4
+ colorFrom: purple
5
+ colorTo: pink
6
+ sdk: gradio
7
+ sdk_version: 5.46.0
8
+ app_file: app.py
9
+ pinned: false
10
  license: apache-2.0
11
+ short_description: face swap
12
  ---
13
+
14
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
app.py ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import os
3
+ import uuid
4
+ import cv2
5
+ from mask import FaceSwapper # الكلاس اللي عملناه قبل كده
6
+
7
+ # تحميل الموديل مره واحده
8
+ swapper = FaceSwapper(
9
+ model_path="models/inswapper_128.onnx",
10
+ gfpgan_model_path="gfpgan/weights/GFPGANv1.4.pth"
11
+ )
12
+
13
+ # دالة للتعامل مع Gradio
14
+ def swap_faces(source_img, target_img):
15
+ try:
16
+ # حفظ الصور المرفوعة مؤقتاً
17
+ source_path = f"temp_source_{uuid.uuid4().hex}.jpg"
18
+ target_path = f"temp_target_{uuid.uuid4().hex}.jpg"
19
+ output_path = f"img/result_{uuid.uuid4().hex}.jpg"
20
+
21
+ cv2.imwrite(source_path, cv2.cvtColor(source_img, cv2.COLOR_RGB2BGR))
22
+ cv2.imwrite(target_path, cv2.cvtColor(target_img, cv2.COLOR_RGB2BGR))
23
+
24
+ # تنفيذ face swap
25
+ result_path = swapper.merge_face_into_image(source_path, target_path, output_path)
26
+
27
+ # تحميل الصورة الناتجة وعرضها
28
+ result_img = cv2.cvtColor(cv2.imread(result_path), cv2.COLOR_BGR2RGB)
29
+
30
+ # مسح الملفات المؤقتة
31
+ os.remove(source_path)
32
+ os.remove(target_path)
33
+
34
+ return result_img
35
+ except Exception as e:
36
+ return f"❌ حصل خطأ: {str(e)}"
37
+
38
+ # واجهة Gradio
39
+ demo = gr.Interface(
40
+ fn=swap_faces,
41
+ inputs=[
42
+ gr.Image(type="numpy", label="Source Image (الطفل)"),
43
+ gr.Image(type="numpy", label="Target Image (المشهد)")
44
+ ],
45
+ outputs=gr.Image(type="numpy", label="النتيجة"),
46
+ title="FaceSwap with GFPGAN",
47
+ description="ارفع صورتين: (1) صورة الطفل (2) المشهد اللي عايز تدخله فيه. وهنرجعلك صورة face swap محسّنة بـ GFPGAN."
48
+ )
49
+
50
+ if __name__ == "__main__":
51
+ demo.launch(server_name="127.0.0.1", server_port=7860)
52
+
53
+
54
+ """import cv2
55
+ import insightface
56
+ import numpy as np
57
+ import os
58
+ from gfpgan import GFPGANer # pip install gfpgan"""
59
+
60
+
61
+ """class FaceSwapper:
62
+ def __init__(self,
63
+ model_path="models/inswapper_128.onnx",
64
+ gfpgan_model_path="gfpgan/weights/GFPGANv1.4.pth"):
65
+ # ============ تحميل FaceAnalysis ============
66
+ self.app = insightface.app.FaceAnalysis(name="buffalo_l", providers=['CPUExecutionProvider'])
67
+ self.app.prepare(ctx_id=0, det_size=(640, 640))
68
+
69
+ # ============ تحميل inswapper ============
70
+ if not os.path.exists(model_path):
71
+ raise FileNotFoundError(f"❌ الموديل مش موجود في: {model_path}")
72
+ self.swapper = insightface.model_zoo.get_model(model_path, providers=['CPUExecutionProvider'])
73
+
74
+ # ============ تحميل GFPGAN ============
75
+ self.gfpganer = GFPGANer(
76
+ model_path=gfpgan_model_path,
77
+ upscale=1,
78
+ arch="clean",
79
+ channel_multiplier=2
80
+ )
81
+
82
+ # ============ دالة مساعدة لاختيار أكبر وجه ============
83
+ @staticmethod
84
+ def get_biggest_face(faces):
85
+ return max(faces, key=lambda f: (f.bbox[2]-f.bbox[0]) * (f.bbox[3]-f.bbox[1]))
86
+
87
+ # ============ دالة الدمج ============
88
+ def merge_face_into_image(self, source_img_path, target_img_path, output_path):
89
+ source_img = cv2.imread(source_img_path)
90
+ target_img = cv2.imread(target_img_path)
91
+
92
+ if source_img is None or target_img is None:
93
+ raise ValueError("❌ مشكلة في قراءة الصور")
94
+
95
+ source_faces = self.app.get(source_img)
96
+ target_faces = self.app.get(target_img)
97
+
98
+ if not source_faces or not target_faces:
99
+ #raise ValueError("❌ مش لاقي وش في الصورة!")
100
+ print("⚠️ No faces detected, returning target image as-is.")
101
+ cv2.imwrite(output_path, target_img)
102
+ return output_path
103
+
104
+ source_face = self.get_biggest_face(source_faces)
105
+ target_face = self.get_biggest_face(target_faces)
106
+
107
+ # استبدال الوجه
108
+ swapped_img = self.swapper.get(target_img.copy(), target_face, source_face, paste_back=True)
109
+
110
+ # قص الوجه من الصورة
111
+ x1, y1, x2, y2 = target_face.bbox.astype(int)
112
+ x1, y1 = max(0, x1), max(0, y1)
113
+ x2, y2 = min(swapped_img.shape[1], x2), min(swapped_img.shape[0], y2)
114
+
115
+ face_crop = swapped_img[y1:y2, x1:x2]
116
+
117
+ if face_crop.size == 0:
118
+ raise ValueError("❌ الوجه المقطوع فاضي (bbox مش مظبوط)")
119
+
120
+ # ماسك بنفس حجم الوجه
121
+ mask = 255 * np.ones(face_crop.shape, face_crop.dtype)
122
+ mask = cv2.GaussianBlur(mask, (25, 25), 30)
123
+
124
+ # مركز الوجه
125
+ center = ((x1 + x2) // 2, (y1 + y2) // 2)
126
+
127
+ # دمج الوجه في الصورة
128
+ blended = cv2.seamlessClone(face_crop, swapped_img, mask, center, cv2.NORMAL_CLONE)
129
+
130
+ # تحسين الصورة بالـ GFPGAN
131
+ _, _, enhanced = self.gfpganer.enhance(blended, has_aligned=False, only_center_face=False, paste_back=True)
132
+
133
+ final_img = enhanced # أو blended لو GFPGAN مش موجود
134
+ return cv2.cvtColor(final_img, cv2.COLOR_BGR2RGB)"""
gfpgan/weights/GFPGANv1.4.pth ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e2cd4703ab14f4d01fd1383a8a8b266f9a5833dacee8e6a79d3bf21a1b6be5ad
3
+ size 348632874
mask.py ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import cv2
2
+ import insightface
3
+ import numpy as np
4
+ import os
5
+ from gfpgan import GFPGANer
6
+ from basicsr.archs.rrdbnet_arch import RRDBNet
7
+ from realesrgan import RealESRGANer # pip install realesrgan
8
+
9
+
10
+ class FaceSwapper:
11
+ def __init__(self,
12
+ model_path="models/inswapper_128.onnx",
13
+ gfpgan_model_path="gfpgan/weights/GFPGANv1.4.pth",
14
+ realesrgan_model_path="models/RealESRGAN_x2plus.pth"):
15
+
16
+ # ============ Face Analysis ============
17
+ self.app = insightface.app.FaceAnalysis(name="buffalo_l", providers=['CPUExecutionProvider'])
18
+ self.app.prepare(ctx_id=0, det_size=(640, 640)) # حافظ عليها صغيرة
19
+
20
+ # ============ Face Swapper ============
21
+ if not os.path.exists(model_path):
22
+ raise FileNotFoundError(f"❌ الموديل مش موجود في: {model_path}")
23
+ self.swapper = insightface.model_zoo.get_model(model_path, providers=['CPUExecutionProvider'])
24
+
25
+ # ============ GFPGAN ============
26
+ self.gfpganer = GFPGANer(
27
+ model_path=gfpgan_model_path,
28
+ upscale=2, # ممكن تخليها 4 حسب جهازك
29
+ arch="clean",
30
+ channel_multiplier=2
31
+ )
32
+
33
+ # ============ Real-ESRGAN ============
34
+ model = RRDBNet(num_in_ch=3, num_out_ch=3, num_feat=64,
35
+ num_block=23, num_grow_ch=32, scale=2)
36
+ self.realesrganer = RealESRGANer(
37
+ scale=2,
38
+ model_path=realesrgan_model_path,
39
+ model=model,
40
+ tile=0,
41
+ tile_pad=10,
42
+ pre_pad=0,
43
+ half=False
44
+ )
45
+
46
+ @staticmethod
47
+ def get_biggest_face(faces):
48
+ return max(faces, key=lambda f: (f.bbox[2]-f.bbox[0]) * (f.bbox[3]-f.bbox[1]))
49
+
50
+ def merge_face_into_image(self, source_img_path, target_img_path, output_path):
51
+ source_img = cv2.imread(source_img_path)
52
+ target_img = cv2.imread(target_img_path)
53
+
54
+ if source_img is None or target_img is None:
55
+ raise ValueError("❌ مشكلة في قراءة الصور")
56
+
57
+ source_faces = self.app.get(source_img)
58
+ target_faces = self.app.get(target_img)
59
+
60
+ if not source_faces or not target_faces:
61
+ print("⚠️ No faces detected, returning target image as-is.")
62
+ cv2.imwrite(output_path, target_img)
63
+ return output_path
64
+
65
+ source_face = self.get_biggest_face(source_faces)
66
+ target_face = self.get_biggest_face(target_faces)
67
+
68
+ swapped_img = self.swapper.get(target_img.copy(), target_face, source_face, paste_back=True)
69
+
70
+ # قص الوجه
71
+ x1, y1, x2, y2 = target_face.bbox.astype(int)
72
+ x1, y1 = max(0, x1), max(0, y1)
73
+ x2, y2 = min(swapped_img.shape[1], x2), min(swapped_img.shape[0], y2)
74
+ face_crop = swapped_img[y1:y2, x1:x2]
75
+
76
+ if face_crop.size == 0:
77
+ raise ValueError("❌ الوجه المقطوع فاضي (bbox مش مظبوط)")
78
+
79
+ # ماسك للدمج
80
+ mask = 255 * np.ones(face_crop.shape, face_crop.dtype)
81
+ mask = cv2.GaussianBlur(mask, (51, 51), 40)
82
+ center = ((x1 + x2) // 2, (y1 + y2) // 2)
83
+
84
+ blended = cv2.seamlessClone(face_crop, swapped_img, mask, center, cv2.MIXED_CLONE)
85
+
86
+ # تحسين الوش بالـ GFPGAN
87
+ _, _, gfpgan_img = self.gfpganer.enhance(blended, has_aligned=False, only_center_face=False, paste_back=True)
88
+
89
+ # تكبير وتحسين الصورة كاملة بالـ Real-ESRGAN
90
+ sr_img, _ = self.realesrganer.enhance(gfpgan_img, outscale=1)
91
+
92
+ cv2.imwrite(output_path, sr_img, [cv2.IMWRITE_PNG_COMPRESSION, 0])
93
+ return output_path
models/inswapper_128.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e4a3f08c753cb72d04e10aa0f7dbe3deebbf39567d4ead6dce08e98aa49e16af
3
+ size 554253681
requirements.txt ADDED
Binary file (310 Bytes). View file