Skip to content

Commit bdace1c

Browse files
committed
remove status, add track score, v0.0.9
1 parent 54604b7 commit bdace1c

14 files changed

+109
-67
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,4 +126,4 @@ Feel free to tune the parameter of Q and R matrix builders to better fit your us
126126
## References, papers, ideas and acknowledgements
127127
- https://github.com/rlabbe/Kalman-and-Bayesian-Filters-in-Python/
128128
- http://elvera.nue.tu-berlin.de/files/1517Bochinski2017.pdf
129-
- https://arxiv.org/abs/1602.00763
129+
- https://arxiv.org/abs/1602.00763

examples/2d_multi_object_tracking.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,12 @@ def demo_tracking_visualization(num_steps: int = 1000, num_objects: int = 10):
3131
active_tracks = tracker.step(detections=detections)
3232

3333
for track in active_tracks:
34+
score = track.score if track.score is not None else -1
3435
img = draw_rectangle(img, track.box, color=(10, 10, 220), thickness=5)
35-
img = draw_text(img, track.id, above_box=track.box)
36+
img = draw_text(img, f'{track.id[:8]}... ({score:.2f})', above_box=track.box)
3637

3738
for det in detections:
38-
img = draw_rectangle(img, det.box, color=(10, 220, 20), thickness=2)
39+
img = draw_rectangle(img, det.box, color=(10, 220, 20), thickness=1)
3940

4041
cv2.imshow('preview', img)
4142
# stop the demo by pressing q

examples/webcam_face_tracking.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from urllib.request import urlretrieve
44

55
import cv2
6-
from motpy import Detection, MultiObjectTracker, NpImage
6+
from motpy import Detection, MultiObjectTracker, NpImage, Box
77
from motpy.core import setup_logger
88
from motpy.detector import BaseObjectDetector
99
from motpy.testing_viz import draw_detection, draw_track
@@ -15,7 +15,7 @@
1515
1616
"""
1717

18-
logger = setup_logger(__name__, is_main=True)
18+
logger = setup_logger(__name__, 'DEBUG', is_main=True)
1919

2020

2121
WEIGHTS_URL = 'https://github.com/opencv/opencv_3rdparty/raw/dnn_samples_face_detector_20170830/res10_300x300_ssd_iter_140000.caffemodel'
@@ -30,7 +30,7 @@ def __init__(self,
3030
weights_path: str = WEIGHTS_PATH,
3131
config_url: str = CONFIG_URL,
3232
config_path: str = CONFIG_PATH,
33-
conf_threshold: float = 0.5):
33+
conf_threshold: float = 0.5) -> None:
3434
super(FaceDetector, self).__init__()
3535

3636
if not os.path.isfile(weights_path) or not os.path.isfile(config_path):
@@ -43,23 +43,23 @@ def __init__(self,
4343
# specify detector hparams
4444
self.conf_threshold = conf_threshold
4545

46-
def process_image(self, image: NpImage) -> Sequence[NpImage]:
46+
def process_image(self, image: NpImage) -> Sequence[Detection]:
4747
blob = cv2.dnn.blobFromImage(image, 1.0, (300, 300), [104, 117, 123], False, False)
4848
self.net.setInput(blob)
4949
detections = self.net.forward()
5050

5151
# convert output from OpenCV detector to tracker expected format [xmin, ymin, xmax, ymax]
52-
bboxes = []
52+
out_detections = []
5353
for i in range(detections.shape[2]):
5454
confidence = detections[0, 0, i, 2]
5555
if confidence > self.conf_threshold:
5656
xmin = int(detections[0, 0, i, 3] * image.shape[1])
5757
ymin = int(detections[0, 0, i, 4] * image.shape[0])
5858
xmax = int(detections[0, 0, i, 5] * image.shape[1])
5959
ymax = int(detections[0, 0, i, 6] * image.shape[0])
60-
bboxes.append([xmin, ymin, xmax, ymax])
61-
62-
return bboxes
60+
out_detections.append(Detection(box=[xmin, ymin, xmax, ymax], score=confidence))
61+
62+
return out_detections
6363

6464

6565
def run():
@@ -84,8 +84,7 @@ def run():
8484
frame = cv2.resize(frame, dsize=None, fx=0.5, fy=0.5)
8585

8686
# run face detector on current frame
87-
bboxes = face_detector.process_image(frame)
88-
detections = [Detection(box=bbox) for bbox in bboxes]
87+
detections = face_detector.process_image(frame)
8988
logger.debug(f'detections: {detections}')
9089

9190
tracker.step(detections)

motpy/core.py

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,13 @@
1515
Vector = np.ndarray
1616

1717
# Track is meant as an output from the object tracker
18-
Track = collections.namedtuple('Track', 'id box')
18+
Track = collections.namedtuple('Track', 'id box score')
1919

2020
# numpy/opencv image alias
2121
NpImage = np.ndarray
2222

2323

2424
class Detection:
25-
# Detection is to be an input the the tracker
2625
def __init__(
2726
self,
2827
box: Box,
@@ -33,10 +32,7 @@ def __init__(
3332
self.feature = feature
3433

3534
def __repr__(self):
36-
fmt = "(detection: box=%s, score=%s, feature=%s)"
37-
return fmt % (str(self.box),
38-
str(self.score) or 'none',
39-
str(self.feature) or 'none')
35+
return f'Detection(box={self.box}, score={self.score:.5f}, feature={self.feature})'
4036

4137

4238
""" utils """
@@ -51,17 +47,17 @@ def setup_logger(name: str,
5147
if level is None:
5248
level = os.getenv(envvar_name)
5349
if level is None:
54-
print(f'[{name}] fallback to INFO log_level; set {envvar_name} envvar to override')
5550
level = 'INFO'
5651
else:
5752
print(f'[{name}] envvar {envvar_name} sets log level to {level}')
5853

5954
level_val = logging.getLevelName(level)
6055

61-
if is_main:
62-
logging.basicConfig(stream=sys.stdout, level=level_val, format=LOG_FORMAT)
63-
6456
logger = logging.getLogger(name)
6557
logger.setLevel(level_val)
58+
logger.addHandler(logging.NullHandler())
59+
60+
if is_main:
61+
logging.basicConfig(stream=sys.stdout, level=level_val, format=LOG_FORMAT)
6662

6763
return logger

motpy/detector.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
from typing import Sequence
22

3-
import numpy as np
43
from motpy.core import NpImage
54
from motpy.tracker import Detection
65

motpy/metrics.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@ def calculate_iou(bboxes1, bboxes2, dim: int = 2):
1010
coords_b1 = np.split(bboxes1, 2 * dim, axis=1)
1111
coords_b2 = np.split(bboxes2, 2 * dim, axis=1)
1212

13-
coords_tl, coords_br = dict(), dict() # tl and br points
13+
coords = np.zeros(shape=(2, dim, bboxes1.shape[0], bboxes2.shape[0]))
1414
val_inter, val_b1, val_b2 = 1.0, 1.0, 1.0
1515
for d in range(dim):
16-
coords_tl[d] = np.maximum(coords_b1[d], np.transpose(coords_b2[d]))
17-
coords_br[d] = np.minimum(coords_b1[d + dim], np.transpose(coords_b2[d + dim]))
16+
coords[0, d] = np.maximum(coords_b1[d], np.transpose(coords_b2[d])) # top-left
17+
coords[1, d] = np.minimum(coords_b1[d + dim], np.transpose(coords_b2[d + dim])) # bottom-right
1818

19-
val_inter *= np.maximum(coords_br[d] - coords_tl[d], 0)
19+
val_inter *= np.maximum(coords[1, d] - coords[0, d], 0)
2020
val_b1 *= coords_b1[d + dim] - coords_b1[d]
2121
val_b2 *= coords_b2[d + dim] - coords_b2[d]
2222

motpy/model.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
1-
21
from enum import Enum
32

43
import numpy as np
54
from filterpy.common import Q_discrete_white_noise
6-
from filterpy.kalman import KalmanFilter
7-
from motpy.core import Box, Detection, Track, Vector
8-
from motpy.metrics import angular_similarity, calculate_iou
95
from scipy.linalg import block_diag
106

7+
from motpy.core import Box, Vector
118

129
""" The list of model presets below is not complete, more reasonable
1310
options will be added in the future """
@@ -140,7 +137,7 @@ def box_to_z(self, box: Box) -> Vector:
140137

141138
def box_to_x(self, box: Box) -> Vector:
142139
""" box is expected to be in [xmin, ymin, zmin, ..., xmax, ymax, zmax, ...] format
143-
for 2d1ord+2d0ord case returns np.array([cx, 0, 0, cy, 0, 0, w, h]) """
140+
for 2d-1ord+2d-0ord case returns np.array([cx, 0, 0, cy, 0, 0, w, h]) """
144141
x = np.zeros((self.state_length,))
145142
x[self.z_in_x_idxs] = self.box_to_z(box)
146143
return x

motpy/testing.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import math
22
import random
33

4-
import numpy as np
5-
64
from motpy.core import Detection
75

86
CANVAS_SIZE = 1000
@@ -73,11 +71,11 @@ def detections(self, step: int):
7371
self.disappear_steps -= 1
7472

7573
# wrap boxes and features as detections
76-
det_gt = Detection(box=box_gt, score=1.0, feature=self.color)
74+
det_gt = Detection(box=box_gt, score=1., feature=self.color)
7775

7876
feature_pred = [random.gauss(0, 5) + v for v in self.color]
7977
det_pred = Detection(box=box_pred,
80-
score=random.random() / 2 + 0.5,
78+
score=random.uniform(0.5, 1.),
8179
feature=feature_pred)
8280

8381
return det_gt, det_pred

0 commit comments

Comments
 (0)