-
Notifications
You must be signed in to change notification settings - Fork 0
/
extract_trainset.py
executable file
·187 lines (168 loc) · 6.03 KB
/
extract_trainset.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
#!/usr/bin/env python
"""
Extract train set.
"""
import multiprocessing as mp
import cv2
import numpy as np
import os
import random
import argparse
import functools
def mine_image(detector, size, path):
"""
Run negative mining on image, and extract false positives.
:param path: Path to image file
:param hog: OpenCV HOG Descriptor
:return: list of features
"""
winSize = size
blockSize = (16,16)
blockStride = (8,8)
cellSize = (8,8)
nbins = 9
hog = cv2.HOGDescriptor(winSize,blockSize,blockStride,cellSize,nbins)
hog.setSVMDetector(np.array(detector, dtype=np.float32))
frame = cv2.imread(path)
if frame is None:
return []
print "\t - Mining " + path
found, w = hog.detectMultiScale(frame)
features = []
for rect in found:
print "\t\t - Mined!"
x, y, w, h = rect
roi = frame[y:y+h, x:x+w]
feature = compute_hog(cv2.resize(roi, hog.winSize), hog)
features.append(feature)
return features
def extract_positive_features(size, path):
"""
Extract positive features from an image
:param path: Path to image file
:param hog: OpenCV HOG Descriptor
:return: list of features
"""
winSize = size
blockSize = (16,16)
blockStride = (8,8)
cellSize = (8,8)
nbins = 9
hog = cv2.HOGDescriptor(winSize,blockSize,blockStride,cellSize,nbins)
frame = cv2.imread(path)
if frame is None:
return None
print "\t - Loading " + path
return compute_hog(cv2.resize(frame, hog.winSize), hog)
def extract_negative_features(size, path):
"""
Extract negative features from an image
:param path: Path to image file
:param hog: OpenCV HOG Descriptor
:return: list of features
"""
winSize = size
blockSize = (16,16)
blockStride = (8,8)
cellSize = (8,8)
nbins = 9
hog = cv2.HOGDescriptor(winSize,blockSize,blockStride,cellSize,nbins)
frame = cv2.imread(path)
if frame is None:
return None
print "\t - Loading " + path
return compute_hog(extract_random_patch(frame, hog.winSize), hog)
def compute_hog(frame, hog):
"""
Computes and returns the HOG features.
:param frame: Image matrix
:param hog: OpenCV HOG Descriptor
:return: features
"""
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
return hog.compute(gray)
def extract_random_patch(frame, size):
"""
Extracts a random patch from frame.
:param frame: Image matrix
:param size: size of the random patch
:return: ROI
"""
frame_h, frame_w = frame.shape[:2]
width = size[0]
height = size[1]
x1 = random.randint(0, frame_w-width-1)
x2 = x1 + width
y1 = random.randint(0, frame_h-height-1)
y2 = y1 + height
roi = frame[y1:y2, x1:x2]
return roi.copy()
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Extract trainset for SVM",
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument("width", metavar="W", type=int, help="width of the HOG window")
parser.add_argument("height", metavar="H", type=int, help="height of the HOG window")
parser.add_argument("-o", "--output", nargs="?", type=str, default=os.getcwd()+"/train",
help="detecting vector output file")
parser.add_argument("-p", "--positive", nargs="?", type=str, default=os.getcwd()+"/positive",
help="positive sample directory")
parser.add_argument("-n", "--negative", nargs="?", type=str, default=os.getcwd()+"/negative",
help="negative sample directory")
parser.add_argument("-m", "--model", nargs="?", type=str, default=os.getcwd()+"/results.features",
help="run negative mining?")
args = parser.parse_args()
random.seed()
width = args.width
height = args.height
output = args.output
model = args.model
positive_dir = args.positive
negative_dir = args.negative
SIZE = (width, height)
# Load the sample paths
positive_samples_path = [os.path.join(positive_dir,f)
for f in os.listdir(positive_dir)
if os.path.isfile(os.path.join(positive_dir,f))]
negative_samples_path = [os.path.join(negative_dir,f)
for f in os.listdir(negative_dir)
if os.path.isfile(os.path.join(negative_dir,f))]
manager = mp.Manager()
queue = manager.Queue()
pool = mp.Pool(mp.cpu_count())
if os.path.isfile(model):
neg_mining = True
trainset = open(output, "a")
detector = [float(line) for line in open(model, "r")]
print "Applying negative mining..."
else:
neg_mining = False
trainset = open(output, "w")
print "Loading samples..."
if neg_mining:
func = functools.partial(mine_image, detector, SIZE)
for result in pool.imap(func, [path for path in negative_samples_path]):
for feature in result:
individual = "-1"
for ind, f in enumerate(feature):
individual += (" "+str(ind+1)+":"+str(f[0]))
individual += "\n"
trainset.write(individual)
else:
pos_func = functools.partial(extract_positive_features, SIZE)
for feature in pool.imap(pos_func, [path for path in positive_samples_path]):
if feature is None:
continue
individual = "+1"
for ind, f in enumerate(feature):
individual += (" "+str(ind+1)+":"+str(f[0]))
individual += "\n"
trainset.write(individual)
neg_func = functools.partial(extract_negative_features, SIZE)
for feature in pool.imap(neg_func, [path for path in negative_samples_path]):
if feature is None:
continue
individual = "-1"
for ind, f in enumerate(feature):
individual += (" "+str(ind+1)+":"+str(f[0]))
individual += "\n"
trainset.write(individual)