KLT实现目标动态追踪

本文最后更新于:2024年9月13日 早上

序言

当时英才计划的时候吴老师曾经介绍过这个算法,不过当时我还很嘴巴选手所以并没有怎么去试着实现。前几天的江苏数学建模省赛有一题是用到了计算机视觉里的路径追踪。想起了老师曾经讲过,便重新学了下这个算法。
和我对神经网络的理解一样,我认为需要知道其背后原理,实际使用可以试着直接调用库来节省时间。

Kanade-Lucas-Tomasi方法

源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt

def save_image(image,addr,num):
address = addr + str(num)+ '.jpg'
cv.imwrite(address,image)

def Frame_Reading(video_path, image_path):
video_capture = cv2.VideoCapture(video_path)
images = []
idx = 0
while True:
ret, frame = video_capture.read()
if ret:
idx = idx + 1
image = Image.fromarray(cv2.cvtColor(frame,cv2.COLOR_BGR2RGB))
image_file=image_path+'/image_'+str(idx)+'.jpg'
print(image_file)
image.save(image_file)
else:
break

lk_params = dict( winSize = (30, 30),
maxLevel = 2,
criteria = (cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 10, 0.03))

feature_params = dict( maxCorners = 500,
qualityLevel = 0.3,
minDistance = 7,
blockSize = 1 )

class Work:
def __init__(self, video_src):
self.track_len = 10
self.detect_interval = 5
self.tracks = []
self.cam = cv.VideoCapture(video_src)
self.frame_idx = 0

def run(self):
while True:
_ret, frame = self.cam.read()
if _ret is not True:
return
#save_image(frame,frame1,j)
frame_gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
#frame1 = cv.fastNlMeansDenoisingColored(frame_gray,None,10,10,7,21)
vis = frame.copy()

if len(self.tracks) > 0:
img0, img1 = self.prev_gray, frame_gray
p0 = np.float32([tr[-1] for tr in self.tracks]).reshape(-1, 1, 2)
p1, _st, _err = cv.calcOpticalFlowPyrLK(img0, img1, p0, None, **lk_params)
d = abs(p1-p0).reshape(-1, 2).max(-1)
good = d > 1

new_tracks = []
for tr, (x, y), good_flag in zip(self.tracks, p1.reshape(-1, 2), good):
if not good_flag:
continue
tr.append((x, y))
if len(tr) > self.track_len:
del tr[0]
new_tracks.append(tr)
cv.circle(vis, (int(x), int(y)), 2, (0, 255, 0), 3)
self.tracks = new_tracks
cv.polylines(vis, [np.int32(tr) for tr in self.tracks], False, (0, 255, 0))

if self.frame_idx % self.detect_interval == 0:
mask = np.zeros_like(frame_gray)
mask[:] = 255
for x, y in [np.int32(tr[-1]) for tr in self.tracks]:
cv.circle(mask, (int(x), int(y)), 5, (0, 255, 0), 3)
p = cv.goodFeaturesToTrack(frame_gray, mask = mask, **feature_params)
if p is not None:
for x, y in np.float32(p).reshape(-1, 2):
self.tracks.append([(x, y)])


if self.frame_idx%10 == 0:
save_image(vis,'./output/West/image',self.frame_idx)

self.frame_idx += 1
self.prev_gray = frame_gray
cv.namedWindow("lk_track",0)
cv.resizeWindow("lk_track", 1200,800)
cv.imshow('lk_track', vis)

ch = cv.waitKey(30)
if ch == 27:
break

def main():
import sys
try:
video_src = sys.argv[1]
except:
video_src = "./附件/附件五_西口/20210311112657.mp4"#相对地址和绝对地址好像都行

Work(video_src).run()


if __name__ == '__main__':
main()
cv.destroyAllWindows()