This article was published as a part of the Data Science Blogathon
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.
# 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.
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:
To get better output, we will perform some transformations on the image. Here we will convert the image into grayscale.
grey = cv2.cvtColor(image_arr,cv2.COLOR_BGR2GRAY) Image.fromarray(grey)
Output:
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().
blur = cv2.GaussianBlur(grey,(5,5),0) Image.fromarray(blur)
Output:
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.
dilated = cv2.dilate(blur,np.ones((3,3))) Image.fromarray(dilated)
Output:
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.
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (2, 2)) closing = cv2.morphologyEx(dilated, cv2.MORPH_CLOSE, kernel) Image.fromarray(closing)
Output:
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
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
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()
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.
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.
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.
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!
We fully system for vehicle counting,