Cars detection in image
Show older comments
I'm working on cars detection project and able to detect few cars. However, I want to at least detect 80-90% of the cars. This is my codes that I've been working on.
%codes
clc;
close all;
clear all;
%image acquisition
f=imread('Cars.jpg');
f=imresize(f,[800 NaN]); % image loading unit
figure (1)
imshow(f)
g=rgb2gray(f);
g=medfilt2(g,[5 5]);
figure (2)
imshow (g)
% morphological image processing
conc=strel('disk',5);
gi=imdilate(g,conc);
conc1=strel('disk',5);
ge=imerode(gi,conc1); % morphological image processing
gdiff=imsubtract(gi,ge);
gdiff1=mat2gray(gdiff);
figure (4)
imshow (gdiff1)
gdiff2=conv2(gdiff1,[1 1;1 1]);
figure (5)
imshow (gdiff2)
gdiff3=imadjust(gdiff2,[0.4 0.9],[0 1],1);
figure (6)
imshow (gdiff3)
B=logical(gdiff3);
[a1 b1]=size(B);
figure(7)
imshow(B)
er=imerode(B,strel('line',60,8));
figure(8)
imshow(er)
out1=imsubtract(B,er);
F=imfill(out1,'holes'); %filling the object
H=bwmorph(F,'thin',0.5);
H=imerode(H,strel('line',8,55));
figure(9)
imshow(H)
%Normalization% & Object Recognition
I=bwareaopen(H,floor((a1/18)*(b1/18)));
I(1:floor(.9*a1),1:2)=1;
I(a1:-1:(a1-20),b1:1:(b1-2))=1;
figure(10)
imshow(I)
%Cars detection in image
figure (11)
imshowpair (f,I)
%Create bounding box on detected cars
Iprops=regionprops(I,'BoundingBox','Image');
hold on
text(8,785,strcat('\color{green}Cars Detected:',num2str(length(Iprops))))
hold on
for n=2:size(Iprops,1)
rectangle('Position',Iprops(n).BoundingBox,'EdgeColor','g','LineWidth',2);
end
hold off
And I get this output:

Where did I do wrong? Can anyone correct the codes? My due date will be up soon. I appreciate if anyone could help asap. Thank you.
This is my original image:

Answers (4)
Image Analyst
on 2 May 2017
2 votes
Well. . . . all kinds of stuff. Did you notice how you were only getting light colored cars and no dark cars? That's because you did a morphological closing (dilation then erosion) which expands the white bars. And other things.
What I'd do is to see if you can get a totally empty parking lot image and then subtract them. If you can't then I'd find the asphalt by converting to hsv color space and looking for pixels that have low saturation and low value - basically find out the color of the asphalt. Then I'd get the color difference between all pixels in the image and the gray asphalt color. You can do this in RGB or LAB color space. Things with a high color difference are either cars or grass. But you can do size filtering because you know that no car will ever be as big as a lawn so use bwareafilt() to remove grass. Grass has high saturation and a hue in the green region and a size larger than the known size of a parking space. So with the grass and asphalt gone, now all you have is cars. But there is still the problem of dark cars because they are close to the color of dark asphalt. There again you'll have to use size information - cars are going to be no larger than the area of a parking spot so you can get rid of large dark asphalt areas. You could also look at the Solidity (returned by regionprops). With cars it will be close to 1 and for weird-shaped asphalt blobs it won't be close to 1.
15 Comments
Joselyn Jok
on 2 May 2017
Joselyn Jok
on 2 May 2017
Image Analyst
on 3 May 2017
Here is the function from the Color Thresholder to get the asphalt:
function [BW,maskedRGBImage] = createMask(RGB)
%createMask Threshold RGB image using auto-generated code from colorThresholder app.
% [BW,MASKEDRGBIMAGE] = createMask(RGB) thresholds image RGB using
% auto-generated code from the colorThresholder App. The colorspace and
% minimum/maximum values for each channel of the colorspace were set in the
% App and result in a binary mask BW and a composite image maskedRGBImage,
% which shows the original RGB image values under the mask BW.
% Auto-generated by colorThresholder app on 02-May-2017
%------------------------------------------------------
% Convert RGB image to chosen color space
I = rgb2hsv(RGB);
% Define thresholds for channel 1 based on histogram settings
channel1Min = 0.537;
channel1Max = 0.121;
% Define thresholds for channel 2 based on histogram settings
channel2Min = 0.000;
channel2Max = 0.268;
% Define thresholds for channel 3 based on histogram settings
channel3Min = 0.458;
channel3Max = 0.715;
% Create mask based on chosen histogram thresholds
sliderBW = ( (I(:,:,1) >= channel1Min) | (I(:,:,1) <= channel1Max) ) & ...
(I(:,:,2) >= channel2Min ) & (I(:,:,2) <= channel2Max) & ...
(I(:,:,3) >= channel3Min ) & (I(:,:,3) <= channel3Max);
BW = sliderBW;
% Initialize output masked image based on input image.
maskedRGBImage = RGB;
% Set background pixels where BW is false to zero.
maskedRGBImage(repmat(~BW,[1 1 3])) = 0;
end
Joselyn Jok
on 4 May 2017
Joselyn Jok
on 4 May 2017
Joselyn Jok
on 4 May 2017
Image Analyst
on 4 May 2017
Get an image, like I did for that asphalt, that is just green pixels. But you don't want to exclude green cars, just green grass. So you can assume that if the blob is not roughly the size of a parking space or car, then it's a patch of grass. You can extract blobs using bwareafilt() like it says in the help, basically
binaryImage = bwareafilt(binaryImage, [lowestAcceptableArea, largestAcceptableArea];
So let's say largestAcceptableArea is the area of a complete parking space and grass and any other things that are bigger than that should be removed. Let's say it's 5000 pixels. And let's say anything smaller than 400 pixels are also bogus. So you'd do
lowestAcceptableArea = 400;
largestAcceptableArea = 5000;
binaryImage = bwareafilt(binaryImage, [lowestAcceptableArea, largestAcceptableArea];
Joselyn Jok
on 15 May 2017
Edited: Joselyn Jok
on 15 May 2017
Joselyn Jok
on 21 May 2017
Image Analyst
on 21 May 2017
Get two masks. One for asphalt, one for grass. Use them as indexes or multipliers of the original image to erase each in turn. I showed you already how to do it for asphalt. Just do the same thing for the output of that process and then you'll have both asphalt and grass removed.
Image Analyst
on 9 Mar 2018
It's called masking, where you basically zero out parts of the image that are inside a mask (white parts of a binary image).
% Mask the image using bsxfun() function to multiply the mask by each channel individually.
maskedRgbImage = bsxfun(@times, rgbImage, cast(mask, 'like', rgbImage));
C M ANUJA
on 9 Mar 2018
Thank you
Nur Farah Aqilah Mohd Fazli
on 11 May 2019
where can i put all the changing coding in your starting coding? i did not understand
Image Analyst
on 11 May 2019
You make two functions createMaskAsphalt(), and createMaskGrass() with different thresholds. You can put them at the end of your main m-file, or have them be separate m-files.
You can determine the thresholds and create the functions by using the "Color Thresholder" app on the Apps tab of the tool ribbon.
Rabious Seajon
on 11 Feb 2018
Edited: Image Analyst
on 11 Feb 2018
I=bwareaopen(H,floor((a1/18)*(b1/18)));
I(1:floor(.9*a1),1:2)=1;
I(a1:-1:(a1-20),b1:1:(b1-2))=1;
figure(10)
imshow(I)
how it works wold u please tell me sir?
2 Comments
Image Analyst
on 11 Feb 2018
It first removes blobs smaller than floor((a1/18)*(b1/18)) pixels in area. Then it sets two rectangular blocks to 1 (white, true). Finally it brings up a figure with label 10 and displays the modified binary image.
sneha madda
on 11 Jun 2019
Thanks a lot, it's working fine but I printed number of vehicles by adding these lines of code after for loop.
result = sprintf('Number of cars: %d.',n-1);
disp(result);% display number of cars
hold off
Jeje Ahmad
on 17 Oct 2020
0 votes
Hi , Can i take this code
please
Jeje Ahmad
on 17 Oct 2020
0 votes
@joselyn jok
@Image Analyst
9 Comments
Image Analyst
on 18 Oct 2020
What? Are you wanting my attached parking demo???
Jeje Ahmad
on 18 Oct 2020
I want a code that works for counting and detecting cars in an image not video using image process
please
Image Analyst
on 18 Oct 2020
Yes, my code did that. It works with still images, not videos.
Image Analyst
on 18 Oct 2020
Yes, I'm putting it all out there in the public domain for anyone to use or modify. Probably modify since I know for a fact that some professors use plagiarism detectors to compare students code to each other and to online code.
Vartika Agarwal
on 11 Feb 2021
This code is working only for particular image. not for all image.
Image Analyst
on 11 Feb 2021
Correct. Obviously you will have to use your own image without cars for the reference image, and create a mask from that. But that should be easy to get since the camera is just monitoring one particular parking lot, not all parking lots in the world.
Johanphilip Davis
on 28 Oct 2021
Can this code be used to detect the number of cars in the video?
Image Analyst
on 28 Oct 2021
Again, it doesn't work for video unless you just process a frame at a time. MATLAB has tracking that works with cars:
Johanphilip Davis
on 28 Oct 2021
Thank you for sharing
Categories
Find more on Image Processing and Computer Vision in Help Center and File Exchange
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!