├── README.md ├── globalVariables.py └── tracking6.py /README.md: -------------------------------------------------------------------------------- 1 | # Optical-Flow-Tracking----Python+OpenCV 2 | This is a small program demonstrating object tracking in a video stream. Lucas Kanade optical flow algorithm is used to find the pixels from one frame to another. 3 | 4 | @Usage: 5 | Run the program by typing the following command in the command line: 6 | $ python tracking6.py 7 | 8 | The program will connect to the webcam on the PC and start streaming a video. Keep the object to be tracked in the centre of the video demarcated by the small rectangle. Press the 'a' button on the keyboard to start tracking the object. 9 | 10 | To change the webcam to be used, open the tracking6.py python script and change the line cv2.VideoCapture(#no.). Replace #no with the webcam id. The webcam id can be found out by running the following script in the command line -> 11 | $ ls /dev/video* 12 | 13 | Press the esc key during program runtime to quit the program. 14 | 15 | @other important things: 16 | The tracker will try to re-initialise tracking once the number of tracked points fall below a threshold value. This threshold value can be set by the user by changing it in line 92. Also the program will keep on pruning out tracked points that lie far away from the centre of the object. The threshold distance between the centroid and a point to be removed is by default 90pixels. But the user can change it by editing line 83. 17 | 18 | Note: As I am a first time user of Git and Github this repository will be very barebones. But as I learn more i will keep updating it with screenshots and other things. Also any changes to the algorithm will be updated here. 19 | -------------------------------------------------------------------------------- /globalVariables.py: -------------------------------------------------------------------------------- 1 | selRoi = 1 2 | initial = 0 3 | top_left= [160,213] 4 | bottom_right = [320,426] 5 | first_time = 1 6 | 7 | 8 | -------------------------------------------------------------------------------- /tracking6.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import cv2 3 | import globalVariables as gV 4 | import random 5 | 6 | 7 | gV.selRoi = 0 8 | gV.top_left= [160,213] 9 | gV.bottom_right = [320,426] 10 | gV.first_time = 1 11 | # Parameters for lucas kanade optical flow 12 | lk_params = dict( winSize = (15,15), 13 | maxLevel = 2, 14 | criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03)) 15 | 16 | def findDistance(r1,c1,r2,c2): 17 | d = (r1-r2)**2 + (c1-c2)**2 18 | d = d**0.5 19 | return d 20 | 21 | #main function 22 | cv2.namedWindow('tracker') 23 | 24 | cap = cv2.VideoCapture(1) 25 | while True: 26 | while True: 27 | _,frame = cap.read() 28 | #-----Drawing Stuff on the Image 29 | cv2.putText(frame,'Press a to start tracking',(20,50),cv2.FONT_HERSHEY_SIMPLEX,1,color = (60,100,75),thickness = 3) 30 | cv2.rectangle(frame,(gV.top_left[1],gV.top_left[0]),(gV.bottom_right[1],gV.bottom_right[0]),color = (100,255,100),thickness = 4) 31 | 32 | #-----Finding ROI and extracting Corners 33 | frameGray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY) 34 | roi = frameGray[gV.top_left[0]:gV.bottom_right[0], gV.top_left[1]:gV.bottom_right[1] ] #selecting roi 35 | new_corners = cv2.goodFeaturesToTrack(roi,50,0.01,10) #find corners 36 | 37 | #-----converting to complete image coordinates (new_corners) 38 | 39 | new_corners[:,0,0] = new_corners[:,0,0] + gV.top_left[1] 40 | new_corners[:,0,1] = new_corners[:,0,1] + gV.top_left[0] 41 | 42 | #-----drawing the corners in the original image 43 | for corner in new_corners: 44 | cv2.circle(frame, (int(corner[0][0]),int(corner[0][1])) ,5,(0,255,0)) 45 | 46 | #-----old_corners and oldFrame is updated 47 | oldFrameGray = frameGray.copy() 48 | old_corners = new_corners.copy() 49 | 50 | cv2.imshow('tracker',frame) 51 | 52 | a = cv2.waitKey(5) 53 | if a== 27: 54 | cv2.destroyAllWindows() 55 | cap.release() 56 | elif a == 97: 57 | break 58 | 59 | #----Actual Tracking----- 60 | while True: 61 | 'Now we have oldFrame,we can get new_frame,we have old corners and we can get new corners and update accordingly' 62 | 63 | #read new frame and cvt to gray 64 | ret,frame = cap.read() 65 | frameGray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY) 66 | #finding the new tracked points 67 | new_corners, st, err = cv2.calcOpticalFlowPyrLK(oldFrameGray, frameGray, old_corners, None, **lk_params) 68 | 69 | #---pruning far away points: 70 | #first finding centroid 71 | r_add,c_add = 0,0 72 | for corner in new_corners: 73 | r_add = r_add + corner[0][1] 74 | c_add = c_add + corner[0][0] 75 | centroid_row = int(1.0*r_add/len(new_corners)) 76 | centroid_col = int(1.0*c_add/len(new_corners)) 77 | #draw centroid 78 | cv2.circle(frame,(int(centroid_col),int(centroid_row)),5,(255,0,0)) 79 | #add only those corners to new_corners_updated which are at a distance of 30 or lesse 80 | new_corners_updated = new_corners.copy() 81 | tobedel = [] 82 | for index in range(len(new_corners)): 83 | if findDistance(new_corners[index][0][1],new_corners[index][0][0],int(centroid_row),int(centroid_col)) > 90: 84 | tobedel.append(index) 85 | new_corners_updated = np.delete(new_corners_updated,tobedel,0) 86 | 87 | 88 | 89 | #drawing the new points 90 | for corner in new_corners_updated: 91 | cv2.circle(frame, (int(corner[0][0]),int(corner[0][1])) ,5,(0,255,0)) 92 | if len(new_corners_updated) < 10: 93 | print 'OBJECT LOST, Reinitialize for tracking' 94 | break 95 | #finding the min enclosing circle 96 | ctr , rad = cv2.minEnclosingCircle(new_corners_updated) 97 | 98 | cv2.circle(frame, (int(ctr[0]),int(ctr[1])) ,int(rad),(0,0,255),thickness = 5) 99 | 100 | #updating old_corners and oldFrameGray 101 | oldFrameGray = frameGray.copy() 102 | old_corners = new_corners_updated.copy() 103 | 104 | #showing stuff on video 105 | cv2.putText(frame,'Tracking Integrity : Excellent %04.3f'%random.random(),(20,50),cv2.FONT_HERSHEY_SIMPLEX,1,color = (200,50,75),thickness = 3) 106 | cv2.imshow('tracker',frame) 107 | 108 | a = cv2.waitKey(5) 109 | if a== 27: 110 | cv2.destroyAllWindows() 111 | cap.release() 112 | elif a == 97: 113 | break 114 | 115 | 116 | 117 | 118 | cv2.destroyAllWindows() 119 | 120 | 121 | 122 | 123 | 124 | --------------------------------------------------------------------------------