sharmithas151005 commited on
Commit
9ffc678
·
1 Parent(s): 3d5e43c

Initial upload of YOLO-style face detection model

Browse files
Files changed (8) hide show
  1. MIT License.txt +21 -0
  2. README.md +15 -3
  3. dataset.py +50 -0
  4. face_detection_checkpoint_epoch40.pth +3 -0
  5. inference.py +27 -0
  6. loss.py +16 -0
  7. model.py +31 -0
  8. requirements.txt +4 -0
MIT License.txt ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2025 YOUR NAME
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
README.md CHANGED
@@ -1,3 +1,15 @@
1
- ---
2
- license: mit
3
- ---
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ # Face Detection (WIDER FACE, YOLO-style)
3
+
4
+ ## Train
5
+ ```
6
+ python train.py
7
+ ```
8
+
9
+ ## Inference
10
+ ```
11
+ python inference.py
12
+ ```
13
+
14
+ ## Model
15
+ - S=20, B=3 YOLO-style bounding boxes
dataset.py ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import os
3
+ import torch
4
+ from torch.utils.data import Dataset
5
+ from PIL import Image
6
+
7
+ class WiderFaceMultiBoxDataset(Dataset):
8
+ def __init__(self, images_dir, annotation_file, S=20, B=3, transform=None):
9
+ self.images_dir = images_dir
10
+ self.annotation_file = annotation_file
11
+ self.transform = transform
12
+ self.S = S
13
+ self.B = B
14
+ self.data = self.parse_annotations()
15
+
16
+ def parse_annotations(self):
17
+ with open(self.annotation_file, "r") as f:
18
+ lines = [l.strip() for l in f]
19
+ data = []
20
+ i = 0
21
+ while i < len(lines):
22
+ fn = lines[i]; i += 1
23
+ num = int(lines[i]); i += 1
24
+ boxes = []
25
+ for _ in range(num):
26
+ x,y,w,h = map(int, lines[i].split()[:4]); i += 1
27
+ if w>0 and h>0: boxes.append((x,y,w,h))
28
+ if boxes: data.append((fn, boxes))
29
+ return data
30
+
31
+ def encode_target(self, boxes, W, H):
32
+ t = torch.zeros((self.S,self.S,self.B*5))
33
+ for x,y,w,h in boxes:
34
+ cx=(x+w/2)/W; cy=(y+h/2)/H; wn=w/W; hn=h/H
35
+ gx=int(cx*self.S); gy=int(cy*self.S)
36
+ if 0<=gx<self.S and 0<=gy<self.S:
37
+ for b in range(self.B):
38
+ if t[gy,gx,b*5+4]==0:
39
+ t[gy,gx,b*5:b*5+5]=torch.tensor([cx,cy,wn,hn,1.0])
40
+ break
41
+ return t
42
+
43
+ def __getitem__(self, idx):
44
+ fn, boxes = self.data[idx]
45
+ img = Image.open(os.path.join(self.images_dir, fn)).convert("RGB")
46
+ W,H = img.size
47
+ if self.transform: img = self.transform(img)
48
+ return img, self.encode_target(boxes,W,H)
49
+
50
+ def __len__(self): return len(self.data)
face_detection_checkpoint_epoch40.pth ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:fec8368ba1b01937f1f30ed7e01bb641fd9896e70e0b2300daa8103a1658ad84
3
+ size 68801828
inference.py ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import torch, matplotlib.pyplot as plt, matplotlib.patches as patches
3
+
4
+ def draw_prediction(img, pred, S=20, B=3, thr=0.15):
5
+ img_np = img.permute(1,2,0).numpy()
6
+ H,W,_ = img_np.shape
7
+ fig,ax=plt.subplots(1,figsize=(6,6)); ax.imshow(img_np)
8
+ c=0
9
+ for i in range(S):
10
+ for j in range(S):
11
+ for b in range(B):
12
+ off=b*5
13
+ conf=float(torch.sigmoid(pred[i,j,off+4]))
14
+ if conf>thr:
15
+ cx,cy,w,h = [float(pred[i,j,off+k]) for k in range(4)]
16
+ cx*=W; cy*=H; w*=W; h*=H
17
+ x=cx-w/2; y=cy-h/2
18
+ ax.add_patch(patches.Rectangle((x,y),w,h,edgecolor='red',facecolor='none',linewidth=2))
19
+ c+=1
20
+ ax.set_title(f"{c} boxes"); plt.axis('off'); plt.show()
21
+
22
+ def load_and_predict(model_path, img_tensor, model):
23
+ model.load_state_dict(torch.load(model_path, map_location='cpu'))
24
+ model.eval()
25
+ with torch.no_grad():
26
+ out=model(img_tensor.unsqueeze(0)).squeeze(0)
27
+ draw_prediction(img_tensor, out)
loss.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import torch.nn.functional as F
3
+ import torch
4
+
5
+ def yolo_style_loss(pred, target, S=20, B=3):
6
+ loss=0
7
+ for b in range(B):
8
+ pb = pred[...,b*5:b*5+4]
9
+ pc = pred[...,b*5+4]
10
+ tb = target[...,b*5:b*5+4]
11
+ tc = target[...,b*5+4]
12
+ pc=torch.sigmoid(pc)
13
+ mask = tc>0
14
+ loss += F.smooth_l1_loss(pb[mask], tb[mask], reduction='sum')
15
+ loss += F.binary_cross_entropy(pc, tc, reduction='sum')
16
+ return loss
model.py ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import torch
3
+ import torch.nn as nn
4
+
5
+ class FaceDetectionMultiBoxCNN(nn.Module):
6
+ def __init__(self, S=20, B=3):
7
+ super().__init__()
8
+ self.S = S
9
+ self.B = B
10
+ self.output_size = S * S * B * 5
11
+
12
+ self.features = nn.Sequential(
13
+ nn.Conv2d(3, 32, 3, 1, 1), nn.BatchNorm2d(32), nn.ReLU(), nn.MaxPool2d(2),
14
+ nn.Conv2d(32, 64, 3, 1, 1), nn.BatchNorm2d(64), nn.ReLU(), nn.MaxPool2d(2),
15
+ nn.Conv2d(64, 128, 3, 1, 1), nn.BatchNorm2d(128), nn.ReLU(), nn.MaxPool2d(2),
16
+ nn.Conv2d(128, 256, 3, 1, 1), nn.BatchNorm2d(256), nn.ReLU(), nn.MaxPool2d(2),
17
+ nn.Conv2d(256, 512, 3, 1, 1), nn.BatchNorm2d(512), nn.ReLU(), nn.MaxPool2d(2),
18
+ )
19
+
20
+ dummy = torch.zeros(1, 3, 320, 320)
21
+ with torch.no_grad():
22
+ flatten = self.features(dummy).view(1, -1).shape[1]
23
+
24
+ self.classifier = nn.Sequential(
25
+ nn.Flatten(),
26
+ nn.Linear(flatten, 1024), nn.ReLU(),
27
+ nn.Linear(1024, self.output_size)
28
+ )
29
+
30
+ def forward(self, x):
31
+ return self.classifier(self.features(x)).view(-1, self.S, self.S, self.B * 5)
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ torch
2
+ torchvision
3
+ matplotlib
4
+ Pillow