Spaces:
Running
Running
import pickle | |
import cv2 | |
import numpy as np | |
import os | |
import sys | |
sys.path.append('../') | |
from utils import measure_distance,measure_xy_distance | |
class CameraMovementEstimator(): | |
def __init__(self,frame): | |
self.minimum_distance = 5 | |
self.lk_params = dict( | |
winSize = (15,15), | |
maxLevel = 2, | |
criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT,10,0.03) | |
) | |
first_frame_grayscale = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY) | |
mask_features = np.zeros_like(first_frame_grayscale) | |
mask_features[:,0:20] = 1 | |
mask_features[:,900:1050] = 1 | |
self.features = dict( | |
maxCorners = 100, | |
qualityLevel = 0.3, | |
minDistance =3, | |
blockSize = 7, | |
mask = mask_features | |
) | |
def add_adjust_positions_to_tracks(self,tracks, camera_movement_per_frame): | |
for object, object_tracks in tracks.items(): | |
for frame_num, track in enumerate(object_tracks): | |
for track_id, track_info in track.items(): | |
position = track_info['position'] | |
camera_movement = camera_movement_per_frame[frame_num] | |
position_adjusted = (position[0]-camera_movement[0],position[1]-camera_movement[1]) | |
tracks[object][frame_num][track_id]['position_adjusted'] = position_adjusted | |
def get_camera_movement(self,frames,read_from_stub=False, stub_path=None): | |
# Read the stub | |
if read_from_stub and stub_path is not None and os.path.exists(stub_path): | |
with open(stub_path,'rb') as f: | |
return pickle.load(f) | |
camera_movement = [[0,0]]*len(frames) | |
old_gray = cv2.cvtColor(frames[0],cv2.COLOR_BGR2GRAY) | |
old_features = cv2.goodFeaturesToTrack(old_gray,**self.features) | |
for frame_num in range(1,len(frames)): | |
frame_gray = cv2.cvtColor(frames[frame_num],cv2.COLOR_BGR2GRAY) | |
new_features, _,_ = cv2.calcOpticalFlowPyrLK(old_gray,frame_gray,old_features,None,**self.lk_params) | |
max_distance = 0 | |
camera_movement_x, camera_movement_y = 0,0 | |
for i, (new,old) in enumerate(zip(new_features,old_features)): | |
new_features_point = new.ravel() | |
old_features_point = old.ravel() | |
distance = measure_distance(new_features_point,old_features_point) | |
if distance>max_distance: | |
max_distance = distance | |
camera_movement_x,camera_movement_y = measure_xy_distance(old_features_point, new_features_point ) | |
if max_distance > self.minimum_distance: | |
camera_movement[frame_num] = [camera_movement_x,camera_movement_y] | |
old_features = cv2.goodFeaturesToTrack(frame_gray,**self.features) | |
old_gray = frame_gray.copy() | |
if stub_path is not None: | |
with open(stub_path,'wb') as f: | |
pickle.dump(camera_movement,f) | |
return camera_movement | |
def draw_camera_movement(self,frames, camera_movement_per_frame): | |
output_frames=[] | |
for frame_num, frame in enumerate(frames): | |
frame= frame.copy() | |
overlay = frame.copy() | |
cv2.rectangle(overlay,(0,0),(500,100),(255,255,255),-1) | |
alpha =0.6 | |
cv2.addWeighted(overlay,alpha,frame,1-alpha,0,frame) | |
x_movement, y_movement = camera_movement_per_frame[frame_num] | |
frame = cv2.putText(frame,f"Camera Movement X: {x_movement:.2f}",(10,30), cv2.FONT_HERSHEY_SIMPLEX,1,(0,0,0),3) | |
frame = cv2.putText(frame,f"Camera Movement Y: {y_movement:.2f}",(10,60), cv2.FONT_HERSHEY_SIMPLEX,1,(0,0,0),3) | |
output_frames.append(frame) | |
return output_frames |