Machine learning for identification of cars

There are plenty of data on internet, however it is raw data. Think for a second about public surveillance cameras - useful to check the traffic on the route or busy place, but anything else? What if you want to know how many cars are on the route? How many car were yesterday at the same time? Given so many cars on the route, how much polluted air in the area?
While working on the road map for data dive event, I started to wonder, how feasible is to use data of public surveillance cameras. So I quickly built a pilot project and now I would like to share my experience.

First step – data acquisition. At beginning I was thinking to plug my smartphone somewhere and collect data of the busy route.  Nevertheless, I quickly found surveillance cameras in Vilnius and started to collect images. Run a search and I’m sure, that you will find them in your city:

Photobucket

Here is bash script, which I use to collect images:

#you need full path for crontab
cd /home/git/carCount/img
a=`date +%s`
b=${a}_4.jpg
wget -O $b -q "http://www.sviesoforai.lt/map/camera.aspx?size=full&image=K7742-1.jpg&rnd=0.15417794161476195"

Data preparation. After while you will have enough data to train your machine (for beginning more than 30 images should be O.K.).
How do we train the algorithm? The goal is to identify the cars in a given image. That means, that we have to provide the examples of positive images (clear image of the cars) and negative images (no car, parts of the car and etc.). Important note – we don’t feed whole image, but we cut a chosen image with sliding window (100×100 in my case). 4 examples of positive images:

Photobucket

Meanwhile, it is worth converting each image to portable grey format PGM. For this specific task, we can sacrifice information about the color of the car – it won’t improve prediction. Besides, PGM images can be loaded into R and easily transformed into matrix. Here is bash script, which converts jpg to pgm and slices each image:

#remove image duplicates
find . -maxdepth 1 -type f -exec md5sum {} \;  >test.txt
awk 'a[$1]++ {gsub(/^\*/,"",$2); print "rm ", $2}' test.txt |sh
rm test.txt
 
#convert jpg
 
if [ -d "out" ]; then
        rm -r out
fi
mkdir out
for k in $(ls *.jpg); do convert $k out/$k.pgm; done
 
cd out
mkdir slide
for filename in $(ls *.pgm);
 do 
 
w=`convert $filename -print "%w" /dev/null`
h=`convert $filename -print "%h" /dev/null`
let "ww= $w/100"
let "hh= $h/100"
for((y=150;y<=250;y+=50))
do
for((i=100;i<=400;i+=50))
do
echo "slide/$i.$filename"
let "h_slide=$i"
convert $filename -crop 100x100+$i+$y slide/$y.$i.$filename
done
done
done

Training, predicting, cross validation. Now is time to open R, load 100×100 images from “train/out/slide” directory and train the algorithm. Important note – each image is a matrix, however you have to feed a matrix of all images to learning algorithm (support vector machine in my case). What you have to do is to “unroll” each image matrix into a vector, get 1X10000 vector and build a new matrix, where each row is an image.
Once training is done, load unseen data from “crossval/out/slide” directory and check “result/” directory, where you will find  images of the cars. R script, which does all above:

?View Code RSPLUS
setwd('/home/git/carCount/')
 
######read positives############
files=list.files('test/pos/')
pos=matrix(nrow=NROW(files),ncol=100*100)
 
for(i in 1:NROW(files))
{
  gray_file=read.pnm(paste('test/pos/',files[i],sep=''))
  pos[i,]=c(gray_file@grey)
}
outcome=vector(length=NROW(files))
outcome[which(outcome!=1)]=1
 
########read negatives#############
files=list.files('test/neg/')
neg=matrix(nrow=NROW(files),ncol=100*100)
 
for(i in 1:NROW(files))
{
  gray_file=read.pnm(paste('test/neg/',files[i],sep=''))
  neg[i,]=c(gray_file@grey)
}
tmp=vector(length=NROW(files))
tmp[which(tmp!=0)]=0
outcome=c(outcome,tmp)
forecast=svm(rbind(pos,neg),outcome)
cross_val=pos[84:90,]
pred=predict(forecast,cross_val,decision.values=TRUE)
 
##########################unseen data######################
files=list.files('crossval/out/slide/')
cross=matrix(nrow=NROW(files),ncol=100*100)
 
for(i in 1:NROW(files))
{
  gray_file=read.pnm(paste('crossval/out/slide/',files[i],sep=''))
  cross[i,]=c(gray_file@grey)
}
pred=predict(forest,cross,decision.values=TRUE)
 
###############copy positives into result directory###############
dir.create('result')
file.copy(paste('crossval/out/slide/',files[which(as.double(pred)&gt;0.6)],sep=''),'result/')

 

Classified as positive by algorithm:
Photobucket

Classified as negative by algorithm:
Photobucket

 

Conclusion. It is truly amazing how well algorithm is able to separate wheat from the chaff without additional tuning. Mind you, my impression is biased after so many fails with financial data, which is noisy and good predictions are scarce.
Nevertheless, this project is far away for ideal – it doesn’t take into account weather condition, traffic jams, perspective view, movements of the camera and etc. But I leave this fun for data-dive event.

Fork the codehttps://github.com/kafka399/carCount/

11 Comments »

  1. Erin Hodgess said,

    April 23, 2012 @ 5:21

    This is SO COOL!

    Thanks for posting.

    I have one question, please: how often does that camera get updated, please?

    Thanks,
    Erin

  2. Dzidorius Martinaitis said,

    April 23, 2012 @ 6:58

    Erin,
    I check for new image once a minute. However, sometimes I get duplicates of the image, so bash script checks for duplicates.

  3. Machine learning for identification of cars | (R news & tutorials) said,

    April 23, 2012 @ 10:23

    [...] of cars April 22, 2012By Dzidorius Martinaitis (This article was first published on Quantitative thoughts » EN, and kindly contributed to [...]

  4. chit said,

    April 23, 2012 @ 16:33

    awesome example with code details

  5. Machine learning for identification of cars | Transport, flow and movement said,

    April 23, 2012 @ 21:32

    [...] Machine learning for identification of cars Posted on 23 April 2012 by Pierre-Olivier Chasset var addthis_product = 'wpp-264'; var addthis_config = {"data_track_clickback":true,"data_ga_property":"UA-30520513-1","data_ga_social":true,"data_track_addressbar":true,"data_track_textcopy":false,"ui_508_compliant":true};if (typeof(addthis_share) == "undefined"){ addthis_share = {"url_transforms":{"shorten":{"twitter":"bitly"}},"shorteners":{"bitly":{"login":"acyak","apiKey":"R_25c81a55f0c4a28fccfb0eaa661e7d03"}}};}http://www.investuotojas.eu/2012/04/22/machine-learning-for-identification-of-cars/ This entry was posted in News by Pierre-Olivier Chasset. Bookmark the permalink. [...]

  6. Paolo said,

    April 24, 2012 @ 10:36

    Nice example of ‘practical’ machine-learning. Thanks for sharing!
    Pedantic note: You should add package dependencies to your R script,i.e.:
    library(pixmap)
    library(e1071)

  7. Dzidorius Martinaitis said,

    April 24, 2012 @ 10:40

    Paolo,
    thank you for comment. Dependencies are in place!

  8. Erin said,

    May 6, 2012 @ 19:36

    Hi! I’m having trouble with a particular website.

    How do I get it to get as my jpeg, please?

    Thanks for your help,
    Sincerely,
    Erin

  9. Dzidorius Martinaitis said,

    May 6, 2012 @ 20:55

    Can you paste the link somewhere else? Paste or gist?
    I use wget or curl and crontab

  10. Erin Hodgess said,

    May 6, 2012 @ 21:26

    Hi…figured it out. I looked at the source code from the website and found the actual site for the jpg. Works like a charm now!

    Thanks,
    Erin

  11. Erin Hodgess said,

    August 18, 2012 @ 5:00

    Hi again!

    Is there a way to use R to run your own webcam to take pictures of cars on my own street, please?

    Thanks,
    Erin

RSS feed for comments on this post · TrackBack URI

Leave a Comment