ender commited on
Commit
ed84fba
1 Parent(s): 8126add
.gitattributes CHANGED
@@ -25,7 +25,6 @@
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
@@ -33,3 +32,11 @@ saved_model/**/* 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
 
 
 
 
 
 
 
 
 
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
  *.tflite filter=lfs diff=lfs merge=lfs -text
29
  *.tgz filter=lfs diff=lfs merge=lfs -text
30
  *.wasm filter=lfs diff=lfs merge=lfs -text
 
32
  *.zip filter=lfs diff=lfs merge=lfs -text
33
  *.zst filter=lfs diff=lfs merge=lfs -text
34
  *tfevents* filter=lfs diff=lfs merge=lfs -text
35
+ Weights/Weights.tar filter=lfs diff=lfs merge=lfs -text
36
+ Weights/FFc23.tar filter=lfs diff=lfs merge=lfs -text
37
+ Examples/Fake1.mp4 filter=lfs diff=lfs merge=lfs -text
38
+ Examples/Real1.mp4 filter=lfs diff=lfs merge=lfs -text
39
+ *.dat filter=lfs diff=lfs merge=lfs -text
40
+ Weights/weights.tar filter=lfs diff=lfs merge=lfs -text
41
+ Examples/Real/Real1.PNG filter=lfs diff=lfs merge=lfs -text
42
+ Examples/Real/Real2.PNG filter=lfs diff=lfs merge=lfs -text
Examples/Fake/Fake1.PNG ADDED
Examples/Fake/Fake2.PNG ADDED
Examples/Fake/Fake3.PNG ADDED
Examples/Fake1.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:ac9f6fde4b2e56822230d969085867e45cecf53daba7f964f340d2f669121cf1
3
+ size 3319584
Examples/Real/Real1.PNG ADDED

Git LFS Details

  • SHA256: 1a4a229e5028fc4d8c3dc74d5ab05f6fa7c03d9e7169cca3b0126f5e39341124
  • Pointer size: 132 Bytes
  • Size of remote file: 1.66 MB
Examples/Real/Real2.PNG ADDED

Git LFS Details

  • SHA256: eec99c6fd86a9208d0125c5341de60d563b2a34d20acd7a8a616563162a4ff5d
  • Pointer size: 132 Bytes
  • Size of remote file: 1.18 MB
Examples/Real1.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:cd8f1fc5cb478949a1b0c8c790351d45b35112c2c8b1a9272a507bed955565ae
3
+ size 344095
README.md CHANGED
@@ -1,12 +1,11 @@
1
  ---
2
  title: DFDetection
3
- emoji: 📊
4
  colorFrom: blue
5
  colorTo: green
6
  sdk: gradio
7
- sdk_version: 4.31.5
8
  app_file: app.py
9
  pinned: false
 
10
  ---
11
-
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
  title: DFDetection
3
+ emoji: 📚
4
  colorFrom: blue
5
  colorTo: green
6
  sdk: gradio
7
+ sdk_version: 4.29.0
8
  app_file: app.py
9
  pinned: false
10
+ license: mit
11
  ---
 
 
Scripts/DeepFakeMask.py ADDED
@@ -0,0 +1,149 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ import cv2
3
+ import numpy as np
4
+
5
+ logger = logging.getLogger(__name__) # pylint: disable=invalid-name
6
+
7
+ class Mask():
8
+ """ Parent class for masks
9
+ the output mask will be <mask_type>.mask
10
+ channels: 1, 3 or 4:
11
+ 1 - Returns a single channel mask
12
+ 3 - Returns a 3 channel mask
13
+ 4 - Returns the original image with the mask in the alpha channel """
14
+
15
+ def __init__(self, landmarks, face, channels=4):
16
+ logger.info("Initializing %s: (face_shape: %s, channels: %s, landmarks: %s)",
17
+ self.__class__.__name__, face.shape, channels, landmarks)
18
+ self.landmarks = landmarks
19
+ self.face = face
20
+ self.channels = channels
21
+
22
+ mask = self.build_mask()
23
+ self.mask = self.merge_mask(mask)
24
+ logger.info("Initialized %s", self.__class__.__name__)
25
+
26
+ def build_mask(self):
27
+ """ Override to build the mask """
28
+ raise NotImplementedError
29
+
30
+ def merge_mask(self, mask):
31
+ """ Return the mask in requested shape """
32
+ logger.info("mask_shape: %s", mask.shape)
33
+ assert self.channels in (1, 3, 4), "Channels should be 1, 3 or 4"
34
+ assert mask.shape[2] == 1 and mask.ndim == 3, "Input mask be 3 dimensions with 1 channel"
35
+
36
+ if self.channels == 3:
37
+ retval = np.tile(mask, 3)
38
+ elif self.channels == 4:
39
+ retval = np.concatenate((self.face, mask), -1)
40
+ else:
41
+ retval = mask
42
+
43
+ logger.info("Final mask shape: %s", retval.shape)
44
+ return retval
45
+
46
+
47
+ class dfl_full(Mask): # pylint: disable=invalid-name
48
+ """ DFL facial mask """
49
+ def build_mask(self):
50
+ mask = np.zeros(self.face.shape[0:2] + (1, ), dtype=np.float32)
51
+
52
+ nose_ridge = (self.landmarks[27:31], self.landmarks[33:34])
53
+ jaw = (self.landmarks[0:17],
54
+ self.landmarks[48:68],
55
+ self.landmarks[0:1],
56
+ self.landmarks[8:9],
57
+ self.landmarks[16:17])
58
+ eyes = (self.landmarks[17:27],
59
+ self.landmarks[0:1],
60
+ self.landmarks[27:28],
61
+ self.landmarks[16:17],
62
+ self.landmarks[33:34])
63
+ parts = [jaw, nose_ridge, eyes]
64
+
65
+ for item in parts:
66
+ merged = np.concatenate(item)
67
+ cv2.fillConvexPoly(mask, cv2.convexHull(merged), 255.) # pylint: disable=no-member
68
+ return mask
69
+
70
+
71
+ class components(Mask): # pylint: disable=invalid-name
72
+ """ Component model mask """
73
+ def build_mask(self):
74
+ mask = np.zeros(self.face.shape[0:2] + (1, ), dtype=np.float32)
75
+
76
+ r_jaw = (self.landmarks[0:9], self.landmarks[17:18])
77
+ l_jaw = (self.landmarks[8:17], self.landmarks[26:27])
78
+ r_cheek = (self.landmarks[17:20], self.landmarks[8:9])
79
+ l_cheek = (self.landmarks[24:27], self.landmarks[8:9])
80
+ nose_ridge = (self.landmarks[19:25], self.landmarks[8:9],)
81
+ r_eye = (self.landmarks[17:22],
82
+ self.landmarks[27:28],
83
+ self.landmarks[31:36],
84
+ self.landmarks[8:9])
85
+ l_eye = (self.landmarks[22:27],
86
+ self.landmarks[27:28],
87
+ self.landmarks[31:36],
88
+ self.landmarks[8:9])
89
+ nose = (self.landmarks[27:31], self.landmarks[31:36])
90
+ parts = [r_jaw, l_jaw, r_cheek, l_cheek, nose_ridge, r_eye, l_eye, nose]
91
+
92
+ for item in parts:
93
+ merged = np.concatenate(item)
94
+ cv2.fillConvexPoly(mask, cv2.convexHull(merged), 255.) # pylint: disable=no-member
95
+ return mask
96
+
97
+
98
+ class extended(Mask): # pylint: disable=invalid-name
99
+ """ Extended mask
100
+ Based on components mask. Attempts to extend the eyebrow points up the forehead
101
+ """
102
+ def build_mask(self):
103
+ mask = np.zeros(self.face.shape[0:2] + (1, ), dtype=np.float32)
104
+
105
+ landmarks = self.landmarks.copy()
106
+ # mid points between the side of face and eye point
107
+ ml_pnt = (landmarks[36] + landmarks[0]) // 2
108
+ mr_pnt = (landmarks[16] + landmarks[45]) // 2
109
+
110
+ # mid points between the mid points and eye
111
+ ql_pnt = (landmarks[36] + ml_pnt) // 2
112
+ qr_pnt = (landmarks[45] + mr_pnt) // 2
113
+
114
+ # Top of the eye arrays
115
+ bot_l = np.array((ql_pnt, landmarks[36], landmarks[37], landmarks[38], landmarks[39]))
116
+ bot_r = np.array((landmarks[42], landmarks[43], landmarks[44], landmarks[45], qr_pnt))
117
+
118
+ # Eyebrow arrays
119
+ top_l = landmarks[17:22]
120
+ top_r = landmarks[22:27]
121
+
122
+ # Adjust eyebrow arrays
123
+ landmarks[17:22] = top_l + ((top_l - bot_l) // 2)
124
+ landmarks[22:27] = top_r + ((top_r - bot_r) // 2)
125
+
126
+ r_jaw = (landmarks[0:9], landmarks[17:18])
127
+ l_jaw = (landmarks[8:17], landmarks[26:27])
128
+ r_cheek = (landmarks[17:20], landmarks[8:9])
129
+ l_cheek = (landmarks[24:27], landmarks[8:9])
130
+ nose_ridge = (landmarks[19:25], landmarks[8:9],)
131
+ r_eye = (landmarks[17:22], landmarks[27:28], landmarks[31:36], landmarks[8:9])
132
+ l_eye = (landmarks[22:27], landmarks[27:28], landmarks[31:36], landmarks[8:9])
133
+ nose = (landmarks[27:31], landmarks[31:36])
134
+ parts = [r_jaw, l_jaw, r_cheek, l_cheek, nose_ridge, r_eye, l_eye, nose]
135
+
136
+ for item in parts:
137
+ merged = np.concatenate(item)
138
+ cv2.fillConvexPoly(mask, cv2.convexHull(merged), 255.) # pylint: disable=no-member
139
+ return mask
140
+
141
+
142
+ class facehull(Mask): # pylint: disable=invalid-name
143
+ """ Basic face hull mask """
144
+ def build_mask(self):
145
+ mask = np.zeros(self.face.shape[0:2] + (1, ), dtype=np.float32)
146
+ hull = cv2.convexHull( # pylint: disable=no-member
147
+ np.array(self.landmarks).reshape((-1, 2)))
148
+ cv2.fillConvexPoly(mask, hull, 255.0, lineType=cv2.LINE_AA) # pylint: disable=no-member
149
+ return mask
Scripts/__init__.py ADDED
File without changes
Scripts/ca_generator.py ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import albumentations as alb
2
+ from albumentations.pytorch import ToTensorV2
3
+ import cv2
4
+
5
+ def get_augs(name):
6
+ IMG_SIZE = 380
7
+ if name == "REAlbu":
8
+ return alb.Compose([
9
+ alb.HorizontalFlip(),
10
+ alb.CoarseDropout(max_holes = 1, min_height=int(IMG_SIZE*0.02), max_height=int(IMG_SIZE*0.2), min_width=int(IMG_SIZE*0.02), max_width=int(IMG_SIZE*0.2), p=1),
11
+ ])
12
+ elif name == "RandCropAlbu":
13
+ return alb.Compose([
14
+ alb.HorizontalFlip(),
15
+ alb.RandomResizedCrop(height = IMG_SIZE, width = IMG_SIZE, scale=(1/1.3, 1.0), ratio=(0.9,1.1)),
16
+ ])
17
+ elif name == "DFDCAlbu":
18
+ return alb.Compose([
19
+ alb.ImageCompression(quality_lower=60, quality_upper=100, p=0.5),
20
+ alb.GaussNoise(p=0.1),
21
+ alb.GaussianBlur(blur_limit=3, p=0.05),
22
+ alb.HorizontalFlip(),
23
+ alb.OneOf([
24
+ alb.LongestMaxSize(max_size=IMG_SIZE, interpolation=cv2.INTER_CUBIC),
25
+ alb.LongestMaxSize(max_size=IMG_SIZE, interpolation=cv2.INTER_AREA),
26
+ alb.LongestMaxSize(max_size=IMG_SIZE, interpolation=cv2.INTER_LINEAR)
27
+ ], p=1.0),
28
+ alb.PadIfNeeded(min_height=IMG_SIZE, min_width=IMG_SIZE, border_mode=cv2.BORDER_CONSTANT),
29
+ alb.OneOf([alb.RandomBrightnessContrast(), alb.FancyPCA(), alb.HueSaturationValue()], p=0.7),
30
+ alb.ToGray(p=0.2),
31
+ alb.ShiftScaleRotate(shift_limit=0.1, scale_limit=0.2, rotate_limit=10, border_mode=cv2.BORDER_CONSTANT, p=0.5),
32
+ ])
Scripts/model.py ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from torch import nn
3
+ from efficientnet_pytorch import EfficientNet
4
+ from pytorch_grad_cam import GradCAMElementWise
5
+ from pytorch_grad_cam.utils.model_targets import ClassifierOutputTarget
6
+
7
+
8
+ class Detector(nn.Module):
9
+ def __init__(self):
10
+ super(Detector, self).__init__()
11
+ self.net=EfficientNet.from_pretrained("efficientnet-b4",advprop=True,num_classes=2)
12
+
13
+ def forward(self,x):
14
+ x=self.net(x)
15
+ return x
16
+
17
+
18
+ def create_model(path="Weights/94_0.9485_val.tar", device=torch.device('cpu')):
19
+ model=Detector()
20
+ model=model.to(device)
21
+ if device == torch.device('cpu'):
22
+ cnn_sd=torch.load(path, map_location=torch.device('cpu') )["model"]
23
+ else:
24
+ cnn_sd=torch.load(path)["model"]
25
+ model.load_state_dict(cnn_sd)
26
+ model.eval()
27
+ return model
28
+
29
+ def create_cam(model):
30
+ target_layers = [model.net._blocks[-1]]
31
+ targets = [ClassifierOutputTarget(1)]
32
+ cam_algorithm = GradCAMElementWise
33
+ cam = cam_algorithm(model=model,target_layers=target_layers,use_cuda=False)
34
+ return cam
Scripts/preprocess.py ADDED
@@ -0,0 +1,149 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import cv2
3
+ from tqdm import tqdm
4
+
5
+ def extract_frames(filename,num_frames,model,image_size=(380,380)):
6
+ cap_org = cv2.VideoCapture(filename)
7
+
8
+ if not cap_org.isOpened():
9
+ print(f'Cannot open: {filename}')
10
+ # sys.exit()
11
+ return []
12
+
13
+ croppedfaces=[]
14
+ idx_list=[]
15
+ frame_count_org = int(cap_org.get(cv2.CAP_PROP_FRAME_COUNT))
16
+
17
+ frame_idxs = np.linspace(0, frame_count_org - 1, num_frames, endpoint=True, dtype=int)
18
+ for cnt_frame in range(frame_count_org):
19
+ ret_org, frame_org = cap_org.read()
20
+ height,width=frame_org.shape[:-1]
21
+ if not ret_org:
22
+ tqdm.write('Frame read {} Error! : {}'.format(cnt_frame,os.path.basename(filename)))
23
+ break
24
+
25
+ if cnt_frame not in frame_idxs:
26
+ continue
27
+
28
+ frame = cv2.cvtColor(frame_org, cv2.COLOR_BGR2RGB)
29
+
30
+ faces = model.predict_jsons(frame)
31
+ try:
32
+ if len(faces)==0:
33
+ tqdm.write('No faces in {}:{}'.format(cnt_frame,os.path.basename(filename)))
34
+ continue
35
+
36
+ size_list=[]
37
+ croppedfaces_temp=[]
38
+ idx_list_temp=[]
39
+
40
+ for face_idx in range(len(faces)):
41
+ x0,y0,x1,y1=faces[face_idx]['bbox']
42
+ bbox=np.array([[x0,y0],[x1,y1]])
43
+ croppedfaces_temp.append(cv2.resize(crop_face(frame,None,bbox,False,crop_by_bbox=True,only_img=True,phase='test'),dsize=image_size).transpose((2,0,1)))
44
+ idx_list_temp.append(cnt_frame)
45
+ size_list.append((x1-x0)*(y1-y0))
46
+
47
+ max_size=max(size_list)
48
+ croppedfaces_temp=[f for face_idx,f in enumerate(croppedfaces_temp) if size_list[face_idx]>=max_size/2]
49
+ idx_list_temp=[f for face_idx,f in enumerate(idx_list_temp) if size_list[face_idx]>=max_size/2]
50
+ croppedfaces+=croppedfaces_temp
51
+ idx_list+=idx_list_temp
52
+ except Exception as e:
53
+ print(f'error in {cnt_frame}:{filename}')
54
+ print(e)
55
+ continue
56
+ cap_org.release()
57
+
58
+
59
+
60
+ return croppedfaces,idx_list
61
+
62
+ def extract_face(frame,model,image_size=(380,380)):
63
+
64
+
65
+ faces = model.predict_jsons(frame)
66
+
67
+ if len(faces[0]['bbox'])==0:
68
+ return []
69
+ croppedfaces=[]
70
+ for face_idx in range(len(faces)):
71
+ x0,y0,x1,y1=faces[face_idx]['bbox']
72
+ bbox=np.array([[x0,y0],[x1,y1]])
73
+ croppedfaces.append(cv2.resize(crop_face(frame,None,bbox,False,crop_by_bbox=True,only_img=True,phase='test'),dsize=image_size).transpose((2,0,1)))
74
+
75
+ return croppedfaces
76
+
77
+
78
+ def crop_face(img,landmark=None,bbox=None,margin=False,crop_by_bbox=True,abs_coord=False,only_img=False,phase='train'):
79
+ assert phase in ['train','val','test']
80
+
81
+ #crop face------------------------------------------
82
+ H,W=len(img),len(img[0])
83
+
84
+ assert landmark is not None or bbox is not None
85
+
86
+ H,W=len(img),len(img[0])
87
+
88
+ if crop_by_bbox:
89
+ x0,y0=bbox[0]
90
+ x1,y1=bbox[1]
91
+ w=x1-x0
92
+ h=y1-y0
93
+ w0_margin=w/4#0#np.random.rand()*(w/8)
94
+ w1_margin=w/4
95
+ h0_margin=h/4#0#np.random.rand()*(h/5)
96
+ h1_margin=h/4
97
+ else:
98
+ x0,y0=landmark[:68,0].min(),landmark[:68,1].min()
99
+ x1,y1=landmark[:68,0].max(),landmark[:68,1].max()
100
+ w=x1-x0
101
+ h=y1-y0
102
+ w0_margin=w/8#0#np.random.rand()*(w/8)
103
+ w1_margin=w/8
104
+ h0_margin=h/2#0#np.random.rand()*(h/5)
105
+ h1_margin=h/5
106
+
107
+
108
+
109
+ if margin:
110
+ w0_margin*=4
111
+ w1_margin*=4
112
+ h0_margin*=2
113
+ h1_margin*=2
114
+ elif phase=='train':
115
+ w0_margin*=(np.random.rand()*0.6+0.2)#np.random.rand()
116
+ w1_margin*=(np.random.rand()*0.6+0.2)#np.random.rand()
117
+ h0_margin*=(np.random.rand()*0.6+0.2)#np.random.rand()
118
+ h1_margin*=(np.random.rand()*0.6+0.2)#np.random.rand()
119
+ else:
120
+ w0_margin*=0.5
121
+ w1_margin*=0.5
122
+ h0_margin*=0.5
123
+ h1_margin*=0.5
124
+
125
+ y0_new=max(0,int(y0-h0_margin))
126
+ y1_new=min(H,int(y1+h1_margin)+1)
127
+ x0_new=max(0,int(x0-w0_margin))
128
+ x1_new=min(W,int(x1+w1_margin)+1)
129
+
130
+ img_cropped=img[y0_new:y1_new,x0_new:x1_new]
131
+ if landmark is not None:
132
+ landmark_cropped=np.zeros_like(landmark)
133
+ for i,(p,q) in enumerate(landmark):
134
+ landmark_cropped[i]=[p-x0_new,q-y0_new]
135
+ else:
136
+ landmark_cropped=None
137
+ if bbox is not None:
138
+ bbox_cropped=np.zeros_like(bbox)
139
+ for i,(p,q) in enumerate(bbox):
140
+ bbox_cropped[i]=[p-x0_new,q-y0_new]
141
+ else:
142
+ bbox_cropped=None
143
+
144
+ if only_img:
145
+ return img_cropped
146
+ if abs_coord:
147
+ return img_cropped,landmark_cropped,bbox_cropped,(y0-y0_new,x0-x0_new,y1_new-y1,x1_new-x1),y0_new,y1_new,x0_new,x1_new
148
+ else:
149
+ return img_cropped,landmark_cropped,bbox_cropped,(y0-y0_new,x0-x0_new,y1_new-y1,x1_new-x1)
Weights/FFc23.tar ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2b05c2ba36ccb9e9f4f9e1aae9acd443ae2e6400ce725f56104fdb175d3c3267
3
+ size 141290933
Weights/shape_predictor_81_face_landmarks.dat ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8cae4375589dd915d9a0a881101bed1bbb4e9887e35e63b024388f1ca25ff869
3
+ size 19743860
Weights/weights.tar ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:5c100e98694faa776fcf71990377f9c4eca46568417339c06843cdcf2a78d35d
3
+ size 141291061
app.py ADDED
@@ -0,0 +1,189 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import warnings
3
+ import cv2
4
+ import dlib
5
+ from pytorch_grad_cam.utils.image import show_cam_on_image
6
+ from pytorch_grad_cam.utils.model_targets import ClassifierOutputTarget
7
+ import numpy as np
8
+ import torch
9
+ from retinaface.pre_trained_models import get_model
10
+
11
+ from Scripts.model import create_cam, create_model
12
+ from Scripts.preprocess import crop_face, extract_face, extract_frames
13
+ from Scripts.ca_generator import get_augs
14
+
15
+ warnings.filterwarnings('ignore')
16
+
17
+
18
+
19
+ device = torch.device('cpu')
20
+
21
+ sbcl = create_model("Weights/weights.tar")
22
+
23
+
24
+ face_detector = get_model("resnet50_2020-07-20", max_size=1024, device=device)
25
+ face_detector.eval()
26
+
27
+ cam_sbcl = create_cam(sbcl)
28
+ targets = [ClassifierOutputTarget(1)]
29
+
30
+ # Examples
31
+ examples = ["Examples/Fake/Fake1.PNG", "Examples/Real/Real1.PNG", "Examples/Real/Real2.PNG", "Examples/Fake/Fake3.PNG",
32
+ "Examples/Fake/Fake2.PNG", ]
33
+ examples_videos = ['Examples/Fake1.mp4', 'Examples/Real1.mp4']
34
+
35
+ # dlib Models
36
+ dlib_face_detector = dlib.get_frontal_face_detector()
37
+ dlib_face_predictor = dlib.shape_predictor(
38
+ 'Weights/shape_predictor_81_face_landmarks.dat')
39
+
40
+
41
+ def predict_image(inp):
42
+
43
+ face_list = extract_face(inp, face_detector)
44
+
45
+ if len(face_list) == 0:
46
+ return {'No face detected!': 1}, None
47
+
48
+ with torch.no_grad():
49
+ img = torch.tensor(face_list).to(device).float()/255
50
+ pred = sbcl(img).softmax(1)[:, 1].cpu().data.numpy().tolist()[0]
51
+ confidences = {'Real': 1-pred, 'Fake': pred}
52
+
53
+ grayscale_cam = cam_sbcl(input_tensor=img, targets=targets, aug_smooth=True)
54
+ grayscale_cam = grayscale_cam[0, :]
55
+ cam_image = show_cam_on_image(face_list[0].transpose(1, 2, 0)/255, grayscale_cam, use_rgb=True)
56
+
57
+ return confidences, cam_image
58
+
59
+
60
+ def predict_video(inp):
61
+
62
+ face_list, idx_list = extract_frames(inp, 10, face_detector)
63
+
64
+ with torch.no_grad():
65
+ img = torch.tensor(face_list).to(device).float()/255
66
+ pred = sbcl(img).softmax(1)[:, 1]
67
+
68
+ pred_list = []
69
+ idx_img = -1
70
+ for i in range(len(pred)):
71
+ if idx_list[i] != idx_img:
72
+ pred_list.append([])
73
+ idx_img = idx_list[i]
74
+ pred_list[-1].append(pred[i].item())
75
+ pred_res = np.zeros(len(pred_list))
76
+ for i in range(len(pred_res)):
77
+ pred_res[i] = max(pred_list[i])
78
+ pred = pred_res.mean()
79
+
80
+ most_fake = np.argmax(pred_res)
81
+ grayscale_cam = cam_sbcl(input_tensor=img[most_fake].unsqueeze(0), targets=targets, aug_smooth=True)
82
+ grayscale_cam = grayscale_cam[0, :]
83
+ cam_image = show_cam_on_image(face_list[most_fake].transpose(1, 2, 0)/255, grayscale_cam, use_rgb=True)
84
+
85
+ return {'Real': 1-pred, 'Fake': pred}, cam_image
86
+
87
+
88
+
89
+ with gr.Blocks(title="Deepfake Detection CL", theme='upsatwal/mlsc_tiet', css="""
90
+ @import url('https://fonts.googleapis.com/css?family=Source+Code+Pro:200');
91
+ #custom_header {
92
+ min-height: 3rem;
93
+ background-image: url('https://static.pexels.com/photos/414171/pexels-photo-414171.jpeg');
94
+ background-size: cover;
95
+ background-position: top;
96
+ color: white;
97
+ text-align: center;
98
+ padding: 0.5rem;
99
+ font-family: 'Source Code Pro', monospace;
100
+ text-transform: uppercase;
101
+ }
102
+ #custom_header:hover {
103
+ -webkit-animation: slidein 10s;
104
+ animation: slidein 10s;
105
+ -webkit-animation-fill-mode: forwards;
106
+ animation-fill-mode: forwards;
107
+ -webkit-animation-iteration-count: infinite;
108
+ animation-iteration-count: infinite;
109
+ -webkit-animation-direction: alternate;
110
+ animation-direction: alternate;
111
+ }
112
+ @-webkit-keyframes slidein {
113
+ from {
114
+ background-position: top;
115
+ background-size: 3000px;
116
+ }
117
+ to {
118
+ background-position: -100px 0px;
119
+ background-size: 2750px;
120
+ }
121
+ }
122
+ @keyframes slidein {
123
+ from {
124
+ background-position: top;
125
+ background-size: 3000px;
126
+ }
127
+ to {
128
+ background-position: -100px 0px;
129
+ background-size: 2750px;
130
+ }
131
+ }
132
+ #custom_title {
133
+ min-height: 3rem;
134
+ text-align: center;
135
+ }
136
+ .full-width {
137
+ width: 100%;
138
+ }
139
+ .full-width:hover {
140
+ background: rgba(75, 75, 250, 0.3);
141
+ color: white;
142
+ }
143
+ """) as demo:
144
+
145
+ with gr.Tab("Image"):
146
+ with gr.Row():
147
+ with gr.Column():
148
+ with gr.Group():
149
+ gr.Markdown("## Deepfake Detection", elem_id="custom_header")
150
+ input_image = gr.Image(label="Input Image", height=240)
151
+ btn = gr.Button(value="Submit", variant="primary", elem_classes="full-width")
152
+ with gr.Column():
153
+ with gr.Group():
154
+ gr.Markdown("## Result", elem_id="custom_header")
155
+ output_image = gr.Image(label="GradCAM Image", height=240)
156
+ label_probs = gr.Label()
157
+ gr.Examples(
158
+ examples=examples,
159
+ inputs=input_image,
160
+ outputs=output_image,
161
+ fn=predict_image,
162
+ cache_examples=False,
163
+ )
164
+ btn.click(predict_image, inputs=input_image, outputs=[label_probs, output_image], api_name="/predict_image")
165
+
166
+ with gr.Tab("Video"):
167
+ with gr.Row():
168
+ with gr.Column():
169
+ with gr.Group():
170
+ gr.Markdown("## Deepfake Detection", elem_id="custom_header")
171
+ input_video = gr.Video(label="Input Video", height=240)
172
+ btn_video = gr.Button(value="Submit", variant="primary", elem_classes="full-width")
173
+
174
+ with gr.Column():
175
+ with gr.Group():
176
+ gr.Markdown("## Result", elem_id="custom_header")
177
+ output_image_video = gr.Image(label="GradCAM", height=240)
178
+ label_probs_video = gr.Label()
179
+ gr.Examples(
180
+ examples=examples_videos,
181
+ inputs=input_video,
182
+ outputs=output_image_video,
183
+ fn=predict_video,
184
+ cache_examples=False,
185
+ )
186
+ btn_video.click(predict_video, inputs=input_video, outputs=[label_probs_video, output_image_video], api_name="/predict_video")
187
+
188
+ if __name__ == "__main__":
189
+ demo.launch()
requirements.txt ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ dlib
2
+ retinaface_pytorch
3
+ imutils
4
+ numpy
5
+ grad-cam==1.4.8
6
+ gradio
7
+ opencv-python
8
+ efficientnet_pytorch
9
+ httpx
10
+ ffmpeg