-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathdata.py
190 lines (147 loc) · 5.42 KB
/
data.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
from torchvision.datasets.folder import IMG_EXTENSIONS, default_loader
from torch.utils import data
import os
import numpy
COEF_SCALE = 1.05
class Folder(object):
"""
This class handle the image loading and parse groundtruth file
form the VOT dataset folder
"""
def __init__(self, folder, loader=default_loader):
# check path
folder = os.path.abspath(os.path.expanduser(folder))
if not os.path.isdir(folder):
raise ValueError('Not a valid foler: %s' %folder)
fn_gtruth = os.path.join(folder, 'groundtruth.txt')
if not os.path.isfile(fn_gtruth):
raise ValueError('Groundtruth file not found: %s' %fn_gtruth)
# load file names
fnames = sorted(
f for f in os.listdir(folder)
if any(f.endswith(ext) for ext in IMG_EXTENSIONS)
)
gtruth = numpy.genfromtxt(fn_gtruth, delimiter=',')
# store data
self.loader = loader
self.data = []
for fn, gt in zip(fnames, gtruth):
# filename prefix
fn = os.path.join(folder, fn)
# gen bbox
pts_x = gt[0::2]
pts_y = gt[1::2]
min_x = min(*pts_x)
min_y = min(*pts_y)
max_x = max(*pts_x)
max_y = max(*pts_y)
bbox = numpy.array((min_x, min_y, max_x, max_y))
# save
self.data.append((fn, bbox))
def __getitem__(self, index):
fn, gt = self.data[index]
img = self.loader(fn)
return img, gt
def __len__(self):
return len(self.data)
class RegionDataset(data.Dataset):
def __init__(self,
img,
crops,
transforms=None,
target_transforms_pos=None,
target_transforms_neg=None
):
self.img = img
self.crops = crops
self.transforms = transforms
self.target_transforms_pos = target_transforms_pos
self.target_transforms_neg = target_transforms_neg
def __len__(self):
return len(self.crops)
def __getitem__(self, index):
is_pos, bbox = self.crops[index]
img = self.img.crop(tuple(bbox))
target = bbox
if self.transforms is not None:
img = self.transforms(img)
if is_pos and (self.target_transforms_pos is not None):
target = self.target_transforms_pos(target)
elif (not is_pos) and (self.target_transforms_neg is not None):
target = self.target_transforms_neg(target)
return img, target
class SimpleSampler(object):
"""
This class implement the sampler in the paper
"""
def __init__(self,
init_bbox, # bbox(bounding box) of initial frame
transforms=None, # image transforms (from PIL)
target_transforms_pos=None,# positive target transforms (from bbox)
target_transforms_neg=None,# negative target transforms (from bbox)
num=[50, 50], # (pos, neg) num of samples to return
threshold=[.7, .5], # (pos, neg) threshold IoU of samples
sigma_xy=[.3, .3], # (x, y) sigma of translation
sigma_s=.5 # sigma of scaling
):
ibox = numpy.array(init_bbox)
lt, br = ibox.reshape([2, 2])
self.isize = br - lt
self.transforms = transforms
self.target_transforms_pos = target_transforms_pos
self.target_transforms_neg = target_transforms_neg
self.num = numpy.array(num)
self.num_total = sum(num)
self.thres_pos, self.thres_neg = threshold
self.sigma_t = numpy.array(sigma_xy)
self.sigma_s = sigma_s
def __call__(self, img, bbox):
bbox = numpy.array(bbox)
lt, br = bbox.reshape([2, 2])
ctr = (lt + br) /2
sz = numpy.mean(br - lt)
area = numpy.prod(sz)
sigma = self.sigma_t * sz
data = []
remain = self.num.copy()
def add_data(is_pos, nlt, nbr):
idx = int(not is_pos)
if remain[idx] == 0:
return
remain[idx] -= 1
data.append((
is_pos,
numpy.concatenate([nlt, nbr])
))
while True:
# gen region
nctr = numpy.random.normal(ctr, sigma)
nsize_2 = self.isize * (COEF_SCALE ** numpy.random.normal(scale=self.sigma_s)) /2
nlt = nctr - nsize_2
nbr = nctr + nsize_2
# overlap test
if (br < nlt).any() or (lt > nbr).any():
add_data(False, nlt, nbr)
continue
# iou
olt = numpy.maximum(lt, nlt)
obr = numpy.minimum(br, nbr)
area_over = numpy.prod(obr-olt)
area_add = numpy.prod(nsize_2) *4
area_union = area + area_add - area_over
iou = area_over / area_union
# iou test
if iou >= self.thres_pos:
add_data(True, nlt, nbr)
elif iou < self.thres_neg:
add_data(False, nlt, nbr)
# loop breaker
if all(remain==0):
break
return RegionDataset(
img,
data,
self.transforms,
self.target_transforms_pos,
self.target_transforms_neg
)