I've been tinkering with Python and OpenCV for a while now, and thought I'd start an actual project. This is my first time making something that I'd actually consider using, and my first time posting to Code Review SE. I'm curious to know your thoughts and opinions on the cleanliness of my code, the efficiency of the program, and the project in general!
The basic function of the program is to find and track objects. I am thinking of hooking this up to a webcam and stepper motor and testing this as a tracking security camera. The program first creates a background image, and then loops until it finds a difference between what it sees currently, and the background image. The difference of these images is taken, then made into its own frame (frame_delta). If this delta is large enough, it is treated as a contour. If there are multiple contours, the largest one is chosen. Once a contour is found, an MIL tracker is created, and set to the size of the contour. This process is repeated every 30 frames to prevent the object from being lost due to tracker inaccuracy. Here's the code!:
# OpenCV for tracking/display import cv2 import time # When program is started if __name__ == '__main__': # Are we finding motion or tracking status = 'motion' # How long have we been tracking idle_time = 0 # Background for motion detection back = None # An MIL tracker for when we find motion tracker = cv2.TrackerMIL_create() # Webcam footage (or video) video = cv2.VideoCapture(0) # LOOP while True: # Check first frame ok, frame = video.read() # Grayscale footage gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY) # Blur footage to prevent artifacts gray = cv2.GaussianBlur(gray,(21,21),0) # Check for background if back is None: # Set background to current frame back = gray if status == 'motion': # Difference between current frame and background frame_delta = cv2.absdiff(back,gray) # Create a threshold to exclude minute movements thresh = cv2.threshold(frame_delta,25,255,cv2.THRESH_BINARY) #Dialate threshold to further reduce error thresh = cv2.dilate(thresh,None,iterations=2) # Check for contours in our threshold _,cnts,hierarchy = cv2.findContours(thresh,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) # Check each contour if len(cnts) != 0: # If the contour is big enough # Set largest contour to first contour largest = 0 # For each contour for i in range(len(cnts)): # If this contour is larger than the largest if i != 0 & int(cv2.contourArea(cnts[i])) > int(cv2.contourArea(cnts[largest])): # This contour is the largest largest = i if cv2.contourArea(cnts[largest]) > 1000: # Create a bounding box for our contour (x,y,w,h) = cv2.boundingRect(cnts) # Convert from float to int, and scale up our boudning box (x,y,w,h) = (int(x),int(y),int(w),int(h)) # Initialize tracker bbox = (x,y,w,h) ok = tracker.init(frame, bbox) # Switch from finding motion to tracking status = 'tracking' # If we are tracking if status == 'tracking': # Update our tracker ok, bbox = tracker.update(frame) # Create a visible rectangle for our viewing pleasure if ok: p1 = (int(bbox), int(bbox)) p2 = (int(bbox + bbox), int(bbox + bbox)) cv2.rectangle(frame,p1,p2,(0,0,255),10) # Show our webcam cv2.imshow("Camera",frame) # If we have been tracking for more than a few seconds if idle_time >= 30: # Reset to motion status = 'motion' # Reset timer idle_time = 0 # Reset background, frame, and tracker back = None tracker = None ok = None # Recreate tracker tracker = cv2.TrackerMIL_create() # Incriment timer idle_time += 1 # Check if we've quit if cv2.waitKey(1) & 0xFF == ord("q") or cv2.getWindowProperty('Camera',0) == -1: break #QUIT video.release() cv2.destroyAllWindows()