-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathyolo.py
113 lines (98 loc) · 4.35 KB
/
yolo.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
"""Run a YOLO_v2 style detection model on test images."""
import numpy as np
from keras import backend as K
from keras.models import load_model
from PIL import Image
from yad2k.models.keras_yolo import yolo_eval, yolo_head
last_pred = None
model_path = 'model_data/yolo.h5'
assert model_path.endswith('.h5'), 'Keras model must be a .h5 file.'
anchors_path = 'model_data/yolo_anchors.txt'
classes_path = 'model_data/pascal_classes.txt'
iou_threshold = 0.5
score_threshold = 0.3
sess = K.get_session() # TODO: Remove dependence on Tensorflow session.
with open(classes_path) as f:
class_names = f.readlines()
class_names = [c.strip() for c in class_names]
with open(anchors_path) as f:
anchors = f.readline()
anchors = [float(x) for x in anchors.split(',')]
anchors = np.array(anchors).reshape(-1, 2)
yolo_model = load_model(model_path)
# Verify model, anchors, and classes are compatible
num_classes = len(class_names)
num_anchors = len(anchors)
model_output_channels = yolo_model.layers[-1].output_shape[-1]
assert model_output_channels == num_anchors * (num_classes + 5), \
'Mismatch between model and given anchor and class sizes. ' \
'Specify matching anchors and classes with --anchors_path and ' \
'--classes_path flags.'
print('{} model, anchors, and classes loaded.'.format(model_path))
# Check if model is fully convolutional, assuming channel last order.
model_image_size = yolo_model.layers[0].input_shape[1:3]
is_fixed_size = model_image_size != (None, None)
# Generate output tensor targets for filtered bounding boxes.
yolo_outputs = yolo_head(yolo_model.output, anchors, len(class_names))
input_image_shape = K.placeholder(shape=(2, ))
boxes, scores, classes = yolo_eval(
yolo_outputs,
input_image_shape,
score_threshold=score_threshold,
iou_threshold=iou_threshold)
def get_pred(image, target_class):
if type(image) == np.ndarray:
image = Image.fromarray(image)
elif not issubclass(type(image),Image.Image):
raise Exception('image must be of type PIL.Image.Image')
if is_fixed_size:
resized_image = image.resize(
tuple(reversed(model_image_size)), Image.BICUBIC)
image_data = np.array(resized_image, dtype='float32')
else:
# Due to skip connection + max pooling in YOLO_v2, inputs must have
# width and height as multiples of 32.
new_image_size = (image.width - (image.width % 32),
image.height - (image.height % 32))
if (image.width,image.height) != new_image_size:
resized_image = image.resize(new_image_size, Image.BICUBIC)
image_data = np.array(resized_image, dtype='float32')
print(image_data.shape)
image_data /= 255.
image_data = np.expand_dims(image_data, 0) # Add batch dimension.
out_boxes, out_scores, out_classes = sess.run(
[boxes, scores, classes],
feed_dict={
yolo_model.input: image_data,
input_image_shape: [image.size[1], image.size[0]],
K.learning_phase(): 0
})
print('Found {} boxes'.format(len(out_boxes)))
preds = []
for i, c in reversed(list(enumerate(out_classes))):
predicted_class = class_names[c]
box = out_boxes[i]
# score = out_scores[i]
if predicted_class != target_class:
continue
# label = '{} {:.2f}'.format(predicted_class, score)
ymin, xmin, ymax, xmax = box
ymin = max(0, np.floor(ymin + 0.5).astype('int32'))
xmin = max(0, np.floor(xmin + 0.5).astype('int32'))
ymax = min(image.size[1], np.floor(ymax + 0.5).astype('int32'))
xmax = min(image.size[0], np.floor(xmax + 0.5).astype('int32'))
# print(label, (xmin, ymin), (xmax, ymax))
preds.append((xmin, ymin, xmax, ymax))
if len(preds) == 0:
last_pred = None
return -1,-1,-1,-1
if type(last_pred) != np.ndarray: # If there isn't a previous prediction
# Pick bounding box with largest area
biggest = max(preds, key=lambda x: (x[2]-x[0])*(x[3]-x[1]))
last_pred = np.array(biggest)
return biggest
else: # If there is a previous prediction
# Pick bounding box with the smallest euclidian distance from the last predicted bounding box
closest = min(preds, key=lambda x: np.linalg.norm(last_pred-np.array(x)))
last_pred = np.array(closest)
return closest