Blobfromimage là gì

Xây dựng hệ thống Real-time Multi-person Tracking với YOLOv3 và DeepSORT

  • Report

Trong bài này chúng ta sẽ xây dựng một hệ thống sử dụng YOLOv3 kết hợp với DeepSORT để tracking được các đối tượng trên camera, YOLO là một thuật toán deep learning ra đời vào tháng 5 năm 2016 và nó nhanh chóng trở nên phổ biến vì nó quá nhanh so với thuật toán deep learning trước đó, sử dụng YOLO trên GPU ta có thể đạt tới 45 fps. Dựa vào YOLO chúng ta sẽ detect được object rồi sau đó ta dùng DeepSORT để tracking object đó qua từng frames.

YOLO và DeepSORT

YOLO

Mặc dù SORT đạt được hiệu suất tổng thể tốt về precision và accuracy, nhưng như nói ở trên nó vẫn tồn tại điểm yếu quá lớn. Để cải thiện điều này tác giả DeepSORT đã tạo ra một distance metric dựa trên appearance của đối tượng. Để tìm hiểu sâu hơn về DeepSORT mời bạn đọc bài này và Bài này của tác giả Bùi Túng Tiền

Oke sau khi các bạn đã hiểu qua về lý thuyết thì phần dưới mới là phần chính của bài này ]

Build everything with some codes

Setup

Đầu tiên các bạn phải clone repo này về từ trên github để xử lý phần detection của YOLOv3:

//github.com/Qidian213/deep_sort_yolov3

Sau đó các bn phải down về 2 files quan trọng nhất là yolov3-tiny.cfgyolov3-tiny.weights Tại đây. Mình chọn bản tiny vì nó nhẹ và có thể chạy trên CPU, các bạn cũng có thể chọn bản yolov3 với weight khác nếu các bạn có GPU [Nghèo nó khổ thể đấy huhu]

Sau đó bạn cấu trục thư mục như sau:

Còn một số thư viện như opencv, numpy, .... Các bạn tự setting nhé :v Chúng ta sẽ thực hiện ở file main.py , đầu tiên là implement các thư viện cần thiết để chạy:

import cv2 import numpy as np import time from deep_sort_yolov3.deep_sort import preprocessing from deep_sort_yolov3.deep_sort import nn_matching from deep_sort_yolov3.deep_sort.detection import Detection from deep_sort_yolov3.deep_sort.tracker import Tracker from deep_sort_yolov3.deep_sort.detection import Detection as ddet from deep_sort_yolov3.tools import generate_detections as gdet from collections import deque

Chú ý import cho chuẩn nhé, ko chuẩn bước này là lần sau ko chạy đc đừng có chửi mình :v Tiếp đó là ta sẽ load YOLO và khởi tạo các tham số cần thiết:

net = cv2.dnn.readNet["yolov3-tiny.weights", "yolov3-tiny.cfg"] model_filename = "./YoloV3/deep_sort_yolov3/model_data/market1501.pb" layer_names = net.getLayerNames[] output_layers = [layer_names[i[0] - 1] for i in net.getUnconnectedOutLayers[]] max_cosine_distance = 0.5 nms_max_overlap = 0.3 classes = [] nn_budget = None counter = [] # fps = 0.0 pts = [deque[maxlen=30] for _ in range[9999]] COLORS = np.random.randint[0, 255, size=[200, 3], dtype="uint8"]

Ở đây mình đã dùng opencv để load weight của YOLO thay vì nó nhanh :v, các tham số như max_cosine_distance để đo khoảng cách hàng xóm gần nhất trong deepSORT và nms_max_overlap là non maximum suppression,...

Sau đó ta sẽ load model deepSORT và khởi tạo các giá trị về khoảng cách với tham số đã tạo ở trên:

encoder = gdet.create_box_encoder[model_filename, batch_size = 1] #Dữ liệu được encode của từng boxs metric = nn_matching.NearestNeighborDistanceMetric["cosine", max_cosine_distance, nn_budget] # Dùng cosine để so sánh khoảng cách của từng boxs tracker = Tracker[metric] # track đối tượng dược trên k/c thu được

Tiếp tục là load camera từ máy, lưu ý là nếu cam rời thìcap = cv2.VideoCapture[1] còn liền thì như dưới:

# Loading camera cap = cv2.VideoCapture[0] font = cv2.FONT_HERSHEY_PLAIN starting_time = time.time[] frame_id = 0

Sau đó ta sẽ bắt từng bounding boxs được detect ra:

while True: _, frame = cap.read[] frame_id += 1 height, width, channels = frame.shape[:3] # Detecting objects blob = cv2.dnn.blobFromImage[frame, 1/255, [416, 416], [0, 0, 0], True, crop=False] net.setInput[blob] outs = net.forward[output_layers] # Showing informations on the screen class_ids = [] confidences = [] bboxes = [] for out in outs: for detection in out: scores = detection[5:] class_id = np.argmax[scores] confidence = scores[class_id] if confidence > 0.5: # Object detected center_x = int[detection[0] * width] center_y = int[detection[1] * height] w = int[detection[2] * width] h = int[detection[3] * height] # Rectangle coordinates x = int[center_x - w / 2] y = int[center_y - h / 2] bboxes.append[[x, y, w, h]] confidences.append[float[confidence]] class_ids.append[class_id]

Tất cả code phần sau vẫn là trong vòng while True: nhé

Sau khi có từng boxs đã được detect ra ta sẽ lấy ra các features qua từng frame để tracking:

#feature extraction features = encoder[frame, bboxes] # import pdb; pdb.set_trace[] detections = [Detection[bbox, 1.0, feature] for bbox, feature in zip[bboxes, features]] #non-maxima supression boxes = np.array[[d.tlwh for d in detections]] scores = np.array[[d.confidence for d in detections]] indices = preprocessing.non_max_suppression[boxes, nms_max_overlap, scores] detections =[detections[i] for i in indices] #Call the tracker tracker.predict[] tracker.update[detections]

Ở trên với mỗi boxes thì sẽ tương ứng với các features sau khi đã detect được objects, indices là những phần tử được xử lý với non-maxima supression để lấy ra được bounding boxs tốt nhất có thể, sau ó hàm tracker.predict[] có nhiệm vụ track các objects đã được dự đoán và update tiếp tục tương tự với các đối tượng khác với tracker.update[detections]

Thực hiện tracking theo IDs theo từng bounding boxs và draw boxs trên từng frames:

for track in tracker.tracks: if not track.is_confirmed[] or track.time_since_update > 1: continue # boxes.append[[track[0], track[1], track[2], track[3]]] indexIDs.append[int[track.track_id]] counter.append[int[track.track_id]] bbox = track.to_tlbr[] color = [int[c] for c in COLORS[indexIDs[i] % len[COLORS]]] cv2.rectangle[frame, [int[bbox[0]], int[bbox[1]]], [int[bbox[2]], int[bbox[3]]], [color], 3] cv2.putText[frame, str[track.track_id], [int[bbox[0]], int[bbox[1] - 50]], 0, 5e-3 * 150, [color], 2] i += 1 # bbox_center_point[x,y] center = [int[[[bbox[0]] + [bbox[2]]] / 2], int[[[bbox[1]] + [bbox[3]]] / 2]] # track_id[center] pts[track.track_id].append[center] thickness = 5 # center point cv2.circle[frame, [center], 1, color, thickness] # draw motion path for j in range[1, len[pts[track.track_id]]]: if pts[track.track_id][j - 1] is None or pts[track.track_id][j] is None: continue thickness = int[np.sqrt[64 / float[j + 1]] * 2] cv2.line[frame, [pts[track.track_id][j - 1]], [pts[track.track_id][j]], [color], thickness] count = len[set[counter]] cv2.putText[frame, "Total Object Counter: " + str[count], [int[20], int[120]], 0, 5e-3 * 200, [0, 255, 0], 2] cv2.putText[frame, "Current Object Counter: " + str[i], [int[20], int[80]], 0, 5e-3 * 200, [0, 255, 0], 2] elapsed_time = time.time[] - starting_time fps = frame_id / elapsed_time cv2.putText[frame, "FPS: %f" % [fps], [int[20], int[40]], 0, 5e-3 * 200, [0, 255, 0], 3] cv2.namedWindow["YOLO3_Deep_SORT", 0] cv2.imshow['YOLO3_Deep_SORT', frame] key = cv2.waitKey[1] if key == 27: break cap.release[] cv2.destroyAllWindows[]

Result

Nhắc lại là ở đây mình cấu hình chạy thẳng trên CPU ở laptop của mình nên vì thế nên mới được có khoảng 6 fps nhé:

Cảm ơn các bạn đã đọc bài, nếu có gì ko hiểu thì các bạn cmt ở dưới nhé, rồi mình sẽ giải đáp sau, chúc mừng năm mới =]]


Video liên quan

Chủ Đề