Skip to content

Commit 4a9b238

Browse files
authored
Merge pull request #1111 from Laicheng0830/added_app
added yolov4
2 parents 93905f0 + 6379d01 commit 4a9b238

8 files changed

Lines changed: 497 additions & 3 deletions

File tree

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ install:
6464
- |
6565
if [[ -v _DOC_AND_YAPF_TEST ]]; then
6666
pip install tensorflow==2.0.0-rc1
67+
pip install opencv-python
6768
pip install yapf
6869
pip install -e .[doc]
6970
else

tensorlayer/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
from tensorlayer import optimizers
4545
from tensorlayer import rein
4646
from tensorlayer import utils
47+
from tensorlayer import app
4748

4849
from tensorlayer.lazy_imports import LazyImport
4950

tensorlayer/app/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#! /usr/bin/python
2+
# -*- coding: utf-8 -*-
3+
4+
from .computer_vision_object_detection import *
5+
from .computer_vision import *

tensorlayer/app/computer_vision.py

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
#! /usr/bin/python
2+
# -*- coding: utf-8 -*-
3+
4+
from tensorlayer.app import YOLOv4, get_anchors, decode, filter_boxes
5+
import numpy as np
6+
import tensorflow as tf
7+
from tensorlayer import logging
8+
import cv2
9+
10+
11+
class object_detection(object):
12+
13+
def __init__(self, model_name='yolo4-mscoco'):
14+
self.model_name = model_name
15+
if self.model_name == 'yolo4-mscoco':
16+
self.model = YOLOv4(NUM_CLASS=80, pretrained=True)
17+
else:
18+
raise ("The model does not support.")
19+
20+
def __call__(self, input_data):
21+
if self.model_name == 'yolo4-mscoco':
22+
batch_data = yolo4_input_processing(input_data)
23+
feature_maps = self.model(batch_data, is_train=False)
24+
output = yolo4_output_processing(feature_maps)
25+
else:
26+
raise NotImplementedError
27+
28+
return output
29+
30+
def __repr__(self):
31+
s = ('(model_name={model_name}, model_structure={model}')
32+
s += ')'
33+
return s.format(classname=self.__class__.__name__, **self.__dict__)
34+
35+
@property
36+
def list(self):
37+
logging.info("The model name list: yolov4-mscoco")
38+
39+
40+
def yolo4_input_processing(original_image):
41+
image_data = cv2.resize(original_image, (416, 416))
42+
image_data = image_data / 255.
43+
images_data = []
44+
for i in range(1):
45+
images_data.append(image_data)
46+
images_data = np.asarray(images_data).astype(np.float32)
47+
batch_data = tf.constant(images_data)
48+
return batch_data
49+
50+
51+
def yolo4_output_processing(feature_maps):
52+
STRIDES = [8, 16, 32]
53+
ANCHORS = get_anchors([12, 16, 19, 36, 40, 28, 36, 75, 76, 55, 72, 146, 142, 110, 192, 243, 459, 401])
54+
NUM_CLASS = 80
55+
XYSCALE = [1.2, 1.1, 1.05]
56+
iou_threshold = 0.45
57+
score_threshold = 0.25
58+
59+
bbox_tensors = []
60+
prob_tensors = []
61+
score_thres = 0.2
62+
for i, fm in enumerate(feature_maps):
63+
if i == 0:
64+
output_tensors = decode(fm, 416 // 8, NUM_CLASS, STRIDES, ANCHORS, i, XYSCALE)
65+
elif i == 1:
66+
output_tensors = decode(fm, 416 // 16, NUM_CLASS, STRIDES, ANCHORS, i, XYSCALE)
67+
else:
68+
output_tensors = decode(fm, 416 // 32, NUM_CLASS, STRIDES, ANCHORS, i, XYSCALE)
69+
bbox_tensors.append(output_tensors[0])
70+
prob_tensors.append(output_tensors[1])
71+
pred_bbox = tf.concat(bbox_tensors, axis=1)
72+
pred_prob = tf.concat(prob_tensors, axis=1)
73+
boxes, pred_conf = filter_boxes(
74+
pred_bbox, pred_prob, score_threshold=score_thres, input_shape=tf.constant([416, 416])
75+
)
76+
pred = {'concat': tf.concat([boxes, pred_conf], axis=-1)}
77+
78+
for key, value in pred.items():
79+
boxes = value[:, :, 0:4]
80+
pred_conf = value[:, :, 4:]
81+
82+
boxes, scores, classes, valid_detections = tf.image.combined_non_max_suppression(
83+
boxes=tf.reshape(boxes, (tf.shape(boxes)[0], -1, 1, 4)),
84+
scores=tf.reshape(pred_conf, (tf.shape(pred_conf)[0], -1, tf.shape(pred_conf)[-1])),
85+
max_output_size_per_class=50, max_total_size=50, iou_threshold=iou_threshold, score_threshold=score_threshold
86+
)
87+
output = [boxes.numpy(), scores.numpy(), classes.numpy(), valid_detections.numpy()]
88+
return output
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#! /usr/bin/python
2+
# -*- coding: utf-8 -*-
3+
4+
from .yolov4 import YOLOv4
5+
from .common import *
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
#! /usr/bin/python
2+
# -*- coding: utf-8 -*-
3+
4+
import tensorflow as tf
5+
import colorsys, random, cv2
6+
import numpy as np
7+
8+
9+
def decode_tf(conv_output, output_size, NUM_CLASS, STRIDES, ANCHORS, i=0, XYSCALE=[1, 1, 1]):
10+
batch_size = tf.shape(conv_output)[0]
11+
conv_output = tf.reshape(conv_output, (batch_size, output_size, output_size, 3, 5 + NUM_CLASS))
12+
13+
conv_raw_dxdy, conv_raw_dwdh, conv_raw_conf, conv_raw_prob = tf.split(conv_output, (2, 2, 1, NUM_CLASS), axis=-1)
14+
15+
xy_grid = tf.meshgrid(tf.range(output_size), tf.range(output_size))
16+
xy_grid = tf.expand_dims(tf.stack(xy_grid, axis=-1), axis=2) # [gx, gy, 1, 2]
17+
xy_grid = tf.tile(tf.expand_dims(xy_grid, axis=0), [batch_size, 1, 1, 3, 1])
18+
19+
xy_grid = tf.cast(xy_grid, tf.float32)
20+
21+
pred_xy = ((tf.sigmoid(conv_raw_dxdy) * XYSCALE[i]) - 0.5 * (XYSCALE[i] - 1) + xy_grid) * \
22+
STRIDES[i]
23+
pred_wh = (tf.exp(conv_raw_dwdh) * ANCHORS[i])
24+
pred_xywh = tf.concat([pred_xy, pred_wh], axis=-1)
25+
26+
pred_conf = tf.sigmoid(conv_raw_conf)
27+
pred_prob = tf.sigmoid(conv_raw_prob)
28+
29+
pred_prob = pred_conf * pred_prob
30+
pred_prob = tf.reshape(pred_prob, (batch_size, -1, NUM_CLASS))
31+
pred_xywh = tf.reshape(pred_xywh, (batch_size, -1, 4))
32+
33+
return pred_xywh, pred_prob
34+
35+
36+
def decode(conv_output, output_size, NUM_CLASS, STRIDES, ANCHORS, i, XYSCALE=[1, 1, 1]):
37+
return decode_tf(conv_output, output_size, NUM_CLASS, STRIDES, ANCHORS, i=i, XYSCALE=XYSCALE)
38+
39+
40+
def filter_boxes(box_xywh, scores, score_threshold=0.4, input_shape=tf.constant([416, 416])):
41+
scores_max = tf.math.reduce_max(scores, axis=-1)
42+
43+
mask = scores_max >= score_threshold
44+
class_boxes = tf.boolean_mask(box_xywh, mask)
45+
pred_conf = tf.boolean_mask(scores, mask)
46+
class_boxes = tf.reshape(class_boxes, [tf.shape(scores)[0], -1, tf.shape(class_boxes)[-1]])
47+
pred_conf = tf.reshape(pred_conf, [tf.shape(scores)[0], -1, tf.shape(pred_conf)[-1]])
48+
49+
box_xy, box_wh = tf.split(class_boxes, (2, 2), axis=-1)
50+
51+
input_shape = tf.cast(input_shape, dtype=tf.float32)
52+
box_yx = box_xy[..., ::-1]
53+
box_hw = box_wh[..., ::-1]
54+
55+
box_mins = (box_yx - (box_hw / 2.)) / input_shape
56+
box_maxes = (box_yx + (box_hw / 2.)) / input_shape
57+
boxes = tf.concat(
58+
[
59+
box_mins[..., 0:1], # y_min
60+
box_mins[..., 1:2], # x_min
61+
box_maxes[..., 0:1], # y_max
62+
box_maxes[..., 1:2] # x_max
63+
],
64+
axis=-1
65+
)
66+
# return tf.concat([boxes, pred_conf], axis=-1)
67+
return (boxes, pred_conf)
68+
69+
70+
def read_class_names(class_file_name):
71+
names = {}
72+
with open(class_file_name, 'r') as data:
73+
for ID, name in enumerate(data):
74+
names[ID] = name.strip('\n')
75+
return names
76+
77+
78+
def draw_bbox(image, bboxes, show_label=True):
79+
classes = read_class_names('model/coco.names')
80+
num_classes = len(classes)
81+
image_h, image_w, _ = image.shape
82+
hsv_tuples = [(1.0 * x / num_classes, 1., 1.) for x in range(num_classes)]
83+
colors = list(map(lambda x: colorsys.hsv_to_rgb(*x), hsv_tuples))
84+
colors = list(map(lambda x: (int(x[0] * 255), int(x[1] * 255), int(x[2] * 255)), colors))
85+
86+
random.seed(0)
87+
random.shuffle(colors)
88+
random.seed(None)
89+
90+
out_boxes, out_scores, out_classes, num_boxes = bboxes
91+
for i in range(num_boxes[0]):
92+
if int(out_classes[0][i]) < 0 or int(out_classes[0][i]) > num_classes: continue
93+
coor = out_boxes[0][i]
94+
coor[0] = int(coor[0] * image_h)
95+
coor[2] = int(coor[2] * image_h)
96+
coor[1] = int(coor[1] * image_w)
97+
coor[3] = int(coor[3] * image_w)
98+
99+
fontScale = 0.5
100+
score = out_scores[0][i]
101+
class_ind = int(out_classes[0][i])
102+
bbox_color = colors[class_ind]
103+
bbox_thick = int(0.6 * (image_h + image_w) / 600)
104+
c1, c2 = (coor[1], coor[0]), (coor[3], coor[2])
105+
cv2.rectangle(image, c1, c2, bbox_color, bbox_thick)
106+
107+
if show_label:
108+
bbox_mess = '%s: %.2f' % (classes[class_ind], score)
109+
t_size = cv2.getTextSize(bbox_mess, 0, fontScale, thickness=bbox_thick // 2)[0]
110+
c3 = (c1[0] + t_size[0], c1[1] - t_size[1] - 3)
111+
cv2.rectangle(image, c1, (np.float32(c3[0]), np.float32(c3[1])), bbox_color, -1) #filled
112+
113+
cv2.putText(
114+
image, bbox_mess, (c1[0], np.float32(c1[1] - 2)), cv2.FONT_HERSHEY_SIMPLEX, fontScale, (0, 0, 0),
115+
bbox_thick // 2, lineType=cv2.LINE_AA
116+
)
117+
return image
118+
119+
120+
def get_anchors(anchors_path, tiny=False):
121+
anchors = np.array(anchors_path)
122+
if tiny:
123+
return anchors.reshape(2, 3, 2)
124+
else:
125+
return anchors.reshape(3, 3, 2)
126+
127+
128+
def decode_train(conv_output, output_size, NUM_CLASS, STRIDES, ANCHORS, i=0, XYSCALE=[1, 1, 1]):
129+
conv_output = tf.reshape(conv_output, (tf.shape(conv_output)[0], output_size, output_size, 3, 5 + NUM_CLASS))
130+
131+
conv_raw_dxdy, conv_raw_dwdh, conv_raw_conf, conv_raw_prob = tf.split(conv_output, (2, 2, 1, NUM_CLASS), axis=-1)
132+
133+
xy_grid = tf.meshgrid(tf.range(output_size), tf.range(output_size))
134+
xy_grid = tf.expand_dims(tf.stack(xy_grid, axis=-1), axis=2) # [gx, gy, 1, 2]
135+
xy_grid = tf.tile(tf.expand_dims(xy_grid, axis=0), [tf.shape(conv_output)[0], 1, 1, 3, 1])
136+
137+
xy_grid = tf.cast(xy_grid, tf.float32)
138+
139+
pred_xy = ((tf.sigmoid(conv_raw_dxdy) * XYSCALE[i]) - 0.5 * (XYSCALE[i] - 1) + xy_grid) * \
140+
STRIDES[i]
141+
pred_wh = (tf.exp(conv_raw_dwdh) * ANCHORS[i])
142+
pred_xywh = tf.concat([pred_xy, pred_wh], axis=-1)
143+
144+
pred_conf = tf.sigmoid(conv_raw_conf)
145+
pred_prob = tf.sigmoid(conv_raw_prob)
146+
147+
return tf.concat([pred_xywh, pred_conf, pred_prob], axis=-1)
148+
149+
150+
# def weights_sorted():
151+
# # download weights
152+
# maybe_download_and_extract(
153+
# 'yolov4.npz',
154+
# model_path,
155+
# 'https://github.com/',
156+
# ) # ls -al
157+
# weights = []
158+
# track_weights = []
159+
# weights_dict = {}
160+
#
161+
# npz = np.load(model_path, allow_pickle=True)
162+
# # get weight list
163+
# for val in sorted(npz.items()):
164+
# logging.info(" Loading weights %s in %s" % (str(val[1].shape), val[0]))
165+
# try:
166+
# weights.append(int(val[0].split('/')[0].split('-')[-1]))
167+
# track_weights.append(val[0])
168+
# except:
169+
# pass
170+
# zip_weights = zip(weights, track_weights)
171+
# zip_weights = sorted(zip_weights)
172+
# for value, key in zip_weights:
173+
# print(key)

0 commit comments

Comments
 (0)