├── .gitignore
├── README.md
├── data
├── __init__.py
├── config.py
└── widerface.py
├── demo.py
├── eval_tools
├── boxoverlap.m
├── evaluation.m
├── ground_truth
│ ├── wider_easy_val.mat
│ ├── wider_face_val.mat
│ ├── wider_hard_val.mat
│ └── wider_medium_val.mat
├── nms.m
├── norm_score.m
├── plot
│ ├── VOCap.m
│ ├── baselines
│ │ ├── Test
│ │ │ ├── setting_ext
│ │ │ │ ├── acf
│ │ │ │ │ ├── wider_pr_info_acf_easy.mat
│ │ │ │ │ ├── wider_pr_info_acf_hard.mat
│ │ │ │ │ └── wider_pr_info_acf_medium.mat
│ │ │ │ ├── dpm
│ │ │ │ │ ├── wider_pr_info_dpm_easy.mat
│ │ │ │ │ ├── wider_pr_info_dpm_hard.mat
│ │ │ │ │ └── wider_pr_info_dpm_medium.mat
│ │ │ │ ├── faceness
│ │ │ │ │ ├── wider_pr_info_faceness_easy.mat
│ │ │ │ │ ├── wider_pr_info_faceness_hard.mat
│ │ │ │ │ └── wider_pr_info_faceness_medium.mat
│ │ │ │ └── vj
│ │ │ │ │ ├── wider_pr_info_vj_easy.mat
│ │ │ │ │ ├── wider_pr_info_vj_hard.mat
│ │ │ │ │ └── wider_pr_info_vj_medium.mat
│ │ │ └── setting_int
│ │ │ │ ├── DSFD
│ │ │ │ ├── wider_pr_info_DSFD_easy.mat
│ │ │ │ ├── wider_pr_info_DSFD_hard.mat
│ │ │ │ └── wider_pr_info_DSFD_medium.mat
│ │ │ │ ├── FAN
│ │ │ │ ├── wider_pr_info_FAN_easy.mat
│ │ │ │ ├── wider_pr_info_FAN_hard.mat
│ │ │ │ └── wider_pr_info_FAN_medium.mat
│ │ │ │ ├── FANet
│ │ │ │ ├── wider_pr_info_FANet_easy.mat
│ │ │ │ ├── wider_pr_info_FANet_hard.mat
│ │ │ │ └── wider_pr_info_FANet_medium.mat
│ │ │ │ ├── FDNet
│ │ │ │ ├── wider_pr_info_FDNet_easy.mat
│ │ │ │ ├── wider_pr_info_FDNet_hard.mat
│ │ │ │ └── wider_pr_info_FDNet_medium.mat
│ │ │ │ ├── Face R-CNN
│ │ │ │ ├── wider_pr_info_Face R-CNN_easy.mat
│ │ │ │ ├── wider_pr_info_Face R-CNN_hard.mat
│ │ │ │ └── wider_pr_info_Face R-CNN_medium.mat
│ │ │ │ ├── Face R-FCN
│ │ │ │ ├── wider_pr_info_Face R-FCN_easy.mat
│ │ │ │ ├── wider_pr_info_Face R-FCN_hard.mat
│ │ │ │ └── wider_pr_info_Face R-FCN_medium.mat
│ │ │ │ ├── HR
│ │ │ │ ├── wider_pr_info_HR_easy.mat
│ │ │ │ ├── wider_pr_info_HR_hard.mat
│ │ │ │ └── wider_pr_info_HR_medium.mat
│ │ │ │ ├── LDCF+
│ │ │ │ ├── .DS_Store
│ │ │ │ ├── wider_pr_info_LDCF+_easy.mat
│ │ │ │ ├── wider_pr_info_LDCF+_hard.mat
│ │ │ │ └── wider_pr_info_LDCF+_medium.mat
│ │ │ │ ├── MSCNN
│ │ │ │ ├── wider_pr_info_MSCNN_easy.mat
│ │ │ │ ├── wider_pr_info_MSCNN_hard.mat
│ │ │ │ └── wider_pr_info_MSCNN_medium.mat
│ │ │ │ ├── PyramidBox
│ │ │ │ ├── wider_pr_info_PyramidBox_easy.mat
│ │ │ │ ├── wider_pr_info_PyramidBox_hard.mat
│ │ │ │ └── wider_pr_info_PyramidBox_medium.mat
│ │ │ │ ├── SFD
│ │ │ │ ├── wider_pr_info_SFD_easy.mat
│ │ │ │ ├── wider_pr_info_SFD_hard.mat
│ │ │ │ └── wider_pr_info_SFD_medium.mat
│ │ │ │ ├── SRN
│ │ │ │ ├── wider_pr_info_SRN_easy.mat
│ │ │ │ ├── wider_pr_info_SRN_hard.mat
│ │ │ │ └── wider_pr_info_SRN_medium.mat
│ │ │ │ ├── SSH
│ │ │ │ ├── wider_pr_info_SSH_easy.mat
│ │ │ │ ├── wider_pr_info_SSH_hard.mat
│ │ │ │ └── wider_pr_info_SSH_medium.mat
│ │ │ │ ├── ScaleFace
│ │ │ │ ├── wider_pr_info_ScaleFace_easy.mat
│ │ │ │ ├── wider_pr_info_ScaleFace_hard.mat
│ │ │ │ └── wider_pr_info_ScaleFace_medium.mat
│ │ │ │ ├── ZCC
│ │ │ │ ├── wider_pr_info_ZCC_easy.mat
│ │ │ │ ├── wider_pr_info_ZCC_hard.mat
│ │ │ │ └── wider_pr_info_ZCC_medium.mat
│ │ │ │ ├── acf
│ │ │ │ ├── wider_pr_info_acf_easy.mat
│ │ │ │ ├── wider_pr_info_acf_hard.mat
│ │ │ │ └── wider_pr_info_acf_medium.mat
│ │ │ │ ├── cms-rcnn
│ │ │ │ ├── wider_pr_info_cms-rcnn_easy.mat
│ │ │ │ ├── wider_pr_info_cms-rcnn_hard.mat
│ │ │ │ └── wider_pr_info_cms-rcnn_medium.mat
│ │ │ │ ├── faceness
│ │ │ │ ├── wider_pr_info_faceness_easy.mat
│ │ │ │ ├── wider_pr_info_faceness_hard.mat
│ │ │ │ └── wider_pr_info_faceness_medium.mat
│ │ │ │ ├── multiscale_cascade
│ │ │ │ ├── wider_pr_info_multiscale_cascade_easy.mat
│ │ │ │ ├── wider_pr_info_multiscale_cascade_hard.mat
│ │ │ │ └── wider_pr_info_multiscale_cascade_medium.mat
│ │ │ │ ├── multitask-cascade-cnn
│ │ │ │ ├── wider_pr_info_multitask-cascade-cnn_easy.mat
│ │ │ │ ├── wider_pr_info_multitask-cascade-cnn_hard.mat
│ │ │ │ └── wider_pr_info_multitask-cascade-cnn_medium.mat
│ │ │ │ └── two_stage_cnn
│ │ │ │ ├── wider_pr_info_two_stage_cnn_easy.mat
│ │ │ │ ├── wider_pr_info_two_stage_cnn_hard.mat
│ │ │ │ └── wider_pr_info_two_stage_cnn_medium.mat
│ │ └── Val
│ │ │ └── setting_int
│ │ │ ├── DSFD
│ │ │ ├── wider_pr_info_DSFD_easy_val.mat
│ │ │ ├── wider_pr_info_DSFD_hard_val.mat
│ │ │ └── wider_pr_info_DSFD_medium_val.mat
│ │ │ ├── FAN
│ │ │ ├── wider_pr_info_fan_easy_val.mat
│ │ │ ├── wider_pr_info_fan_hard_val.mat
│ │ │ └── wider_pr_info_fan_medium_val.mat
│ │ │ ├── FANet
│ │ │ ├── .DS_Store
│ │ │ ├── wider_pr_info_FANet_easy_val.mat
│ │ │ ├── wider_pr_info_FANet_hard_val.mat
│ │ │ └── wider_pr_info_FANet_medium_val.mat
│ │ │ ├── FDNet
│ │ │ ├── wider_pr_info_FDNet_easy_val.mat
│ │ │ ├── wider_pr_info_FDNet_hard_val.mat
│ │ │ └── wider_pr_info_FDNet_medium_val.mat
│ │ │ ├── Face R-CNN
│ │ │ ├── wider_pr_info_Face R-CNN_easy_val.mat
│ │ │ ├── wider_pr_info_Face R-CNN_hard_val.mat
│ │ │ └── wider_pr_info_Face R-CNN_medium_val.mat
│ │ │ ├── Face R-FCN
│ │ │ ├── wider_pr_info_Face R-FCN_easy_val.mat
│ │ │ ├── wider_pr_info_Face R-FCN_hard_val.mat
│ │ │ └── wider_pr_info_Face R-FCN_medium_val.mat
│ │ │ ├── HR
│ │ │ ├── wider_pr_info_HR_easy_val.mat
│ │ │ ├── wider_pr_info_HR_hard_val.mat
│ │ │ └── wider_pr_info_HR_medium_val.mat
│ │ │ ├── LDCF+
│ │ │ ├── wider_pr_info_LDCF+_easy_val.mat
│ │ │ ├── wider_pr_info_LDCF+_hard_val.mat
│ │ │ └── wider_pr_info_LDCF+_medium_val.mat
│ │ │ ├── MSCNN
│ │ │ ├── wider_pr_info_MSCNN_easy_val.mat
│ │ │ ├── wider_pr_info_MSCNN_hard_val.mat
│ │ │ └── wider_pr_info_MSCNN_medium_val.mat
│ │ │ ├── PyramidBox
│ │ │ ├── wider_pr_info_PyramidBox_easy_val.mat
│ │ │ ├── wider_pr_info_PyramidBox_hard_val.mat
│ │ │ └── wider_pr_info_PyramidBox_medium_val.mat
│ │ │ ├── SFD
│ │ │ ├── wider_pr_info_SFD_easy_val.mat
│ │ │ ├── wider_pr_info_SFD_hard_val.mat
│ │ │ └── wider_pr_info_SFD_medium_val.mat
│ │ │ ├── SRN
│ │ │ ├── wider_pr_info_SRN_easy_val.mat
│ │ │ ├── wider_pr_info_SRN_hard_val.mat
│ │ │ └── wider_pr_info_SRN_medium_val.mat
│ │ │ ├── SSH
│ │ │ ├── wider_pr_info_SSH_easy_val.mat
│ │ │ ├── wider_pr_info_SSH_hard_val.mat
│ │ │ └── wider_pr_info_SSH_medium_val.mat
│ │ │ ├── ScaleFace
│ │ │ ├── wider_pr_info_ScaleFace_easy_val.mat
│ │ │ ├── wider_pr_info_ScaleFace_hard_val.mat
│ │ │ └── wider_pr_info_ScaleFace_medium_val.mat
│ │ │ ├── ZCC
│ │ │ ├── wider_pr_info_ZCC_easy_val.mat
│ │ │ ├── wider_pr_info_ZCC_hard_val.mat
│ │ │ └── wider_pr_info_ZCC_medium_val.mat
│ │ │ ├── acf
│ │ │ ├── wider_pr_info_acf_easy_val.mat
│ │ │ ├── wider_pr_info_acf_hard_val.mat
│ │ │ └── wider_pr_info_acf_medium_val.mat
│ │ │ ├── cms-rcnn
│ │ │ ├── wider_pr_info_cms-rcnn_easy_val.mat
│ │ │ ├── wider_pr_info_cms-rcnn_hard_val.mat
│ │ │ └── wider_pr_info_cms-rcnn_medium_val.mat
│ │ │ ├── faceness
│ │ │ ├── wider_pr_info_faceness_easy_val.mat
│ │ │ ├── wider_pr_info_faceness_hard_val.mat
│ │ │ └── wider_pr_info_faceness_medium_val.mat
│ │ │ ├── multiscale_cascade
│ │ │ ├── wider_pr_info_multiscale_cascade_easy_val.mat
│ │ │ ├── wider_pr_info_multiscale_cascade_hard_val.mat
│ │ │ └── wider_pr_info_multiscale_cascade_medium_val.mat
│ │ │ ├── multitask-cascade-cnn
│ │ │ ├── wider_pr_info_multitask-cascade-cnn_easy_val.mat
│ │ │ ├── wider_pr_info_multitask-cascade-cnn_hard_val.mat
│ │ │ └── wider_pr_info_multitask-cascade-cnn_medium_val.mat
│ │ │ ├── s3fd.pytorch
│ │ │ ├── wider_pr_info_s3fd.pytorch_easy_val.mat
│ │ │ ├── wider_pr_info_s3fd.pytorch_hard_val.mat
│ │ │ └── wider_pr_info_s3fd.pytorch_medium_val.mat
│ │ │ └── two_stage_cnn
│ │ │ ├── wider_pr_info_two_stage_cnn_easy_val.mat
│ │ │ ├── wider_pr_info_two_stage_cnn_hard_val.mat
│ │ │ └── wider_pr_info_two_stage_cnn_medium_val.mat
│ ├── figure
│ │ ├── Test
│ │ │ ├── wider_pr_cruve_ext_easy.pdf
│ │ │ ├── wider_pr_cruve_ext_hard.pdf
│ │ │ ├── wider_pr_cruve_ext_medium.pdf
│ │ │ ├── wider_pr_cruve_int_easy.pdf
│ │ │ ├── wider_pr_cruve_int_hard.pdf
│ │ │ └── wider_pr_cruve_int_medium.pdf
│ │ └── Val
│ │ │ ├── wider_pr_cruve_int_easy_val.pdf
│ │ │ ├── wider_pr_cruve_int_hard_val.pdf
│ │ │ └── wider_pr_cruve_int_medium_val.pdf
│ ├── plot_pr.m
│ ├── saveTightFigure.m
│ └── wider_plot.m
├── read_pred.m
├── wider_eval.m
├── wider_face_test.mat
└── wider_face_val.mat
├── img
├── 0_Parade_marchingband_1_20.jpg
├── 0_Parade_marchingband_1_234.jpg
├── 0_Parade_marchingband_1_329.jpg
├── 0_Parade_marchingband_1_488.jpg
└── 0_Parade_marchingband_1_629.jpg
├── layers
├── __init__.py
├── bbox_utils.py
├── functions
│ ├── __init__.py
│ ├── detection.py
│ └── prior_box.py
└── modules
│ ├── __init__.py
│ ├── l2norm.py
│ └── multibox_loss.py
├── models
├── DSFD_resnet.py
├── DSFD_vgg.py
├── __init__.py
└── factory.py
├── prepare_wider_data.py
├── tmp
├── 0_Parade_marchingband_1_20.jpg
├── 0_Parade_marchingband_1_234.jpg
├── 0_Parade_marchingband_1_329.jpg
├── 0_Parade_marchingband_1_488.jpg
└── 0_Parade_marchingband_1_629.jpg
├── tools
├── afw_img_list.txt
├── afw_test.py
├── fddb_test.py
├── pascal_img_list.txt
├── pascal_test.py
└── wider_test.py
├── train.py
└── utils
├── __init__.py
└── augmentations.py
/.gitignore:
--------------------------------------------------------------------------------
1 | *.pyc
2 | *.pth
3 | log/
4 | eval_tools/s3fd_val/
5 | eval_tools/sfd_val/
6 | eval_tools/dsfd_val/
7 | data/train.txt
8 | data/val.txt
9 | data/*.txt
10 | img/02*.jpg
11 | img/tj*.jpg
12 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## DSFD: Dual Shot Face Detector ##
2 | [A PyTorch Implementation of Dual Shot Face Detector](https://arxiv.org/abs/1810.10220?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+arxiv%2FQSXk+%28ExcitingAds%21+cs+updates+on+arXiv.org%29)
3 |
4 | ### Description
5 | I use basenet [vgg](https://pan.baidu.com/s/1Q-YqoxJyqvln6KTcIck1tQ) to train DSFD,the model can be downloaded in [DSFD](https://pan.baidu.com/s/17cpDHEwYVxWmOIPqUy5zCQ).the AP in WIDER FACE as following:
6 |
7 | | Easy MAP | Medium MAP | hard MAP |
8 | | ---------|------------| --------- |
9 | | 0.946 | 0.937 | 0.880 |
10 |
11 | the AP in AFW,PASCAL,FDDB as following:
12 |
13 | | AFW | PASCAL | FDDB |
14 | | --------- |-----------| ---------|
15 | | 99.89 | 99.11 | 0.983 |
16 |
17 | I'm using resnet50/resnet101 to train DSFD,the result will be published later on
18 | ### Requirement
19 | * pytorch 0.3
20 | * opencv
21 | * numpy
22 | * easydict
23 |
24 | ### Prepare data
25 | 1. download WIDER face dataset
26 | 2. modify data/config.py
27 | 3. ``` python prepare_wider_data.py```
28 |
29 |
30 | ### Train
31 | ```
32 | python train.py --batch_size 4
33 | --model vgg\resnet50\resnet101
34 | --lr 5e-4
35 | ```
36 |
37 | ### Evalution
38 | according to yourself dataset path,modify data/config.py
39 | 1. Evaluate on AFW.
40 | ```
41 | python tools/afw_test.py
42 | ```
43 | 2. Evaluate on FDDB
44 | ```
45 | python tools/fddb_test.py
46 | ```
47 | 3. Evaluate on PASCAL face
48 | ```
49 | python tools/pascal_test.py
50 | ```
51 | 4. test on WIDER FACE
52 | ```
53 | python tools/wider_test.py
54 | ```
55 | ### Demo
56 | you can test yourself image
57 | ```
58 | python demo.py
59 | ```
60 |
61 | ### Result
62 | 1. demo
63 |
64 |

65 |

66 |
67 |
68 |
69 | ### References
70 | * [Dual Shot Face Detector](https://arxiv.org/abs/1810.10220?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+arxiv%2FQSXk+%28ExcitingAds%21+cs+updates+on+arXiv.org%29)
71 | * [ssd.pytorch](https://github.com/amdegroot/ssd.pytorch)
--------------------------------------------------------------------------------
/data/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/data/__init__.py
--------------------------------------------------------------------------------
/data/config.py:
--------------------------------------------------------------------------------
1 | #-*- coding:utf-8 -*-
2 |
3 | from __future__ import division
4 | from __future__ import absolute_import
5 | from __future__ import print_function
6 |
7 | import os
8 | from easydict import EasyDict
9 | import numpy as np
10 |
11 |
12 | _C = EasyDict()
13 | cfg = _C
14 | # data augument config
15 | _C.expand_prob = 0.5
16 | _C.expand_max_ratio = 4
17 | _C.hue_prob = 0.5
18 | _C.hue_delta = 18
19 | _C.contrast_prob = 0.5
20 | _C.contrast_delta = 0.5
21 | _C.saturation_prob = 0.5
22 | _C.saturation_delta = 0.5
23 | _C.brightness_prob = 0.5
24 | _C.brightness_delta = 0.125
25 | _C.data_anchor_sampling_prob = 0.5
26 | _C.min_face_size = 6.0
27 | _C.apply_distort = True
28 | _C.apply_expand = False
29 | _C.img_mean = np.array([104., 117., 123.])[:, np.newaxis, np.newaxis].astype(
30 | 'float32')
31 | _C.resize_width = 640
32 | _C.resize_height = 640
33 | _C.scale = 1 / 127.0
34 | _C.anchor_sampling = True
35 | _C.filter_min_face = True
36 |
37 | # train config
38 | _C.LR_STEPS = (80000,100000,120000)
39 | _C.MAX_STEPS = 150000
40 | _C.EPOCHES = 100
41 |
42 | # anchor config
43 | _C.FEATURE_MAPS = [160, 80, 40, 20, 10, 5]
44 | _C.INPUT_SIZE = 640
45 | _C.STEPS = [4, 8, 16, 32, 64, 128]
46 | _C.ANCHOR_SIZES1 = [8, 16, 32, 64, 128, 256]
47 | _C.ANCHOR_SIZES2 = [16, 32, 64, 128, 256, 512]
48 | _C.ASPECT_RATIO = [1.0]
49 | _C.CLIP = False
50 | _C.VARIANCE = [0.1, 0.2]
51 |
52 | # detection config
53 | _C.NMS_THRESH = 0.3
54 | _C.NMS_TOP_K = 5000
55 | _C.TOP_K = 750
56 | _C.CONF_THRESH = 0.05
57 |
58 | # loss config
59 | _C.NEG_POS_RATIOS = 3
60 | _C.NUM_CLASSES = 2
61 |
62 | # dataset config
63 | _C.HOME = '/home/lijun/data/'
64 |
65 |
66 | # face config
67 | _C.FACE = EasyDict()
68 | _C.FACE.TRAIN_FILE = './data/face_train.txt'
69 | _C.FACE.VAL_FILE = './data/face_val.txt'
70 | _C.FACE.FDDB_DIR = '/home/lijun/data/FDDB'
71 | _C.FACE.WIDER_DIR = '/home/lijun/data/WIDER'
72 | _C.FACE.AFW_DIR = '/home/lijun/data/AFW'
73 | _C.FACE.PASCAL_DIR = '/home/lijun/data/PASCAL_FACE'
74 | _C.FACE.OVERLAP_THRESH = 0.35
75 |
--------------------------------------------------------------------------------
/data/widerface.py:
--------------------------------------------------------------------------------
1 | #-*- coding:utf-8 -*-
2 |
3 | from __future__ import absolute_import
4 | from __future__ import division
5 | from __future__ import print_function
6 |
7 | import torch
8 | from PIL import Image, ImageDraw
9 | import torch.utils.data as data
10 | import numpy as np
11 | import random
12 | from utils.augmentations import preprocess
13 |
14 |
15 | class WIDERDetection(data.Dataset):
16 | """docstring for WIDERDetection"""
17 |
18 | def __init__(self, list_file, mode='train'):
19 | super(WIDERDetection, self).__init__()
20 | self.mode = mode
21 | self.fnames = []
22 | self.boxes = []
23 | self.labels = []
24 |
25 | with open(list_file) as f:
26 | lines = f.readlines()
27 |
28 | for line in lines:
29 | line = line.strip().split()
30 | num_faces = int(line[1])
31 | box = []
32 | label = []
33 | for i in xrange(num_faces):
34 | x = float(line[2 + 5 * i])
35 | y = float(line[3 + 5 * i])
36 | w = float(line[4 + 5 * i])
37 | h = float(line[5 + 5 * i])
38 | c = int(line[6 + 5 * i])
39 | if w <= 0 or h <= 0:
40 | continue
41 | box.append([x, y, x + w, y + h])
42 | label.append(c)
43 | if len(box) > 0:
44 | self.fnames.append(line[0])
45 | self.boxes.append(box)
46 | self.labels.append(label)
47 |
48 | self.num_samples = len(self.boxes)
49 |
50 | def __len__(self):
51 | return self.num_samples
52 |
53 | def __getitem__(self, index):
54 | img, target, h, w = self.pull_item(index)
55 | return img, target
56 |
57 | def pull_item(self, index):
58 | while True:
59 | image_path = self.fnames[index]
60 | img = Image.open(image_path)
61 | if img.mode == 'L':
62 | img = img.convert('RGB')
63 |
64 | im_width, im_height = img.size
65 | boxes = self.annotransform(
66 | np.array(self.boxes[index]), im_width, im_height)
67 | label = np.array(self.labels[index])
68 | bbox_labels = np.hstack((label[:, np.newaxis], boxes)).tolist()
69 | img, sample_labels = preprocess(
70 | img, bbox_labels, self.mode, image_path)
71 | sample_labels = np.array(sample_labels)
72 | if len(sample_labels) > 0:
73 | target = np.hstack(
74 | (sample_labels[:, 1:], sample_labels[:, 0][:, np.newaxis]))
75 |
76 | assert (target[:, 2] > target[:, 0]).any()
77 | assert (target[:, 3] > target[:, 1]).any()
78 | break
79 | else:
80 | index = random.randrange(0, self.num_samples)
81 |
82 |
83 | #img = Image.fromarray(img)
84 | '''
85 | draw = ImageDraw.Draw(img)
86 | w,h = img.size
87 | for bbox in sample_labels:
88 | bbox = (bbox[1:] * np.array([w, h, w, h])).tolist()
89 |
90 | draw.rectangle(bbox,outline='red')
91 | img.save('image.jpg')
92 | '''
93 | return torch.from_numpy(img), target, im_height, im_width
94 |
95 |
96 | def annotransform(self, boxes, im_width, im_height):
97 | boxes[:, 0] /= im_width
98 | boxes[:, 1] /= im_height
99 | boxes[:, 2] /= im_width
100 | boxes[:, 3] /= im_height
101 | return boxes
102 |
103 |
104 | def detection_collate(batch):
105 | """Custom collate fn for dealing with batches of images that have a different
106 | number of associated object annotations (bounding boxes).
107 |
108 | Arguments:
109 | batch: (tuple) A tuple of tensor images and lists of annotations
110 |
111 | Return:
112 | A tuple containing:
113 | 1) (tensor) batch of images stacked on their 0 dim
114 | 2) (list of tensors) annotations for a given image are stacked on
115 | 0 dim
116 | """
117 | targets = []
118 | imgs = []
119 | for sample in batch:
120 | imgs.append(sample[0])
121 | targets.append(torch.FloatTensor(sample[1]))
122 | return torch.stack(imgs, 0), targets
123 |
124 |
125 | if __name__ == '__main__':
126 | from config import cfg
127 | dataset = WIDERDetection(cfg.FACE.TRAIN_FILE)
128 | #for i in range(len(dataset)):
129 | dataset.pull_item(14)
130 |
--------------------------------------------------------------------------------
/demo.py:
--------------------------------------------------------------------------------
1 | #-*- coding:utf-8 -*-
2 |
3 | from __future__ import division
4 | from __future__ import absolute_import
5 | from __future__ import print_function
6 |
7 | import os
8 | import torch
9 | import argparse
10 | import torch.nn as nn
11 | import torch.utils.data as data
12 | import torch.backends.cudnn as cudnn
13 | import torchvision.transforms as transforms
14 |
15 | import cv2
16 | import time
17 | import numpy as np
18 | from PIL import Image
19 |
20 | from data.config import cfg
21 | from models.factory import build_net
22 | from torch.autograd import Variable
23 | from utils.augmentations import to_chw_bgr
24 |
25 |
26 | parser = argparse.ArgumentParser(description='dsfd demo')
27 | parser.add_argument('--network',
28 | default='vgg', type=str,
29 | choices=['vgg', 'resnet50', 'resnet101', 'resnet152'],
30 | help='model for training')
31 | parser.add_argument('--save_dir',
32 | type=str, default='tmp/',
33 | help='Directory for detect result')
34 | parser.add_argument('--model',
35 | type=str,
36 | default='weights/dsfd_face.pth', help='trained model')
37 | parser.add_argument('--thresh',
38 | default=0.4, type=float,
39 | help='Final confidence threshold')
40 | args = parser.parse_args()
41 |
42 |
43 | if not os.path.exists(args.save_dir):
44 | os.makedirs(args.save_dir)
45 |
46 | use_cuda = torch.cuda.is_available()
47 |
48 | if use_cuda:
49 | torch.set_default_tensor_type('torch.cuda.FloatTensor')
50 | else:
51 | torch.set_default_tensor_type('torch.FloatTensor')
52 |
53 |
54 | def detect(net, img_path, thresh):
55 | img = Image.open(img_path)
56 | if img.mode == 'L':
57 | img = img.convert('RGB')
58 |
59 | img = np.array(img)
60 | height, width, _ = img.shape
61 | max_im_shrink = np.sqrt(
62 | 1500 * 1000 / (img.shape[0] * img.shape[1]))
63 | image = cv2.resize(img, None, None, fx=max_im_shrink,
64 | fy=max_im_shrink, interpolation=cv2.INTER_LINEAR)
65 |
66 | x = to_chw_bgr(image)
67 | x = x.astype('float32')
68 | x -= cfg.img_mean
69 | x = x[[2, 1, 0], :, :]
70 |
71 | x = Variable(torch.from_numpy(x).unsqueeze(0))
72 | if use_cuda:
73 | x = x.cuda()
74 | t1 = time.time()
75 | y = net(x)
76 | detections = y.data
77 | scale = torch.Tensor([img.shape[1], img.shape[0],
78 | img.shape[1], img.shape[0]])
79 |
80 | img = cv2.imread(img_path, cv2.IMREAD_COLOR)
81 |
82 | for i in range(detections.size(1)):
83 | j = 0
84 | while detections[0, i, j, 0] >= thresh:
85 | score = detections[0, i, j, 0]
86 | pt = (detections[0, i, j, 1:] * scale).cpu().numpy().astype(int)
87 | left_up, right_bottom = (pt[0], pt[1]), (pt[2], pt[3])
88 | j += 1
89 | cv2.rectangle(img, left_up, right_bottom, (0, 0, 255), 2)
90 | conf = "{:.2f}".format(score)
91 | text_size, baseline = cv2.getTextSize(
92 | conf, cv2.FONT_HERSHEY_SIMPLEX, 0.3, 1)
93 | p1 = (left_up[0], left_up[1] - text_size[1])
94 | cv2.rectangle(img, (p1[0] - 2 // 2, p1[1] - 2 - baseline),
95 | (p1[0] + text_size[0], p1[1] + text_size[1]),[255,0,0], -1)
96 | cv2.putText(img, conf, (p1[0], p1[
97 | 1] + baseline), cv2.FONT_HERSHEY_SIMPLEX, 0.3, (255, 255, 255), 1, 8)
98 |
99 | t2 = time.time()
100 | print('detect:{} timer:{}'.format(img_path, t2 - t1))
101 |
102 | cv2.imwrite(os.path.join(args.save_dir, os.path.basename(img_path)), img)
103 |
104 |
105 | if __name__ == '__main__':
106 | net = build_net('test', cfg.NUM_CLASSES, args.network)
107 | net.load_state_dict(torch.load(args.model))
108 | net.eval()
109 |
110 | if use_cuda:
111 | net.cuda()
112 | cudnn.benckmark = True
113 |
114 | img_path = './img'
115 | img_list = [os.path.join(img_path, x)
116 | for x in os.listdir(img_path) if x.endswith('jpg')]
117 | for path in img_list:
118 | detect(net, path, args.thresh)
119 |
--------------------------------------------------------------------------------
/eval_tools/boxoverlap.m:
--------------------------------------------------------------------------------
1 | function o = boxoverlap(a, b)
2 | % Compute the symmetric intersection over union overlap between a set of
3 | % bounding boxes in a and a single bounding box in b.
4 | %
5 | % a a matrix where each row specifies a bounding box
6 | % b a single bounding box
7 |
8 | % AUTORIGHTS
9 | % -------------------------------------------------------
10 | % Copyright (C) 2011-2012 Ross Girshick
11 | % Copyright (C) 2008, 2009, 2010 Pedro Felzenszwalb, Ross Girshick
12 | %
13 | % This file is part of the voc-releaseX code
14 | % (http://people.cs.uchicago.edu/~rbg/latent/)
15 | % and is available under the terms of an MIT-like license
16 | % provided in COPYING. Please retain this notice and
17 | % COPYING if you use this file (or a portion of it) in
18 | % your project.
19 | % -------------------------------------------------------
20 |
21 | x1 = max(a(:,1), b(1));
22 | y1 = max(a(:,2), b(2));
23 | x2 = min(a(:,3), b(3));
24 | y2 = min(a(:,4), b(4));
25 |
26 | w = x2-x1+1;
27 | h = y2-y1+1;
28 | inter = w.*h;
29 | aarea = (a(:,3)-a(:,1)+1) .* (a(:,4)-a(:,2)+1);
30 | barea = (b(3)-b(1)+1) * (b(4)-b(2)+1);
31 | % intersection over union overlap
32 | o = inter ./ (aarea+barea-inter);
33 | % set invalid entries to 0 overlap
34 | o(w <= 0) = 0;
35 | o(h <= 0) = 0;
36 |
--------------------------------------------------------------------------------
/eval_tools/evaluation.m:
--------------------------------------------------------------------------------
1 | function evaluation(norm_pred_list,gt_dir,setting_name,setting_class,legend_name)
2 | load(gt_dir);
3 | if ~exist(sprintf('./plot/baselines/Val/%s/%s',setting_class,legend_name),'dir')
4 | mkdir(sprintf('./plot/baselines/Val/%s/%s',setting_class,legend_name));
5 | end
6 | IoU_thresh = 0.5;
7 | event_num = 61;
8 | thresh_num = 1000;
9 | org_pr_cruve = zeros(thresh_num,2);
10 | count_face = 0;
11 |
12 | for i = 1:event_num
13 | img_list = file_list{i};
14 | gt_bbx_list = face_bbx_list{i};
15 | pred_list = norm_pred_list{i};
16 | sub_gt_list = gt_list{i};
17 | img_pr_info_list = cell(length(img_list),1);
18 |
19 | fprintf('%s, current event %d\n',setting_name,i);
20 | for j = 1:length(img_list)
21 | gt_bbx = gt_bbx_list{j};
22 | pred_info = pred_list{j};
23 | keep_index = sub_gt_list{j};
24 | count_face = count_face + length(keep_index);
25 |
26 | if isempty(gt_bbx) || isempty(pred_info)
27 | continue;
28 | end
29 | ignore = zeros(size(gt_bbx,1),1);
30 | if ~isempty(keep_index)
31 | ignore(keep_index) = 1;
32 | end
33 |
34 | [pred_recall, proposal_list] = image_evaluation(pred_info, gt_bbx, ignore, IoU_thresh);
35 |
36 | img_pr_info = image_pr_info(thresh_num, pred_info, proposal_list, pred_recall);
37 | img_pr_info_list{j} = img_pr_info;
38 | end
39 | for j = 1:length(img_list)
40 | img_pr_info = img_pr_info_list{j};
41 | if ~isempty(img_pr_info)
42 | org_pr_cruve(:,1) = org_pr_cruve(:,1) + img_pr_info(:,1);
43 | org_pr_cruve(:,2) = org_pr_cruve(:,2) + img_pr_info(:,2);
44 | end
45 | end
46 | end
47 | pr_cruve = dataset_pr_info(thresh_num, org_pr_cruve, count_face);
48 | save(sprintf('./plot/baselines/Val/%s/%s/wider_pr_info_%s_%s.mat',setting_class,legend_name,legend_name,setting_name),'pr_cruve','legend_name','-v7.3');
49 | end
50 |
51 | function [pred_recall,proposal_list] = image_evaluation(pred_info, gt_bbx, ignore, IoU_thresh)
52 | pred_recall = zeros(size(pred_info,1),1);
53 | recall_list = zeros(size(gt_bbx,1),1);
54 | proposal_list = zeros(size(pred_info,1),1);
55 | proposal_list = proposal_list + 1;
56 | pred_info(:,3) = pred_info(:,1) + pred_info(:,3);
57 | pred_info(:,4) = pred_info(:,2) + pred_info(:,4);
58 | gt_bbx(:,3) = gt_bbx(:,1) + gt_bbx(:,3);
59 | gt_bbx(:,4) = gt_bbx(:,2) + gt_bbx(:,4);
60 | for h = 1:size(pred_info,1)
61 | overlap_list = boxoverlap(gt_bbx, pred_info(h,1:4));
62 | [max_overlap, idx] = max(overlap_list);
63 | if max_overlap >= IoU_thresh
64 | if (ignore(idx) == 0)
65 | recall_list(idx) = -1;
66 | proposal_list(h) = -1;
67 | elseif (recall_list(idx)==0)
68 | recall_list(idx) = 1;
69 | end
70 | end
71 | r_keep_index = find(recall_list == 1);
72 | pred_recall(h) = length(r_keep_index);
73 | end
74 | end
75 |
76 | function img_pr_info = image_pr_info(thresh_num, pred_info, proposal_list, pred_recall)
77 | img_pr_info = zeros(thresh_num,2);
78 | for t = 1:thresh_num
79 | thresh = 1-t/thresh_num;
80 | r_index = find(pred_info(:,5)>=thresh,1,'last');
81 | if (isempty(r_index))
82 | img_pr_info(t,2) = 0;
83 | img_pr_info(t,1) = 0;
84 | else
85 | p_index = find(proposal_list(1:r_index) == 1);
86 | img_pr_info(t,1) = length(p_index);
87 | img_pr_info(t,2) = pred_recall(r_index);
88 | end
89 | end
90 | end
91 |
92 | function pr_cruve = dataset_pr_info(thresh_num, org_pr_cruve, count_face)
93 | pr_cruve = zeros(thresh_num,2);
94 | for i = 1:thresh_num
95 | pr_cruve(i,1) = org_pr_cruve(i,2)/org_pr_cruve(i,1);
96 | pr_cruve(i,2) = org_pr_cruve(i,2)/count_face;
97 | end
98 | end
99 |
--------------------------------------------------------------------------------
/eval_tools/ground_truth/wider_easy_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/ground_truth/wider_easy_val.mat
--------------------------------------------------------------------------------
/eval_tools/ground_truth/wider_face_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/ground_truth/wider_face_val.mat
--------------------------------------------------------------------------------
/eval_tools/ground_truth/wider_hard_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/ground_truth/wider_hard_val.mat
--------------------------------------------------------------------------------
/eval_tools/ground_truth/wider_medium_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/ground_truth/wider_medium_val.mat
--------------------------------------------------------------------------------
/eval_tools/nms.m:
--------------------------------------------------------------------------------
1 | function pick = nms(boxes, overlap)
2 | % top = nms(boxes, overlap)
3 | % Non-maximum suppression. (FAST VERSION)
4 | % Greedily select high-scoring detections and skip detections
5 | % that are significantly covered by a previously selected
6 | % detection.
7 | %
8 | % NOTE: This is adapted from Pedro Felzenszwalb's version (nms.m),
9 | % but an inner loop has been eliminated to significantly speed it
10 | % up in the case of a large number of boxes
11 |
12 | % Copyright (C) 2011-12 by Tomasz Malisiewicz
13 | % All rights reserved.
14 | %
15 | % This file is part of the Exemplar-SVM library and is made
16 | % available under the terms of the MIT license (see COPYING file).
17 | % Project homepage: https://github.com/quantombone/exemplarsvm
18 |
19 |
20 | if isempty(boxes)
21 | pick = [];
22 | return;
23 | end
24 |
25 | x1 = boxes(:,1);
26 | y1 = boxes(:,2);
27 | x2 = boxes(:,3);
28 | y2 = boxes(:,4);
29 | s = boxes(:,end);
30 |
31 | area = (x2-x1+1) .* (y2-y1+1);
32 | [vals, I] = sort(s);
33 |
34 | pick = s*0;
35 | counter = 1;
36 | while ~isempty(I)
37 | last = length(I);
38 | i = I(last);
39 | pick(counter) = i;
40 | counter = counter + 1;
41 |
42 | xx1 = max(x1(i), x1(I(1:last-1)));
43 | yy1 = max(y1(i), y1(I(1:last-1)));
44 | xx2 = min(x2(i), x2(I(1:last-1)));
45 | yy2 = min(y2(i), y2(I(1:last-1)));
46 |
47 | w = max(0.0, xx2-xx1+1);
48 | h = max(0.0, yy2-yy1+1);
49 |
50 | inter = w.*h;
51 | o = inter ./ (area(i) + area(I(1:last-1)) - inter);
52 |
53 | I = I(find(o<=overlap));
54 | end
55 |
56 | pick = pick(1:(counter-1));
--------------------------------------------------------------------------------
/eval_tools/norm_score.m:
--------------------------------------------------------------------------------
1 | function norm_pred_list = norm_score(org_pred_list)
2 |
3 | event_num = 61;
4 | norm_pred_list = cell(event_num,1);
5 | max_score = realmin('single');
6 | min_score = realmax('single');
7 | parfor i = 1:event_num
8 | pred_list = org_pred_list{i};
9 | for j = 1:size(pred_list,1)
10 | if(isempty(pred_list{j}))
11 | continue;
12 | end
13 | score_list = pred_list{j}(:,5);
14 | max_score = max(max_score,max(score_list));
15 | min_score = min(min_score,min(score_list));
16 | end
17 | end
18 |
19 | parfor i = 1:event_num
20 | fprintf('Norm prediction: current event %d\n',i);
21 | pred_list = org_pred_list{i};
22 | for j = 1:size(pred_list,1)
23 | if(isempty(pred_list{j}))
24 | continue;
25 | end
26 | score_list = pred_list{j}(:,5);
27 | norm_score_list = (score_list - min_score)/(max_score - min_score);
28 | pred_list{j}(:,5) = norm_score_list;
29 | end
30 | norm_pred_list{i} = pred_list;
31 | end
32 |
--------------------------------------------------------------------------------
/eval_tools/plot/VOCap.m:
--------------------------------------------------------------------------------
1 | function ap = VOCap(rec,prec)
2 |
3 | mrec=[0 ; rec ; 1];
4 | mpre=[0 ; prec ; 0];
5 | for i=numel(mpre)-1:-1:1
6 | mpre(i)=max(mpre(i),mpre(i+1));
7 | end
8 | i=find(mrec(2:end)~=mrec(1:end-1))+1;
9 | ap=sum((mrec(i)-mrec(i-1)).*mpre(i));
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_ext/acf/wider_pr_info_acf_easy.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_ext/acf/wider_pr_info_acf_easy.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_ext/acf/wider_pr_info_acf_hard.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_ext/acf/wider_pr_info_acf_hard.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_ext/acf/wider_pr_info_acf_medium.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_ext/acf/wider_pr_info_acf_medium.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_ext/dpm/wider_pr_info_dpm_easy.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_ext/dpm/wider_pr_info_dpm_easy.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_ext/dpm/wider_pr_info_dpm_hard.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_ext/dpm/wider_pr_info_dpm_hard.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_ext/dpm/wider_pr_info_dpm_medium.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_ext/dpm/wider_pr_info_dpm_medium.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_ext/faceness/wider_pr_info_faceness_easy.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_ext/faceness/wider_pr_info_faceness_easy.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_ext/faceness/wider_pr_info_faceness_hard.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_ext/faceness/wider_pr_info_faceness_hard.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_ext/faceness/wider_pr_info_faceness_medium.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_ext/faceness/wider_pr_info_faceness_medium.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_ext/vj/wider_pr_info_vj_easy.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_ext/vj/wider_pr_info_vj_easy.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_ext/vj/wider_pr_info_vj_hard.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_ext/vj/wider_pr_info_vj_hard.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_ext/vj/wider_pr_info_vj_medium.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_ext/vj/wider_pr_info_vj_medium.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/DSFD/wider_pr_info_DSFD_easy.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/DSFD/wider_pr_info_DSFD_easy.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/DSFD/wider_pr_info_DSFD_hard.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/DSFD/wider_pr_info_DSFD_hard.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/DSFD/wider_pr_info_DSFD_medium.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/DSFD/wider_pr_info_DSFD_medium.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/FAN/wider_pr_info_FAN_easy.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/FAN/wider_pr_info_FAN_easy.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/FAN/wider_pr_info_FAN_hard.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/FAN/wider_pr_info_FAN_hard.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/FAN/wider_pr_info_FAN_medium.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/FAN/wider_pr_info_FAN_medium.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/FANet/wider_pr_info_FANet_easy.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/FANet/wider_pr_info_FANet_easy.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/FANet/wider_pr_info_FANet_hard.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/FANet/wider_pr_info_FANet_hard.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/FANet/wider_pr_info_FANet_medium.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/FANet/wider_pr_info_FANet_medium.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/FDNet/wider_pr_info_FDNet_easy.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/FDNet/wider_pr_info_FDNet_easy.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/FDNet/wider_pr_info_FDNet_hard.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/FDNet/wider_pr_info_FDNet_hard.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/FDNet/wider_pr_info_FDNet_medium.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/FDNet/wider_pr_info_FDNet_medium.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/Face R-CNN/wider_pr_info_Face R-CNN_easy.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/Face R-CNN/wider_pr_info_Face R-CNN_easy.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/Face R-CNN/wider_pr_info_Face R-CNN_hard.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/Face R-CNN/wider_pr_info_Face R-CNN_hard.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/Face R-CNN/wider_pr_info_Face R-CNN_medium.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/Face R-CNN/wider_pr_info_Face R-CNN_medium.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/Face R-FCN/wider_pr_info_Face R-FCN_easy.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/Face R-FCN/wider_pr_info_Face R-FCN_easy.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/Face R-FCN/wider_pr_info_Face R-FCN_hard.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/Face R-FCN/wider_pr_info_Face R-FCN_hard.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/Face R-FCN/wider_pr_info_Face R-FCN_medium.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/Face R-FCN/wider_pr_info_Face R-FCN_medium.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/HR/wider_pr_info_HR_easy.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/HR/wider_pr_info_HR_easy.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/HR/wider_pr_info_HR_hard.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/HR/wider_pr_info_HR_hard.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/HR/wider_pr_info_HR_medium.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/HR/wider_pr_info_HR_medium.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/LDCF+/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/LDCF+/.DS_Store
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/LDCF+/wider_pr_info_LDCF+_easy.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/LDCF+/wider_pr_info_LDCF+_easy.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/LDCF+/wider_pr_info_LDCF+_hard.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/LDCF+/wider_pr_info_LDCF+_hard.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/LDCF+/wider_pr_info_LDCF+_medium.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/LDCF+/wider_pr_info_LDCF+_medium.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/MSCNN/wider_pr_info_MSCNN_easy.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/MSCNN/wider_pr_info_MSCNN_easy.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/MSCNN/wider_pr_info_MSCNN_hard.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/MSCNN/wider_pr_info_MSCNN_hard.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/MSCNN/wider_pr_info_MSCNN_medium.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/MSCNN/wider_pr_info_MSCNN_medium.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/PyramidBox/wider_pr_info_PyramidBox_easy.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/PyramidBox/wider_pr_info_PyramidBox_easy.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/PyramidBox/wider_pr_info_PyramidBox_hard.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/PyramidBox/wider_pr_info_PyramidBox_hard.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/PyramidBox/wider_pr_info_PyramidBox_medium.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/PyramidBox/wider_pr_info_PyramidBox_medium.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/SFD/wider_pr_info_SFD_easy.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/SFD/wider_pr_info_SFD_easy.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/SFD/wider_pr_info_SFD_hard.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/SFD/wider_pr_info_SFD_hard.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/SFD/wider_pr_info_SFD_medium.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/SFD/wider_pr_info_SFD_medium.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/SRN/wider_pr_info_SRN_easy.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/SRN/wider_pr_info_SRN_easy.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/SRN/wider_pr_info_SRN_hard.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/SRN/wider_pr_info_SRN_hard.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/SRN/wider_pr_info_SRN_medium.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/SRN/wider_pr_info_SRN_medium.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/SSH/wider_pr_info_SSH_easy.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/SSH/wider_pr_info_SSH_easy.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/SSH/wider_pr_info_SSH_hard.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/SSH/wider_pr_info_SSH_hard.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/SSH/wider_pr_info_SSH_medium.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/SSH/wider_pr_info_SSH_medium.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/ScaleFace/wider_pr_info_ScaleFace_easy.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/ScaleFace/wider_pr_info_ScaleFace_easy.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/ScaleFace/wider_pr_info_ScaleFace_hard.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/ScaleFace/wider_pr_info_ScaleFace_hard.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/ScaleFace/wider_pr_info_ScaleFace_medium.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/ScaleFace/wider_pr_info_ScaleFace_medium.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/ZCC/wider_pr_info_ZCC_easy.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/ZCC/wider_pr_info_ZCC_easy.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/ZCC/wider_pr_info_ZCC_hard.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/ZCC/wider_pr_info_ZCC_hard.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/ZCC/wider_pr_info_ZCC_medium.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/ZCC/wider_pr_info_ZCC_medium.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/acf/wider_pr_info_acf_easy.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/acf/wider_pr_info_acf_easy.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/acf/wider_pr_info_acf_hard.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/acf/wider_pr_info_acf_hard.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/acf/wider_pr_info_acf_medium.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/acf/wider_pr_info_acf_medium.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/cms-rcnn/wider_pr_info_cms-rcnn_easy.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/cms-rcnn/wider_pr_info_cms-rcnn_easy.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/cms-rcnn/wider_pr_info_cms-rcnn_hard.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/cms-rcnn/wider_pr_info_cms-rcnn_hard.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/cms-rcnn/wider_pr_info_cms-rcnn_medium.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/cms-rcnn/wider_pr_info_cms-rcnn_medium.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/faceness/wider_pr_info_faceness_easy.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/faceness/wider_pr_info_faceness_easy.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/faceness/wider_pr_info_faceness_hard.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/faceness/wider_pr_info_faceness_hard.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/faceness/wider_pr_info_faceness_medium.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/faceness/wider_pr_info_faceness_medium.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/multiscale_cascade/wider_pr_info_multiscale_cascade_easy.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/multiscale_cascade/wider_pr_info_multiscale_cascade_easy.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/multiscale_cascade/wider_pr_info_multiscale_cascade_hard.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/multiscale_cascade/wider_pr_info_multiscale_cascade_hard.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/multiscale_cascade/wider_pr_info_multiscale_cascade_medium.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/multiscale_cascade/wider_pr_info_multiscale_cascade_medium.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/multitask-cascade-cnn/wider_pr_info_multitask-cascade-cnn_easy.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/multitask-cascade-cnn/wider_pr_info_multitask-cascade-cnn_easy.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/multitask-cascade-cnn/wider_pr_info_multitask-cascade-cnn_hard.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/multitask-cascade-cnn/wider_pr_info_multitask-cascade-cnn_hard.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/multitask-cascade-cnn/wider_pr_info_multitask-cascade-cnn_medium.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/multitask-cascade-cnn/wider_pr_info_multitask-cascade-cnn_medium.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/two_stage_cnn/wider_pr_info_two_stage_cnn_easy.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/two_stage_cnn/wider_pr_info_two_stage_cnn_easy.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/two_stage_cnn/wider_pr_info_two_stage_cnn_hard.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/two_stage_cnn/wider_pr_info_two_stage_cnn_hard.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Test/setting_int/two_stage_cnn/wider_pr_info_two_stage_cnn_medium.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Test/setting_int/two_stage_cnn/wider_pr_info_two_stage_cnn_medium.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/DSFD/wider_pr_info_DSFD_easy_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/DSFD/wider_pr_info_DSFD_easy_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/DSFD/wider_pr_info_DSFD_hard_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/DSFD/wider_pr_info_DSFD_hard_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/DSFD/wider_pr_info_DSFD_medium_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/DSFD/wider_pr_info_DSFD_medium_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/FAN/wider_pr_info_fan_easy_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/FAN/wider_pr_info_fan_easy_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/FAN/wider_pr_info_fan_hard_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/FAN/wider_pr_info_fan_hard_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/FAN/wider_pr_info_fan_medium_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/FAN/wider_pr_info_fan_medium_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/FANet/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/FANet/.DS_Store
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/FANet/wider_pr_info_FANet_easy_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/FANet/wider_pr_info_FANet_easy_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/FANet/wider_pr_info_FANet_hard_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/FANet/wider_pr_info_FANet_hard_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/FANet/wider_pr_info_FANet_medium_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/FANet/wider_pr_info_FANet_medium_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/FDNet/wider_pr_info_FDNet_easy_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/FDNet/wider_pr_info_FDNet_easy_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/FDNet/wider_pr_info_FDNet_hard_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/FDNet/wider_pr_info_FDNet_hard_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/FDNet/wider_pr_info_FDNet_medium_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/FDNet/wider_pr_info_FDNet_medium_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/Face R-CNN/wider_pr_info_Face R-CNN_easy_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/Face R-CNN/wider_pr_info_Face R-CNN_easy_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/Face R-CNN/wider_pr_info_Face R-CNN_hard_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/Face R-CNN/wider_pr_info_Face R-CNN_hard_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/Face R-CNN/wider_pr_info_Face R-CNN_medium_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/Face R-CNN/wider_pr_info_Face R-CNN_medium_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/Face R-FCN/wider_pr_info_Face R-FCN_easy_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/Face R-FCN/wider_pr_info_Face R-FCN_easy_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/Face R-FCN/wider_pr_info_Face R-FCN_hard_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/Face R-FCN/wider_pr_info_Face R-FCN_hard_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/Face R-FCN/wider_pr_info_Face R-FCN_medium_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/Face R-FCN/wider_pr_info_Face R-FCN_medium_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/HR/wider_pr_info_HR_easy_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/HR/wider_pr_info_HR_easy_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/HR/wider_pr_info_HR_hard_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/HR/wider_pr_info_HR_hard_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/HR/wider_pr_info_HR_medium_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/HR/wider_pr_info_HR_medium_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/LDCF+/wider_pr_info_LDCF+_easy_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/LDCF+/wider_pr_info_LDCF+_easy_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/LDCF+/wider_pr_info_LDCF+_hard_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/LDCF+/wider_pr_info_LDCF+_hard_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/LDCF+/wider_pr_info_LDCF+_medium_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/LDCF+/wider_pr_info_LDCF+_medium_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/MSCNN/wider_pr_info_MSCNN_easy_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/MSCNN/wider_pr_info_MSCNN_easy_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/MSCNN/wider_pr_info_MSCNN_hard_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/MSCNN/wider_pr_info_MSCNN_hard_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/MSCNN/wider_pr_info_MSCNN_medium_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/MSCNN/wider_pr_info_MSCNN_medium_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/PyramidBox/wider_pr_info_PyramidBox_easy_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/PyramidBox/wider_pr_info_PyramidBox_easy_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/PyramidBox/wider_pr_info_PyramidBox_hard_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/PyramidBox/wider_pr_info_PyramidBox_hard_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/PyramidBox/wider_pr_info_PyramidBox_medium_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/PyramidBox/wider_pr_info_PyramidBox_medium_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/SFD/wider_pr_info_SFD_easy_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/SFD/wider_pr_info_SFD_easy_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/SFD/wider_pr_info_SFD_hard_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/SFD/wider_pr_info_SFD_hard_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/SFD/wider_pr_info_SFD_medium_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/SFD/wider_pr_info_SFD_medium_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/SRN/wider_pr_info_SRN_easy_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/SRN/wider_pr_info_SRN_easy_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/SRN/wider_pr_info_SRN_hard_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/SRN/wider_pr_info_SRN_hard_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/SRN/wider_pr_info_SRN_medium_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/SRN/wider_pr_info_SRN_medium_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/SSH/wider_pr_info_SSH_easy_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/SSH/wider_pr_info_SSH_easy_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/SSH/wider_pr_info_SSH_hard_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/SSH/wider_pr_info_SSH_hard_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/SSH/wider_pr_info_SSH_medium_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/SSH/wider_pr_info_SSH_medium_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/ScaleFace/wider_pr_info_ScaleFace_easy_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/ScaleFace/wider_pr_info_ScaleFace_easy_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/ScaleFace/wider_pr_info_ScaleFace_hard_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/ScaleFace/wider_pr_info_ScaleFace_hard_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/ScaleFace/wider_pr_info_ScaleFace_medium_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/ScaleFace/wider_pr_info_ScaleFace_medium_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/ZCC/wider_pr_info_ZCC_easy_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/ZCC/wider_pr_info_ZCC_easy_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/ZCC/wider_pr_info_ZCC_hard_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/ZCC/wider_pr_info_ZCC_hard_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/ZCC/wider_pr_info_ZCC_medium_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/ZCC/wider_pr_info_ZCC_medium_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/acf/wider_pr_info_acf_easy_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/acf/wider_pr_info_acf_easy_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/acf/wider_pr_info_acf_hard_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/acf/wider_pr_info_acf_hard_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/acf/wider_pr_info_acf_medium_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/acf/wider_pr_info_acf_medium_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/cms-rcnn/wider_pr_info_cms-rcnn_easy_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/cms-rcnn/wider_pr_info_cms-rcnn_easy_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/cms-rcnn/wider_pr_info_cms-rcnn_hard_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/cms-rcnn/wider_pr_info_cms-rcnn_hard_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/cms-rcnn/wider_pr_info_cms-rcnn_medium_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/cms-rcnn/wider_pr_info_cms-rcnn_medium_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/faceness/wider_pr_info_faceness_easy_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/faceness/wider_pr_info_faceness_easy_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/faceness/wider_pr_info_faceness_hard_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/faceness/wider_pr_info_faceness_hard_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/faceness/wider_pr_info_faceness_medium_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/faceness/wider_pr_info_faceness_medium_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/multiscale_cascade/wider_pr_info_multiscale_cascade_easy_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/multiscale_cascade/wider_pr_info_multiscale_cascade_easy_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/multiscale_cascade/wider_pr_info_multiscale_cascade_hard_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/multiscale_cascade/wider_pr_info_multiscale_cascade_hard_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/multiscale_cascade/wider_pr_info_multiscale_cascade_medium_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/multiscale_cascade/wider_pr_info_multiscale_cascade_medium_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/multitask-cascade-cnn/wider_pr_info_multitask-cascade-cnn_easy_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/multitask-cascade-cnn/wider_pr_info_multitask-cascade-cnn_easy_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/multitask-cascade-cnn/wider_pr_info_multitask-cascade-cnn_hard_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/multitask-cascade-cnn/wider_pr_info_multitask-cascade-cnn_hard_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/multitask-cascade-cnn/wider_pr_info_multitask-cascade-cnn_medium_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/multitask-cascade-cnn/wider_pr_info_multitask-cascade-cnn_medium_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/s3fd.pytorch/wider_pr_info_s3fd.pytorch_easy_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/s3fd.pytorch/wider_pr_info_s3fd.pytorch_easy_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/s3fd.pytorch/wider_pr_info_s3fd.pytorch_hard_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/s3fd.pytorch/wider_pr_info_s3fd.pytorch_hard_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/s3fd.pytorch/wider_pr_info_s3fd.pytorch_medium_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/s3fd.pytorch/wider_pr_info_s3fd.pytorch_medium_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/two_stage_cnn/wider_pr_info_two_stage_cnn_easy_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/two_stage_cnn/wider_pr_info_two_stage_cnn_easy_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/two_stage_cnn/wider_pr_info_two_stage_cnn_hard_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/two_stage_cnn/wider_pr_info_two_stage_cnn_hard_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/baselines/Val/setting_int/two_stage_cnn/wider_pr_info_two_stage_cnn_medium_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/baselines/Val/setting_int/two_stage_cnn/wider_pr_info_two_stage_cnn_medium_val.mat
--------------------------------------------------------------------------------
/eval_tools/plot/figure/Test/wider_pr_cruve_ext_easy.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/figure/Test/wider_pr_cruve_ext_easy.pdf
--------------------------------------------------------------------------------
/eval_tools/plot/figure/Test/wider_pr_cruve_ext_hard.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/figure/Test/wider_pr_cruve_ext_hard.pdf
--------------------------------------------------------------------------------
/eval_tools/plot/figure/Test/wider_pr_cruve_ext_medium.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/figure/Test/wider_pr_cruve_ext_medium.pdf
--------------------------------------------------------------------------------
/eval_tools/plot/figure/Test/wider_pr_cruve_int_easy.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/figure/Test/wider_pr_cruve_int_easy.pdf
--------------------------------------------------------------------------------
/eval_tools/plot/figure/Test/wider_pr_cruve_int_hard.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/figure/Test/wider_pr_cruve_int_hard.pdf
--------------------------------------------------------------------------------
/eval_tools/plot/figure/Test/wider_pr_cruve_int_medium.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/figure/Test/wider_pr_cruve_int_medium.pdf
--------------------------------------------------------------------------------
/eval_tools/plot/figure/Val/wider_pr_cruve_int_easy_val.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/figure/Val/wider_pr_cruve_int_easy_val.pdf
--------------------------------------------------------------------------------
/eval_tools/plot/figure/Val/wider_pr_cruve_int_hard_val.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/figure/Val/wider_pr_cruve_int_hard_val.pdf
--------------------------------------------------------------------------------
/eval_tools/plot/figure/Val/wider_pr_cruve_int_medium_val.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/plot/figure/Val/wider_pr_cruve_int_medium_val.pdf
--------------------------------------------------------------------------------
/eval_tools/plot/plot_pr.m:
--------------------------------------------------------------------------------
1 | function plot_pr(propose,recall,lendge_name,seting_class,setting_name,dateset_class)
2 | model_num = size(propose,1);
3 | figure1 = figure('PaperSize',[20.98 29.68],'Color',[1 1 1], 'rend','painters','pos',[1 1 800 400]);
4 | axes1 = axes('Parent',figure1,...
5 | 'LineWidth',2,...
6 | 'FontSize',10,...
7 | 'FontName','Times New Roman',...
8 | 'FontWeight','bold');
9 | box(axes1,'on');
10 | hold on;
11 |
12 | LineColor = colormap(hsv(model_num));
13 | for i=1:model_num
14 | plot(propose{i},recall{i},...
15 | 'MarkerEdgeColor',LineColor(i,:),...
16 | 'MarkerFaceColor',LineColor(i,:),...
17 | 'LineWidth',3,...
18 | 'Color',LineColor(i,:))
19 | grid on;
20 | hold on;
21 | end
22 | legend1 = legend(lendge_name,'show');
23 | set(legend1,'Location','EastOutside');
24 |
25 | xlim([0,1]);
26 | ylim([0,1]);
27 | xlabel('Recall');
28 | ylabel('Precision');
29 |
30 | savename = sprintf('./plot/figure/%s/wider_pr_cruve_%s_%s.pdf',dateset_class,seting_class,setting_name);
31 | saveTightFigure(gcf,savename);
32 | clear gcf;
33 | hold off;
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/eval_tools/plot/saveTightFigure.m:
--------------------------------------------------------------------------------
1 | function saveTightFigure(h,outfilename)
2 | % SAVETIGHTFIGURE(OUTFILENAME) Saves the current figure without the white
3 | % space/margin around it to the file OUTFILENAME. Output file type is
4 | % determined by the extension of OUTFILENAME. All formats that are
5 | % supported by MATLAB's "saveas" are supported.
6 | %
7 | % SAVETIGHTFIGURE(H, OUTFILENAME) Saves the figure with handle H.
8 | %
9 | % E Akbas (c) Aug 2010
10 | % * Updated to handle subplots and multiple axes. March 2014.
11 | %
12 |
13 | if nargin==1
14 | hfig = gcf;
15 | outfilename = h;
16 | else
17 | hfig = h;
18 | end
19 |
20 | %% find all the axes in the figure
21 | hax = findall(hfig, 'type', 'axes');
22 |
23 | %% compute the tighest box that includes all axes
24 | tighest_box = [Inf Inf -Inf -Inf]; % left bottom right top
25 | for i=1:length(hax)
26 | set(hax(i), 'units', 'centimeters');
27 |
28 | p = get(hax(i), 'position');
29 | ti = get(hax(i), 'tightinset');
30 |
31 | % get position as left, bottom, right, top
32 | p = [p(1) p(2) p(1)+p(3) p(2)+p(4)] + ti.*[-1 -1 1 1];
33 |
34 | tighest_box(1) = min(tighest_box(1), p(1));
35 | tighest_box(2) = min(tighest_box(2), p(2));
36 | tighest_box(3) = max(tighest_box(3), p(3));
37 | tighest_box(4) = max(tighest_box(4), p(4));
38 | end
39 |
40 | %% move all axes to left-bottom
41 | for i=1:length(hax)
42 | if strcmp(get(hax(i),'tag'),'legend')
43 | continue
44 | end
45 | p = get(hax(i), 'position');
46 | set(hax(i), 'position', [p(1)-tighest_box(1) p(2)-tighest_box(2) p(3) p(4)]);
47 | end
48 |
49 | %% resize figure to fit tightly
50 | set(hfig, 'units', 'centimeters');
51 | p = get(hfig, 'position');
52 |
53 | width = tighest_box(3)-tighest_box(1);
54 | height = tighest_box(4)-tighest_box(2);
55 | set(hfig, 'position', [p(1) p(2) p(3) p(4)]);
56 |
57 | %% set papersize
58 | set(hfig,'PaperUnits','centimeters');
59 | set(hfig,'PaperSize', [width height]);
60 | set(hfig,'PaperPositionMode', 'manual');
61 | set(hfig,'PaperPosition',[0 0 width height]);
62 |
63 |
64 | %% save
65 | saveas(hfig,outfilename);
66 |
--------------------------------------------------------------------------------
/eval_tools/plot/wider_plot.m:
--------------------------------------------------------------------------------
1 | function wider_plot(set_list,dir_ext,seting_class,dateset_class)
2 |
3 | method_list = dir(dir_ext);
4 | model_num = size(method_list,1) - 2;
5 | model_name = cell(model_num,1);
6 |
7 | for i = 3:size(method_list,1)
8 | model_name{i-2} = method_list(i).name;
9 | end
10 |
11 | for i = 1:size(set_list,1)
12 | propose = cell(model_num,1);
13 | recall = cell(model_num,1);
14 | name_list = cell(model_num,1);
15 | ap_list = zeros(model_num,1);
16 | for j = 1:model_num
17 | load(sprintf('%s/%s/wider_pr_info_%s_%s.mat',dir_ext, model_name{j}, model_name{j}, set_list{i}));
18 | propose{j} = pr_cruve(:,2);
19 | recall{j} = pr_cruve(:,1);
20 | ap = VOCap(propose{j},recall{j});
21 | ap_list(j) = ap;
22 | ap = num2str(ap);
23 | if length(ap) < 5
24 | name_list{j} = [legend_name '-' ap];
25 | else
26 | name_list{j} = [legend_name '-' ap(1:5)];
27 | end
28 | end
29 | [~,index] = sort(ap_list,'descend');
30 | propose = propose(index);
31 | recall = recall(index);
32 | name_list = name_list(index);
33 | plot_pr(propose, recall, name_list, seting_class, set_list{i},dateset_class);
34 | end
35 |
--------------------------------------------------------------------------------
/eval_tools/read_pred.m:
--------------------------------------------------------------------------------
1 | function pred_list = read_pred(file_dir, gt_dir)
2 |
3 | load(gt_dir);
4 | event_num = 61;
5 | pred_list = cell(event_num,1);
6 |
7 | for i = 1:event_num
8 | fprintf('Read prediction: current event %d\n',i);
9 | img_list = file_list{i};
10 | img_num = size(img_list,1);
11 | bbx_list = cell(img_num,1);
12 | for j = 1:img_num
13 | if ~exist(sprintf('%s/%s/%s.txt',file_dir,event_list{i},img_list{j}),'file')
14 | fprintf('Can not find the prediction file %s %s \n',event_list{i},img_list{j});
15 | continue;
16 | end
17 |
18 | fid = fopen(sprintf('%s/%s/%s.txt',file_dir,event_list{i},img_list{j}),'r');
19 | tmp = textscan(fid,'%s','Delimiter','\n');
20 | tmp = tmp{1};
21 | fclose(fid);
22 | try
23 | bbx_num = tmp{2,1};
24 | bbx_num = str2num(bbx_num);
25 | bbx = zeros(bbx_num,5);
26 | if bbx_num ==0
27 | continue;
28 | end
29 | for k = 1:bbx_num
30 | raw_info = str2num(tmp{k+2,1});
31 | bbx(k,1) = raw_info(1);
32 | bbx(k,2) = raw_info(2);
33 | bbx(k,3) = raw_info(3);
34 | bbx(k,4) = raw_info(4);
35 | bbx(k,5) = raw_info(5);
36 | end
37 | [~, s_index] = sort(bbx(:,5),'descend');
38 | bbx_list{j} = bbx(s_index,:);
39 | catch
40 | fprintf('Invalid format %s %s\n',event_list{i},img_list{j});
41 | end
42 | end
43 | pred_list{i} = bbx_list;
44 | end
45 |
--------------------------------------------------------------------------------
/eval_tools/wider_eval.m:
--------------------------------------------------------------------------------
1 | % WIDER FACE Evaluation
2 | % Conduct the evaluation on the WIDER FACE validation set.
3 | %
4 | % Shuo Yang Dec 2015
5 | %
6 | clear;
7 | close all;
8 | addpath(genpath('./plot'));
9 | %Please specify your prediction directory.
10 | pred_dir = './sfd_val';
11 | gt_dir = './ground_truth/wider_face_val.mat';
12 | %preprocessing
13 | pred_list = read_pred(pred_dir,gt_dir);
14 | norm_pred_list = norm_score(pred_list);
15 |
16 | %evaluate on different settings
17 | setting_name_list = {'easy_val';'medium_val';'hard_val'};
18 | setting_class = 'setting_int';
19 |
20 | %Please specify your algorithm name.
21 | legend_name = 's3fd.pytorch';
22 | for i = 1:size(setting_name_list,1)
23 | fprintf('Current evaluation setting %s\n',setting_name_list{i});
24 | setting_name = setting_name_list{i};
25 | gt_dir = sprintf('./ground_truth/wider_%s.mat',setting_name);
26 | evaluation(norm_pred_list,gt_dir,setting_name,setting_class,legend_name);
27 | end
28 |
29 | fprintf('Plot pr curve under overall setting.\n');
30 | dateset_class = 'Val';
31 |
32 | % scenario-Int:
33 | seting_class = 'int';
34 | dir_int = sprintf('./plot/baselines/%s/setting_%s',dateset_class, seting_class);
35 | wider_plot(setting_name_list,dir_int,seting_class,dateset_class);
36 |
--------------------------------------------------------------------------------
/eval_tools/wider_face_test.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/wider_face_test.mat
--------------------------------------------------------------------------------
/eval_tools/wider_face_val.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/eval_tools/wider_face_val.mat
--------------------------------------------------------------------------------
/img/0_Parade_marchingband_1_20.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/img/0_Parade_marchingband_1_20.jpg
--------------------------------------------------------------------------------
/img/0_Parade_marchingband_1_234.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/img/0_Parade_marchingband_1_234.jpg
--------------------------------------------------------------------------------
/img/0_Parade_marchingband_1_329.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/img/0_Parade_marchingband_1_329.jpg
--------------------------------------------------------------------------------
/img/0_Parade_marchingband_1_488.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/img/0_Parade_marchingband_1_488.jpg
--------------------------------------------------------------------------------
/img/0_Parade_marchingband_1_629.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/img/0_Parade_marchingband_1_629.jpg
--------------------------------------------------------------------------------
/layers/__init__.py:
--------------------------------------------------------------------------------
1 | #-*- coding:utf-8 -*-
2 |
3 | from __future__ import division
4 | from __future__ import absolute_import
5 | from __future__ import print_function
6 |
7 |
8 | from .functions import *
9 | from .modules import *
10 |
--------------------------------------------------------------------------------
/layers/bbox_utils.py:
--------------------------------------------------------------------------------
1 | #-*- coding:utf-8 -*-
2 |
3 | from __future__ import division
4 | from __future__ import absolute_import
5 | from __future__ import print_function
6 |
7 |
8 | import torch
9 |
10 |
11 | def point_form(boxes):
12 | """ Convert prior_boxes to (xmin, ymin, xmax, ymax)
13 | representation for comparison to point form ground truth data.
14 | Args:
15 | boxes: (tensor) center-size default boxes from priorbox layers.
16 | Return:
17 | boxes: (tensor) Converted xmin, ymin, xmax, ymax form of boxes.
18 | """
19 | return torch.cat((boxes[:, :2] - boxes[:, 2:] / 2, # xmin, ymin
20 | boxes[:, :2] + boxes[:, 2:] / 2), 1) # xmax, ymax
21 |
22 |
23 | def center_size(boxes):
24 | """ Convert prior_boxes to (cx, cy, w, h)
25 | representation for comparison to center-size form ground truth data.
26 | Args:
27 | boxes: (tensor) point_form boxes
28 | Return:
29 | boxes: (tensor) Converted xmin, ymin, xmax, ymax form of boxes.
30 | """
31 | return torch.cat([(boxes[:, 2:] + boxes[:, :2]) / 2, # cx, cy
32 | boxes[:, 2:] - boxes[:, :2]], 1) # w, h
33 |
34 |
35 | def intersect(box_a, box_b):
36 | """ We resize both tensors to [A,B,2] without new malloc:
37 | [A,2] -> [A,1,2] -> [A,B,2]
38 | [B,2] -> [1,B,2] -> [A,B,2]
39 | Then we compute the area of intersect between box_a and box_b.
40 | Args:
41 | box_a: (tensor) bounding boxes, Shape: [A,4].
42 | box_b: (tensor) bounding boxes, Shape: [B,4].
43 | Return:
44 | (tensor) intersection area, Shape: [A,B].
45 | """
46 | A = box_a.size(0)
47 | B = box_b.size(0)
48 | max_xy = torch.min(box_a[:, 2:].unsqueeze(1).expand(A, B, 2),
49 | box_b[:, 2:].unsqueeze(0).expand(A, B, 2))
50 | min_xy = torch.max(box_a[:, :2].unsqueeze(1).expand(A, B, 2),
51 | box_b[:, :2].unsqueeze(0).expand(A, B, 2))
52 | inter = torch.clamp((max_xy - min_xy), min=0)
53 | return inter[:, :, 0] * inter[:, :, 1]
54 |
55 |
56 | def jaccard(box_a, box_b):
57 | """Compute the jaccard overlap of two sets of boxes. The jaccard overlap
58 | is simply the intersection over union of two boxes. Here we operate on
59 | ground truth boxes and default boxes.
60 | E.g.:
61 | A ∩ B / A ∪ B = A ∩ B / (area(A) + area(B) - A ∩ B)
62 | Args:
63 | box_a: (tensor) Ground truth bounding boxes, Shape: [num_objects,4]
64 | box_b: (tensor) Prior boxes from priorbox layers, Shape: [num_priors,4]
65 | Return:
66 | jaccard overlap: (tensor) Shape: [box_a.size(0), box_b.size(0)]
67 | """
68 | inter = intersect(box_a, box_b)
69 | area_a = ((box_a[:, 2] - box_a[:, 0]) *
70 | (box_a[:, 3] - box_a[:, 1])).unsqueeze(1).expand_as(inter) # [A,B]
71 | area_b = ((box_b[:, 2] - box_b[:, 0]) *
72 | (box_b[:, 3] - box_b[:, 1])).unsqueeze(0).expand_as(inter) # [A,B]
73 | union = area_a + area_b - inter
74 | return inter / union # [A,B]
75 |
76 |
77 | def match(threshold, truths, priors, variances, labels, loc_t, conf_t, idx):
78 | """Match each prior box with the ground truth box of the highest jaccard
79 | overlap, encode the bounding boxes, then return the matched indices
80 | corresponding to both confidence and location preds.
81 | Args:
82 | threshold: (float) The overlap threshold used when mathing boxes.
83 | truths: (tensor) Ground truth boxes, Shape: [num_obj, num_priors].
84 | priors: (tensor) Prior boxes from priorbox layers, Shape: [n_priors,4].
85 | variances: (tensor) Variances corresponding to each prior coord,
86 | Shape: [num_priors, 4].
87 | labels: (tensor) All the class labels for the image, Shape: [num_obj].
88 | loc_t: (tensor) Tensor to be filled w/ endcoded location targets.
89 | conf_t: (tensor) Tensor to be filled w/ matched indices for conf preds.
90 | idx: (int) current batch index
91 | Return:
92 | The matched indices corresponding to 1)location and 2)confidence preds.
93 | """
94 | # jaccard index
95 | overlaps = jaccard(
96 | truths,
97 | point_form(priors)
98 | )
99 | # (Bipartite Matching)
100 | # [1,num_objects] best prior for each ground truth
101 | best_prior_overlap, best_prior_idx = overlaps.max(1, keepdim=True)
102 | # [1,num_priors] best ground truth for each prior
103 | best_truth_overlap, best_truth_idx = overlaps.max(
104 | 0, keepdim=True) # 0-2000
105 | best_truth_idx.squeeze_(0)
106 | best_truth_overlap.squeeze_(0)
107 | best_prior_idx.squeeze_(1)
108 | best_prior_overlap.squeeze_(1)
109 | best_truth_overlap.index_fill_(0, best_prior_idx, 2) # ensure best prior
110 | # TODO refactor: index best_prior_idx with long tensor
111 | # ensure every gt matches with its prior of max overlap
112 | for j in range(best_prior_idx.size(0)):
113 | best_truth_idx[best_prior_idx[j]] = j
114 | _th1, _th2, _th3 = threshold # _th1 = 0.1 ,_th2 = 0.35,_th3 = 0.5
115 |
116 | N = (torch.sum(best_prior_overlap >= _th2) +
117 | torch.sum(best_prior_overlap >= _th3)) // 2
118 | matches = truths[best_truth_idx] # Shape: [num_priors,4]
119 | conf = labels[best_truth_idx] # Shape: [num_priors]
120 | conf[best_truth_overlap < _th2] = 0 # label as background
121 |
122 | best_truth_overlap_clone = best_truth_overlap.clone()
123 | add_idx = best_truth_overlap_clone.gt(
124 | _th1).eq(best_truth_overlap_clone.lt(_th2))
125 | best_truth_overlap_clone[1 - add_idx] = 0
126 | stage2_overlap, stage2_idx = best_truth_overlap_clone.sort(descending=True)
127 |
128 | stage2_overlap = stage2_overlap.gt(_th1)
129 |
130 | if N > 0:
131 | N = torch.sum(stage2_overlap[:N]) if torch.sum(
132 | stage2_overlap[:N]) < N else N
133 | conf[stage2_idx[:N]] += 1
134 |
135 | loc = encode(matches, priors, variances)
136 | loc_t[idx] = loc # [num_priors,4] encoded offsets to learn
137 | conf_t[idx] = conf # [num_priors] top class label for each prior
138 |
139 |
140 | def match_ssd(threshold, truths, priors, variances, labels, loc_t, conf_t, idx):
141 | """Match each prior box with the ground truth box of the highest jaccard
142 | overlap, encode the bounding boxes, then return the matched indices
143 | corresponding to both confidence and location preds.
144 | Args:
145 | threshold: (float) The overlap threshold used when mathing boxes.
146 | truths: (tensor) Ground truth boxes, Shape: [num_obj, num_priors].
147 | priors: (tensor) Prior boxes from priorbox layers, Shape: [n_priors,4].
148 | variances: (tensor) Variances corresponding to each prior coord,
149 | Shape: [num_priors, 4].
150 | labels: (tensor) All the class labels for the image, Shape: [num_obj].
151 | loc_t: (tensor) Tensor to be filled w/ endcoded location targets.
152 | conf_t: (tensor) Tensor to be filled w/ matched indices for conf preds.
153 | idx: (int) current batch index
154 | Return:
155 | The matched indices corresponding to 1)location and 2)confidence preds.
156 | """
157 | # jaccard index
158 | overlaps = jaccard(
159 | truths,
160 | point_form(priors)
161 | )
162 | # (Bipartite Matching)
163 | # [1,num_objects] best prior for each ground truth
164 | best_prior_overlap, best_prior_idx = overlaps.max(1, keepdim=True)
165 | # [1,num_priors] best ground truth for each prior
166 | best_truth_overlap, best_truth_idx = overlaps.max(
167 | 0, keepdim=True) # 0-2000
168 | best_truth_idx.squeeze_(0)
169 | best_truth_overlap.squeeze_(0)
170 | best_prior_idx.squeeze_(1)
171 | best_prior_overlap.squeeze_(1)
172 | best_truth_overlap.index_fill_(0, best_prior_idx, 2) # ensure best prior
173 | # TODO refactor: index best_prior_idx with long tensor
174 | # ensure every gt matches with its prior of max overlap
175 | for j in range(best_prior_idx.size(0)):
176 | best_truth_idx[best_prior_idx[j]] = j
177 | matches = truths[best_truth_idx] # Shape: [num_priors,4]
178 | conf = labels[best_truth_idx] # Shape: [num_priors]
179 | conf[best_truth_overlap < threshold] = 0 # label as background
180 | loc = encode(matches, priors, variances)
181 | loc_t[idx] = loc # [num_priors,4] encoded offsets to learn
182 | conf_t[idx] = conf # [num_priors] top class label for each prior
183 |
184 |
185 | def encode(matched, priors, variances):
186 | """Encode the variances from the priorbox layers into the ground truth boxes
187 | we have matched (based on jaccard overlap) with the prior boxes.
188 | Args:
189 | matched: (tensor) Coords of ground truth for each prior in point-form
190 | Shape: [num_priors, 4].
191 | priors: (tensor) Prior boxes in center-offset form
192 | Shape: [num_priors,4].
193 | variances: (list[float]) Variances of priorboxes
194 | Return:
195 | encoded boxes (tensor), Shape: [num_priors, 4]
196 | """
197 |
198 | # dist b/t match center and prior's center
199 | g_cxcy = (matched[:, :2] + matched[:, 2:]) / 2 - priors[:, :2]
200 | # encode variance
201 | g_cxcy /= (variances[0] * priors[:, 2:])
202 | # match wh / prior wh
203 | g_wh = (matched[:, 2:] - matched[:, :2]) / priors[:, 2:]
204 | #g_wh = torch.log(g_wh) / variances[1]
205 | g_wh = torch.log(g_wh) / variances[1]
206 | # return target for smooth_l1_loss
207 | return torch.cat([g_cxcy, g_wh], 1) # [num_priors,4]
208 |
209 |
210 | # Adapted from https://github.com/Hakuyume/chainer-ssd
211 | def decode(loc, priors, variances):
212 | """Decode locations from predictions using priors to undo
213 | the encoding we did for offset regression at train time.
214 | Args:
215 | loc (tensor): location predictions for loc layers,
216 | Shape: [num_priors,4]
217 | priors (tensor): Prior boxes in center-offset form.
218 | Shape: [num_priors,4].
219 | variances: (list[float]) Variances of priorboxes
220 | Return:
221 | decoded bounding box predictions
222 | """
223 |
224 | boxes = torch.cat((
225 | priors[:, :2] + loc[:, :2] * variances[0] * priors[:, 2:],
226 | priors[:, 2:] * torch.exp(loc[:, 2:] * variances[1])), 1)
227 | boxes[:, :2] -= boxes[:, 2:] / 2
228 | boxes[:, 2:] += boxes[:, :2]
229 | return boxes
230 |
231 |
232 | def log_sum_exp(x):
233 | """Utility function for computing log_sum_exp while determining
234 | This will be used to determine unaveraged confidence loss across
235 | all examples in a batch.
236 | Args:
237 | x (Variable(tensor)): conf_preds from conf layers
238 | """
239 | x_max = x.data.max()
240 | return torch.log(torch.sum(torch.exp(x - x_max), 1, keepdim=True)) + x_max
241 |
242 |
243 | # Original author: Francisco Massa:
244 | # https://github.com/fmassa/object-detection.torch
245 | # Ported to PyTorch by Max deGroot (02/01/2017)
246 | def nms(boxes, scores, overlap=0.5, top_k=200):
247 | """Apply non-maximum suppression at test time to avoid detecting too many
248 | overlapping bounding boxes for a given object.
249 | Args:
250 | boxes: (tensor) The location preds for the img, Shape: [num_priors,4].
251 | scores: (tensor) The class predscores for the img, Shape:[num_priors].
252 | overlap: (float) The overlap thresh for suppressing unnecessary boxes.
253 | top_k: (int) The Maximum number of box preds to consider.
254 | Return:
255 | The indices of the kept boxes with respect to num_priors.
256 | """
257 |
258 | keep = scores.new(scores.size(0)).zero_().long()
259 | if boxes.numel() == 0:
260 | return keep
261 | x1 = boxes[:, 0]
262 | y1 = boxes[:, 1]
263 | x2 = boxes[:, 2]
264 | y2 = boxes[:, 3]
265 | area = torch.mul(x2 - x1, y2 - y1)
266 | v, idx = scores.sort(0) # sort in ascending order
267 | # I = I[v >= 0.01]
268 | idx = idx[-top_k:] # indices of the top-k largest vals
269 | xx1 = boxes.new()
270 | yy1 = boxes.new()
271 | xx2 = boxes.new()
272 | yy2 = boxes.new()
273 | w = boxes.new()
274 | h = boxes.new()
275 |
276 | # keep = torch.Tensor()
277 | count = 0
278 | while idx.numel() > 0:
279 | i = idx[-1] # index of current largest val
280 | # keep.append(i)
281 | keep[count] = i
282 | count += 1
283 | if idx.size(0) == 1:
284 | break
285 | idx = idx[:-1] # remove kept element from view
286 | # load bboxes of next highest vals
287 | torch.index_select(x1, 0, idx, out=xx1)
288 | torch.index_select(y1, 0, idx, out=yy1)
289 | torch.index_select(x2, 0, idx, out=xx2)
290 | torch.index_select(y2, 0, idx, out=yy2)
291 | # store element-wise max with next highest score
292 | xx1 = torch.clamp(xx1, min=x1[i])
293 | yy1 = torch.clamp(yy1, min=y1[i])
294 | xx2 = torch.clamp(xx2, max=x2[i])
295 | yy2 = torch.clamp(yy2, max=y2[i])
296 | w.resize_as_(xx2)
297 | h.resize_as_(yy2)
298 | w = xx2 - xx1
299 | h = yy2 - yy1
300 | # check sizes of xx1 and xx2.. after each iteration
301 | w = torch.clamp(w, min=0.0)
302 | h = torch.clamp(h, min=0.0)
303 | inter = w * h
304 | # IoU = i / (area(a) + area(b) - i)
305 | rem_areas = torch.index_select(area, 0, idx) # load remaining areas)
306 | union = (rem_areas - inter) + area[i]
307 | IoU = inter / union # store result in iou
308 | # keep only elements with an IoU <= overlap
309 | idx = idx[IoU.le(overlap)]
310 | return keep, count
311 |
--------------------------------------------------------------------------------
/layers/functions/__init__.py:
--------------------------------------------------------------------------------
1 | from .prior_box import PriorBox
2 | from detection import Detect
3 |
4 | __all__=['Detect','PriorBox']
5 |
6 |
--------------------------------------------------------------------------------
/layers/functions/detection.py:
--------------------------------------------------------------------------------
1 | #-*- coding:utf-8 -*-
2 |
3 | from __future__ import division
4 | from __future__ import absolute_import
5 | from __future__ import print_function
6 |
7 | import torch
8 |
9 | from ..bbox_utils import decode, nms
10 | from torch.autograd import Function
11 |
12 |
13 | class Detect(Function):
14 | """At test time, Detect is the final layer of SSD. Decode location preds,
15 | apply non-maximum suppression to location predictions based on conf
16 | scores and threshold to a top_k number of output predictions for both
17 | confidence score and locations.
18 | """
19 |
20 | def __init__(self, cfg):
21 | self.num_classes = cfg.NUM_CLASSES
22 | self.top_k = cfg.TOP_K
23 | self.nms_thresh = cfg.NMS_THRESH
24 | self.conf_thresh = cfg.CONF_THRESH
25 | self.variance = cfg.VARIANCE
26 | self.nms_top_k = cfg.NMS_TOP_K
27 |
28 | def forward(self, loc_data, conf_data, prior_data):
29 | """
30 | Args:
31 | loc_data: (tensor) Loc preds from loc layers
32 | Shape: [batch,num_priors*4]
33 | conf_data: (tensor) Shape: Conf preds from conf layers
34 | Shape: [batch*num_priors,num_classes]
35 | prior_data: (tensor) Prior boxes and variances from priorbox layers
36 | Shape: [1,num_priors,4]
37 | """
38 | num = loc_data.size(0)
39 | num_priors = prior_data.size(0)
40 |
41 | conf_preds = conf_data.view(
42 | num, num_priors, self.num_classes).transpose(2, 1)
43 | batch_priors = prior_data.view(-1, num_priors,
44 | 4).expand(num, num_priors, 4)
45 | batch_priors = batch_priors.contiguous().view(-1, 4)
46 |
47 | decoded_boxes = decode(loc_data.view(-1, 4),
48 | batch_priors, self.variance)
49 | decoded_boxes = decoded_boxes.view(num, num_priors, 4)
50 |
51 | output = torch.zeros(num, self.num_classes, self.top_k, 5)
52 |
53 | for i in range(num):
54 | boxes = decoded_boxes[i].clone()
55 | conf_scores = conf_preds[i].clone()
56 |
57 | for cl in range(1, self.num_classes):
58 | c_mask = conf_scores[cl].gt(self.conf_thresh)
59 | scores = conf_scores[cl][c_mask]
60 |
61 | if scores.dim() == 0:
62 | continue
63 | l_mask = c_mask.unsqueeze(1).expand_as(boxes)
64 | boxes_ = boxes[l_mask].view(-1, 4)
65 | ids, count = nms(
66 | boxes_, scores, self.nms_thresh, self.nms_top_k)
67 | count = count if count < self.top_k else self.top_k
68 |
69 | output[i, cl, :count] = torch.cat((scores[ids[:count]].unsqueeze(1),
70 | boxes_[ids[:count]]), 1)
71 |
72 | return output
73 |
--------------------------------------------------------------------------------
/layers/functions/prior_box.py:
--------------------------------------------------------------------------------
1 | #-*- coding:utf-8 -*-
2 |
3 | from __future__ import division
4 | from __future__ import absolute_import
5 | from __future__ import print_function
6 |
7 | import torch
8 | from itertools import product as product
9 | import math
10 |
11 |
12 | class PriorBox(object):
13 | """Compute priorbox coordinates in center-offset form for each source
14 | feature map.
15 | """
16 |
17 | def __init__(self, input_size, feature_maps,cfg,pal=2):
18 | super(PriorBox, self).__init__()
19 | self.imh = input_size[0]
20 | self.imw = input_size[1]
21 |
22 | # number of priors for feature map location (either 4 or 6)
23 | self.variance = cfg.VARIANCE or [0.1]
24 | #self.feature_maps = cfg.FEATURE_MAPS
25 | if pal==1:
26 | self.min_sizes = cfg.ANCHOR_SIZES1
27 | elif pal==2:
28 | self.min_sizes = cfg.ANCHOR_SIZES2
29 | self.aspect_ratio = cfg.ASPECT_RATIO
30 | self.steps = cfg.STEPS
31 | self.clip = cfg.CLIP
32 | for v in self.variance:
33 | if v <= 0:
34 | raise ValueError('Variances must be greater than 0')
35 | self.feature_maps = feature_maps
36 |
37 |
38 | def forward(self):
39 | mean = []
40 | for k in range(len(self.feature_maps)):
41 | feath = self.feature_maps[k][0]
42 | featw = self.feature_maps[k][1]
43 | for i, j in product(range(feath), range(featw)):
44 | f_kw = self.imw / self.steps[k]
45 | f_kh = self.imh / self.steps[k]
46 |
47 | cx = (j + 0.5) / f_kw
48 | cy = (i + 0.5) / f_kh
49 |
50 | s_kw = self.min_sizes[k] / self.imw
51 | s_kh = self.min_sizes[k] / self.imh
52 | for ar in self.aspect_ratio:
53 | mean += [cx, cy, s_kw/math.sqrt(ar), s_kh*math.sqrt(ar)]
54 |
55 | output = torch.Tensor(mean).view(-1, 4)
56 | if self.clip:
57 | output.clamp_(max=1, min=0)
58 | return output
59 |
60 |
61 | if __name__ == '__main__':
62 | from data.config import cfg
63 | p = PriorBox([640, 640], cfg)
64 | out = p.forward()
65 | print(out.size())
66 |
--------------------------------------------------------------------------------
/layers/modules/__init__.py:
--------------------------------------------------------------------------------
1 | #-*- coding:utf-8 -*-
2 |
3 | from __future__ import division
4 | from __future__ import absolute_import
5 | from __future__ import print_function
6 |
7 |
8 | from .l2norm import L2Norm
9 | from .multibox_loss import MultiBoxLoss
10 |
11 | __all__ = ['L2Norm', 'MultiBoxLoss']
12 |
13 |
--------------------------------------------------------------------------------
/layers/modules/l2norm.py:
--------------------------------------------------------------------------------
1 | #-*- coding:utf-8 -*-
2 |
3 | from __future__ import division
4 | from __future__ import absolute_import
5 | from __future__ import print_function
6 |
7 |
8 | import torch
9 | import torch.nn as nn
10 | import torch.nn.init as init
11 | from torch.autograd import Function
12 | from torch.autograd import Variable
13 |
14 |
15 |
16 | class L2Norm(nn.Module):
17 | def __init__(self,n_channels, scale):
18 | super(L2Norm,self).__init__()
19 | self.n_channels = n_channels
20 | self.gamma = scale or None
21 | self.eps = 1e-10
22 | self.weight = nn.Parameter(torch.Tensor(self.n_channels))
23 | self.reset_parameters()
24 |
25 | def reset_parameters(self):
26 | init.constant(self.weight,self.gamma)
27 |
28 | def forward(self, x):
29 | norm = x.pow(2).sum(dim=1, keepdim=True).sqrt()+self.eps
30 | #x /= norm
31 | x = torch.div(x,norm)
32 | out = self.weight.unsqueeze(0).unsqueeze(2).unsqueeze(3).expand_as(x) * x
33 | return out
34 |
35 |
36 |
--------------------------------------------------------------------------------
/layers/modules/multibox_loss.py:
--------------------------------------------------------------------------------
1 | #-*- coding:utf-8 -*-
2 |
3 | from __future__ import division
4 | from __future__ import absolute_import
5 | from __future__ import print_function
6 |
7 | import math
8 | import torch
9 | import torch.nn as nn
10 | import torch.nn.functional as F
11 | from torch.autograd import Variable
12 |
13 |
14 | from ..bbox_utils import match, log_sum_exp, match_ssd
15 |
16 |
17 | class MultiBoxLoss(nn.Module):
18 | """SSD Weighted Loss Function
19 | Compute Targets:
20 | 1) Produce Confidence Target Indices by matching ground truth boxes
21 | with (default) 'priorboxes' that have jaccard index > threshold parameter
22 | (default threshold: 0.5).
23 | 2) Produce localization target by 'encoding' variance into offsets of ground
24 | truth boxes and their matched 'priorboxes'.
25 | 3) Hard negative mining to filter the excessive number of negative examples
26 | that comes with using a large number of default bounding boxes.
27 | (default negative:positive ratio 3:1)
28 | Objective Loss:
29 | L(x,c,l,g) = (Lconf(x, c) + αLloc(x,l,g)) / N
30 | Where, Lconf is the CrossEntropy Loss and Lloc is the SmoothL1 Loss
31 | weighted by α which is set to 1 by cross val.
32 | Args:
33 | c: class confidences,
34 | l: predicted boxes,
35 | g: ground truth boxes
36 | N: number of matched default boxes
37 | See: https://arxiv.org/pdf/1512.02325.pdf for more details.
38 | """
39 |
40 | def __init__(self, cfg, use_gpu=True):
41 | super(MultiBoxLoss, self).__init__()
42 | self.use_gpu = use_gpu
43 | self.num_classes = cfg.NUM_CLASSES
44 | self.negpos_ratio = cfg.NEG_POS_RATIOS
45 | self.variance = cfg.VARIANCE
46 |
47 | self.threshold = cfg.FACE.OVERLAP_THRESH
48 | self.match = match_ssd
49 |
50 | def forward(self, predictions, targets):
51 | """Multibox Loss
52 | Args:
53 | predictions (tuple): A tuple containing loc preds, conf preds,
54 | and prior boxes from SSD net.
55 | conf shape: torch.size(batch_size,num_priors,num_classes)
56 | loc shape: torch.size(batch_size,num_priors,4)
57 | priors shape: torch.size(num_priors,4)
58 |
59 | targets (tensor): Ground truth boxes and labels for a batch,
60 | shape: [batch_size,num_objs,5] (last idx is the label).
61 | """
62 | loc_data, conf_data, priors = predictions
63 | num = loc_data.size(0)
64 | priors = priors[:loc_data.size(1), :]
65 | num_priors = (priors.size(0))
66 | num_classes = self.num_classes
67 |
68 | # match priors (default boxes) and ground truth boxes
69 | loc_t = torch.Tensor(num, num_priors, 4)
70 | conf_t = torch.LongTensor(num, num_priors)
71 | for idx in range(num):
72 | truths = targets[idx][:, :-1].data
73 | labels = targets[idx][:, -1].data
74 | defaults = priors.data
75 | self.match(self.threshold, truths, defaults, self.variance, labels,
76 | loc_t, conf_t, idx)
77 | if self.use_gpu:
78 | loc_t = loc_t.cuda()
79 | conf_t = conf_t.cuda()
80 | # wrap targets
81 | loc_t = Variable(loc_t, requires_grad=False)
82 | conf_t = Variable(conf_t, requires_grad=False)
83 |
84 | pos = conf_t > 0
85 | num_pos = pos.sum(dim=1, keepdim=True)
86 | # Localization Loss (Smooth L1)
87 | # Shape: [batch,num_priors,4]
88 | pos_idx = pos.unsqueeze(pos.dim()).expand_as(loc_data)
89 | loc_p = loc_data[pos_idx].view(-1, 4)
90 | loc_t = loc_t[pos_idx].view(-1, 4)
91 | loss_l = F.smooth_l1_loss(loc_p, loc_t, size_average=False)
92 | # print(loc_p)
93 | # Compute max conf across batch for hard negative mining
94 | batch_conf = conf_data.view(-1, self.num_classes)
95 | loss_c = log_sum_exp(batch_conf) - \
96 | batch_conf.gather(1, conf_t.view(-1, 1))
97 |
98 | # Hard Negative Mining
99 | loss_c[pos.view(-1, 1)] = 0 # filter out pos boxes for now
100 | loss_c = loss_c.view(num, -1)
101 | _, loss_idx = loss_c.sort(1, descending=True)
102 | _, idx_rank = loss_idx.sort(1)
103 | num_pos = pos.long().sum(1, keepdim=True)
104 | num_neg = torch.clamp(self.negpos_ratio *
105 | num_pos, max=pos.size(1) - 1)
106 | neg = idx_rank < num_neg.expand_as(idx_rank)
107 |
108 | # Confidence Loss Including Positive and Negative Examples
109 | pos_idx = pos.unsqueeze(2).expand_as(conf_data)
110 | neg_idx = neg.unsqueeze(2).expand_as(conf_data)
111 | conf_p = conf_data[(pos_idx + neg_idx).gt(0)
112 | ].view(-1, self.num_classes)
113 | targets_weighted = conf_t[(pos + neg).gt(0)]
114 | loss_c = F.cross_entropy(conf_p, targets_weighted, size_average=False)
115 |
116 | # Sum of losses: L(x,c,l,g) = (Lconf(x, c) + αLloc(x,l,g)) / N
117 | N = num_pos.data.sum() if num_pos.data.sum() > 0 else num
118 | loss_l /= N
119 | loss_c /= N
120 | return loss_l, loss_c
121 |
--------------------------------------------------------------------------------
/models/DSFD_resnet.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import division
3 | from __future__ import print_function
4 | from __future__ import absolute_import
5 |
6 | import torch
7 | import torch.nn as nn
8 | import torch.nn.functional as F
9 | import torch.nn.init as init
10 |
11 | from torch.autograd import Variable
12 |
13 | from layers import *
14 | from data.config import cfg
15 |
16 |
17 | def conv3x3(in_planes, out_planes, stride=1, bias=False):
18 | """3x3 convolution with padding"""
19 | return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride,
20 | padding=1, bias=bias)
21 |
22 |
23 | def conv1x1(in_planes, out_planes, stride=1):
24 | """1x1 convolution"""
25 | return nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=stride, bias=False)
26 |
27 |
28 | class BasicBlock(nn.Module):
29 | expansion = 1
30 |
31 | def __init__(self, inplanes, planes, stride=1, downsample=None):
32 | super(BasicBlock, self).__init__()
33 | self.conv1 = conv3x3(inplanes, planes, stride)
34 | self.bn1 = nn.BatchNorm2d(planes)
35 | self.relu = nn.ReLU(inplace=True)
36 | self.conv2 = conv3x3(planes, planes)
37 | self.bn2 = nn.BatchNorm2d(planes)
38 | self.downsample = downsample
39 | self.stride = stride
40 |
41 | def forward(self, x):
42 | residual = x
43 |
44 | out = self.conv1(x)
45 | out = self.bn1(out)
46 | out = self.relu(out)
47 |
48 | out = self.conv2(out)
49 | out = self.bn2(out)
50 |
51 | if self.downsample is not None:
52 | residual = self.downsample(x)
53 |
54 | out += residual
55 | out = self.relu(out)
56 |
57 | return out
58 |
59 |
60 | class Bottleneck(nn.Module):
61 | expansion = 4
62 |
63 | def __init__(self, inplanes, planes, stride=1, downsample=None):
64 | super(Bottleneck, self).__init__()
65 | self.conv1 = conv1x1(inplanes, planes)
66 | self.bn1 = nn.BatchNorm2d(planes)
67 | self.conv2 = conv3x3(planes, planes, stride)
68 | self.bn2 = nn.BatchNorm2d(planes)
69 | self.conv3 = conv1x1(planes, planes * self.expansion)
70 | self.bn3 = nn.BatchNorm2d(planes * self.expansion)
71 | self.relu = nn.ReLU(inplace=True)
72 | self.downsample = downsample
73 | self.stride = stride
74 |
75 | def forward(self, x):
76 | residual = x
77 |
78 | out = self.conv1(x)
79 | out = self.bn1(out)
80 | out = self.relu(out)
81 |
82 | out = self.conv2(out)
83 | out = self.bn2(out)
84 | out = self.relu(out)
85 |
86 | out = self.conv3(out)
87 | out = self.bn3(out)
88 |
89 | if self.downsample is not None:
90 | residual = self.downsample(x)
91 |
92 | out += residual
93 | out = self.relu(out)
94 |
95 | return out
96 |
97 |
98 | class ResNet(nn.Module):
99 |
100 | def __init__(self, block, layers):
101 | super(ResNet, self).__init__()
102 | self.inplanes = 64
103 | self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3,
104 | bias=False)
105 | self.bn1 = nn.BatchNorm2d(64)
106 | self.relu = nn.ReLU(inplace=True)
107 | self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
108 | self.layer1 = self._make_layer(block, 64, layers[0])
109 | self.layer2 = self._make_layer(block, 128, layers[1], stride=2)
110 | self.layer3 = self._make_layer(block, 256, layers[2], stride=2)
111 | self.layer4 = self._make_layer(block, 512, layers[3], stride=2)
112 |
113 | def _make_layer(self, block, planes, blocks, stride=1):
114 | downsample = None
115 | if stride != 1 or self.inplanes != planes * block.expansion:
116 | downsample = nn.Sequential(
117 | conv1x1(self.inplanes, planes * block.expansion, stride),
118 | nn.BatchNorm2d(planes * block.expansion),
119 | )
120 |
121 | layers = []
122 | layers.append(block(self.inplanes, planes, stride, downsample))
123 | self.inplanes = planes * block.expansion
124 | for _ in range(1, blocks):
125 | layers.append(block(self.inplanes, planes))
126 |
127 | return nn.Sequential(*layers)
128 |
129 | def forward(self, x):
130 | sources = []
131 |
132 | x = self.conv1(x)
133 | x = self.bn1(x)
134 | x = self.relu(x)
135 | x = self.maxpool(x)
136 |
137 | x = self.layer1(x)
138 | sources += [x]
139 |
140 | x = self.layer2(x)
141 | sources += [x]
142 |
143 | x = self.layer3(x)
144 | sources += [x]
145 |
146 | x = self.layer4(x)
147 | sources += [x]
148 |
149 | return sources
150 |
151 |
152 | class FEM(nn.Module):
153 | """docstring for FEM"""
154 |
155 | def __init__(self, in_planes):
156 | super(FEM, self).__init__()
157 | inter_planes = in_planes // 3
158 | inter_planes1 = in_planes - 2 * inter_planes
159 | self.branch1 = nn.Conv2d(
160 | in_planes, inter_planes, kernel_size=3, stride=1, padding=3, dilation=3)
161 |
162 | self.branch2 = nn.Sequential(
163 | nn.Conv2d(in_planes, inter_planes, kernel_size=3,
164 | stride=1, padding=3, dilation=3),
165 | nn.ReLU(inplace=True),
166 | nn.Conv2d(inter_planes, inter_planes, kernel_size=3,
167 | stride=1, padding=3, dilation=3)
168 | )
169 | self.branch3 = nn.Sequential(
170 | nn.Conv2d(in_planes, inter_planes1, kernel_size=3,
171 | stride=1, padding=3, dilation=3),
172 | nn.ReLU(inplace=True),
173 | nn.Conv2d(inter_planes1, inter_planes1, kernel_size=3,
174 | stride=1, padding=3, dilation=3),
175 | nn.ReLU(inplace=True),
176 | nn.Conv2d(inter_planes1, inter_planes1, kernel_size=3,
177 | stride=1, padding=3, dilation=3)
178 | )
179 |
180 | def forward(self, x):
181 | x1 = self.branch1(x)
182 | x2 = self.branch2(x)
183 | x3 = self.branch3(x)
184 | out = torch.cat((x1, x2, x3), dim=1)
185 | out = F.relu(out, inplace=True)
186 | return out
187 |
188 |
189 | class DSFD(nn.Module):
190 | """docstring for SRN"""
191 |
192 | def __init__(self, phase, base, extras, fem_modules, head1, head2, num_classes=2):
193 | super(DSFD, self).__init__()
194 | self.resnet = base
195 | self.phase = phase
196 | self.num_classes = num_classes
197 | self.extras = nn.ModuleList(extras)
198 |
199 | self.fpn_topdown = nn.ModuleList(fem_modules[0])
200 | self.fpn_latlayer = nn.ModuleList(fem_modules[1])
201 | self.fpn_fem = nn.ModuleList(fem_modules[2])
202 |
203 | self.loc_pal1 = nn.ModuleList(head1[0])
204 | self.conf_pal1 = nn.ModuleList(head1[1])
205 | self.loc_pal2 = nn.ModuleList(head2[0])
206 | self.conf_pal2 = nn.ModuleList(head2[1])
207 |
208 | if self.phase == 'test':
209 | self.softmax = nn.Softmax(dim=-1)
210 | self.detect = Detect(cfg)
211 |
212 | def _upsample_prod(self, x, y):
213 | _, _, H, W = y.size()
214 | return F.upsample(x, size=(H, W), mode='bilinear') * y
215 |
216 | def forward(self, x):
217 | size = x.size()[2:]
218 | of1, of2, of3, of4 = self.resnet(x)
219 |
220 | x = of4
221 | for i in range(2):
222 | x = F.relu(self.extras[i](x), inplace=True)
223 | of5 = x
224 |
225 | for i in range(2, len(self.extras)):
226 | x = F.relu(self.extras[i](x), inplace=True)
227 | of6 = x
228 |
229 | conv7 = F.relu(self.fpn_topdown[0](of6), inplace=True)
230 |
231 | x = F.relu(self.fpn_topdown[1](conv7), inplace=True)
232 | conv6 = F.relu(self._upsample_prod(
233 | x, self.fpn_latlayer[0](of5)), inplace=True)
234 |
235 | x = F.relu(self.fpn_topdown[2](conv6), inplace=True)
236 | conv5 = F.relu(self._upsample_prod(
237 | x, self.fpn_latlayer[1](of4)), inplace=True)
238 |
239 | x = F.relu(self.fpn_topdown[3](conv5), inplace=True)
240 | conv4 = F.relu(self._upsample_prod(
241 | x, self.fpn_latlayer[2](of3)), inplace=True)
242 |
243 | x = F.relu(self.fpn_topdown[4](conv4), inplace=True)
244 | conv3 = F.relu(self._upsample_prod(
245 | x, self.fpn_latlayer[3](of2)), inplace=True)
246 |
247 | x = F.relu(self.fpn_topdown[5](conv3), inplace=True)
248 | conv2 = F.relu(self._upsample_prod(
249 | x, self.fpn_latlayer[4](of1)), inplace=True)
250 |
251 | ef1 = self.fpn_fem[0](conv2)
252 | ef2 = self.fpn_fem[1](conv3)
253 | ef3 = self.fpn_fem[2](conv4)
254 | ef4 = self.fpn_fem[3](conv5)
255 | ef5 = self.fpn_fem[4](conv6)
256 | ef6 = self.fpn_fem[5](conv7)
257 |
258 | sources_pal1 = [of1, of2, of3, of4, of5, of6]
259 | sources_pal2 = [ef1, ef2, ef3, ef4, ef5, ef6]
260 | loc_pal1, conf_pal1 = list(), list()
261 | loc_pal2, conf_pal2 = list(), list()
262 |
263 | for (x, l, c) in zip(sources_pal1, self.loc_pal1, self.conf_pal1):
264 | loc_pal1.append(l(x).permute(0, 2, 3, 1).contiguous())
265 | conf_pal1.append(c(x).permute(0, 2, 3, 1).contiguous())
266 |
267 | for (x, l, c) in zip(sources_pal2, self.loc_pal2, self.conf_pal2):
268 | loc_pal2.append(l(x).permute(0, 2, 3, 1).contiguous())
269 | conf_pal2.append(c(x).permute(0, 2, 3, 1).contiguous())
270 |
271 | features_maps = []
272 | for i in range(len(loc_pal1)):
273 | feat = []
274 | feat += [loc_pal1[i].size(1), loc_pal1[i].size(2)]
275 | features_maps += [feat]
276 |
277 | loc_pal1 = torch.cat([o.view(o.size(0), -1) for o in loc_pal1], 1)
278 | conf_pal1 = torch.cat([o.view(o.size(0), -1) for o in conf_pal1], 1)
279 |
280 | loc_pal2 = torch.cat([o.view(o.size(0), -1) for o in loc_pal2], 1)
281 | conf_pal2 = torch.cat([o.view(o.size(0), -1) for o in conf_pal2], 1)
282 |
283 | priorbox = PriorBox(size, features_maps, cfg, pal=1)
284 | self.priors_pal1 = Variable(priorbox.forward(), volatile=True)
285 |
286 | priorbox = PriorBox(size, features_maps, cfg, pal=2)
287 | self.priors_pal2 = Variable(priorbox.forward(), volatile=True)
288 |
289 | if self.phase == 'test':
290 | output = self.detect(
291 | loc_pal2.view(loc_pal2.size(0), -1, 4),
292 | self.softmax(conf_pal2.view(conf_pal2.size(0), -1,
293 | self.num_classes)), # conf preds
294 | self.priors_pal2.type(type(x.data))
295 | )
296 |
297 | else:
298 | output = (
299 | loc_pal1.view(loc_pal1.size(0), -1, 4),
300 | conf_pal1.view(conf_pal1.size(0), -1, self.num_classes),
301 | self.priors_pal1,
302 | loc_pal2.view(loc_pal2.size(0), -1, 4),
303 | conf_pal2.view(conf_pal2.size(0), -1, self.num_classes),
304 | self.priors_pal2)
305 | return output
306 |
307 | def load_weights(self, base_file):
308 | other, ext = os.path.splitext(base_file)
309 | if ext == '.pkl' or '.pth':
310 | print('Loading weights into state dict...')
311 | mdata = torch.load(base_file,
312 | map_location=lambda storage, loc: storage)
313 | weights = mdata['weight']
314 | epoch = mdata['epoch']
315 | self.load_state_dict(weights)
316 | print('Finished!')
317 | else:
318 | print('Sorry only .pth and .pkl files supported.')
319 | return epoch
320 |
321 | def xavier(self, param):
322 | init.xavier_uniform(param)
323 |
324 | def weights_init(self, m):
325 | if isinstance(m, nn.Conv2d):
326 | self.xavier(m.weight.data)
327 | m.bias.data.zero_()
328 |
329 | if isinstance(m, nn.ConvTranspose2d):
330 | self.xavier(m.weight.data)
331 | if 'bias' in m.state_dict().keys():
332 | m.bias.data.zero_()
333 |
334 | if isinstance(m, nn.BatchNorm2d):
335 | m.weight.data[...] = 1
336 | m.bias.data.zero_()
337 |
338 | extras_cfg = [256, 'S', 512, 128, 'S', 256]
339 |
340 | net_cfg = [256, 512, 1024, 2048, 512, 256]
341 |
342 |
343 | def add_extras(cfg, i):
344 | layers = []
345 | in_channels = i
346 | flag = False
347 | for k, v in enumerate(cfg):
348 | if in_channels != 'S':
349 | if v == 'S':
350 | layers += [nn.Conv2d(in_channels, cfg[k + 1],
351 | kernel_size=(1, 3)[flag], stride=2, padding=1)]
352 | else:
353 | layers += [nn.Conv2d(in_channels, v, kernel_size=(1, 3)[flag])]
354 | flag = not flag
355 | in_channels = v
356 | return layers
357 |
358 |
359 | def multibox(cfg, num_classes=2):
360 | conf_layers = []
361 | loc_layers = []
362 | for k, v in enumerate(cfg):
363 | loc_layers += [nn.Conv2d(v, 4, kernel_size=3, padding=1)]
364 | conf_layers += [nn.Conv2d(v, num_classes, kernel_size=3, padding=1)]
365 | return (loc_layers, conf_layers)
366 |
367 |
368 | def fem_module(cfg):
369 | topdown_layers = []
370 | lat_layers = []
371 | fem_layers = []
372 |
373 | topdown_layers += [nn.Conv2d(cfg[-1], cfg[-1],
374 | kernel_size=1, stride=1, padding=0)]
375 | for k, v in enumerate(cfg):
376 | fem_layers += [FEM(v)]
377 | cur_channel = cfg[len(cfg) - 1 - k]
378 | if len(cfg) - 1 - k > 0:
379 | last_channel = cfg[len(cfg) - 2 - k]
380 | topdown_layers += [nn.Conv2d(cur_channel, last_channel,
381 | kernel_size=1, stride=1, padding=0)]
382 | lat_layers += [nn.Conv2d(last_channel, last_channel,
383 | kernel_size=1, stride=1, padding=0)]
384 | return (topdown_layers, lat_layers, fem_layers)
385 |
386 |
387 | def resnet50():
388 | """Constructs a ResNet-50 model.
389 | Args:
390 | pretrained (bool): If True, returns a model pre-trained on ImageNet
391 | """
392 | model = ResNet(Bottleneck, [3, 4, 6, 3])
393 | return model
394 |
395 |
396 | def resnet101():
397 | model = ResNet(Bottleneck, [3, 4, 23, 3])
398 | return model
399 |
400 |
401 | def resnet152():
402 | model = ResNet(Bottleneck, [3, 8, 36, 3])
403 | return model
404 |
405 |
406 | def model_map(net_name='resnet50'):
407 | _dicts = {'resnet50': resnet50,
408 | 'resnet101': resnet101, 'resnet152': resnet152}
409 | return _dicts[net_name]()
410 |
411 |
412 | def build_net_resnet(phase, num_classes=2, net_name='resnet50'):
413 | resnet = model_map(net_name)
414 | extras = add_extras(extras_cfg, 2048)
415 | head_pal1 = multibox(net_cfg, num_classes)
416 | head_pal2 = multibox(net_cfg, num_classes)
417 | fem_modules = fem_module(net_cfg)
418 | model = DSFD(phase, resnet, extras, fem_modules,
419 | head_pal1, head_pal2, num_classes)
420 | return model
421 |
422 | if __name__ == '__main__':
423 | inputs = Variable(torch.randn(1, 3, 640, 640))
424 | net = build_net('train', 2, 101)
425 | out = net(inputs)
426 |
--------------------------------------------------------------------------------
/models/DSFD_vgg.py:
--------------------------------------------------------------------------------
1 | #-*- coding:utf-8 -*-
2 |
3 | from __future__ import division
4 | from __future__ import absolute_import
5 | from __future__ import print_function
6 |
7 | import os
8 | import numpy as np
9 |
10 | import torch
11 | import torch.nn as nn
12 | import torch.nn.init as init
13 | import torch.nn.functional as F
14 | from torch.autograd import Variable
15 |
16 | from layers import *
17 | from data.config import cfg
18 |
19 |
20 | class FEM(nn.Module):
21 | """docstring for FEM"""
22 |
23 | def __init__(self, in_planes):
24 | super(FEM, self).__init__()
25 | inter_planes = in_planes // 3
26 | inter_planes1 = in_planes - 2 * inter_planes
27 | self.branch1 = nn.Conv2d(
28 | in_planes, inter_planes, kernel_size=3, stride=1, padding=3, dilation=3)
29 |
30 | self.branch2 = nn.Sequential(
31 | nn.Conv2d(in_planes, inter_planes, kernel_size=3,
32 | stride=1, padding=3, dilation=3),
33 | nn.ReLU(inplace=True),
34 | nn.Conv2d(inter_planes, inter_planes, kernel_size=3,
35 | stride=1, padding=3, dilation=3)
36 | )
37 | self.branch3 = nn.Sequential(
38 | nn.Conv2d(in_planes, inter_planes1, kernel_size=3,
39 | stride=1, padding=3, dilation=3),
40 | nn.ReLU(inplace=True),
41 | nn.Conv2d(inter_planes1, inter_planes1, kernel_size=3,
42 | stride=1, padding=3, dilation=3),
43 | nn.ReLU(inplace=True),
44 | nn.Conv2d(inter_planes1, inter_planes1, kernel_size=3,
45 | stride=1, padding=3, dilation=3)
46 | )
47 |
48 | def forward(self, x):
49 | x1 = self.branch1(x)
50 | x2 = self.branch2(x)
51 | x3 = self.branch3(x)
52 | out = torch.cat((x1, x2, x3), dim=1)
53 | out = F.relu(out, inplace=True)
54 | return out
55 |
56 |
57 | class DSFD(nn.Module):
58 | """Single Shot Multibox Architecture
59 | The network is composed of a base VGG network followed by the
60 | added multibox conv layers. Each multibox layer branches into
61 | 1) conv2d for class conf scores
62 | 2) conv2d for localization predictions
63 | 3) associated priorbox layer to produce default bounding
64 | boxes specific to the layer's feature map size.
65 | See: https://arxiv.org/pdf/1512.02325.pdf for more details.
66 |
67 | Args:
68 | phase: (string) Can be "test" or "train"
69 | size: input image size
70 | base: VGG16 layers for input, size of either 300 or 500
71 | extras: extra layers that feed to multibox loc and conf layers
72 | head: "multibox head" consists of loc and conf conv layers
73 | """
74 |
75 | def __init__(self, phase, base, extras, fem, head1, head2, num_classes):
76 | super(DSFD, self).__init__()
77 | self.phase = phase
78 | self.num_classes = num_classes
79 | self.vgg = nn.ModuleList(base)
80 |
81 | self.L2Normof1 = L2Norm(256, 10)
82 | self.L2Normof2 = L2Norm(512, 8)
83 | self.L2Normof3 = L2Norm(512, 5)
84 |
85 | self.extras = nn.ModuleList(extras)
86 | self.fpn_topdown = nn.ModuleList(fem[0])
87 | self.fpn_latlayer = nn.ModuleList(fem[1])
88 |
89 | self.fpn_fem = nn.ModuleList(fem[2])
90 |
91 | self.L2Normef1 = L2Norm(256, 10)
92 | self.L2Normef2 = L2Norm(512, 8)
93 | self.L2Normef3 = L2Norm(512, 5)
94 |
95 | self.loc_pal1 = nn.ModuleList(head1[0])
96 | self.conf_pal1 = nn.ModuleList(head1[1])
97 |
98 | self.loc_pal2 = nn.ModuleList(head2[0])
99 | self.conf_pal2 = nn.ModuleList(head2[1])
100 |
101 | if self.phase=='test':
102 | self.softmax = nn.Softmax(dim=-1)
103 | self.detect = Detect(cfg)
104 |
105 | def _upsample_prod(self, x, y):
106 | _, _, H, W = y.size()
107 | return F.upsample(x, size=(H, W), mode='bilinear') * y
108 |
109 | def forward(self, x):
110 | size = x.size()[2:]
111 | pal1_sources = list()
112 | pal2_sources = list()
113 | loc_pal1 = list()
114 | conf_pal1 = list()
115 | loc_pal2 = list()
116 | conf_pal2 = list()
117 |
118 | # apply vgg up to conv4_3 relu
119 | for k in range(16):
120 | x = self.vgg[k](x)
121 | of1 = x
122 | s = self.L2Normof1(of1)
123 | pal1_sources.append(s)
124 | # apply vgg up to fc7
125 | for k in range(16, 23):
126 | x = self.vgg[k](x)
127 | of2 = x
128 | s = self.L2Normof2(of2)
129 | pal1_sources.append(s)
130 |
131 | for k in range(23, 30):
132 | x = self.vgg[k](x)
133 | of3 = x
134 | s = self.L2Normof3(of3)
135 | pal1_sources.append(s)
136 |
137 | for k in range(30, len(self.vgg)):
138 | x = self.vgg[k](x)
139 | of4 = x
140 | pal1_sources.append(of4)
141 | # apply extra layers and cache source layer outputs
142 |
143 | for k in range(2):
144 | x = F.relu(self.extras[k](x), inplace=True)
145 | of5 = x
146 | pal1_sources.append(of5)
147 | for k in range(2, 4):
148 | x = F.relu(self.extras[k](x), inplace=True)
149 | of6 = x
150 | pal1_sources.append(of6)
151 |
152 | conv7 = F.relu(self.fpn_topdown[0](of6), inplace=True)
153 |
154 | x = F.relu(self.fpn_topdown[1](conv7), inplace=True)
155 | conv6 = F.relu(self._upsample_prod(
156 | x, self.fpn_latlayer[0](of5)), inplace=True)
157 |
158 | x = F.relu(self.fpn_topdown[2](conv6), inplace=True)
159 | convfc7_2 = F.relu(self._upsample_prod(
160 | x, self.fpn_latlayer[1](of4)), inplace=True)
161 |
162 | x = F.relu(self.fpn_topdown[3](convfc7_2), inplace=True)
163 | conv5 = F.relu(self._upsample_prod(
164 | x, self.fpn_latlayer[2](of3)), inplace=True)
165 |
166 | x = F.relu(self.fpn_topdown[4](conv5), inplace=True)
167 | conv4 = F.relu(self._upsample_prod(
168 | x, self.fpn_latlayer[3](of2)), inplace=True)
169 |
170 | x = F.relu(self.fpn_topdown[5](conv4), inplace=True)
171 | conv3 = F.relu(self._upsample_prod(
172 | x, self.fpn_latlayer[4](of1)), inplace=True)
173 |
174 | ef1 = self.fpn_fem[0](conv3)
175 | ef1 = self.L2Normef1(ef1)
176 | ef2 = self.fpn_fem[1](conv4)
177 | ef2 = self.L2Normef2(ef2)
178 | ef3 = self.fpn_fem[2](conv5)
179 | ef3 = self.L2Normef3(ef3)
180 | ef4 = self.fpn_fem[3](convfc7_2)
181 | ef5 = self.fpn_fem[4](conv6)
182 | ef6 = self.fpn_fem[5](conv7)
183 |
184 | pal2_sources = (ef1, ef2, ef3, ef4, ef5, ef6)
185 | for (x, l, c) in zip(pal1_sources, self.loc_pal1, self.conf_pal1):
186 | loc_pal1.append(l(x).permute(0, 2, 3, 1).contiguous())
187 | conf_pal1.append(c(x).permute(0, 2, 3, 1).contiguous())
188 |
189 | for (x, l, c) in zip(pal2_sources, self.loc_pal2, self.conf_pal2):
190 | loc_pal2.append(l(x).permute(0, 2, 3, 1).contiguous())
191 | conf_pal2.append(c(x).permute(0, 2, 3, 1).contiguous())
192 |
193 | features_maps = []
194 | for i in range(len(loc_pal1)):
195 | feat = []
196 | feat += [loc_pal1[i].size(1), loc_pal1[i].size(2)]
197 | features_maps += [feat]
198 |
199 | loc_pal1 = torch.cat([o.view(o.size(0), -1)
200 | for o in loc_pal1], 1)
201 | conf_pal1 = torch.cat([o.view(o.size(0), -1)
202 | for o in conf_pal1], 1)
203 |
204 | loc_pal2 = torch.cat([o.view(o.size(0), -1)
205 | for o in loc_pal2], 1)
206 | conf_pal2 = torch.cat([o.view(o.size(0), -1)
207 | for o in conf_pal2], 1)
208 |
209 | priorbox = PriorBox(size, features_maps, cfg, pal=1)
210 | self.priors_pal1 = Variable(priorbox.forward(), volatile=True)
211 |
212 | priorbox = PriorBox(size, features_maps, cfg, pal=2)
213 | self.priors_pal2 = Variable(priorbox.forward(), volatile=True)
214 |
215 | if self.phase == 'test':
216 | output = self.detect(
217 | loc_pal2.view(loc_pal2.size(0), -1, 4),
218 | self.softmax(conf_pal2.view(conf_pal2.size(0), -1,
219 | self.num_classes)), # conf preds
220 | self.priors_pal2.type(type(x.data))
221 | )
222 |
223 | else:
224 | output = (
225 | loc_pal1.view(loc_pal1.size(0), -1, 4),
226 | conf_pal1.view(conf_pal1.size(0), -1, self.num_classes),
227 | self.priors_pal1,
228 | loc_pal2.view(loc_pal2.size(0), -1, 4),
229 | conf_pal2.view(conf_pal2.size(0), -1, self.num_classes),
230 | self.priors_pal2)
231 | return output
232 |
233 | def load_weights(self, base_file):
234 | other, ext = os.path.splitext(base_file)
235 | if ext == '.pkl' or '.pth':
236 | print('Loading weights into state dict...')
237 | mdata = torch.load(base_file,
238 | map_location=lambda storage, loc: storage)
239 | weights = mdata['weight']
240 | epoch = mdata['epoch']
241 | self.load_state_dict(weights)
242 | print('Finished!')
243 | else:
244 | print('Sorry only .pth and .pkl files supported.')
245 | return epoch
246 |
247 | def xavier(self, param):
248 | init.xavier_uniform(param)
249 |
250 | def weights_init(self, m):
251 | if isinstance(m, nn.Conv2d):
252 | self.xavier(m.weight.data)
253 | m.bias.data.zero_()
254 |
255 | if isinstance(m,nn.ConvTranspose2d):
256 | self.xavier(m.weight.data)
257 | if 'bias' in m.state_dict().keys():
258 | m.bias.data.zero_()
259 |
260 | if isinstance(m,nn.BatchNorm2d):
261 | m.weight.data[...] = 1
262 | m.bias.data.zero_()
263 |
264 |
265 | vgg_cfg = [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'C', 512, 512, 512, 'M',
266 | 512, 512, 512, 'M']
267 |
268 | extras_cfg = [256, 'S', 512, 128, 'S', 256]
269 |
270 | fem_cfg = [256, 512, 512, 1024, 512, 256]
271 |
272 |
273 | def fem_module(cfg):
274 | topdown_layers = []
275 | lat_layers = []
276 | fem_layers = []
277 |
278 | topdown_layers += [nn.Conv2d(cfg[-1], cfg[-1],
279 | kernel_size=1, stride=1, padding=0)]
280 | for k, v in enumerate(cfg):
281 | fem_layers += [FEM(v)]
282 | cur_channel = cfg[len(cfg) - 1 - k]
283 | if len(cfg) - 1 - k > 0:
284 | last_channel = cfg[len(cfg) - 2 - k]
285 | topdown_layers += [nn.Conv2d(cur_channel, last_channel,
286 | kernel_size=1, stride=1, padding=0)]
287 | lat_layers += [nn.Conv2d(last_channel, last_channel,
288 | kernel_size=1, stride=1, padding=0)]
289 | return (topdown_layers, lat_layers, fem_layers)
290 |
291 |
292 | def vgg(cfg, i, batch_norm=False):
293 | layers = []
294 | in_channels = i
295 | for v in cfg:
296 | if v == 'M':
297 | layers += [nn.MaxPool2d(kernel_size=2, stride=2)]
298 | elif v == 'C':
299 | layers += [nn.MaxPool2d(kernel_size=2, stride=2, ceil_mode=True)]
300 | else:
301 | conv2d = nn.Conv2d(in_channels, v, kernel_size=3, padding=1)
302 | if batch_norm:
303 | layers += [conv2d, nn.BatchNorm2d(v), nn.ReLU(inplace=True)]
304 | else:
305 | layers += [conv2d, nn.ReLU(inplace=True)]
306 | in_channels = v
307 | conv6 = nn.Conv2d(512, 1024, kernel_size=3, padding=3, dilation=3)
308 | conv7 = nn.Conv2d(1024, 1024, kernel_size=1)
309 | layers += [conv6,
310 | nn.ReLU(inplace=True), conv7, nn.ReLU(inplace=True)]
311 | return layers
312 |
313 |
314 | def add_extras(cfg, i, batch_norm=False):
315 | # Extra layers added to VGG for feature scaling
316 | layers = []
317 | in_channels = i
318 | flag = False
319 | for k, v in enumerate(cfg):
320 | if in_channels != 'S':
321 | if v == 'S':
322 | layers += [nn.Conv2d(in_channels, cfg[k + 1],
323 | kernel_size=(1, 3)[flag], stride=2, padding=1)]
324 | else:
325 | layers += [nn.Conv2d(in_channels, v, kernel_size=(1, 3)[flag])]
326 | flag = not flag
327 | in_channels = v
328 | return layers
329 |
330 |
331 | def multibox(vgg, extra_layers, num_classes):
332 | loc_layers = []
333 | conf_layers = []
334 | vgg_source = [14, 21, 28, -2]
335 |
336 | for k, v in enumerate(vgg_source):
337 | loc_layers += [nn.Conv2d(vgg[v].out_channels,
338 | 4, kernel_size=3, padding=1)]
339 | conf_layers += [nn.Conv2d(vgg[v].out_channels,
340 | num_classes, kernel_size=3, padding=1)]
341 | for k, v in enumerate(extra_layers[1::2], 2):
342 | loc_layers += [nn.Conv2d(v.out_channels,
343 | 4, kernel_size=3, padding=1)]
344 | conf_layers += [nn.Conv2d(v.out_channels,
345 | num_classes, kernel_size=3, padding=1)]
346 | return (loc_layers, conf_layers)
347 |
348 |
349 | def build_net_vgg(phase, num_classes=2):
350 | base = vgg(vgg_cfg, 3)
351 | extras = add_extras(extras_cfg, 1024)
352 | head1 = multibox(base, extras, num_classes)
353 | head2 = multibox(base, extras, num_classes)
354 | fem = fem_module(fem_cfg)
355 | return DSFD(phase, base, extras, fem, head1, head2, num_classes)
356 |
357 | if __name__ == '__main__':
358 | inputs = Variable(torch.randn(1, 3, 640, 640))
359 | net = build_net('train', 2)
360 | out = net(inputs)
361 |
--------------------------------------------------------------------------------
/models/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/models/__init__.py
--------------------------------------------------------------------------------
/models/factory.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import division
3 | from __future__ import print_function
4 | from __future__ import absolute_import
5 |
6 | import torch
7 | import torch.backends.cudnn as cudnn
8 |
9 | from .DSFD_vgg import build_net_vgg
10 | from .DSFD_resnet import build_net_resnet
11 |
12 |
13 | def build_net(phase, num_classes=2, model='vgg'):
14 | if phase != "test" and phase != "train":
15 | print("ERROR: Phase: " + phase + " not recognized")
16 | return
17 |
18 | if model != 'vgg' and 'resnet' not in model:
19 | print("ERROR: model:" + model + " not recognized")
20 | return
21 |
22 | if model == 'vgg':
23 | return build_net_vgg(phase, num_classes)
24 | else:
25 | return build_net_resnet(phase, num_classes, model)
26 |
27 |
28 |
29 | def basenet_factory(model='vgg'):
30 | if model=='vgg':
31 | basenet = 'vgg16_reducedfc.pth'
32 |
33 | elif 'resnet' in model:
34 | basenet = '{}.pth'.format(model)
35 | return basenet
36 |
37 |
--------------------------------------------------------------------------------
/prepare_wider_data.py:
--------------------------------------------------------------------------------
1 | #-*- coding:utf-8 -*-
2 |
3 | from __future__ import division
4 | from __future__ import absolute_import
5 | from __future__ import print_function
6 |
7 |
8 | import os
9 | from data.config import cfg
10 | import cv2
11 |
12 | WIDER_ROOT = os.path.join(cfg.HOME, 'WIDER')
13 | train_list_file = os.path.join(WIDER_ROOT, 'wider_face_split',
14 | 'wider_face_train_bbx_gt.txt')
15 | val_list_file = os.path.join(WIDER_ROOT, 'wider_face_split',
16 | 'wider_face_val_bbx_gt.txt')
17 |
18 | WIDER_TRAIN = os.path.join(WIDER_ROOT, 'WIDER_train', 'images')
19 | WIDER_VAL = os.path.join(WIDER_ROOT, 'WIDER_val', 'images')
20 |
21 |
22 | def parse_wider_file(root, file):
23 | with open(file, 'r') as fr:
24 | lines = fr.readlines()
25 | face_count = []
26 | img_paths = []
27 | face_loc = []
28 | img_faces = []
29 | count = 0
30 | flag = False
31 | for k, line in enumerate(lines):
32 | line = line.strip().strip('\n')
33 | if count > 0:
34 | line = line.split(' ')
35 | count -= 1
36 | loc = [int(line[0]), int(line[1]), int(line[2]), int(line[3])]
37 | face_loc += [loc]
38 | if flag:
39 | face_count += [int(line)]
40 | flag = False
41 | count = int(line)
42 | if 'jpg' in line:
43 | img_paths += [os.path.join(root, line)]
44 | flag = True
45 |
46 | total_face = 0
47 | for k in face_count:
48 | face_ = []
49 | for x in xrange(total_face, total_face + k):
50 | face_.append(face_loc[x])
51 | img_faces += [face_]
52 | total_face += k
53 | return img_paths, img_faces
54 |
55 |
56 | def wider_data_file():
57 | img_paths, bbox = parse_wider_file(WIDER_TRAIN, train_list_file)
58 | fw = open(cfg.FACE.TRAIN_FILE, 'w')
59 | for index in xrange(len(img_paths)):
60 | path = img_paths[index]
61 | boxes = bbox[index]
62 | fw.write(path)
63 | fw.write(' {}'.format(len(boxes)))
64 | for box in boxes:
65 | data = ' {} {} {} {} {}'.format(box[0], box[1], box[2], box[3], 1)
66 | fw.write(data)
67 | fw.write('\n')
68 | fw.close()
69 |
70 | img_paths, bbox = parse_wider_file(WIDER_VAL, val_list_file)
71 | fw = open(cfg.FACE.VAL_FILE, 'w')
72 | for index in xrange(len(img_paths)):
73 | path = img_paths[index]
74 | boxes = bbox[index]
75 | fw.write(path)
76 | fw.write(' {}'.format(len(boxes)))
77 | for box in boxes:
78 | data = ' {} {} {} {} {}'.format(box[0], box[1], box[2], box[3], 1)
79 | fw.write(data)
80 | fw.write('\n')
81 | fw.close()
82 |
83 |
84 | if __name__ == '__main__':
85 | wider_data_file()
86 |
--------------------------------------------------------------------------------
/tmp/0_Parade_marchingband_1_20.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/tmp/0_Parade_marchingband_1_20.jpg
--------------------------------------------------------------------------------
/tmp/0_Parade_marchingband_1_234.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/tmp/0_Parade_marchingband_1_234.jpg
--------------------------------------------------------------------------------
/tmp/0_Parade_marchingband_1_329.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/tmp/0_Parade_marchingband_1_329.jpg
--------------------------------------------------------------------------------
/tmp/0_Parade_marchingband_1_488.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/tmp/0_Parade_marchingband_1_488.jpg
--------------------------------------------------------------------------------
/tmp/0_Parade_marchingband_1_629.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yxlijun/DSFD.pytorch/f3d88dccc1b2e06cf3ae8659efe37afa1102f142/tmp/0_Parade_marchingband_1_629.jpg
--------------------------------------------------------------------------------
/tools/afw_img_list.txt:
--------------------------------------------------------------------------------
1 | 1004109301
2 | 111076519
3 | 1139324862
4 | 1204062305
5 | 1224897301
6 | 1254885428
7 | 1295311477
8 | 1361196352
9 | 1372188757
10 | 14424972
11 | 156474078
12 | 1587030290
13 | 1634816
14 | 1636651575
15 | 1648807314
16 | 170817766
17 | 1709378501
18 | 174692320
19 | 1814664578
20 | 18489332
21 | 199759840
22 | 2030653815
23 | 2043831280
24 | 2118625994
25 | 2120936774
26 | 213654866
27 | 2147052512
28 | 2186255795
29 | 2233672250
30 | 2239710476
31 | 225191079
32 | 2266416332
33 | 22699817
34 | 2288136183
35 | 2312639559
36 | 2353849
37 | 2372995574
38 | 237815567
39 | 2404040793
40 | 2417212918
41 | 2437602091
42 | 2451065225
43 | 250277765
44 | 2542662563
45 | 2580479214
46 | 261068
47 | 2653111362
48 | 270814102
49 | 2715171150
50 | 281972218
51 | 2844520516
52 | 2863107962
53 | 2911658494
54 | 2939015820
55 | 3062021448
56 | 3089202157
57 | 310076750
58 | 3187108438
59 | 3210734866
60 | 3284354538
61 | 3331716292
62 | 342149506
63 | 3464901851
64 | 346731834
65 | 347629355
66 | 347826333
67 | 3576294411
68 | 364259537
69 | 3662810723
70 | 3684472818
71 | 368987306
72 | 37096733
73 | 3729198156
74 | 3796238727
75 | 3854178896
76 | 3858593140
77 | 3873491482
78 | 3893740955
79 | 3929640120
80 | 3944399031
81 | 3989161
82 | 399829006
83 | 40014967
84 | 4017305068
85 | 4022732812
86 | 406798473
87 | 4082680322
88 | 4141887018
89 | 4174638819
90 | 4237203680
91 | 4250120238
92 | 4253907822
93 | 4285163979
94 | 432269399
95 | 4332978153
96 | 4337161543
97 | 4351876664
98 | 435926861
99 | 437595409
100 | 442651885
101 | 4470478982
102 | 4471110141
103 | 447910249
104 | 448291547
105 | 4492032921
106 | 45092961
107 | 4512714865
108 | 4520272436
109 | 4553922208
110 | 4555082379
111 | 4560029166
112 | 4584451140
113 | 4683040401
114 | 4739664721
115 | 4758145781
116 | 47618649
117 | 4774338842
118 | 4801259916
119 | 4821642
120 | 4856974482
121 | 4880083461
122 | 4970182488
123 | 5002723411
124 | 5007442
125 | 5020454673
126 | 5065140719
127 | 5083671561
128 | 5144909700
129 | 5146483815
130 | 5151536225
131 | 5188566452
132 | 5201079592
133 | 5204730083
134 | 5227275045
135 | 52381600
136 | 5301057994
137 | 539722510
138 | 5452623
139 | 56054945
140 | 59354095
141 | 642820626
142 | 658607626
143 | 79378097
144 | 815038
145 | 82161078
146 | 823016568
147 | 878985234
148 | 88094323
149 | 899545263
150 | 90800092
151 | 91328372
152 | 9545523490
153 | 955659370
154 | 1051618982
155 | 1130084326
156 | 120563545
157 | 134212
158 | 1602308
159 | 16413031
160 | 2037185414
161 | 2060241469
162 | 2080551997
163 | 2086996835
164 | 2099639490
165 | 2122067003
166 | 2201628776
167 | 2239259
168 | 2296215131
169 | 2316734819
170 | 2329110240
171 | 2339510439
172 | 2392075438
173 | 2406586388
174 | 24795717
175 | 2519293956
176 | 253915276
177 | 255360810
178 | 2751381965
179 | 2803423910
180 | 2805422179
181 | 3020248483
182 | 3116931144
183 | 3346359383
184 | 3363054468
185 | 3504938758
186 | 3532475790
187 | 3722549017
188 | 378492784
189 | 397921011
190 | 4009440741
191 | 410225851
192 | 411555970
193 | 4145388945
194 | 4239974048
195 | 4400753623
196 | 442743156
197 | 4538917191
198 | 4573422380
199 | 4906266640
200 | 507521047
201 | 5082623456
202 | 5106695994
203 | 5169701116
204 | 70037463
205 | 719902933
--------------------------------------------------------------------------------
/tools/afw_test.py:
--------------------------------------------------------------------------------
1 | #-*- coding:utf-8 -*-
2 |
3 | from __future__ import division
4 | from __future__ import absolute_import
5 | from __future__ import print_function
6 |
7 | import os
8 | import sys
9 | import torch
10 | import argparse
11 | import torch.nn as nn
12 | import torch.utils.data as data
13 | import torch.backends.cudnn as cudnn
14 | import torchvision.transforms as transforms
15 |
16 | import cv2
17 | import time
18 | import numpy as np
19 | from PIL import Image
20 |
21 | from data.config import cfg
22 | from models.factory import build_net
23 | from torch.autograd import Variable
24 | from utils.augmentations import to_chw_bgr
25 |
26 |
27 | parser = argparse.ArgumentParser(description='dsfd evaluatuon afw')
28 | parser.add_argument('--network',
29 | default='vgg', type=str,
30 | choices=['vgg', 'resnet50', 'resnet101', 'resnet152'],
31 | help='model for training')
32 | parser.add_argument('--model',
33 | type=str,
34 | default='weights/dsfd_face.pth', help='trained model')
35 | parser.add_argument('--thresh', default=0.1, type=float,
36 | help='Final confidence threshold')
37 | args = parser.parse_args()
38 |
39 | use_cuda = torch.cuda.is_available()
40 |
41 | if use_cuda:
42 | torch.set_default_tensor_type('torch.cuda.FloatTensor')
43 | else:
44 | torch.set_default_tensor_type('torch.FloatTensor')
45 |
46 | AFW_IMG_DIR = os.path.join(cfg.FACE.AFW_DIR, 'images')
47 | AFW_RESULT_DIR = os.path.join(cfg.FACE.AFW_DIR, 'dsfd')
48 | AFW_RESULT_IMG_DIR = os.path.join(AFW_RESULT_DIR, 'images')
49 |
50 | if not os.path.exists(AFW_RESULT_IMG_DIR):
51 | os.makedirs(AFW_RESULT_IMG_DIR)
52 |
53 |
54 | def detect_face(net, img, thresh):
55 | height, width, _ = img.shape
56 | im_shrink = 640.0 / max(height, width)
57 | image = cv2.resize(img, None, None, fx=im_shrink,
58 | fy=im_shrink, interpolation=cv2.INTER_LINEAR).copy()
59 |
60 | x = to_chw_bgr(image)
61 | x = x.astype('float32')
62 | x -= cfg.img_mean
63 | x = x[[2, 1, 0], :, :]
64 |
65 | x = Variable(torch.from_numpy(x).unsqueeze(0))
66 | if use_cuda:
67 | x = x.cuda()
68 |
69 | y = net(x)
70 | detections = y.data
71 | scale = torch.Tensor([img.shape[1], img.shape[0],
72 | img.shape[1], img.shape[0]])
73 |
74 | bboxes = []
75 | for i in range(detections.size(1)):
76 | j = 0
77 | while detections[0, i, j, 0] >= thresh:
78 | box = []
79 | score = detections[0, i, j, 0]
80 | pt = (detections[0, i, j, 1:] * scale).cpu().numpy().astype(np.int)
81 | j += 1
82 | box += [pt[0], pt[1], pt[2], pt[3], score]
83 | box[1] += 0.2 * (box[3] - box[1] + 1)
84 | bboxes += [box]
85 |
86 | return bboxes
87 |
88 |
89 | if __name__ == '__main__':
90 | net = build_net('test', cfg.NUM_CLASSES, args.network)
91 | net.load_state_dict(torch.load(args.model))
92 | net.eval()
93 |
94 | if use_cuda:
95 | net.cuda()
96 | cudnn.benckmark = True
97 |
98 | #transform = S3FDBasicTransform(cfg.INPUT_SIZE, cfg.MEANS)
99 |
100 | counter = 0
101 | txt_out = os.path.join(AFW_RESULT_DIR, 'dsfd_dets.txt')
102 | txt_in = os.path.join('./tools/afw_img_list.txt')
103 |
104 | fout = open(txt_out, 'w')
105 | fin = open(txt_in, 'r')
106 |
107 | for line in fin.readlines():
108 | line = line.strip()
109 | img_file = os.path.join(AFW_IMG_DIR, line + '.jpg')
110 | out_file = os.path.join(AFW_RESULT_IMG_DIR, line + '.jpg')
111 | counter += 1
112 | t1 = time.time()
113 | #img = cv2.imread(img_file, cv2.IMREAD_COLOR)
114 | img = Image.open(img_file)
115 | if img.mode == 'L':
116 | img = img.convert('RGB')
117 | img = np.array(img)
118 | bboxes = detect_face(net, img, args.thresh)
119 | t2 = time.time()
120 | print('Detect %04d th image costs %.4f' % (counter, t2 - t1))
121 | for bbox in bboxes:
122 | x1, y1, x2, y2, score = bbox
123 | fout.write('{:s} {:.3f} {:.1f} {:.1f} {:.1f} {:.1f}\n'.format(
124 | line, score, x1, y1, x2, y2))
125 | for bbox in bboxes:
126 | x1, y1, x2, y2, score = bbox
127 | x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2)
128 | cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2)
129 | cv2.imwrite(out_file, img)
130 |
131 | fout.close()
132 | fin.close()
133 |
--------------------------------------------------------------------------------
/tools/fddb_test.py:
--------------------------------------------------------------------------------
1 | #-*- coding:utf-8 -*-
2 |
3 | from __future__ import division
4 | from __future__ import absolute_import
5 | from __future__ import print_function
6 |
7 | import os
8 | import sys
9 | import torch
10 | import argparse
11 | import torch.nn as nn
12 | import torch.utils.data as data
13 | import torch.backends.cudnn as cudnn
14 | import torchvision.transforms as transforms
15 |
16 | import cv2
17 | import time
18 | import numpy as np
19 | from PIL import Image
20 |
21 | from data.config import cfg
22 | from models.factory import build_net
23 | from torch.autograd import Variable
24 | from utils.augmentations import to_chw_bgr
25 |
26 | parser = argparse.ArgumentParser(description='dsfd evaluatuon fddb')
27 | parser.add_argument('--network',
28 | default='vgg', type=str,
29 | choices=['vgg', 'resnet50', 'resnet101', 'resnet152'],
30 | help='model for training')
31 | parser.add_argument('--model',
32 | type=str,
33 | default='weights/dsfd_face.pth', help='trained model')
34 | parser.add_argument('--thresh', default=0.1, type=float,
35 | help='Final confidence threshold')
36 | args = parser.parse_args()
37 |
38 | use_cuda = torch.cuda.is_available()
39 |
40 | if use_cuda:
41 | torch.set_default_tensor_type('torch.cuda.FloatTensor')
42 | else:
43 | torch.set_default_tensor_type('torch.FloatTensor')
44 |
45 |
46 | FDDB_IMG_DIR = os.path.join(cfg.FACE.FDDB_DIR, 'images')
47 | FDDB_FOLD_DIR = os.path.join(cfg.FACE.FDDB_DIR, 'FDDB-folds')
48 | FDDB_RESULT_DIR = os.path.join(cfg.FACE.FDDB_DIR, 'dsfd')
49 | FDDB_RESULT_IMG_DIR = os.path.join(FDDB_RESULT_DIR, 'images')
50 |
51 | if not os.path.exists(FDDB_RESULT_IMG_DIR):
52 | os.makedirs(FDDB_RESULT_IMG_DIR)
53 |
54 |
55 | def detect_face(net, img, thresh):
56 | height, width, _ = img.shape
57 | x = to_chw_bgr(img)
58 | x = x.astype('float32')
59 | x -= cfg.img_mean
60 | x = x[[2, 1, 0], :, :]
61 |
62 | x = Variable(torch.from_numpy(x).unsqueeze(0))
63 | if use_cuda:
64 | x = x.cuda()
65 |
66 | y = net(x)
67 | detections = y.data
68 | scale = torch.Tensor([img.shape[1], img.shape[0],
69 | img.shape[1], img.shape[0]])
70 |
71 | bboxes = []
72 | for i in range(detections.size(1)):
73 | j = 0
74 | while detections[0, i, j, 0] >= thresh:
75 | box = []
76 | score = detections[0, i, j, 0]
77 | pt = (detections[0, i, j, 1:] * scale).cpu().numpy().astype(np.int)
78 | j += 1
79 | box += [pt[0], pt[1], pt[2] - pt[0], pt[3] - pt[1], score]
80 | bboxes += [box]
81 |
82 | return bboxes
83 |
84 |
85 | if __name__ == '__main__':
86 | net = build_net('test', cfg.NUM_CLASSES, args.network)
87 | net.load_state_dict(torch.load(args.model))
88 | net.eval()
89 |
90 | if use_cuda:
91 | net.cuda()
92 | cudnn.benckmark = True
93 |
94 | #transform = S3FDBasicTransform(cfg.INPUT_SIZE, cfg.MEANS)
95 |
96 | counter = 0
97 |
98 | for i in range(10):
99 | txt_in = os.path.join(FDDB_FOLD_DIR, 'FDDB-fold-%02d.txt' % (i + 1))
100 | txt_out = os.path.join(FDDB_RESULT_DIR, 'fold-%02d-out.txt' % (i + 1))
101 | answer_in = os.path.join(
102 | FDDB_FOLD_DIR, 'FDDB-fold-%02d-ellipseList.txt' % (i + 1))
103 | with open(txt_in, 'r') as fr:
104 | lines = fr.readlines()
105 | fout = open(txt_out, 'w')
106 | ain = open(answer_in, 'r')
107 | for line in lines:
108 | line = line.strip()
109 | img_file = os.path.join(FDDB_IMG_DIR, line + '.jpg')
110 | out_file = os.path.join(
111 | FDDB_RESULT_IMG_DIR, line.replace('/', '_') + '.jpg')
112 | counter += 1
113 | t1 = time.time()
114 | #img = cv2.imread(img_file, cv2.IMREAD_COLOR)
115 | img = Image.open(img_file)
116 | if img.mode == 'L':
117 | img = img.convert('RGB')
118 | img = np.array(img)
119 | bboxes = detect_face(net, img, args.thresh)
120 | t2 = time.time()
121 | print('Detect %04d th image costs %.4f' % (counter, t2 - t1))
122 | fout.write('%s\n' % line)
123 | fout.write('%d\n' % len(bboxes))
124 | for bbox in bboxes:
125 | x1, y1, w, h, score = bbox
126 | fout.write('%d %d %d %d %lf\n' % (x1, y1, w, h, score))
127 | ain.readline()
128 | n = int(ain.readline().strip())
129 | for i in range(n):
130 | line = ain.readline().strip()
131 | line_data = [float(_) for _ in line.split(' ')[:5]]
132 | major_axis_radius, minor_axis_radius, angle, center_x, center_y = line_data
133 | angle = angle / 3.1415926 * 180.
134 | center_x, center_y = int(center_x), int(center_y)
135 | major_axis_radius, minor_axis_radius = int(
136 | major_axis_radius), int(minor_axis_radius)
137 | cv2.ellipse(img, (center_x, center_y), (major_axis_radius,
138 | minor_axis_radius), angle, 0, 360, (255, 0, 0), 2)
139 |
140 | for bbox in bboxes:
141 | x1, y1, w, h, score = bbox
142 | x1, y1, x2, y2 = int(x1), int(y1), int(x1 + w), int(y1 + h)
143 | cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2)
144 | cv2.imwrite(out_file, img)
145 | fout.close()
146 | ain.close()
147 |
--------------------------------------------------------------------------------
/tools/pascal_img_list.txt:
--------------------------------------------------------------------------------
1 | 2007_000272.jpg
2 | 2007_000664.jpg
3 | 2007_000807.jpg
4 | 2007_001558.jpg
5 | 2007_001583.jpg
6 | 2007_001627.jpg
7 | 2007_002079.jpg
8 | 2007_002262.jpg
9 | 2007_002344.jpg
10 | 2007_003091.jpg
11 | 2007_003226.jpg
12 | 2007_003329.jpg
13 | 2007_003581.jpg
14 | 2007_003745.jpg
15 | 2007_003747.jpg
16 | 2007_003831.jpg
17 | 2007_004000.jpg
18 | 2007_004049.jpg
19 | 2007_004092.jpg
20 | 2007_004133.jpg
21 | 2007_004197.jpg
22 | 2007_004238.jpg
23 | 2007_004397.jpg
24 | 2007_004517.jpg
25 | 2007_004713.jpg
26 | 2007_004770.jpg
27 | 2007_004831.jpg
28 | 2007_005019.jpg
29 | 2007_005310.jpg
30 | 2007_005405.jpg
31 | 2007_005450.jpg
32 | 2007_005527.jpg
33 | 2007_005657.jpg
34 | 2007_005691.jpg
35 | 2007_005695.jpg
36 | 2007_005748.jpg
37 | 2007_005896.jpg
38 | 2007_005969.jpg
39 | 2007_005971.jpg
40 | 2007_005972.jpg
41 | 2007_006163.jpg
42 | 2007_006240.jpg
43 | 2007_006282.jpg
44 | 2007_006442.jpg
45 | 2007_006559.jpg
46 | 2007_006614.jpg
47 | 2007_006744.jpg
48 | 2007_006786.jpg
49 | 2007_006808.jpg
50 | 2007_006809.jpg
51 | 2007_006856.jpg
52 | 2007_007031.jpg
53 | 2007_007080.jpg
54 | 2007_007083.jpg
55 | 2007_007119.jpg
56 | 2007_007151.jpg
57 | 2007_007161.jpg
58 | 2007_007277.jpg
59 | 2007_007330.jpg
60 | 2007_007420.jpg
61 | 2007_007438.jpg
62 | 2007_007582.jpg
63 | 2007_007595.jpg
64 | 2007_007606.jpg
65 | 2007_007618.jpg
66 | 2007_007763.jpg
67 | 2007_007769.jpg
68 | 2007_007871.jpg
69 | 2007_007877.jpg
70 | 2007_007892.jpg
71 | 2007_007910.jpg
72 | 2007_007917.jpg
73 | 2007_007940.jpg
74 | 2007_007955.jpg
75 | 2007_008013.jpg
76 | 2007_008211.jpg
77 | 2007_008321.jpg
78 | 2007_008396.jpg
79 | 2007_008446.jpg
80 | 2007_008559.jpg
81 | 2007_008567.jpg
82 | 2007_008647.jpg
83 | 2007_008664.jpg
84 | 2007_008690.jpg
85 | 2007_008816.jpg
86 | 2007_008921.jpg
87 | 2007_009040.jpg
88 | 2007_009153.jpg
89 | 2007_009253.jpg
90 | 2007_009391.jpg
91 | 2007_009402.jpg
92 | 2007_009425.jpg
93 | 2007_009578.jpg
94 | 2007_009579.jpg
95 | 2007_009610.jpg
96 | 2007_009612.jpg
97 | 2007_009653.jpg
98 | 2007_009736.jpg
99 | 2007_009783.jpg
100 | 2007_009910.jpg
101 | 2008_000210.jpg
102 | 2008_000216.jpg
103 | 2008_000263.jpg
104 | 2008_000280.jpg
105 | 2008_000317.jpg
106 | 2008_000325.jpg
107 | 2008_000331.jpg
108 | 2008_000355.jpg
109 | 2008_000407.jpg
110 | 2008_000438.jpg
111 | 2008_000451.jpg
112 | 2008_000528.jpg
113 | 2008_000568.jpg
114 | 2008_000569.jpg
115 | 2008_000574.jpg
116 | 2008_000610.jpg
117 | 2008_000611.jpg
118 | 2008_000616.jpg
119 | 2008_000618.jpg
120 | 2008_000624.jpg
121 | 2008_000637.jpg
122 | 2008_000642.jpg
123 | 2008_000662.jpg
124 | 2008_000700.jpg
125 | 2008_000701.jpg
126 | 2008_000715.jpg
127 | 2008_000720.jpg
128 | 2008_000728.jpg
129 | 2008_000730.jpg
130 | 2008_000733.jpg
131 | 2008_000735.jpg
132 | 2008_000737.jpg
133 | 2008_000740.jpg
134 | 2008_000745.jpg
135 | 2008_000778.jpg
136 | 2008_000780.jpg
137 | 2008_000822.jpg
138 | 2008_000825.jpg
139 | 2008_000925.jpg
140 | 2008_000927.jpg
141 | 2008_000946.jpg
142 | 2008_000983.jpg
143 | 2008_000992.jpg
144 | 2008_001003.jpg
145 | 2008_001063.jpg
146 | 2008_001074.jpg
147 | 2008_001076.jpg
148 | 2008_001090.jpg
149 | 2008_001094.jpg
150 | 2008_001095.jpg
151 | 2008_001215.jpg
152 | 2008_001255.jpg
153 | 2008_001273.jpg
154 | 2008_001397.jpg
155 | 2008_001429.jpg
156 | 2008_001487.jpg
157 | 2008_001491.jpg
158 | 2008_001504.jpg
159 | 2008_001534.jpg
160 | 2008_001540.jpg
161 | 2008_001561.jpg
162 | 2008_001598.jpg
163 | 2008_001602.jpg
164 | 2008_001607.jpg
165 | 2008_001619.jpg
166 | 2008_001646.jpg
167 | 2008_001657.jpg
168 | 2008_001668.jpg
169 | 2008_001671.jpg
170 | 2008_001726.jpg
171 | 2008_001731.jpg
172 | 2008_001745.jpg
173 | 2008_001748.jpg
174 | 2008_001754.jpg
175 | 2008_001763.jpg
176 | 2008_001767.jpg
177 | 2008_001778.jpg
178 | 2008_001802.jpg
179 | 2008_001840.jpg
180 | 2008_001847.jpg
181 | 2008_001874.jpg
182 | 2008_001901.jpg
183 | 2008_001907.jpg
184 | 2008_001909.jpg
185 | 2008_001919.jpg
186 | 2008_001976.jpg
187 | 2008_001984.jpg
188 | 2008_001995.jpg
189 | 2008_001996.jpg
190 | 2008_002006.jpg
191 | 2008_002017.jpg
192 | 2008_002035.jpg
193 | 2008_002052.jpg
194 | 2008_002078.jpg
195 | 2008_002097.jpg
196 | 2008_002145.jpg
197 | 2008_002169.jpg
198 | 2008_002176.jpg
199 | 2008_002183.jpg
200 | 2008_002247.jpg
201 | 2008_002251.jpg
202 | 2008_002259.jpg
203 | 2008_002260.jpg
204 | 2008_002277.jpg
205 | 2008_002319.jpg
206 | 2008_002346.jpg
207 | 2008_002351.jpg
208 | 2008_002355.jpg
209 | 2008_002470.jpg
210 | 2008_002520.jpg
211 | 2008_002537.jpg
212 | 2008_002538.jpg
213 | 2008_002576.jpg
214 | 2008_002596.jpg
215 | 2008_002627.jpg
216 | 2008_002633.jpg
217 | 2008_002651.jpg
218 | 2008_002658.jpg
219 | 2008_002664.jpg
220 | 2008_002677.jpg
221 | 2008_002729.jpg
222 | 2008_002756.jpg
223 | 2008_002803.jpg
224 | 2008_002809.jpg
225 | 2008_002827.jpg
226 | 2008_002829.jpg
227 | 2008_002851.jpg
228 | 2008_002853.jpg
229 | 2008_002855.jpg
230 | 2008_002867.jpg
231 | 2008_002908.jpg
232 | 2008_002910.jpg
233 | 2008_002924.jpg
234 | 2008_002949.jpg
235 | 2008_003002.jpg
236 | 2008_003007.jpg
237 | 2008_003012.jpg
238 | 2008_003044.jpg
239 | 2008_003080.jpg
240 | 2008_003096.jpg
241 | 2008_003126.jpg
242 | 2008_003190.jpg
243 | 2008_003220.jpg
244 | 2008_003257.jpg
245 | 2008_003279.jpg
246 | 2008_003284.jpg
247 | 2008_003332.jpg
248 | 2008_003342.jpg
249 | 2008_003365.jpg
250 | 2008_003419.jpg
251 | 2008_003424.jpg
252 | 2008_003438.jpg
253 | 2008_003446.jpg
254 | 2008_003460.jpg
255 | 2008_003483.jpg
256 | 2008_003505.jpg
257 | 2008_003531.jpg
258 | 2008_003593.jpg
259 | 2008_003601.jpg
260 | 2008_003603.jpg
261 | 2008_003610.jpg
262 | 2008_003616.jpg
263 | 2008_003632.jpg
264 | 2008_003671.jpg
265 | 2008_003696.jpg
266 | 2008_003721.jpg
267 | 2008_003736.jpg
268 | 2008_003754.jpg
269 | 2008_003765.jpg
270 | 2008_003766.jpg
271 | 2008_003773.jpg
272 | 2008_003836.jpg
273 | 2008_003861.jpg
274 | 2008_003871.jpg
275 | 2008_003874.jpg
276 | 2008_003880.jpg
277 | 2008_003884.jpg
278 | 2008_003933.jpg
279 | 2008_003960.jpg
280 | 2008_004018.jpg
281 | 2008_004065.jpg
282 | 2008_004076.jpg
283 | 2008_004095.jpg
284 | 2008_004135.jpg
285 | 2008_004137.jpg
286 | 2008_004263.jpg
287 | 2008_004341.jpg
288 | 2008_004370.jpg
289 | 2008_004379.jpg
290 | 2008_004392.jpg
291 | 2008_004440.jpg
292 | 2008_004456.jpg
293 | 2008_004517.jpg
294 | 2008_004521.jpg
295 | 2008_004534.jpg
296 | 2008_004567.jpg
297 | 2008_004569.jpg
298 | 2008_004604.jpg
299 | 2008_004657.jpg
300 | 2008_004954.jpg
301 | 2008_005098.jpg
302 | 2008_005490.jpg
303 | 2008_005701.jpg
304 | 2008_006971.jpg
305 | 2008_007387.jpg
306 | 2008_007982.jpg
307 | 2008_008122.jpg
308 | 2008_008251.jpg
309 | 2008_008335.jpg
310 | 2008_008742.jpg
311 | 2009_000043.jpg
312 | 2009_000044.jpg
313 | 2009_000061.jpg
314 | 2009_000072.jpg
315 | 2009_000179.jpg
316 | 2009_000183.jpg
317 | 2009_000272.jpg
318 | 2009_000301.jpg
319 | 2009_000322.jpg
320 | 2009_000337.jpg
321 | 2009_000436.jpg
322 | 2009_000456.jpg
323 | 2009_000470.jpg
324 | 2009_000606.jpg
325 | 2009_000706.jpg
326 | 2009_000781.jpg
327 | 2009_000815.jpg
328 | 2009_000827.jpg
329 | 2009_000833.jpg
330 | 2009_000865.jpg
331 | 2009_000936.jpg
332 | 2009_000942.jpg
333 | 2009_000962.jpg
334 | 2009_001073.jpg
335 | 2009_001084.jpg
336 | 2009_001254.jpg
337 | 2009_001256.jpg
338 | 2009_001330.jpg
339 | 2009_001389.jpg
340 | 2009_001454.jpg
341 | 2009_001479.jpg
342 | 2009_001521.jpg
343 | 2009_001578.jpg
344 | 2009_001580.jpg
345 | 2009_001602.jpg
346 | 2009_001617.jpg
347 | 2009_001641.jpg
348 | 2009_001740.jpg
349 | 2009_001841.jpg
350 | 2009_001876.jpg
351 | 2009_001909.jpg
352 | 2009_001979.jpg
353 | 2009_001983.jpg
354 | 2009_001994.jpg
355 | 2009_002013.jpg
356 | 2009_002160.jpg
357 | 2009_002241.jpg
358 | 2009_002242.jpg
359 | 2009_002261.jpg
360 | 2009_002321.jpg
361 | 2009_002349.jpg
362 | 2009_002407.jpg
363 | 2009_002489.jpg
364 | 2009_002492.jpg
365 | 2009_002514.jpg
366 | 2009_002580.jpg
367 | 2009_002587.jpg
368 | 2009_002607.jpg
369 | 2009_002690.jpg
370 | 2009_002721.jpg
371 | 2009_002873.jpg
372 | 2009_002918.jpg
373 | 2009_002922.jpg
374 | 2009_002976.jpg
375 | 2009_003000.jpg
376 | 2009_003026.jpg
377 | 2009_003064.jpg
378 | 2009_003220.jpg
379 | 2009_003275.jpg
380 | 2009_003290.jpg
381 | 2009_003490.jpg
382 | 2009_003496.jpg
383 | 2009_003540.jpg
384 | 2009_003563.jpg
385 | 2009_003594.jpg
386 | 2009_003630.jpg
387 | 2009_003641.jpg
388 | 2009_003662.jpg
389 | 2009_003683.jpg
390 | 2009_003751.jpg
391 | 2009_003829.jpg
392 | 2009_003872.jpg
393 | 2009_003874.jpg
394 | 2009_004004.jpg
395 | 2009_004063.jpg
396 | 2009_004071.jpg
397 | 2009_004110.jpg
398 | 2009_004113.jpg
399 | 2009_004205.jpg
400 | 2009_004221.jpg
401 | 2009_004251.jpg
402 | 2009_004256.jpg
403 | 2009_004326.jpg
404 | 2009_004393.jpg
405 | 2009_004405.jpg
406 | 2009_004410.jpg
407 | 2009_004525.jpg
408 | 2009_004531.jpg
409 | 2009_004587.jpg
410 | 2009_004622.jpg
411 | 2009_004697.jpg
412 | 2009_004761.jpg
413 | 2009_004806.jpg
414 | 2009_004809.jpg
415 | 2009_004865.jpg
416 | 2009_004899.jpg
417 | 2009_004995.jpg
418 | 2009_005045.jpg
419 | 2009_005166.jpg
420 | 2009_005297.jpg
421 | 2010_000041.jpg
422 | 2010_000120.jpg
423 | 2010_000204.jpg
424 | 2010_000474.jpg
425 | 2010_000476.jpg
426 | 2010_000597.jpg
427 | 2010_000617.jpg
428 | 2010_000733.jpg
429 | 2010_000775.jpg
430 | 2010_000778.jpg
431 | 2010_000993.jpg
432 | 2010_001008.jpg
433 | 2010_001236.jpg
434 | 2010_001278.jpg
435 | 2010_001379.jpg
436 | 2010_001397.jpg
437 | 2010_001438.jpg
438 | 2010_001482.jpg
439 | 2010_001739.jpg
440 | 2010_001870.jpg
441 | 2010_001878.jpg
442 | 2010_001917.jpg
443 | 2010_001935.jpg
444 | 2010_002096.jpg
445 | 2010_002100.jpg
446 | 2010_002122.jpg
447 | 2010_002154.jpg
448 | 2010_002188.jpg
449 | 2010_002201.jpg
450 | 2010_002282.jpg
451 | 2010_002380.jpg
452 | 2010_002403.jpg
453 | 2010_002597.jpg
454 | 2010_002675.jpg
455 | 2010_002717.jpg
456 | 2010_002769.jpg
457 | 2010_002853.jpg
458 | 2010_002914.jpg
459 | 2010_002981.jpg
460 | 2010_003003.jpg
461 | 2010_003111.jpg
462 | 2010_003112.jpg
463 | 2010_003185.jpg
464 | 2010_003213.jpg
465 | 2010_003250.jpg
466 | 2010_003326.jpg
467 | 2010_003414.jpg
468 | 2010_003431.jpg
469 | 2010_003510.jpg
470 | 2010_003618.jpg
471 | 2010_003620.jpg
472 | 2010_003626.jpg
473 | 2010_003649.jpg
474 | 2010_003755.jpg
475 | 2010_003831.jpg
476 | 2010_003927.jpg
477 | 2010_003949.jpg
478 | 2010_003955.jpg
479 | 2010_003964.jpg
480 | 2010_004031.jpg
481 | 2010_004272.jpg
482 | 2010_004280.jpg
483 | 2010_004282.jpg
484 | 2010_004400.jpg
485 | 2010_004418.jpg
486 | 2010_004424.jpg
487 | 2010_004622.jpg
488 | 2010_004698.jpg
489 | 2010_004708.jpg
490 | 2010_004818.jpg
491 | 2010_004887.jpg
492 | 2010_004940.jpg
493 | 2010_004972.jpg
494 | 2010_005127.jpg
495 | 2010_005132.jpg
496 | 2010_005141.jpg
497 | 2010_005148.jpg
498 | 2010_005156.jpg
499 | 2010_005303.jpg
500 | 2010_005319.jpg
501 | 2010_005403.jpg
502 | 2010_005405.jpg
503 | 2010_005489.jpg
504 | 2010_005539.jpg
505 | 2010_005541.jpg
506 | 2010_005631.jpg
507 | 2010_005773.jpg
508 | 2011_000004.jpg
509 | 2011_000023.jpg
510 | 2011_000024.jpg
511 | 2011_000055.jpg
512 | 2011_000073.jpg
513 | 2011_000075.jpg
514 | 2011_000080.jpg
515 | 2011_000093.jpg
516 | 2011_000100.jpg
517 | 2011_000113.jpg
518 | 2011_000136.jpg
519 | 2011_000139.jpg
520 | 2011_000140.jpg
521 | 2011_000144.jpg
522 | 2011_000148.jpg
523 | 2011_000151.jpg
524 | 2011_000153.jpg
525 | 2011_000155.jpg
526 | 2011_000160.jpg
527 | 2011_000168.jpg
528 | 2011_000187.jpg
529 | 2011_000189.jpg
530 | 2011_000190.jpg
531 | 2011_000207.jpg
532 | 2011_000223.jpg
533 | 2011_000237.jpg
534 | 2011_000242.jpg
535 | 2011_000256.jpg
536 | 2011_000260.jpg
537 | 2011_000264.jpg
538 | 2011_000272.jpg
539 | 2011_000280.jpg
540 | 2011_000287.jpg
541 | 2011_000318.jpg
542 | 2011_000327.jpg
543 | 2011_000360.jpg
544 | 2011_000363.jpg
545 | 2011_000368.jpg
546 | 2011_000372.jpg
547 | 2011_000393.jpg
548 | 2011_000395.jpg
549 | 2011_000415.jpg
550 | 2011_000433.jpg
551 | 2011_000443.jpg
552 | 2011_000460.jpg
553 | 2011_000467.jpg
554 | 2011_000486.jpg
555 | 2011_000497.jpg
556 | 2011_000507.jpg
557 | 2011_000516.jpg
558 | 2011_000517.jpg
559 | 2011_000522.jpg
560 | 2011_000533.jpg
561 | 2011_000535.jpg
562 | 2011_000539.jpg
563 | 2011_000545.jpg
564 | 2011_000547.jpg
565 | 2011_000553.jpg
566 | 2011_000561.jpg
567 | 2011_000564.jpg
568 | 2011_000570.jpg
569 | 2011_000580.jpg
570 | 2011_000583.jpg
571 | 2011_000590.jpg
572 | 2011_000593.jpg
573 | 2011_000611.jpg
574 | 2011_000613.jpg
575 | 2011_000614.jpg
576 | 2011_000623.jpg
577 | 2011_000625.jpg
578 | 2011_000635.jpg
579 | 2011_000644.jpg
580 | 2011_000645.jpg
581 | 2011_000647.jpg
582 | 2011_000648.jpg
583 | 2011_000649.jpg
584 | 2011_000674.jpg
585 | 2011_000678.jpg
586 | 2011_000680.jpg
587 | 2011_000696.jpg
588 | 2011_000700.jpg
589 | 2011_000715.jpg
590 | 2011_000716.jpg
591 | 2011_000717.jpg
592 | 2011_000719.jpg
593 | 2011_000720.jpg
594 | 2011_000732.jpg
595 | 2011_000761.jpg
596 | 2011_000779.jpg
597 | 2011_000787.jpg
598 | 2011_000792.jpg
599 | 2011_000797.jpg
600 | 2011_000798.jpg
601 | 2011_000803.jpg
602 | 2011_000812.jpg
603 | 2011_000818.jpg
604 | 2011_000832.jpg
605 | 2011_000842.jpg
606 | 2011_000861.jpg
607 | 2011_000862.jpg
608 | 2011_000865.jpg
609 | 2011_000871.jpg
610 | 2011_000876.jpg
611 | 2011_000877.jpg
612 | 2011_000878.jpg
613 | 2011_000904.jpg
614 | 2011_000921.jpg
615 | 2011_000928.jpg
616 | 2011_000935.jpg
617 | 2011_000936.jpg
618 | 2011_000942.jpg
619 | 2011_000945.jpg
620 | 2011_000946.jpg
621 | 2011_000949.jpg
622 | 2011_000955.jpg
623 | 2011_000959.jpg
624 | 2011_000972.jpg
625 | 2011_001003.jpg
626 | 2011_001018.jpg
627 | 2011_001038.jpg
628 | 2011_001043.jpg
629 | 2011_001051.jpg
630 | 2011_001067.jpg
631 | 2011_001083.jpg
632 | 2011_001095.jpg
633 | 2011_001108.jpg
634 | 2011_001109.jpg
635 | 2011_001122.jpg
636 | 2011_001142.jpg
637 | 2011_001143.jpg
638 | 2011_001170.jpg
639 | 2011_001199.jpg
640 | 2011_001205.jpg
641 | 2011_001206.jpg
642 | 2011_001210.jpg
643 | 2011_001212.jpg
644 | 2011_001222.jpg
645 | 2011_001225.jpg
646 | 2011_001235.jpg
647 | 2011_001239.jpg
648 | 2011_001243.jpg
649 | 2011_001250.jpg
650 | 2011_001268.jpg
651 | 2011_001269.jpg
652 | 2011_001278.jpg
653 | 2011_001298.jpg
654 | 2011_001300.jpg
655 | 2011_001307.jpg
656 | 2011_001308.jpg
657 | 2011_001331.jpg
658 | 2011_001347.jpg
659 | 2011_001353.jpg
660 | 2011_001362.jpg
661 | 2011_001378.jpg
662 | 2011_001380.jpg
663 | 2011_001385.jpg
664 | 2011_001391.jpg
665 | 2011_001409.jpg
666 | 2011_001429.jpg
667 | 2011_001436.jpg
668 | 2011_001458.jpg
669 | 2011_001462.jpg
670 | 2011_001470.jpg
671 | 2011_001473.jpg
672 | 2011_001481.jpg
673 | 2011_001494.jpg
674 | 2011_001502.jpg
675 | 2011_001511.jpg
676 | 2011_001520.jpg
677 | 2011_001522.jpg
678 | 2011_001562.jpg
679 | 2011_001563.jpg
680 | 2011_001570.jpg
681 | 2011_001579.jpg
682 | 2011_001581.jpg
683 | 2011_001583.jpg
684 | 2011_001590.jpg
685 | 2011_001598.jpg
686 | 2011_001610.jpg
687 | 2011_001615.jpg
688 | 2011_001627.jpg
689 | 2011_001645.jpg
690 | 2011_001659.jpg
691 | 2011_001670.jpg
692 | 2011_001685.jpg
693 | 2011_001687.jpg
694 | 2011_001701.jpg
695 | 2011_001718.jpg
696 | 2011_001731.jpg
697 | 2011_001756.jpg
698 | 2011_001763.jpg
699 | 2011_001767.jpg
700 | 2011_001780.jpg
701 | 2011_001792.jpg
702 | 2011_001803.jpg
703 | 2011_001821.jpg
704 | 2011_001839.jpg
705 | 2011_001861.jpg
706 | 2011_001878.jpg
707 | 2011_001894.jpg
708 | 2011_001903.jpg
709 | 2011_001912.jpg
710 | 2011_001921.jpg
711 | 2011_001943.jpg
712 | 2011_001955.jpg
713 | 2011_001958.jpg
714 | 2011_001976.jpg
715 | 2011_001979.jpg
716 | 2011_001994.jpg
717 | 2011_002024.jpg
718 | 2011_002025.jpg
719 | 2011_002026.jpg
720 | 2011_002030.jpg
721 | 2011_002051.jpg
722 | 2011_002052.jpg
723 | 2011_002054.jpg
724 | 2011_002058.jpg
725 | 2011_002072.jpg
726 | 2011_002078.jpg
727 | 2011_002101.jpg
728 | 2011_002122.jpg
729 | 2011_002129.jpg
730 | 2011_002130.jpg
731 | 2011_002133.jpg
732 | 2011_002168.jpg
733 | 2011_002171.jpg
734 | 2011_002190.jpg
735 | 2011_002191.jpg
736 | 2011_002196.jpg
737 | 2011_002202.jpg
738 | 2011_002203.jpg
739 | 2011_002207.jpg
740 | 2011_002212.jpg
741 | 2011_002217.jpg
742 | 2011_002225.jpg
743 | 2011_002226.jpg
744 | 2011_002275.jpg
745 | 2011_002277.jpg
746 | 2011_002290.jpg
747 | 2011_002320.jpg
748 | 2011_002321.jpg
749 | 2011_002351.jpg
750 | 2011_002353.jpg
751 | 2011_002360.jpg
752 | 2011_002363.jpg
753 | 2011_002372.jpg
754 | 2011_002376.jpg
755 | 2011_002428.jpg
756 | 2011_002431.jpg
757 | 2011_002432.jpg
758 | 2011_002446.jpg
759 | 2011_002472.jpg
760 | 2011_002478.jpg
761 | 2011_002506.jpg
762 | 2011_002517.jpg
763 | 2011_002521.jpg
764 | 2011_002527.jpg
765 | 2011_002550.jpg
766 | 2011_002569.jpg
767 | 2011_002577.jpg
768 | 2011_002580.jpg
769 | 2011_002581.jpg
770 | 2011_002586.jpg
771 | 2011_002591.jpg
772 | 2011_002603.jpg
773 | 2011_002619.jpg
774 | 2011_002626.jpg
775 | 2011_002645.jpg
776 | 2011_002651.jpg
777 | 2011_002666.jpg
778 | 2011_002668.jpg
779 | 2011_002670.jpg
780 | 2011_002671.jpg
781 | 2011_002679.jpg
782 | 2011_002683.jpg
783 | 2011_002684.jpg
784 | 2011_002690.jpg
785 | 2011_002698.jpg
786 | 2011_002701.jpg
787 | 2011_002708.jpg
788 | 2011_002712.jpg
789 | 2011_002723.jpg
790 | 2011_002732.jpg
791 | 2011_002744.jpg
792 | 2011_002745.jpg
793 | 2011_002755.jpg
794 | 2011_002757.jpg
795 | 2011_002778.jpg
796 | 2011_002785.jpg
797 | 2011_002787.jpg
798 | 2011_002789.jpg
799 | 2011_002793.jpg
800 | 2011_002794.jpg
801 | 2011_002797.jpg
802 | 2011_002822.jpg
803 | 2011_002837.jpg
804 | 2011_002848.jpg
805 | 2011_002853.jpg
806 | 2011_002857.jpg
807 | 2011_002858.jpg
808 | 2011_002861.jpg
809 | 2011_002877.jpg
810 | 2011_002902.jpg
811 | 2011_002904.jpg
812 | 2011_002915.jpg
813 | 2011_002918.jpg
814 | 2011_002931.jpg
815 | 2011_002946.jpg
816 | 2011_002957.jpg
817 | 2011_002972.jpg
818 | 2011_002981.jpg
819 | 2011_002996.jpg
820 | 2011_003006.jpg
821 | 2011_003022.jpg
822 | 2011_003032.jpg
823 | 2011_003037.jpg
824 | 2011_003042.jpg
825 | 2011_003069.jpg
826 | 2011_003075.jpg
827 | 2011_003082.jpg
828 | 2011_003094.jpg
829 | 2011_003099.jpg
830 | 2011_003116.jpg
831 | 2011_003118.jpg
832 | 2011_003136.jpg
833 | 2011_003143.jpg
834 | 2011_003144.jpg
835 | 2011_003165.jpg
836 | 2011_003172.jpg
837 | 2011_003173.jpg
838 | 2011_003174.jpg
839 | 2011_003186.jpg
840 | 2011_003190.jpg
841 | 2011_003200.jpg
842 | 2011_003206.jpg
843 | 2011_003214.jpg
844 | 2011_003217.jpg
845 | 2011_003229.jpg
846 | 2011_003237.jpg
847 | 2011_003252.jpg
848 | 2011_003258.jpg
849 | 2011_003270.jpg
850 | 2011_003272.jpg
851 | 2011_003273.jpg
--------------------------------------------------------------------------------
/tools/pascal_test.py:
--------------------------------------------------------------------------------
1 | #-*- coding:utf-8 -*-
2 |
3 | from __future__ import division
4 | from __future__ import absolute_import
5 | from __future__ import print_function
6 |
7 | import os
8 | import sys
9 | import torch
10 | import argparse
11 | import torch.nn as nn
12 | import torch.utils.data as data
13 | import torch.backends.cudnn as cudnn
14 | import torchvision.transforms as transforms
15 |
16 | import cv2
17 | import time
18 | import numpy as np
19 | from PIL import Image
20 |
21 | from data.config import cfg
22 | from models.factory import build_net
23 | from torch.autograd import Variable
24 | from utils.augmentations import to_chw_bgr
25 |
26 |
27 | parser = argparse.ArgumentParser(description='dsfd evaluatuon pascal')
28 | parser.add_argument('--network',
29 | default='vgg', type=str,
30 | choices=['vgg', 'resnet50', 'resnet101', 'resnet152'],
31 | help='model for training')
32 | parser.add_argument('--model',
33 | type=str,
34 | default='weights/dsfd_face.pth', help='trained model')
35 | parser.add_argument('--thresh', default=0.1, type=float,
36 | help='Final confidence threshold')
37 | args = parser.parse_args()
38 |
39 |
40 | use_cuda = torch.cuda.is_available()
41 |
42 | if use_cuda:
43 | torch.set_default_tensor_type('torch.cuda.FloatTensor')
44 | else:
45 | torch.set_default_tensor_type('torch.FloatTensor')
46 |
47 | PASCAL_IMG_DIR = os.path.join(cfg.FACE.PASCAL_DIR, 'images')
48 | PASCAL_RESULT_DIR = os.path.join(cfg.FACE.PASCAL_DIR, 'dsfd')
49 | PASCAL_RESULT_IMG_DIR = os.path.join(PASCAL_RESULT_DIR, 'images')
50 |
51 | if not os.path.exists(PASCAL_RESULT_IMG_DIR):
52 | os.makedirs(PASCAL_RESULT_IMG_DIR)
53 |
54 |
55 | def detect_face(net, img, thresh):
56 | height, width, _ = img.shape
57 | im_shrink = 640.0 / max(height, width)
58 | image = cv2.resize(img, None, None, fx=im_shrink,
59 | fy=im_shrink, interpolation=cv2.INTER_LINEAR).copy()
60 |
61 | x = to_chw_bgr(image)
62 | x = x.astype('float32')
63 | x -= cfg.img_mean
64 | x = x[[2, 1, 0], :, :]
65 |
66 | x = Variable(torch.from_numpy(x).unsqueeze(0))
67 | if use_cuda:
68 | x = x.cuda()
69 |
70 | y = net(x)
71 | detections = y.data
72 | scale = torch.Tensor([img.shape[1], img.shape[0],
73 | img.shape[1], img.shape[0]])
74 |
75 | bboxes = []
76 | for i in range(detections.size(1)):
77 | j = 0
78 | while detections[0, i, j, 0] >= thresh:
79 | box = []
80 | score = detections[0, i, j, 0]
81 | pt = (detections[0, i, j, 1:] * scale).cpu().numpy().astype(np.int)
82 | j += 1
83 | box += [pt[0], pt[1], pt[2], pt[3], score]
84 | box[1] += 0.2 * (box[3] - box[1] + 1)
85 | bboxes += [box]
86 |
87 | return bboxes
88 |
89 |
90 | if __name__ == '__main__':
91 | net = build_net('test', cfg.NUM_CLASSES, args.network)
92 | net.load_state_dict(torch.load(args.model))
93 | net.eval()
94 |
95 | if use_cuda:
96 | net.cuda()
97 | cudnn.benckmark = True
98 |
99 | #transform = S3FDBasicTransform(cfg.INPUT_SIZE, cfg.MEANS)
100 |
101 | counter = 0
102 | txt_out = os.path.join(PASCAL_RESULT_DIR, 'dsfd_dets.txt')
103 | txt_in = os.path.join('./tools/pascal_img_list.txt')
104 |
105 | fout = open(txt_out, 'w')
106 | fin = open(txt_in, 'r')
107 |
108 | for line in fin.readlines():
109 | line = line.strip()
110 | img_file = os.path.join(PASCAL_IMG_DIR, line)
111 | out_file = os.path.join(PASCAL_RESULT_IMG_DIR, line)
112 | counter += 1
113 | t1 = time.time()
114 | #img = cv2.imread(img_file, cv2.IMREAD_COLOR)
115 | img = Image.open(img_file)
116 | if img.mode == 'L':
117 | img = img.convert('RGB')
118 | img = np.array(img)
119 | bboxes = detect_face(net, img, args.thresh)
120 | t2 = time.time()
121 | print('Detect %04d th image costs %.4f' % (counter, t2 - t1))
122 | for bbox in bboxes:
123 | x1, y1, x2, y2, score = bbox
124 | fout.write('{:s} {:.3f} {:.1f} {:.1f} {:.1f} {:.1f}\n'.format(
125 | line, score, x1, y1, x2, y2))
126 | for bbox in bboxes:
127 | x1, y1, x2, y2, score = bbox
128 | x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2)
129 | cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2)
130 | cv2.imwrite(out_file, img)
131 |
132 | fout.close()
133 | fin.close()
134 |
--------------------------------------------------------------------------------
/tools/wider_test.py:
--------------------------------------------------------------------------------
1 | #-*- coding:utf-8 -*-
2 |
3 | from __future__ import division
4 | from __future__ import absolute_import
5 | from __future__ import print_function
6 |
7 | import os
8 | import torch
9 | import argparse
10 | import torch.nn as nn
11 | import torch.utils.data as data
12 | import torch.backends.cudnn as cudnn
13 | import torchvision.transforms as transforms
14 | import os.path as osp
15 |
16 | import cv2
17 | import time
18 | import numpy as np
19 | from PIL import Image
20 | import scipy.io as sio
21 |
22 | from data.config import cfg
23 | from models.factory import build_net
24 | from torch.autograd import Variable
25 | from utils.augmentations import to_chw_bgr
26 |
27 |
28 | parser = argparse.ArgumentParser(description='dsfd evaluatuon wider')
29 | parser.add_argument('--network',
30 | default='vgg', type=str,
31 | choices=['vgg', 'resnet50', 'resnet101', 'resnet152'],
32 | help='model for training')
33 | parser.add_argument('--model',
34 | type=str,
35 | default='weights/dsfd_face.pth', help='trained model')
36 | parser.add_argument('--thresh', default=0.05, type=float,
37 | help='Final confidence threshold')
38 | args = parser.parse_args()
39 |
40 |
41 | use_cuda = torch.cuda.is_available()
42 |
43 | if use_cuda:
44 | torch.set_default_tensor_type('torch.cuda.FloatTensor')
45 | else:
46 | torch.set_default_tensor_type('torch.FloatTensor')
47 |
48 |
49 | def detect_face(net, img, shrink):
50 | if shrink != 1:
51 | img = cv2.resize(img, None, None, fx=shrink, fy=shrink,
52 | interpolation=cv2.INTER_LINEAR)
53 |
54 | x = to_chw_bgr(img)
55 | x = x.astype('float32')
56 | x -= cfg.img_mean
57 | x = x[[2, 1, 0], :, :]
58 |
59 | x = Variable(torch.from_numpy(x).unsqueeze(0))
60 |
61 | if use_cuda:
62 | x = x.cuda()
63 | # print(x.size())
64 | y = net(x)
65 | detections = y.data
66 | detections = detections.cpu().numpy()
67 |
68 | det_conf = detections[0, 1, :, 0]
69 | det_xmin = img.shape[1] * detections[0, 1, :, 1] / shrink
70 | det_ymin = img.shape[0] * detections[0, 1, :, 2] / shrink
71 | det_xmax = img.shape[1] * detections[0, 1, :, 3] / shrink
72 | det_ymax = img.shape[0] * detections[0, 1, :, 4] / shrink
73 | det = np.column_stack((det_xmin, det_ymin, det_xmax, det_ymax, det_conf))
74 |
75 | keep_index = np.where(det[:, 4] >= args.thresh)[0]
76 | det = det[keep_index, :]
77 |
78 | return det
79 |
80 |
81 | def flip_test(net, image, shrink):
82 | image_f = cv2.flip(image, 1)
83 | det_f = detect_face(net, image_f, shrink)
84 |
85 | det_t = np.zeros(det_f.shape)
86 | det_t[:, 0] = image.shape[1] - det_f[:, 2]
87 | det_t[:, 1] = det_f[:, 1]
88 | det_t[:, 2] = image.shape[1] - det_f[:, 0]
89 | det_t[:, 3] = det_f[:, 3]
90 | det_t[:, 4] = det_f[:, 4]
91 | return det_t
92 |
93 |
94 | def multi_scale_test(net, image, max_im_shrink):
95 | # shrink detecting and shrink only detect big face
96 | st = 0.5 if max_im_shrink >= 0.75 else 0.5 * max_im_shrink
97 | det_s = detect_face(net, image, st)
98 | index = np.where(np.maximum(
99 | det_s[:, 2] - det_s[:, 0] + 1, det_s[:, 3] - det_s[:, 1] + 1) > 30)[0]
100 | det_s = det_s[index, :]
101 |
102 | # enlarge one times
103 | bt = min(2, max_im_shrink) if max_im_shrink > 1 else (
104 | st + max_im_shrink) / 2
105 | det_b = detect_face(net, image, bt)
106 |
107 | # enlarge small image x times for small face
108 | if max_im_shrink > 2:
109 | bt *= 2
110 | while bt < max_im_shrink:
111 | det_b = np.row_stack((det_b, detect_face(net, image, bt)))
112 | bt *= 2
113 | det_b = np.row_stack((det_b, detect_face(net, image, max_im_shrink)))
114 |
115 | # enlarge only detect small face
116 | if bt > 1:
117 | index = np.where(np.minimum(
118 | det_b[:, 2] - det_b[:, 0] + 1, det_b[:, 3] - det_b[:, 1] + 1) < 100)[0]
119 | det_b = det_b[index, :]
120 | else:
121 | index = np.where(np.maximum(
122 | det_b[:, 2] - det_b[:, 0] + 1, det_b[:, 3] - det_b[:, 1] + 1) > 30)[0]
123 | det_b = det_b[index, :]
124 |
125 | return det_s, det_b
126 |
127 |
128 | def bbox_vote(det):
129 | order = det[:, 4].ravel().argsort()[::-1]
130 | det = det[order, :]
131 | while det.shape[0] > 0:
132 | # IOU
133 | area = (det[:, 2] - det[:, 0] + 1) * (det[:, 3] - det[:, 1] + 1)
134 | xx1 = np.maximum(det[0, 0], det[:, 0])
135 | yy1 = np.maximum(det[0, 1], det[:, 1])
136 | xx2 = np.minimum(det[0, 2], det[:, 2])
137 | yy2 = np.minimum(det[0, 3], det[:, 3])
138 | w = np.maximum(0.0, xx2 - xx1 + 1)
139 | h = np.maximum(0.0, yy2 - yy1 + 1)
140 | inter = w * h
141 | o = inter / (area[0] + area[:] - inter)
142 |
143 | # get needed merge det and delete these det
144 | merge_index = np.where(o >= 0.3)[0]
145 | det_accu = det[merge_index, :]
146 | det = np.delete(det, merge_index, 0)
147 |
148 | if merge_index.shape[0] <= 1:
149 | continue
150 | det_accu[:, 0:4] = det_accu[:, 0:4] * np.tile(det_accu[:, -1:], (1, 4))
151 | max_score = np.max(det_accu[:, 4])
152 | det_accu_sum = np.zeros((1, 5))
153 | det_accu_sum[:, 0:4] = np.sum(
154 | det_accu[:, 0:4], axis=0) / np.sum(det_accu[:, -1:])
155 | det_accu_sum[:, 4] = max_score
156 | try:
157 | dets = np.row_stack((dets, det_accu_sum))
158 | except:
159 | dets = det_accu_sum
160 |
161 | dets = dets[0:750, :]
162 | return dets
163 |
164 |
165 | def get_data():
166 | subset = 'val'
167 | if subset is 'val':
168 | wider_face = sio.loadmat(
169 | './eval_tools/wider_face_val.mat')
170 | else:
171 | wider_face = sio.loadmat(
172 | './eval_tools/wider_face_test.mat')
173 | event_list = wider_face['event_list']
174 | file_list = wider_face['file_list']
175 | del wider_face
176 |
177 | imgs_path = os.path.join(
178 | cfg.FACE.WIDER_DIR, 'WIDER_{}'.format(subset), 'images')
179 | save_path = 'eval_tools/dsfd_{}'.format(subset)
180 |
181 | return event_list, file_list, imgs_path, save_path
182 |
183 | if __name__ == '__main__':
184 | event_list, file_list, imgs_path, save_path = get_data()
185 | net = build_net('test', cfg.NUM_CLASSES, args.network)
186 | net.load_state_dict(torch.load(args.model))
187 | net.eval()
188 |
189 | if use_cuda:
190 | net.cuda()
191 | cudnn.benckmark = True
192 |
193 | #transform = S3FDBasicTransform(cfg.INPUT_SIZE, cfg.MEANS)
194 |
195 | counter = 0
196 |
197 | for index, event in enumerate(event_list):
198 | filelist = file_list[index][0]
199 | path = os.path.join(save_path, event[0][0].encode('utf-8'))
200 | if not os.path.exists(path):
201 | os.makedirs(path)
202 |
203 | for num, file in enumerate(filelist):
204 | im_name = file[0][0].encode('utf-8')
205 | in_file = os.path.join(imgs_path, event[0][0], im_name[:] + '.jpg')
206 | #img = cv2.imread(in_file)
207 | img = Image.open(in_file)
208 | if img.mode == 'L':
209 | img = img.convert('RGB')
210 | img = np.array(img)
211 |
212 | max_im_shrink = np.sqrt(
213 | 1500 * 1000 / (img.shape[0] * img.shape[1]))
214 |
215 | shrink = max_im_shrink if max_im_shrink < 1 else 1
216 | counter += 1
217 |
218 | t1 = time.time()
219 | det0 = detect_face(net, img, shrink)
220 |
221 | det1 = flip_test(net, img, shrink) # flip test
222 | [det2, det3] = multi_scale_test(net, img, max_im_shrink)
223 |
224 | det = np.row_stack((det0, det1, det2, det3))
225 | dets = bbox_vote(det)
226 |
227 | t2 = time.time()
228 | print('Detect %04d th image costs %.4f' % (counter, t2 - t1))
229 |
230 | fout = open(osp.join(save_path, event[0][
231 | 0].encode('utf-8'), im_name + '.txt'), 'w')
232 | fout.write('{:s}\n'.format(event[0][0].encode(
233 | 'utf-8') + '/' + im_name + '.jpg'))
234 | fout.write('{:d}\n'.format(dets.shape[0]))
235 | for i in xrange(dets.shape[0]):
236 | xmin = dets[i][0]
237 | ymin = dets[i][1]
238 | xmax = dets[i][2]
239 | ymax = dets[i][3]
240 | score = dets[i][4]
241 | fout.write('{:.1f} {:.1f} {:.1f} {:.1f} {:.3f}\n'.
242 | format(xmin, ymin, (xmax - xmin + 1), (ymax - ymin + 1), score))
243 |
--------------------------------------------------------------------------------
/train.py:
--------------------------------------------------------------------------------
1 | #-*- coding:utf-8 -*-
2 |
3 | from __future__ import division
4 | from __future__ import absolute_import
5 | from __future__ import print_function
6 |
7 | import os
8 | import time
9 | import torch
10 | import argparse
11 | import torch.nn as nn
12 | import torch.optim as optim
13 | import torch.nn.init as init
14 | import torch.utils.data as data
15 | import numpy as np
16 | from torch.autograd import Variable
17 | import torch.backends.cudnn as cudnn
18 |
19 | from data.config import cfg
20 | from layers.modules import MultiBoxLoss
21 | from data.widerface import WIDERDetection, detection_collate
22 | from models.factory import build_net, basenet_factory
23 |
24 | parser = argparse.ArgumentParser(
25 | description='DSFD face Detector Training With Pytorch')
26 | train_set = parser.add_mutually_exclusive_group()
27 | parser.add_argument('--batch_size',
28 | default=16, type=int,
29 | help='Batch size for training')
30 | parser.add_argument('--model',
31 | default='vgg', type=str,
32 | choices=['vgg', 'resnet50', 'resnet101', 'resnet152'],
33 | help='model for training')
34 | parser.add_argument('--resume',
35 | default=None, type=str,
36 | help='Checkpoint state_dict file to resume training from')
37 | parser.add_argument('--num_workers',
38 | default=4, type=int,
39 | help='Number of workers used in dataloading')
40 | parser.add_argument('--cuda',
41 | default=True, type=bool,
42 | help='Use CUDA to train model')
43 | parser.add_argument('--lr', '--learning-rate',
44 | default=1e-3, type=float,
45 | help='initial learning rate')
46 | parser.add_argument('--momentum',
47 | default=0.9, type=float,
48 | help='Momentum value for optim')
49 | parser.add_argument('--weight_decay',
50 | default=5e-4, type=float,
51 | help='Weight decay for SGD')
52 | parser.add_argument('--gamma',
53 | default=0.1, type=float,
54 | help='Gamma update for SGD')
55 | parser.add_argument('--multigpu',
56 | default=False, type=bool,
57 | help='Use mutil Gpu training')
58 | parser.add_argument('--save_folder',
59 | default='weights/',
60 | help='Directory for saving checkpoint models')
61 | args = parser.parse_args()
62 |
63 | if not args.multigpu:
64 | os.environ['CUDA_LAUNCH_BLOCKING'] = '1'
65 |
66 | if torch.cuda.is_available():
67 | if args.cuda:
68 | torch.set_default_tensor_type('torch.cuda.FloatTensor')
69 | if not args.cuda:
70 | print("WARNING: It looks like you have a CUDA device, but aren't " +
71 | "using CUDA.\nRun with --cuda for optimal training speed.")
72 | torch.set_default_tensor_type('torch.FloatTensor')
73 | else:
74 | torch.set_default_tensor_type('torch.FloatTensor')
75 |
76 |
77 | save_folder = os.path.join(args.save_folder, args.model)
78 | if not os.path.exists(save_folder):
79 | os.mkdir(save_folder)
80 |
81 |
82 | train_dataset = WIDERDetection(cfg.FACE.TRAIN_FILE, mode='train')
83 |
84 | val_dataset = WIDERDetection(cfg.FACE.VAL_FILE, mode='val')
85 |
86 | train_loader = data.DataLoader(train_dataset, args.batch_size,
87 | num_workers=args.num_workers,
88 | shuffle=True,
89 | collate_fn=detection_collate,
90 | pin_memory=True)
91 | val_batchsize = args.batch_size // 2
92 | val_loader = data.DataLoader(val_dataset, val_batchsize,
93 | num_workers=args.num_workers,
94 | shuffle=False,
95 | collate_fn=detection_collate,
96 | pin_memory=True)
97 |
98 |
99 | min_loss = np.inf
100 |
101 |
102 | def train():
103 | per_epoch_size = len(train_dataset) // args.batch_size
104 | start_epoch = 0
105 | iteration = 0
106 | step_index = 0
107 |
108 | basenet = basenet_factory(args.model)
109 | dsfd_net = build_net('train', cfg.NUM_CLASSES, args.model)
110 | net = dsfd_net
111 |
112 | if args.resume:
113 | print('Resuming training, loading {}...'.format(args.resume))
114 | start_epoch = net.load_weights(args.resume)
115 | iteration = start_epoch * per_epoch_size
116 | else:
117 | base_weights = torch.load(args.save_folder + basenet)
118 | print('Load base network {}'.format(args.save_folder + basenet))
119 | if args.model == 'vgg':
120 | net.vgg.load_state_dict(base_weights)
121 | else:
122 | net.resnet.load_state_dict(base_weights)
123 |
124 | if args.cuda:
125 | if args.multigpu:
126 | net = torch.nn.DataParallel(dsfd_net)
127 | net = net.cuda()
128 | cudnn.benckmark = True
129 |
130 | if not args.resume:
131 | print('Initializing weights...')
132 | dsfd_net.extras.apply(dsfd_net.weights_init)
133 | dsfd_net.fpn_topdown.apply(dsfd_net.weights_init)
134 | dsfd_net.fpn_latlayer.apply(dsfd_net.weights_init)
135 | dsfd_net.fpn_fem.apply(dsfd_net.weights_init)
136 | dsfd_net.loc_pal1.apply(dsfd_net.weights_init)
137 | dsfd_net.conf_pal1.apply(dsfd_net.weights_init)
138 | dsfd_net.loc_pal2.apply(dsfd_net.weights_init)
139 | dsfd_net.conf_pal2.apply(dsfd_net.weights_init)
140 |
141 | optimizer = optim.SGD(net.parameters(), lr=args.lr, momentum=args.momentum,
142 | weight_decay=args.weight_decay)
143 | criterion = MultiBoxLoss(cfg, args.cuda)
144 | print('Loading wider dataset...')
145 | print('Using the specified args:')
146 | print(args)
147 |
148 | for step in cfg.LR_STEPS:
149 | if iteration > step:
150 | step_index += 1
151 | adjust_learning_rate(optimizer, args.gamma, step_index)
152 |
153 | net.train()
154 | for epoch in range(start_epoch, cfg.EPOCHES):
155 | losses = 0
156 | for batch_idx, (images, targets) in enumerate(train_loader):
157 | if args.cuda:
158 | images = Variable(images.cuda())
159 | targets = [Variable(ann.cuda(), volatile=True)
160 | for ann in targets]
161 | else:
162 | images = Variable(images)
163 | targets = [Variable(ann, volatile=True) for ann in targets]
164 |
165 | if iteration in cfg.LR_STEPS:
166 | step_index += 1
167 | adjust_learning_rate(optimizer, args.gamma, step_index)
168 |
169 | t0 = time.time()
170 | out = net(images)
171 | # backprop
172 | optimizer.zero_grad()
173 | loss_l_pa1l, loss_c_pal1 = criterion(out[:3], targets)
174 | loss_l_pa12, loss_c_pal2 = criterion(out[3:], targets)
175 |
176 | loss = loss_l_pa1l + loss_c_pal1 + loss_l_pa12 + loss_c_pal2
177 | loss.backward()
178 | optimizer.step()
179 | t1 = time.time()
180 | losses += loss.data[0]
181 |
182 | if iteration % 10 == 0:
183 | tloss = losses / (batch_idx + 1)
184 | print('Timer: %.4f' % (t1 - t0))
185 | print('epoch:' + repr(epoch) + ' || iter:' +
186 | repr(iteration) + ' || Loss:%.4f' % (tloss))
187 | print('->> pal1 conf loss:{:.4f} || pal1 loc loss:{:.4f}'.format(
188 | loss_c_pal1.data[0], loss_l_pa1l.data[0]))
189 | print('->> pal2 conf loss:{:.4f} || pal2 loc loss:{:.4f}'.format(
190 | loss_c_pal2.data[0], loss_l_pa12.data[0]))
191 | print('->>lr:{}'.format(optimizer.param_groups[0]['lr']))
192 |
193 | if iteration != 0 and iteration % 5000 == 0:
194 | print('Saving state, iter:', iteration)
195 | file = 'dsfd_' + repr(iteration) + '.pth'
196 | torch.save(dsfd_net.state_dict(),
197 | os.path.join(save_folder, file))
198 | iteration += 1
199 |
200 | val(epoch, net, dsfd_net, criterion)
201 | if iteration == cfg.MAX_STEPS:
202 | break
203 |
204 |
205 | def val(epoch, net, dsfd_net, criterion):
206 | net.eval()
207 | step = 0
208 | losses = 0
209 | t1 = time.time()
210 | for batch_idx, (images, targets) in enumerate(val_loader):
211 | if args.cuda:
212 | images = Variable(images.cuda())
213 | targets = [Variable(ann.cuda(), volatile=True)
214 | for ann in targets]
215 | else:
216 | images = Variable(images)
217 | targets = [Variable(ann, volatile=True) for ann in targets]
218 |
219 | out = net(images)
220 | loss_l_pa1l, loss_c_pal1 = criterion(out[:3], targets)
221 | loss_l_pa12, loss_c_pal2 = criterion(out[3:], targets)
222 | loss = loss_l_pa12 + loss_c_pal2
223 | losses += loss.data[0]
224 | step += 1
225 |
226 | tloss = losses / step
227 | t2 = time.time()
228 | print('Timer: %.4f' % (t2 - t1))
229 | print('test epoch:' + repr(epoch) + ' || Loss:%.4f' % (tloss))
230 |
231 | global min_loss
232 | if tloss < min_loss:
233 | print('Saving best state,epoch', epoch)
234 | torch.save(dsfd_net.state_dict(), os.path.join(
235 | save_folder, 'dsfd.pth'))
236 | min_loss = tloss
237 |
238 | states = {
239 | 'epoch': epoch,
240 | 'weight': dsfd_net.state_dict(),
241 | }
242 | torch.save(states, os.path.join(save_folder, 'dsfd_checkpoint.pth'))
243 |
244 |
245 | def adjust_learning_rate(optimizer, gamma, step):
246 | """Sets the learning rate to the initial LR decayed by 10 at every
247 | specified step
248 | # Adapted from PyTorch Imagenet example:
249 | # https://github.com/pytorch/examples/blob/master/imagenet/main.py
250 | """
251 | lr = args.lr * (gamma ** (step))
252 | for param_group in optimizer.param_groups:
253 | param_group['lr'] = lr
254 |
255 |
256 | if __name__ == '__main__':
257 | train()
258 |
--------------------------------------------------------------------------------
/utils/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------