├── .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 | demo 65 | demo 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 | --------------------------------------------------------------------------------