Last active
September 16, 2021 19:31
-
-
Save AlexTitovWork/dc005a8778e5b9f874888191b340cef6 to your computer and use it in GitHub Desktop.
faces detection based on yolo3 standard model
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# load yolov3 model and perform object detection | |
# based on https://github.com/experiencor/keras-yolo3 | |
# Partically coded by Interceptor 16.09.2021 | |
# @name Alex Titov | |
# @email [email protected] | |
import numpy as np | |
from numpy import expand_dims | |
from keras.models import load_model | |
from keras.preprocessing.image import load_img | |
from keras.preprocessing.image import img_to_array | |
from matplotlib import pyplot | |
from matplotlib.patches import Rectangle | |
import cv2 | |
from utils.utils import get_yolo_boxes, makedirs | |
class BoundBox: | |
def __init__(self, xmin, ymin, xmax, ymax, objness = None, classes = None): | |
self.xmin = xmin | |
self.ymin = ymin | |
self.xmax = xmax | |
self.ymax = ymax | |
self.objness = objness | |
self.classes = classes | |
self.label = -1 | |
self.score = -1 | |
def get_label(self): | |
if self.label == -1: | |
self.label = np.argmax(self.classes) | |
return self.label | |
def get_score(self): | |
if self.score == -1: | |
self.score = self.classes[self.get_label()] | |
return self.score | |
def _sigmoid(x): | |
return 1. / (1. + np.exp(-x)) | |
def decode_netout(netout, anchors, obj_thresh, net_h, net_w): | |
grid_h, grid_w = netout.shape[:2] | |
nb_box = 3 | |
netout = netout.reshape((grid_h, grid_w, nb_box, -1)) | |
nb_class = netout.shape[-1] - 5 | |
boxes = [] | |
netout[..., :2] = _sigmoid(netout[..., :2]) | |
netout[..., 4:] = _sigmoid(netout[..., 4:]) | |
netout[..., 5:] = netout[..., 4][..., np.newaxis] * netout[..., 5:] | |
netout[..., 5:] *= netout[..., 5:] > obj_thresh | |
for i in range(grid_h*grid_w): | |
row = i / grid_w | |
col = i % grid_w | |
for b in range(nb_box): | |
# 4th element is objectness score | |
objectness = netout[int(row)][int(col)][b][4] | |
if(objectness.all() <= obj_thresh): continue | |
# first 4 elements are x, y, w, and h | |
x, y, w, h = netout[int(row)][int(col)][b][:4] | |
x = (col + x) / grid_w # center position, unit: image width | |
y = (row + y) / grid_h # center position, unit: image height | |
w = anchors[2 * b + 0] * np.exp(w) / net_w # unit: image width | |
h = anchors[2 * b + 1] * np.exp(h) / net_h # unit: image height | |
# last elements are class probabilities | |
classes = netout[int(row)][col][b][5:] | |
box = BoundBox(x-w/2, y-h/2, x+w/2, y+h/2, objectness, classes) | |
boxes.append(box) | |
return boxes | |
def correct_yolo_boxes(boxes, image_h, image_w, net_h, net_w): | |
new_w, new_h = net_w, net_h | |
for i in range(len(boxes)): | |
x_offset, x_scale = (net_w - new_w)/2./net_w, float(new_w)/net_w | |
y_offset, y_scale = (net_h - new_h)/2./net_h, float(new_h)/net_h | |
boxes[i].xmin = int((boxes[i].xmin - x_offset) / x_scale * image_w) | |
boxes[i].xmax = int((boxes[i].xmax - x_offset) / x_scale * image_w) | |
boxes[i].ymin = int((boxes[i].ymin - y_offset) / y_scale * image_h) | |
boxes[i].ymax = int((boxes[i].ymax - y_offset) / y_scale * image_h) | |
def _interval_overlap(interval_a, interval_b): | |
x1, x2 = interval_a | |
x3, x4 = interval_b | |
if x3 < x1: | |
if x4 < x1: | |
return 0 | |
else: | |
return min(x2,x4) - x1 | |
else: | |
if x2 < x3: | |
return 0 | |
else: | |
return min(x2,x4) - x3 | |
def bbox_iou(box1, box2): | |
intersect_w = _interval_overlap([box1.xmin, box1.xmax], [box2.xmin, box2.xmax]) | |
intersect_h = _interval_overlap([box1.ymin, box1.ymax], [box2.ymin, box2.ymax]) | |
intersect = intersect_w * intersect_h | |
w1, h1 = box1.xmax-box1.xmin, box1.ymax-box1.ymin | |
w2, h2 = box2.xmax-box2.xmin, box2.ymax-box2.ymin | |
union = w1*h1 + w2*h2 - intersect | |
return float(intersect) / union | |
def do_nms(boxes, nms_thresh): | |
if len(boxes) > 0: | |
nb_class = len(boxes[0].classes) | |
else: | |
return | |
for c in range(nb_class): | |
sorted_indices = np.argsort([-box.classes[c] for box in boxes]) | |
for i in range(len(sorted_indices)): | |
index_i = sorted_indices[i] | |
if boxes[index_i].classes[c] == 0: continue | |
for j in range(i+1, len(sorted_indices)): | |
index_j = sorted_indices[j] | |
if bbox_iou(boxes[index_i], boxes[index_j]) >= nms_thresh: | |
boxes[index_j].classes[c] = 0 | |
# load and prepare an image | |
def load_image_pixels(filename, shape): | |
# load the image to get its shape | |
image = load_img(filename) | |
width, height = image.size | |
# load the image with the required size | |
image = load_img(filename, target_size=shape) | |
# convert to numpy array | |
image = img_to_array(image) | |
# scale pixel values to [0, 1] | |
image = image.astype('float32') | |
image /= 255.0 | |
# add a dimension so that we have one sample | |
image = expand_dims(image, 0) | |
return image, width, height | |
# get all of the results above a threshold | |
def get_boxes(boxes, labels, thresh): | |
v_boxes, v_labels, v_scores = list(), list(), list() | |
# enumerate all boxes | |
for box in boxes: | |
# enumerate all possible labels | |
for i in range(len(labels)): | |
# check if the threshold for this label is high enough | |
if box.classes[i] > thresh: | |
v_boxes.append(box) | |
v_labels.append(labels[i]) | |
v_scores.append(box.classes[i]*100) | |
# don't break, many labels may trigger for one box | |
return v_boxes, v_labels, v_scores | |
# draw all results | |
def draw_boxes(filename, v_boxes, v_labels, v_scores): | |
# load the image | |
data = pyplot.imread(filename) | |
# plot the image | |
pyplot.imshow(data) | |
# get the context for drawing boxes | |
ax = pyplot.gca() | |
# plot each box | |
for i in range(len(v_boxes)): | |
box = v_boxes[i] | |
# get coordinates | |
y1, x1, y2, x2 = box.ymin, box.xmin, box.ymax, box.xmax | |
# calculate width and height of the box | |
width, height = x2 - x1, y2 - y1 | |
# create the shape | |
rect = Rectangle((x1, y1), width, height, fill=False, color='white') | |
# draw the box | |
ax.add_patch(rect) | |
# draw text and score in top left corner | |
label = "%s (%.3f)" % (v_labels[i], v_scores[i]) | |
pyplot.text(x1, y1, label, color='white') | |
# show the plot | |
pyplot.show() | |
# load yolov3 model | |
model = load_model('./backend.h5') | |
# define the expected input shape for the model | |
input_w, input_h = 416, 416 | |
# photo with objects | |
# photo_filename = "../../YOLO3/food.jpeg" | |
photo_filename = "./data_test/val_super/nocarX/human_faces_man_women_eyes_head_facial_expression_voltage-734262.jpg!d.jpeg" | |
# load and prepare image | |
# define the anchors | |
anchors = [5, 9, 11, 16, 19, 27, 29, 94, 31, 39, 50, 58, 74, 90, 97, 146, 148, 201] # original anchors of BDD image size (800,600) | |
# define the probability threshold for detected objects | |
obj_thresh, nms_thresh = 0.4, 0.4 | |
# define standart the labels | |
labels = ["person", "bicycle", "car", "motorbike", "aeroplane", "bus", "train", "truck", | |
"boat", "traffic light", "fire hydrant", "stop sign", "parking meter", "bench", | |
"bird", "cat", "dog", "horse", "sheep", "cow", "elephant", "bear", "zebra", "giraffe", | |
"backpack", "umbrella", "handbag", "tie", "suitcase", "frisbee", "skis", "snowboard", | |
"sports ball", "kite", "baseball bat", "baseball glove", "skateboard", "surfboard", | |
"tennis racket", "bottle", "wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", | |
"apple", "sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza", "donut", "cake", | |
"chair", "sofa", "pottedplant", "bed", "diningtable", "toilet", "tvmonitor", "laptop", "mouse", | |
"remote", "keyboard", "cell phone", "microwave", "oven", "toaster", "sink", "refrigerator", | |
"book", "clock", "vase", "scissors", "teddy bear", "hair drier", "toothbrush"] | |
# get the details of the detected objects | |
image = cv2.imread(photo_filename) | |
boxes = list() | |
boxes = get_yolo_boxes(model, [image], input_h, input_w, anchors, obj_thresh, nms_thresh)[0] | |
print("Get YOLO3 boxes") | |
# draw bounding boxes on the image using labels | |
v_boxes, v_labels, v_scores = get_boxes(boxes, labels, obj_thresh) | |
draw_boxes(photo_filename, v_boxes, v_labels, v_scores) | |
print("Draw boxes") | |
# write the image with bounding boxes to file | |
cv2.imwrite("./out.jpg", np.uint8(image)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment