Vehicle Detection and Counting System using OpenCV

Aman Preet Gulati 31 Dec, 2021 • 6 min read

This article was published as a part of the Data Science Blogathon

Overview

In this article, we will be coding a vehicle counting and detection system. It will be enough to work for both the images or the video, for the same, we will be using OpenCV for doing all the image processing operations and for classification the car and bus haar cascade classifier for detecting and counting the cars and buses having said that you can also make your haar cascade classifier.

vehicle counting and detection system
Image source: Indiamart

Scope

  1. Helps traffic police: A vehicle detection and counting system could be beneficial for the traffic police because everything they can monitor from one place only likes how many vehicles have crossed this toll and which vehicle.
  2. Maintaining records: It is challenging for some individuals to record all the vehicles with them because the cars are passing by in real-time. It’s not like that one is watching the video, and they can pause it and have a note of it, so to remove this limitation, this application can be very well-versed to attain the time-saving quality and be automated.
  3. Traffic surveillance control: As this application can be planted anywhere as it only requires a camera or some wires (for establishing the connectivity with the central system) hence if the traffic is high at someplace, then from that area, an officer can monitor it and forward the information to next toll officer so that they could be prepared beforehand.

Importing required libraries

# Import libraries
from PIL import Image
import cv2
import numpy as np
import requests

Next, we will fetch the image from the internet that we will be working on. We will then resize the image and convert it into a NumPy array.

Reading image from URL

image = Image.open(requests.get('https://a57.foxnews.com/media.foxbusiness.com/BrightCove/854081161001/201805/2879/931/524/854081161001_5782482890001_5782477388001-vs.jpg', stream=True).raw)
image = image.resize((450,250))
image_arr = np.array(image)
image

Output:

Reading image from URL

 

To get better output, we will perform some transformations on the image. Here we will convert the image into grayscale.

Grayscale

grey = cv2.cvtColor(image_arr,cv2.COLOR_BGR2GRAY)
Image.fromarray(grey)

Output:

 

Grayscale

Next, we will apply GaussianBlur to remove the noise from the image. Gaussian blur is one of the techniques of image processing. It is widely used in graphics designing too for reducing the noise and smoothing the image so that for further preprocessing, it will generate better output. Along with reducing the noise in the image Gaussian blur technique also reduces the image’s details. Here for applying this preprocessing technique, we will be using the GaussianBlur function().

Gaussian Blur

blur = cv2.GaussianBlur(grey,(5,5),0)
Image.fromarray(blur)

Output:

Gaussian Blur

Here we will dilate the image. Dilation is one of the morphological techniques where we try to fill the pixels with the element, also known as kernels (structured pieces), to fill the missing parts of the images whenever needed.

Note: It is just the opposite of erosion.

Dilation

dilated = cv2.dilate(blur,np.ones((3,3)))
Image.fromarray(dilated)

Output:

 

Dilation

Now we will perform a Morphology transformation with the kernel. Here we are using a morphology-Ex technique that tells the function on which image processing operations need to be done. The second argument is about what operations must be done, and you may need elliptical/circular shaped kernels. To implement the morphology-Ex method using OpenCV we will be using the get structuring element method.

Morphology-Ex, structuring element

kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (2, 2))
closing = cv2.morphologyEx(dilated, cv2.MORPH_CLOSE, kernel) 
Image.fromarray(closing)

Output:

Detecting cars using car cascade

Now we need a car cascade to detect cars. So, we first need to upload them to collab (if you are doing it in the collab, if you are doing it in the local machine, then add the cascade files in the same folder) and specify the path car_cascade_src. Here we will use the CascadeClassifier function, the predefined function of OpenCV, to train the images from the pre-trained XML file (Cascade file – car). We need to detect multiple objects, i.e. cars, to use detectMultiScale.

car_cascade_src = 'cars.xml'
car_cascade = cv2.CascadeClassifier(car_cascade_src)
cars = car_cascade.detectMultiScale(closing, 1.1, 1)
cars

Output:

array([[376,   1,  22,  22],
       [307,   4,  27,  27],
       [196,  10,  28,  28],
       [ 35,   2,  30,  30],
       [150, 163,  68,  68],
       [318, 121,  82,  82],
       [101,   3,  43,  43],
       [317,  66,  66,  66],
       [274,  20,  38,  38],
       [256,  52,  79,  79],
       [245,  24,  20,  20],
       [250,  35,  25,  25],
       [ 63,  40,  22,  22],
       [209,  88,  54,  54],
       [ 13,  25,  43,  43],
       [384,  84,  59,  59],
       [145,  91,  53,  53],
       [ 52,  44,  39,  39],
       [237,  38,  49,  49],
       [362,  43,  46,  46],
       [268, 106,  60,  60]], dtype=int32)

We will use the above-returned contours and draw a rectangle around detected cars. Here we will see that it will create the rectangle with a red boundary around every car it detects.

cnt = 0
for (x,y,w,h) in cars:
    cv2.rectangle(image_arr,(x,y),(x+w,y+h),(255,0,0),2)
    cnt += 1
print(cnt, " cars found")
Image.fromarray(image_arr)

Output:

21  cars found
Detecting cars using car cascade

For bus detection

Now we will use another image, i.e. bus image, and we will fetch this image from the internet. We will resize the image, store it as a NumPy array, and convert it into grayscale.

# Reading image form url
image2 = Image.open(requests.get('https://qph.fs.quoracdn.net/main-qimg-b5c4e39dcd48dddd9e609e6022f74d85', stream=True).raw)
image2 = image2.resize((450,250))
image_arr2 = np.array(image2)
grey2 = cv2.cvtColor(image_arr2,cv2.COLOR_BGR2GRAY)

We are working with the bus image here, so we require the cascade to detect the bus. We will use Bus_front cascade to identify buses from the image, and we will perform a similar operation as performed above.

bus_cascade_src = 'Bus_front.xml'
bus_cascade = cv2.CascadeClassifier(bus_cascade_src)
bus = bus_cascade.detectMultiScale(grey2, 1.1, 1)

As we did in car cascading similarly, we will be performing the same contour operations on the bus image and create a rectangle around the bus if detected any.

cnt = 0
for (x,y,w,h) in bus:
    cv2.rectangle(image_arr2,(x,y),(x+w,y+h),(255,0,0),2)
    cnt += 1
print(cnt, " bus's found")
Image.fromarray(image_arr2)

Output:

1  bus's found
For bus detection

Now we will perform the vehicle detection and counting in a video. For creating the output video from frames or images, we need cv2.VideoWriter() method. It takes the path with extension as the first parameter; the second parameter is the codec for the output format, then we also need to pass frames per second and height and width.

cascade_src = 'cars.xml'
video_src = 'Cars.mp4'

cap = cv2.VideoCapture(video_src)
car_cascade = cv2.CascadeClassifier(cascade_src)
video = cv2.VideoWriter('result.avi',cv2.VideoWriter_fourcc(*'DIVX'), 15, (450,250))

Now we will read frames one by one from the input video, convert them into grayscale, and use car cascade to detect all cars in that particular frame. In the end, we write this video using video.write() method and video.release() will save this video to the given path.

while True:
    ret, img = cap.read()

    if (type(img) == type(None)):
        break

    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    cars = car_cascade.detectMultiScale(gray, 1.1, 2)

    for (x,y,w,h) in cars:
        cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,255),2)

video.write(img) 
video.release()

Conclusion

We started with downloading the image we will be working on and performed different operations. We saw how we could use haar cascade, which is used for object detection, and how different haar cascades are used for car detection and bus detection. Similarly, you can use many pre-trained haar cascades for other object detection.

As haar cascade is used for object detection, we have a vast scope. It can be used for object detection, and we can also create our custom haar cascade for specific objects.

Endnotes

Here’s the repo link to this article.

Here you can access my other articles, which are published on Analytics Vidhya as a part of the Blogathon (link)

If you have any queries, you can connect with me on LinkedIn; refer to this link.

About me

Greeting to everyone, I’m currently working in TCS and previously, I worked as a Data Science Associate Analyst in Zorba Consulting India. I am passionate about Data Science, along with its other subsets of Artificial Intelligence such as Computer Vision, Machine learning, and Deep Learning. If you liked my article and would like to collaborate with me on any project on the domains mentioned above (LinkedIn).

The media shown in this article is not owned by Analytics Vidhya and are used at the Author’s discretion.

Aman Preet Gulati 31 Dec 2021

Frequently Asked Questions

Lorem ipsum dolor sit amet, consectetur adipiscing elit,

Responses From Readers

Clear

AndyKok
AndyKok 17 May, 2022

Thank you so much for the incredibly helpful article and resources that you have provided. May I know, for the bus recognition model, is it designed to recognise double decker buses? If not, how can I go about implementing the feature of recognising double decker buses into the model? If you could point me at some resources on how you train your mode, that will be very helpful! Once again, thank you very much!

Alok lenka
Alok lenka 09 Jan, 2023

We fully system for vehicle counting,

Computer Vision
Become a full stack data scientist