Skip to content

Commit 0516b9e

Browse files
WindowsWindows
Windows
authored and
Windows
committed
Repo init
1 parent fde09f0 commit 0516b9e

18 files changed

+1832
-0
lines changed

README.md

+44
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,46 @@
11
# ObjectTracking_CNN
22
A KCF tracker implementation which uses cnn feature as core.
3+
4+
# Inspired
5+
This project was inspired from [tiago-cerveira/KCF-Tracker-CNN-Features].But change the backend from theano + lasagne to pytorch.And add muti-target tracing function.
6+
7+
# Details
8+
* Support Muti-Target tracking
9+
* Support tripwire and restricted zone checking
10+
* Support CUDA accleration
11+
* Use PyTorch as cnn backend
12+
13+
[tiago-cerveira/KCF-Tracker-CNN-Features]: https://github.com/tiago-cerveira/KCF-Tracker-CNN-Features
14+
15+
# Requirement
16+
17+
## Runtime
18+
* Anaconda: Python 3.7.5
19+
20+
## Library Requirement
21+
22+
### From Python pip
23+
* numpy == any
24+
* opencv == 3.4.5.20
25+
26+
### From Anaconda
27+
* PyTorch == any
28+
29+
### CUDA (Optional)
30+
* CUDA == 9.1
31+
* cuDNN == 9.1
32+
33+
# Useage
34+
## Run main
35+
```
36+
python main.py <path of the video file>
37+
```
38+
39+
## Use KCFMultiTracker
40+
```
41+
tracker = KCFMultiTracker(True, True)
42+
tracker.init(rois, frist_frame)
43+
while not_ended:
44+
success, result_rois = tracker.update(next_frame)
45+
next_frame = get_next_frame()
46+
```

gui/backend_gui_bridge.py

+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
import cv2
2+
import gui.util.cv_rectutil as cvrect
3+
import gui.extra_function.area_monitor as amonitor
4+
import gui.extra_function.structs as structs
5+
from motion_detect import motion_detector as motdet
6+
7+
white = (255, 255, 255)
8+
red = (255, 0, 0)
9+
green = (0, 255, 0)
10+
blue = (0, 0, 255)
11+
black = (0, 0, 0)
12+
13+
14+
class BackendGuiBridge:
15+
def __init__(self, video_path, lines=[], areas=[], draw_trace=True):
16+
self._video_cap = cv2.VideoCapture(video_path)
17+
self._area_monitor = amonitor.AreaMonitor()
18+
self._draw_trace = draw_trace
19+
self._current_frame_index = 0
20+
self._motion_detector = motdet.MotionDetector()
21+
self._log_list = []
22+
self._rect_touched_area = 0
23+
self._rect_touched_line = 0
24+
self._all_frame_rect_centers = []
25+
for l in lines:
26+
sline = structs.Line()
27+
sline.from_cv_line(l)
28+
self._area_monitor.add_line(sline)
29+
for a in areas:
30+
sarea = structs.Rectangle()
31+
sarea.from_cv_rect(a)
32+
self._area_monitor.add_rect(sarea)
33+
34+
def __del__(self):
35+
self._video_cap.release()
36+
37+
# add tripwire
38+
def add_tripwire(self, line: structs.Line):
39+
self._area_monitor.add_line(line)
40+
41+
# add forbidden area
42+
def add_area(self, area: structs.Rectangle):
43+
sarea = structs.Rectangle()
44+
sarea.from_cv_rect(area)
45+
self._area_monitor.add_rect(sarea)
46+
47+
# print log touched log
48+
def _print_line_log(self, rect: structs.Rectangle, line: structs.Line):
49+
r = rect.to_cv_rect()
50+
p0 = list(line.a_point.to_cv_point())
51+
p1 = list(line.b_point.to_cv_point())
52+
self._log_list.append(
53+
'target ({0},{1},{2},{3}) has touched the line [({4},{5}),({6},{7})]'.format(int(r[0]), int(r[1]),
54+
int(r[2]), int(r[3]),
55+
int(p0[0]), int(p0[1]),
56+
int(p1[0]),
57+
int(p1[1])))
58+
59+
# Print area entrance log
60+
def _print_area_log(self, rect: structs.Rectangle, area: structs.Rectangle):
61+
r = rect.to_cv_rect()
62+
a = area.to_cv_rect()
63+
self._log_list.append(
64+
'target ({0},{1},{2},{3}) has entered the area({4},{5},{6},{7})'.format(int(r[0]), int(r[1]), int(r[2]),
65+
int(r[3]),
66+
int(a[0]), int(a[1]), int(a[2]),
67+
int(a[3])))
68+
69+
def _draw_area(self, frame):
70+
for line in self._area_monitor.get_lines():
71+
cvrect.draw_line(frame, line.a_point.to_cv_point(), line.b_point.to_cv_point(), blue)
72+
for area in self._area_monitor.get_rects():
73+
cvrect.draw_rect(frame, area.to_cv_rect(), blue)
74+
return frame
75+
76+
def _draw_tracking_rects(self, frame, rect_problems=[]):
77+
# clear log
78+
self._log_list.clear()
79+
# check warnings
80+
for rect_problem in rect_problems:
81+
who = rect_problem.which_rect
82+
# tripwire warnings
83+
for line in rect_problem.line_touched:
84+
self._print_line_log(who, line)
85+
# area warnings
86+
for area in rect_problem.rect_trespassed:
87+
self._print_area_log(who, area)
88+
# change different color for different target
89+
if len(rect_problem.rect_trespassed) > 0 or len(rect_problem.line_touched) > 0:
90+
cvrect.draw_rect(frame, who.to_cv_rect(), red)
91+
else:
92+
cvrect.draw_rect(frame, who.to_cv_rect(), green)
93+
return frame
94+
95+
# get a pre-processed frame
96+
def get_frame(self):
97+
success, frame = self._video_cap.read()
98+
if success:
99+
self._current_frame_index = self._current_frame_index + 1
100+
rects = self._motion_detector.detect(frame)
101+
if self._draw_trace:
102+
self._all_frame_rect_centers.append(self._get_rect_centers(rects))
103+
rect_problems = self._area_monitor.check_problems(rects)
104+
frame = self._draw_area(frame)
105+
frame = self._draw_tracking_rects(frame, rect_problems)
106+
if self._draw_trace:
107+
frame = self._draw_trace(frame)
108+
return success, frame
109+
else:
110+
return success, None
111+
112+
def get_logs(self):
113+
return self._log_list
114+
115+
def _get_rect_centers(self, rects=[]):
116+
current_frame_center = []
117+
for x, y, a, b in rects:
118+
center = [x + a / 2, y + b / 2]
119+
current_frame_center.append(center)
120+
return current_frame_center

gui/extra_function/area_monitor.py

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import gui.extra_function.structs as models
2+
import gui.extra_function.intersection_check as icheck
3+
4+
5+
class AreaMonitor:
6+
def __init__(self):
7+
self._lines = []
8+
self._rects = []
9+
10+
def add_line(self, new_line: models.Line):
11+
self._lines.append(new_line)
12+
13+
def get_lines(self):
14+
return self._lines
15+
16+
def add_rect(self, new_rect: models.Rectangle):
17+
self._rects.append(new_rect)
18+
19+
def get_rects(self):
20+
return self._rects
21+
22+
def clear_monitoring_area(self):
23+
self._lines = []
24+
self._rects = []
25+
26+
def check_problems(self, tracking_rects=[]):
27+
result = []
28+
for tracking_rect in tracking_rects:
29+
rect_problem = models.RectProblem()
30+
rect_problem.which_rect.from_cv_rect(tracking_rect)
31+
result.append(rect_problem)
32+
for i in range(len(tracking_rects)):
33+
for line in self._lines:
34+
if icheck.is_line_rect_intersection(line=line, rect=result[i].which_rect):
35+
result[i].line_touched.append(line)
36+
for area in self._rects:
37+
center = result[i].which_rect.center()
38+
if icheck.is_point_in_rect(center, area):
39+
result[i].rect_trespassed.append(area)
40+
return result
+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import gui.extra_function.structs as structs
2+
3+
4+
def is_cross(p0: structs.Point, p1: structs.Point, p2: structs.Point):
5+
x1 = p1.x - p0.x
6+
y1 = p1.y - p0.y
7+
x2 = p2.x - p0.x
8+
y2 = p2.y - p0.y
9+
return x1 * y2 - x2 * y1
10+
11+
12+
def is_line_line_intersection(line0: structs.Line, line1: structs.Line):
13+
p0 = line0.a_point
14+
p1 = line0.b_point
15+
p2 = line1.a_point
16+
p3 = line1.b_point
17+
result = False
18+
if (
19+
max(p0.x, p1.x) >= min(p2.x, p3.x)
20+
and max(p2.x, p3.x) >= min(p0.x, p1.x)
21+
and max(p0.y, p1.y) >= min(p2.y, p3.y)
22+
and max(p2.y, p3.y) >= min(p0.y, p1.y)
23+
):
24+
if (is_cross(p0, p1, p2) * is_cross(p0, p1, p3) <= 0 and is_cross(p2, p3, p0) * is_cross(p2, p3, p1) <= 0):
25+
result = True
26+
27+
return result
28+
29+
30+
def is_point_in_rect(point: structs.Point, rect: structs.Rectangle):
31+
minx, miny = rect.a_point.to_cv_point()
32+
maxx, maxy = rect.c_point.to_cv_point()
33+
return (point.x >= minx and point.x <= maxx and point.y >= miny and point.y <= maxy)
34+
35+
36+
def is_line_rect_intersection(line: structs.Line, rect: structs.Rectangle):
37+
if is_point_in_rect(line.a_point, rect) and is_point_in_rect(line.b_point, rect):
38+
return True
39+
pa, pb = rect.a_point, rect.c_point
40+
line0 = structs.Line()
41+
line0.a_point = rect.a_point
42+
line0.b_point = rect.d_point
43+
44+
line1 = structs.Line()
45+
line1.a_point = rect.a_point
46+
line1.b_point = rect.b_point
47+
48+
line2 = structs.Line()
49+
line2.a_point = rect.b_point
50+
line2.b_point = rect.c_point
51+
52+
line3 = structs.Line()
53+
line3.a_point = rect.c_point
54+
line3.b_point = rect.d_point
55+
56+
if is_line_line_intersection(line, line0):
57+
return True
58+
if is_line_line_intersection(line, line1):
59+
return True
60+
if is_line_line_intersection(line, line2):
61+
return True
62+
if is_line_line_intersection(line, line3):
63+
return True
64+
return False
65+
66+
67+
def is_rect_rect_intersection(rect0: structs.Rectangle, rect1: structs.Rectangle):
68+
if is_point_in_rect(rect0.a_point, rect1):
69+
return True
70+
if is_point_in_rect(rect0.b_point, rect1):
71+
return True
72+
if is_point_in_rect(rect0.c_point, rect1):
73+
return True
74+
if is_point_in_rect(rect0.d_point, rect1):
75+
return True
76+
return False

gui/extra_function/structs.py

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
class Point:
2+
def __init__(self):
3+
self.x = int()
4+
self.y = int()
5+
6+
def from_cv_point(self, cv_point):
7+
self.x, self.y = list(cv_point)
8+
9+
def to_cv_point(self):
10+
return (self.x, self.y)
11+
12+
13+
'''
14+
a_point *------* b_point
15+
| |
16+
| |
17+
| |
18+
d_point *------* c_point
19+
'''
20+
21+
22+
class Rectangle:
23+
def __init__(self):
24+
self.a_point = Point()
25+
self.b_point = Point()
26+
self.c_point = Point()
27+
self.d_point = Point()
28+
self.width = int()
29+
self.height = int()
30+
31+
def center(self):
32+
p = Point()
33+
p.x = self.a_point.x + self.width / 2
34+
p.y = self.a_point.y + self.height / 2
35+
return p
36+
37+
def from_cv_rect(self, cv_rect):
38+
x, y, self.width, self.height = cv_rect
39+
self.a_point.from_cv_point([x, y])
40+
self.b_point.from_cv_point([x + self.width, y])
41+
self.c_point.from_cv_point([x + self.width, y + self.height])
42+
self.d_point.from_cv_point([x, y + self.height])
43+
44+
def to_cv_rect(self):
45+
return [self.a_point.x, self.a_point.y, self.width, self.height]
46+
47+
48+
'''
49+
a_point *------* b_point
50+
'''
51+
52+
53+
class Line:
54+
def __init__(self):
55+
self.a_point = Point()
56+
self.b_point = Point()
57+
58+
def from_cv_line(self, line):
59+
self.a_point.from_cv_point(line[0])
60+
self.b_point.from_cv_point(line[1])
61+
62+
def to_cv_line(self):
63+
return [self.a_point.to_cv_point(), self.a_point.to_cv_point()]
64+
65+
66+
class RectProblem:
67+
def __init__(self):
68+
self.which_rect = Rectangle()
69+
self.line_touched = []
70+
self.rect_trespassed = []

0 commit comments

Comments
 (0)