Detect speed of a car with OpenCV in Python
In this tutorial, you will learn how to detect the speed of a car using Python OpenCV library and some basic mathematical calculations. In the area of traffic management, checking the speed of a vehicle passing through a road becomes very crucial when there is the rule of speed limitations. This Python program exactly checks the speed of the car passing through a specified lane and prints it on the console window.
To do this, you need the footage of cars passing through the road or you can directly take input from any camera device. The camera must be fixed at a specific position so that it can not move in any direction.
In this tutorial, we are using a trained model that can detect the car which can be downloaded by clicking on this link. These type of files contains the features of a car and provides the advantage to detect a car.
The concept behind this program
Speed= distance/time. We all know this little formula. Now we are going to implement that in our code. We need to draw a polygon in our footage and we must know the distance (In our case it is 3 meters) between the two horizontal lines provided in the image link below.
When (x,y) coordinate of detected car strikes to the first line the program will be going to print “Car Entered.” in the console and start to calculate time till (x,y) of a car reaches to the second horizontal line and prints “Car left.” and also prints the speed by using simple formula distance covered(3m in our case)/time taken(which is being calculated). Here (x,y) refers to the coordinate of the top left corner of the rectangle which is being drawn after a successful detection of a car.
Now we are moving towards our coding section.
Detect speed of a car with OpenCV in Python – Code
Firstly, import OpenCV and time libraries.
import cv2 import time
Visit this page to see how to install OpenCV library if you haven’t installed it yet.
cap = cv2.VideoCapture('traffic.mp4') #Path to footage car_cascade = cv2.CascadeClassifier('cars.xml') #Path to cars.xml model
In the first line through the function VideoCapture, the footage is taken however if we pass argument as 0 instead of the path it will directly take input from the webcam or camera attached to your configured system. In the second line, we must give a path to the car model which has features of cars.
#Coordinates of polygon in frame::: [[x1,y1],[x2,y2],[x3,y3],[x4,y4]] coord=[[637,352],[904,352],[631,512],[952,512]] #Distance between two horizontal lines in (meter) dist = 3
In the above code, we have to give the coordinates of our polygon which is to be drawn in the footage. Also, we have to provide the distance between the two horizontal red lines which has been shown in the image link.
while True: ret, img = cap.read() gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) cars=car_cascade.detectMultiScale(gray,1.8,2)
Now we are going to write our code in while loop so that it takes every frame, which looks like a video. Second-line reads the data from the cap object which has been previously defined. The next line turns frame into gray because we don’t need a colored image and also this step increases the speed of the process as it takes less time to load the gray frame. Then after the gray object is given to cars object which uses car_cascade to give the coordinates of detected cars (x,y,w,h) w stands for width and h for height.
for (x,y,w,h) in cars: cv2.rectangle(img,(x,y),(x+w,y+h),(225,0,0),2)
These lines also to be written in a while loop and it draws a blue rectangle over the detected car.
Till now, we have detected cars successfully. Keep in mind that to constantly show rectangle on a detected car we need a good trained car_cascade model.
Now we will draw our polygon in the footage.
cv2.line(img, (coord[0][0],coord[0][1]),(coord[1][0],coord[1][1]),(0,0,255),2) #First horizontal line cv2.line(img, (coord[0][0],coord[0][1]), (coord[2][0],coord[2][1]), (0, 0, 255), 2) #Vertical left line cv2.line(img, (coord[2][0],coord[2][1]), (coord[3][0], coord[3][1]), (0, 0, 255), 2) #Second horizontal line cv2.line(img, (coord[1][0],coord[1][1]), (coord[3][0], coord[3][1]), (0, 0, 255), 2) #Vertical right line
The above lines draw a red-colored polygon referring to the list ‘coord’ which we have given previously. The line function takes an image on which the polygon is to be drawn, two coordinates, color in BGR format and line width respectively. This is also to be written in a while loop.
for (x, y, w, h) in cars: if(x>=coord[0][0] and y==coord[0][1]): cv2.line(img, (coord[0][0], coord[0][1]), (coord[1][0], coord[1][1]), (0, 255,0), 2) #Changes color of the line tim1= time.time() #Initial time print("Car Entered.") if (x>=coord[2][0] and y==coord[2][1]): cv2.line(img, (coord[2][0],coord[2][1]), (coord[3][0], coord[3][1]), (0, 0, 255), 2) tim2 = time.time() print("Car Left.") #We know that distance is 3m print("Speed in (m/s) is:", dist/((tim2-tim1)))
Again in while loop, this for loop contains two if statements. The first one says that if (x,y) means the car touches the first horizontal line then the color of that line turns to green and time.time() stores initial time tim1 when the car hits the first horizontal line and prints “Car Entered.” in the console. x>=coord[0][0] denotes that we are looking in a specific region.
Same if cars leaves, (x,y) touches second horizontal line the lines turn into green and calculates tim2 and prints “Car Left.”. tim2-tim1 gives the total time taken for car to pass polygon region and we already know that distance between those horizontal lines is 3 meters as we defined earlier it calculates speed in (m/s) using simple mathematical formula speed=distance/time and prints it to the console.
cv2.imshow('img',img)
This line is again to be written in a while loop to show footage frame.
if cv2.waitKey(20) & 0xFF == ord('q'): break
The next line is, If we press ‘q’ then the program will terminate.
cap.release() cv2.destroyAllWindows()
These lines are to release the camera if any and de-allocate the memory use for footage. These lines are to be written out of a while loop.
Final Code for the above problem
Below is the complete and final Python code to detect the speed of the car using Python OpenCV library:
import cv2 import time cap = cv2.VideoCapture('traffic.mp4') #Path to footage car_cascade = cv2.CascadeClassifier('cars.xml') #Path to cars.xml #Coordinates of polygon in frame::: [[x1,y1],[x2,y2],[x3,y3],[x4,y4]] coord=[[637,352],[904,352],[631,512],[952,512]] #Distance between two horizontal lines in (meter) dist = 3 while True: ret, img = cap.read() gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) cars=car_cascade.detectMultiScale(gray,1.8,2) for (x,y,w,h) in cars: cv2.rectangle(img,(x,y),(x+w,y+h),(225,0,0),2) cv2.line(img, (coord[0][0],coord[0][1]),(coord[1][0],coord[1][1]),(0,0,255),2) #First horizontal line cv2.line(img, (coord[0][0],coord[0][1]), (coord[2][0],coord[2][1]), (0, 0, 255), 2) #Vertical left line cv2.line(img, (coord[2][0],coord[2][1]), (coord[3][0], coord[3][1]), (0, 0, 255), 2) #Second horizontal line cv2.line(img, (coord[1][0],coord[1][1]), (coord[3][0], coord[3][1]), (0, 0, 255), 2) #Vertical right line for (x, y, w, h) in cars: if(x>=coord[0][0] and y==coord[0][1]): cv2.line(img, (coord[0][0], coord[0][1]), (coord[1][0], coord[1][1]), (0, 255,0), 2) #Changes line color to green tim1= time.time() #Initial time print("Car Entered.") if (x>=coord[2][0] and y==coord[2][1]): cv2.line(img, (coord[2][0],coord[2][1]), (coord[3][0], coord[3][1]), (0, 0, 255), 2) #Changes line color to green tim2 = time.time() #Final time print("Car Left.") #We know that distance is 3m print("Speed in (m/s) is:", dist/((tim2-tim1))) cv2.imshow('img',img) #Shows the frame if cv2.waitKey(20) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows()
This was a very simple and conceptual approach to calculate the speed of a car using the Python OpenCV library. Now give footage input to this program, define the coordinates of the polygon as per your requirements like shown in the image link and then run the program. If everything goes right, you will able to see the window open with red polygon drawn and cars detected if any.
So, we have successfully able to detect the speed of a car in Python using the OpenCV library.
Also read: Detect and Translate in Python
Hey,
Your article is very interesting. I think I will use it this year for a school project, and upgrade it.
But i’ve a pb with the results. You didn’t link the video you used to test your script, so I looked for highways webcams. I found this one : ‘Webcam autoroute.fr à 11h09 ce samedi’ (sorry can’t post a link in comments) on youtube. The problem is that the ‘car detector’ can’t find the cars and has a lot of fake positives.Did you have some problems with cars recognition and how did you find the correct parameters for your script?
Thank you for this tutorial and have a nice day!
Try to use SSD-MobileNet or YOLOv4-tiny model to detect the cars…otherwise you cannot detetect properly the moving object with Cascade Classifier…
How did you come up with the coordinates of the bounding polygon that the car was crossing? Was it trial and error or is there any intuition behind it?
To find the cords:
Take a screenshot, paste it in Photoshop, get the cursor coords.
can u provide a link to your video and can u tell how can i set coordinates in my video
the code showing error at line 1 import cv2 not defined
you Haven’t install the opencv…..
Hello, good afternoon.
Harsh Parmar, your explanation is excellent. But I don’t understand the “cars.xml” file.
Cheers
Edgar
Sir,can you please tell me what is cars.xml in 4th line sir