Multi object tracking
Project description
Multi object tracking class
Perform multi object tracking and use a custom function for tracked objects
MOT arguments:
- mot_cfg - configuration dictionary for MOT (tamplate below)
mot_cfg = {
'od_classes':'SPECIFY', # Object detection algorithm classes path
'od_algo':'yolo',
'od_wpath':'SPECIFY', # Object detection algorithm weights path
'od_cpath':'SPECIFY', # Object detection algorithm config path
'od_nms_thr':0.4,
'od_conf_thr':0.5,
'od_img_size':416,
'od_cuda':True,
't_classes':'SPECIFY', # List of classes to track
't_algo':'deepsort',
't_cuda':True,
't_metric':'cosine',
't_max_cosine_distance':0.2,
't_budget':100,
't_max_iou_distance':0.7,
't_max_age':70,
't_n_init':3
}
MOT methods:
- detect_objects - detect object from a frame
- track_objects - perform a tracking update on frame
Algorithms
Currently available object detection algorithms:
- YOLOv3
- YOLOv4
Currently available tracking algorithms:
- DeepSORT
Installation
To use the package torch, torchvision and opencv must be also installed.
Note: It is recommended to use opencv compiled with CUDA support, because algorithms that use opencv's darknet backend like YOLOv3/v4 run an order of magnitude faster on a GPU.
pip install pymot
Usage
Without a custom function for tracked objects
from pymot.mot import MOT
import cv2
mot_tracker = MOT(mot_cfg)
cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read()
if not ret:
break
if cv2.waitKey(1) & 0xFF == ord("q"):
cap.release()
cv2.destroyAllWindows()
break
tracked_ojb_info, frame_with_bboxes, _ = mot_tracker.track_objects(frame)
cv2.imshow('Object tracking with deepSORT', frame_with_bboxes)
With a custom function for tracked objects
from pymot.mot import MOT
import cv2
mot_tracker = MOT(mot_cfg)
cap = cv2.VideoCapture(0)
def custom_processing_function(
frame,
tracking_id,
obj_coord,
**proc_kwargs
) -> tuple[tuple, tuple]:
xmin, ymin, xmax, ymax = obj_coord
# If number of processed objects is more than max limit,
# delete the first to enter.
if len(proc_kwargs['proc_obj_info'])>proc_kwargs['max_n_obj']:
if proc_kwargs['last_obj_to_del'] not in proc_kwargs['proc_obj_info']:
proc_kwargs['last_obj_to_del'] += 1
else:
del proc_kwargs['proc_obj_info'][proc_kwargs['last_obj_to_del']]
# If there are no processed objects set the first to enter id
# as last_obj_to_del.
if len(proc_kwargs['proc_obj_info']) == 0:
proc_kwargs['last_obj_to_del'] = tracking_id
# If new tracking id, create new entry in the processed objects dict.
if tracking_id>proc_kwargs['prev_id']:
proc_kwargs['prev_id'] = tracking_id
proc_kwargs['proc_obj_info'][tracking_id] = [1, [], [], False]
# Processing object information dict list element meaning:
# 0 - counter,
# 1 - custom intermediate data accumulated until final processing,
# 2 - data assigned after final processing,
# 3 - if object has 2 states, e.g. recognized, unrecognized
# If the number of performed processings on a object with a certain
# tracking id is less than needed, do another processing.
if proc_kwargs['proc_obj_info'][tracking_id][0]<=proc_kwargs['n_det']:
# DO SOMETHING
proc_kwargs['proc_obj_info'][tracking_id][1].append(plate_number)
idx = int(proc_kwargs['proc_obj_info'][tracking_id][0] \
* (len(proc_kwargs['proc_animation']) / proc_kwargs['n_det']))
proc_kwargs['proc_obj_info'][tracking_id][2] \
= proc_kwargs['proc_animation'][idx - 1 \
if idx==len(proc_kwargs['proc_animation']) else idx]
proc_kwargs['proc_obj_info'][tracking_id][0] += 1
# If the number of performed processings on a object with a certain
# tracking id has sufficed do final processing.
if proc_kwargs['proc_obj_info'][tracking_id][0]==proc_kwargs['n_det']+1:
# DO SOMETHING
proc_kwargs['proc_obj_info'][tracking_id][0] += 1
output = (
(
proc_kwargs['proc_obj_info'],
proc_kwargs['last_obj_to_del'],
proc_kwargs['prev_id']
),
(
False,
proc_kwargs['proc_obj_info'][tracking_id][3],
((0,255,0),(0,0,255)),
proc_kwargs['proc_obj_info'][tracking_id][2]
)
)
return output
prev_id = -1
n_det = 10
max_n_obj = 50
last_obj_to_del = 0
proc_obj_info = {}
proc_animation = {i:'|'*(i+1) for i in range(8)}
while True:
ret, frame = cap.read()
if not ret:
break
if cv2.waitKey(1) & 0xFF == ord("q"):
cap.release()
cv2.destroyAllWindows()
break
output = mot_tracker.track_objects(
frame,
custom_processing_function,
prev_id=prev_id,
n_det=n_det,
max_n_obj=max_n_obj,
last_obj_to_del=last_obj_to_del,
proc_animation=proc_animation,
# Custom kwargs
)
tracked_ojb_info, frame_with_bboxes, proc_obj_info_tuple = output
if None not in proc_obj_info_tuple:
proc_obj_info, last_obj_to_del, prev_id = proc_obj_info_tuple
cv2.imshow('Object tracking with deepSORT', frame_with_bboxes)
Changelog
License
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
pymot-0.0.5.tar.gz
(43.0 MB
view details)
Built Distribution
pymot-0.0.5-py3-none-any.whl
(43.0 MB
view details)
File details
Details for the file pymot-0.0.5.tar.gz
.
File metadata
- Download URL: pymot-0.0.5.tar.gz
- Upload date:
- Size: 43.0 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: python-requests/2.28.1
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | d149045d352bbdae14f2dfb7fee4338884c8e139a2abf6bbe70cd3f3f0269f58 |
|
MD5 | ca0db34b2ab9fc28e1e9db5770011e47 |
|
BLAKE2b-256 | fa854629d5d30617e302912b1abfe81d944716d83be4d33efee015204609cbb5 |
File details
Details for the file pymot-0.0.5-py3-none-any.whl
.
File metadata
- Download URL: pymot-0.0.5-py3-none-any.whl
- Upload date:
- Size: 43.0 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: python-requests/2.28.1
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 123665513ad2b1bb722973e4aa7494ab56460055e7ddbc561acece45a5011448 |
|
MD5 | 5b5817f0131821a0b4ce4c1910a6fe70 |
|
BLAKE2b-256 | 5e7a15bb7bef20f564b0c2388e3ec8d94df76805eb5f1cb22d3c8e05b76a1d2b |