-
Notifications
You must be signed in to change notification settings - Fork 32
/
drone_optical_flow.py
74 lines (68 loc) · 3.35 KB
/
drone_optical_flow.py
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
# pip install opencv-python==4.5.3.56
import sys
import cv2
import numpy as np
# argv
if len(sys.argv)>1:
if sys.argv[1]=='cam':
mode='camera'
else:
mode='video'
filename = sys.argv[1]
else:
mode='video'
filename = 'video/MOT16-03-raw.webm'
# Parameters for Shi-Tomasi corner detection
feature_params = dict(maxCorners = 300, qualityLevel = 0.2, minDistance = 2, blockSize = 7)
# Parameters for Lucas-Kanade optical flow
lk_params = dict(winSize = (15,15), maxLevel = 2, criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))
if mode=='video':
cap = cv2.VideoCapture(filename)
if mode=='camera':
cap = cv2.VideoCapture(0)
color = (0, 255, 0) # color to draw optical flow track
ret, first_frame = cap.read()
# Converts frame to grayscale because we only need the luminance channel for detecting edges - less computationally expensive
prev_gray= cv2.cvtColor(first_frame, cv2.COLOR_BGR2GRAY)
# Finds the strongest corners in the first frame by Shi-Tomasi method - we will track the optical flow for these corners
# https://docs.opencv.org/3.0-beta/modules/imgproc/doc/feature_detection.html#goodfeaturestotrack
prev = cv2.goodFeaturesToTrack(prev_gray, mask = None, **feature_params)
# Creates an image filled with zero intensities with the same dimensions as the frame - for later drawing purposes
mask = np.zeros_like(first_frame)
while(cap.isOpened()):
ret, frame = cap.read() # capture a frame
#frame = cv2.flip(frame, 0)
#frame = cv2.flip(frame, 1)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # convert to Gray
# Calculates sparse optical flow by Lucas-Kanade method
# https://docs.opencv.org/3.0-beta/modules/video/doc/motion_analysis_and_object_tracking.html#calcopticalflowpyrlk
next, status, error = cv2.calcOpticalFlowPyrLK(prev_gray, gray, prev, None, **lk_params)
# Selects good feature points for previous position
good_old = prev[status == 1]
# Selects good feature points for next position
good_new = next[status == 1]
# Draws the optical flow tracks
for i, (new, old) in enumerate(zip(good_new, good_old)):
# Returns a contiguous flattened array as (x, y) coordinates for new point
a, b = new.ravel()
# Returns a contiguous flattened array as (x, y) coordinates for old point
c, d = old.ravel()
# Draws line between new and old position with green color and 2 thickness
mask = cv2.line(mask, (int(a), int(b)), (int(c), int(d)), color, 2)
# Draws filled circle (thickness of -1) at new position with green color and radius of 3
frame = cv2.circle(frame, (int(a), int(b)), 3, color, -1)
# Overlays the optical flow tracks on the original frame
output = cv2.add(frame, mask)
# Updates previous frame
prev_gray = gray.copy()
# Updates previous good feature points
prev = good_new.reshape(-1, 1, 2)
# Opens a new window and displays the output frame
#cv2.imshow("sparse optical flow", output)
cv2.imshow("sparse optical flow", mask)
# Frames are read by intervals of 10 milliseconds. The programs breaks out of the while loop when the user presses the 'q' key
if cv2.waitKey(10) & 0xFF == ord('q'):
break
# The following frees up resources and closes all windows
cap.release()
cv2.destroyAllWindows()