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.

Detect speed of a car with OpenCV in Python

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

2 responses to “Detect speed of a car with OpenCV in Python”

  1. Sylvain says:

    Hey,
    Your article is very interesting. I think I will use it this year for a school project, and upgrade it.

    • Sylvain says:

      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!

Leave a Reply