Skip to content

Commit f8292fe

Browse files
committed
support cpu training and testing
1 parent 01e5826 commit f8292fe

File tree

7 files changed

+64
-53
lines changed

7 files changed

+64
-53
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ $FaceBoxes_ROOT/data/FDDB/images/
7575
```Shell
7676
# dataset choices = ['AFW', 'PASCAL', 'FDDB']
7777
python3 test.py --dataset FDDB
78+
# evaluate using cpu
79+
python3 test.py --cpu
7880
```
7981

8082
3. Download [eval_tool](https://bitbucket.org/marcopede/face-eval) to evaluate the performance.

data/config.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@
99
'aspect_ratios': [[1], [1], [1]],
1010
'variance': [0.1, 0.2],
1111
'clip': False,
12-
'loc_weight': 2.0
12+
'loc_weight': 2.0,
13+
'gpu_train': True
1314
}

data/data_augment.py

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44
from utils.box_utils import matrix_iof
55

66

7-
def _crop(image, boxes, labels, img_dim, rgb_means):
7+
def _crop(image, boxes, labels, img_dim):
88
height, width, _ = image.shape
9+
pad_image_flag = True
910

1011
for _ in range(250):
1112
if random.uniform(0, 1) <= 0.2:
@@ -41,7 +42,7 @@ def _crop(image, boxes, labels, img_dim, rgb_means):
4142
b_h_t = (boxes_t[:, 3] - boxes_t[:, 1] + 1) / h * img_dim
4243
mask_b = np.minimum(b_w_t, b_h_t) > 16.0
4344
boxes_t = boxes_t[mask_b]
44-
labels_t = labels_t[mask_b].copy()
45+
labels_t = labels_t[mask_b]
4546

4647
if boxes_t.shape[0] == 0:
4748
continue
@@ -53,14 +54,10 @@ def _crop(image, boxes, labels, img_dim, rgb_means):
5354
boxes_t[:, 2:] = np.minimum(boxes_t[:, 2:], roi[2:])
5455
boxes_t[:, 2:] -= roi[:2]
5556

56-
return image_t, boxes_t, labels_t
57+
pad_image_flag = False
5758

58-
long_side = max(width, height)
59-
image_t = np.empty((long_side, long_side, 3), dtype=image.dtype)
60-
image_t[:, :] = rgb_means
61-
image_t[0:0 + height, 0:0 + width] = image
62-
63-
return image_t, boxes, labels
59+
return image_t, boxes_t, labels_t, pad_image_flag
60+
return image, boxes, labels, pad_image_flag
6461

6562

6663
def _distort(image):
@@ -85,7 +82,7 @@ def _convert(image, alpha=1, beta=0):
8582

8683
image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
8784

88-
# saturation distortion
85+
#saturation distortion
8986
if random.randrange(2):
9087
_convert(image[:, :, 1], alpha=random.uniform(0.5, 1.5))
9188

@@ -105,7 +102,7 @@ def _convert(image, alpha=1, beta=0):
105102

106103
image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
107104

108-
# saturation distortion
105+
#saturation distortion
109106
if random.randrange(2):
110107
_convert(image[:, :, 1], alpha=random.uniform(0.5, 1.5))
111108

@@ -159,12 +156,23 @@ def _mirror(image, boxes):
159156
return image, boxes
160157

161158

162-
def preproc_for_test(image, insize, mean):
159+
def _pad_to_square(image, rgb_mean, pad_image_flag):
160+
if not pad_image_flag:
161+
return image
162+
height, width, _ = image.shape
163+
long_side = max(width, height)
164+
image_t = np.empty((long_side, long_side, 3), dtype=image.dtype)
165+
image_t[:, :] = rgb_mean
166+
image_t[0:0 + height, 0:0 + width] = image
167+
return image_t
168+
169+
170+
def _resize_subtract_mean(image, insize, rgb_mean):
163171
interp_methods = [cv2.INTER_LINEAR, cv2.INTER_CUBIC, cv2.INTER_AREA, cv2.INTER_NEAREST, cv2.INTER_LANCZOS4]
164172
interp_method = interp_methods[random.randrange(5)]
165173
image = cv2.resize(image, (insize, insize), interpolation=interp_method)
166174
image = image.astype(np.float32)
167-
image -= mean
175+
image -= rgb_mean
168176
return image.transpose(2, 0, 1)
169177

170178

@@ -181,12 +189,15 @@ def __call__(self, image, targets):
181189
boxes = targets[:, :-1].copy()
182190
labels = targets[:, -1].copy()
183191

184-
image_t = _distort(image)
185-
# image_t, boxes_t = _expand(image_t, boxes, self.cfg['rgb_mean'], self.cfg['max_expand_ratio'])
186-
image_t, boxes_t, labels_t = _crop(image_t, boxes, labels, self.img_dim, self.rgb_means)
192+
#image_t = _distort(image)
193+
#image_t, boxes_t = _expand(image_t, boxes, self.cfg['rgb_mean'], self.cfg['max_expand_ratio'])
194+
#image_t, boxes_t, labels_t = _crop(image_t, boxes, labels, self.img_dim, self.rgb_means)
195+
image_t, boxes_t, labels_t, pad_image_flag = _crop(image, boxes, labels, self.img_dim)
196+
image_t = _distort(image_t)
197+
image_t = _pad_to_square(image_t,self.rgb_means, pad_image_flag)
187198
image_t, boxes_t = _mirror(image_t, boxes_t)
188199
height, width, _ = image_t.shape
189-
image_t = preproc_for_test(image_t, self.img_dim, self.rgb_means)
200+
image_t = _resize_subtract_mean(image_t, self.img_dim, self.rgb_means)
190201
boxes_t[:, 0::2] /= width
191202
boxes_t[:, 1::2] /= height
192203

layers/modules/multibox_loss.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,8 @@
33
import torch.nn.functional as F
44
from torch.autograd import Variable
55
from utils.box_utils import match, log_sum_exp
6-
GPU = False
7-
if torch.cuda.is_available():
8-
GPU = True
9-
6+
from data import cfg
7+
GPU = cfg['gpu_train']
108

119
class MultiBoxLoss(nn.Module):
1210
"""SSD Weighted Loss Function

models/faceboxes.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ def forward(self, x):
123123
x = self.inception1(x)
124124
x = self.inception2(x)
125125
x = self.inception3(x)
126-
detection_dimension += [x.shape[2:]]
126+
detection_dimension.append(x.shape[2:])
127127
sources.append(x)
128128
x = self.conv3_1(x)
129129
x = self.conv3_2(x)
@@ -134,8 +134,7 @@ def forward(self, x):
134134
detection_dimension.append(x.shape[2:])
135135
sources.append(x)
136136

137-
detection_dimension = torch.Tensor(detection_dimension)
138-
detection_dimension = detection_dimension.cuda()
137+
detection_dimension = torch.tensor(detection_dimension, device=x.device)
139138

140139
for (x, l, c) in zip(sources, self.loc, self.conf):
141140
loc.append(l(x).permute(0, 2, 3, 1).contiguous())

test.py

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from data import cfg
88
from layers.functions.prior_box import PriorBox
99
from utils.nms_wrapper import nms
10+
#from utils.nms.py_cpu_nms import py_cpu_nms
1011
import cv2
1112
from models.faceboxes import FaceBoxes
1213
from utils.box_utils import decode
@@ -17,9 +18,8 @@
1718
parser.add_argument('-m', '--trained_model', default='weights/FaceBoxes.pth',
1819
type=str, help='Trained state_dict file path to open')
1920
parser.add_argument('--save_folder', default='eval/', type=str, help='Dir to save results')
20-
parser.add_argument('--cuda', default=True, type=bool, help='Use cuda to train model')
21-
parser.add_argument('--cpu', default=False, type=bool, help='Use cpu nms')
22-
parser.add_argument('--dataset', default='FDDB', type=str, choices=['AFW', 'PASCAL', 'FDDB'], help='dataset')
21+
parser.add_argument('--cpu', action="store_true", default=False, help='Use cpu inference')
22+
parser.add_argument('--dataset', default='PASCAL', type=str, choices=['AFW', 'PASCAL', 'FDDB'], help='dataset')
2323
parser.add_argument('--confidence_threshold', default=0.05, type=float, help='confidence_threshold')
2424
parser.add_argument('--top_k', default=5000, type=int, help='top_k')
2525
parser.add_argument('--nms_threshold', default=0.3, type=float, help='nms_threshold')
@@ -47,10 +47,13 @@ def remove_prefix(state_dict, prefix):
4747
return {f(key): value for key, value in state_dict.items()}
4848

4949

50-
def load_model(model, pretrained_path):
50+
def load_model(model, pretrained_path, load_to_cpu):
5151
print('Loading pretrained model from {}'.format(pretrained_path))
52-
device = torch.cuda.current_device()
53-
pretrained_dict = torch.load(pretrained_path, map_location=lambda storage, loc: storage.cuda(device))
52+
if load_to_cpu:
53+
pretrained_dict = torch.load(pretrained_path, map_location=lambda storage, loc: storage)
54+
else:
55+
device = torch.cuda.current_device()
56+
pretrained_dict = torch.load(pretrained_path, map_location=lambda storage, loc: storage.cuda(device))
5457
if "state_dict" in pretrained_dict.keys():
5558
pretrained_dict = remove_prefix(pretrained_dict['state_dict'], 'module.')
5659
else:
@@ -61,17 +64,17 @@ def load_model(model, pretrained_path):
6164

6265

6366
if __name__ == '__main__':
67+
torch.set_grad_enabled(False)
6468
# net and model
6569
net = FaceBoxes(phase='test', size=None, num_classes=2) # initialize detector
66-
net = load_model(net, args.trained_model)
70+
net = load_model(net, args.trained_model, args.cpu)
6771
net.eval()
6872
print('Finished loading model!')
6973
print(net)
70-
if args.cuda:
71-
net = net.cuda()
72-
cudnn.benchmark = True
73-
else:
74-
net = net.cpu()
74+
cudnn.benchmark = True
75+
device = torch.device("cpu" if args.cpu else "cuda")
76+
net = net.to(device)
77+
7578

7679
# save file
7780
if not os.path.exists(args.save_folder):
@@ -106,18 +109,16 @@ def load_model(model, pretrained_path):
106109
img -= (104, 117, 123)
107110
img = img.transpose(2, 0, 1)
108111
img = torch.from_numpy(img).unsqueeze(0)
109-
if args.cuda:
110-
img = img.cuda()
111-
scale = scale.cuda()
112+
img = img.to(device)
113+
scale = scale.to(device)
112114

113115
_t['forward_pass'].tic()
114116
out = net(img) # forward pass
115117
_t['forward_pass'].toc()
116118
_t['misc'].tic()
117119
priorbox = PriorBox(cfg, out[2], (im_height, im_width), phase='test')
118120
priors = priorbox.forward()
119-
if args.cuda:
120-
priors = priors.cuda()
121+
priors = priors.to(device)
121122
loc, conf, _ = out
122123
prior_data = priors.data
123124
boxes = decode(loc.data.squeeze(0), prior_data, cfg['variance'])
@@ -137,7 +138,8 @@ def load_model(model, pretrained_path):
137138

138139
# do NMS
139140
dets = np.hstack((boxes, scores[:, np.newaxis])).astype(np.float32, copy=False)
140-
keep = nms(dets, args.nms_threshold, force_cpu=args.cpu)
141+
#keep = py_cpu_nms(dets, args.nms_threshold)
142+
keep = nms(dets, args.nms_threshold,force_cpu=args.cpu)
141143
dets = dets[keep, :]
142144

143145
# keep top-K faster NMS

train.py

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
from __future__ import print_function
22
import os
3-
os.environ["CUDA_VISIBLE_DEVICES"] = "0,1"
43
import torch
54
import torch.optim as optim
65
import torch.backends.cudnn as cudnn
@@ -18,7 +17,6 @@
1817
parser.add_argument('--training_dataset', default='./data/WIDER_FACE', help='Training dataset directory')
1918
parser.add_argument('-b', '--batch_size', default=32, type=int, help='Batch size for training')
2019
parser.add_argument('--num_workers', default=8, type=int, help='Number of workers used in dataloading')
21-
parser.add_argument('--cuda', default=True, type=bool, help='Use cuda to train model')
2220
parser.add_argument('--ngpu', default=2, type=int, help='gpus')
2321
parser.add_argument('--lr', '--learning-rate', default=1e-3, type=float, help='initial learning rate')
2422
parser.add_argument('--momentum', default=0.9, type=float, help='momentum')
@@ -34,12 +32,13 @@
3432
os.mkdir(args.save_folder)
3533

3634
img_dim = 1024
37-
rgb_means = (104, 117, 123)
35+
rgb_means = (104, 117, 123) #bgr order
3836
num_classes = 2
3937
batch_size = args.batch_size
4038
weight_decay = args.weight_decay
4139
gamma = args.gamma
4240
momentum = args.momentum
41+
gpu_train = cfg['gpu_train']
4342

4443
net = FaceBoxes('train', img_dim, num_classes)
4544
print("Printing net...")
@@ -60,21 +59,20 @@
6059
new_state_dict[name] = v
6160
net.load_state_dict(new_state_dict)
6261

63-
if args.ngpu > 1:
62+
if args.ngpu > 1 and gpu_train:
6463
net = torch.nn.DataParallel(net, device_ids=list(range(args.ngpu)))
6564

66-
if args.cuda:
67-
net.cuda()
68-
cudnn.benchmark = True
65+
device = torch.device('cuda:0' if gpu_train else 'cpu')
66+
cudnn.benchmark = True
67+
net = net.to(device)
6968

7069
optimizer = optim.SGD(net.parameters(), lr=args.lr, momentum=args.momentum, weight_decay=args.weight_decay)
7170
criterion = MultiBoxLoss(num_classes, 0.35, True, 0, True, 7, 0.35, False)
7271

7372
priorbox = PriorBox(cfg)
7473
with torch.no_grad():
7574
priors = priorbox.forward()
76-
if args.cuda:
77-
priors = priors.cuda()
75+
priors = priors.to(device)
7876

7977

8078
def train():
@@ -110,7 +108,7 @@ def train():
110108

111109
# load train data
112110
images, targets = next(batch_iterator)
113-
if args.cuda:
111+
if gpu_train:
114112
images = Variable(images.cuda())
115113
targets = [Variable(anno.cuda()) for anno in targets]
116114
else:

0 commit comments

Comments
 (0)