Count the cars going to the city center.
Track the y and x co-ordinate as the car comes from right to left and add to counter if that is the case.
If cars move from left to right, ignore.
There are lines that are currently commented out that will give a visual indication of how the counting works.
Both videos are imported in line 10 and 11 in the code below.
You need to select the desired video in line 14 by making either:
Baseline code reference:
Install the required Python libraries
pip install pyttsx3
pip install pywin32
pip install numpy
pip install opencv-python
These libraries apply to both exercise 1.1 and 1.2
pip install pyttsx3
Requirement already satisfied: pyttsx3 in c:\users\sjhen\anaconda3\lib\site-packages (2.90) Requirement already satisfied: pypiwin32 in c:\users\sjhen\anaconda3\lib\site-packages (from pyttsx3) (223) Requirement already satisfied: pywin32 in c:\users\sjhen\anaconda3\lib\site-packages (from pyttsx3) (228) Requirement already satisfied: comtypes in c:\users\sjhen\anaconda3\lib\site-packages (from pyttsx3) (1.1.10) Note: you may need to restart the kernel to use updated packages.
pip install pywin32
Requirement already satisfied: pywin32 in c:\users\sjhen\anaconda3\lib\site-packages (228) Note: you may need to restart the kernel to use updated packages.
pip install numpy
Requirement already satisfied: numpy in c:\users\sjhen\anaconda3\lib\site-packages (1.20.3) Note: you may need to restart the kernel to use updated packages.
pip install opencv-python
Requirement already satisfied: opencv-python in c:\users\sjhen\anaconda3\lib\site-packages (4.5.5.62) Requirement already satisfied: numpy>=1.17.3 in c:\users\sjhen\anaconda3\lib\site-packages (from opencv-python) (1.20.3) Note: you may need to restart the kernel to use updated packages.
As we can see above, all the required packages are installed.
Lets start with the code.
First, import the required libraries.
# let’s import the libraries
# For playing the audio, we will be using “pyttsx3” python library to convert text to speech
import cv2
import numpy as np
import time
Lets create a funtion to run and analyse the video clips, this way we can just call the function with the wanted video.
def analyseVideo(video):
initial_frame = None
# Check if the video opened successfully
if (video.isOpened()== False):
print("Error opening video file")
# Run video on successfully opening it
else:
# Get video dimentions and set the cutoff point for motion detection
video_width = int(video.get(3)) # float `width`
video_height = int(video.get(4)) # float `height`
video_cutoff_point_H = int(video_height/2) + 30
video_count_trigger_W = int(video_width/2) + 30
# Counting variable
vehicle_count_R_L = 0
# Frame count
frame_count = 0
# Get frames per second
fps = video.get(cv2.CAP_PROP_FPS)
# Get 1st frame
check, frame = video.read()
# Counting related variables
from_right = 0
counted = 0
carsPerMin = 0
# We start an infinite loop and keep reading frames from the video until we press 'q' or the video comes to an end.
while video.isOpened():
try:
# Count frames
frame_count += 1
# Gray conversion and noise reduction (smoothening)
gray_frame=cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
blur_frame=cv2.GaussianBlur(gray_frame, (25,25), 0)
# The first captured frame is the baseline image
if initial_frame is None:
initial_frame = blur_frame
continue
# The difference between the baseline and the new frame
delta_frame = cv2.absdiff(initial_frame, blur_frame)
# The difference (the delta_frame) is converted into a binary image
# If a particular pixel value is greater than a certain threshold (specified by us here as 150),
# it will be assigned the value for White (255) else Black(0)
threshold_frame = cv2.threshold(delta_frame, 20, 255, cv2.THRESH_BINARY)[1]
# apply image dilation
kernel = np.ones((3,3), np.uint8)
dilated_frame = cv2.dilate(threshold_frame, kernel, iterations = 3)
# The cv2.findContours() method we will identify all the contours in our image.
# This method expects 3 parameters, (a) image, (b) contour retrieval mode and
# (c) contour approximation method
(contours,_) = cv2.findContours(dilated_frame, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# Itterate over contours and process
for i,c in enumerate(contours):
(x, y, w, h) = cv2.boundingRect(contours[i])
# Only check the are that covers main street
if y >= video_cutoff_point_H:
#contourArea() method filters out any small contours
#You can change this value
if cv2.contourArea(c) < 4000:
continue
cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 1)
# # Show line that isolates main street
# cv2.line(frame, (0, video_cutoff_point_H),(video_width, video_cutoff_point_H),(250, 0, 0))
# cv2.line(frame, (0, video_cutoff_point_H + 150),(video_width, video_cutoff_point_H + 150),(250, 0, 0))
# # Show line that acts as the trigger for counting
# cv2.line(frame, (video_count_trigger_W+20, video_cutoff_point_H),(video_count_trigger_W+20, video_height),(0, 250, 250))
# cv2.line(frame, (video_count_trigger_W+40, video_cutoff_point_H),(video_count_trigger_W+40, video_height),(0, 0, 250))
# cv2.line(frame, (video_count_trigger_W+60, video_cutoff_point_H),(video_count_trigger_W+60, video_height),(0, 250, 0))
# cv2.line(frame, (video_count_trigger_W+80, video_cutoff_point_H),(video_count_trigger_W+80, video_height),(250, 250, 0))
# Coming from right direction and going left
if x >= video_count_trigger_W - 20 and y > video_cutoff_point_H and y < video_cutoff_point_H + 150: # Isolate the main street part of interest
center = (int(x),int(y))
radius = 5
cv2.circle(frame, center, radius, (0,0,255),2)
# Set count reset from right to left
# Set, cars from the right
if from_right == 0 and x > video_count_trigger_W + 60 and x < video_count_trigger_W + 80:
from_right = 1
# Reset cars from the left
elif from_right == 1 and x > video_count_trigger_W + 80:
from_right = 0
# Count
elif from_right == 1 and counted == 0 and x > video_count_trigger_W + 40 and x < video_count_trigger_W + 60:
vehicle_count_R_L += 1
counted = 1
# Reset
elif from_right == 1 and counted == 1 and x > video_count_trigger_W + 20 and x < video_count_trigger_W + 40:
from_right = 0
counted = 0
# Update the car per minute count
if vehicle_count_R_L != 0:
carsPerMin = vehicle_count_R_L/((frame_count/fps)/60)
# Display info on the screen
cv2.putText(frame, "Count: {}".format(vehicle_count_R_L), (10, 15), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
cv2.putText(frame, "Trigger: {}".format(from_right), (100, 15), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
cv2.putText(frame, "Cars / Min: {:.2f}".format(carsPerMin), (10, 35), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
cv2.putText(frame, "Time: {}".format(frame_count/fps), (10, 55), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
# To better understand the application, we can visualise the different frames generated
cv2.imshow('Original Video', frame)
#cv2.imshow('Gray Frame', gray_frame)
#cv2.imshow('Blur Frame', blur_frame)
#cv2.imshow('Delta Frame', delta_frame)
#cv2.imshow('Threshold Frame', threshold_frame)
#cv2.imshow('Dilated Frame', dilated_frame)
# Stop the program by pressing 'q'
if cv2.waitKey(10) == ord('q'):
print("Manually exited video by pressing q")
cv2.destroyAllWindows()
video.release()
break
# Get the next frame and save previous frame
check, frame = video.read()
# Error or no more frames and end of video
except Exception as e:
print(e)
print("Final cars per minute for the entire duration of the video: " + str(carsPerMin))
cv2.destroyAllWindows()
video.release()
break
Lets call the function above with the first video.
# We use VideoCapture function to create the video capture object
video1 = cv2.VideoCapture('Video/Traffic_Laramie_1.mp4')
analyseVideo(video1)
OpenCV(4.5.5) D:\a\opencv-python\opencv-python\opencv\modules\imgproc\src\color.cpp:182: error: (-215:Assertion failed) !_src.empty() in function 'cv::cvtColor' Final cars per minute for the entire duration of the video: 2.0229265003371544
Lets call the function above with the second video.
video2 = cv2.VideoCapture('Video/Traffic_Laramie_2.mp4')
analyseVideo(video2)
OpenCV(4.5.5) D:\a\opencv-python\opencv-python\opencv\modules\imgproc\src\color.cpp:182: error: (-215:Assertion failed) !_src.empty() in function 'cv::cvtColor' Final cars per minute for the entire duration of the video: 2.2701475595913734