Detect and track objects in live webcam video based on color and size by c#
Introduction
u can select a color in real time and it it track that color object and give u the position. i use aforge library for that also i used dotnetframework 4.0, it is a c# desktop application, it can take up to 25 frame per second .u can change color size any time u want, the color of drawing point will also be change
Background
I see a very interesting project in codeproject name making of lego pit camera, by help of this project i thought a realtime tracker could be made where color and objects size could also be changed in real time. and can draw movement of that objects in a bitmap with that color. i use some part of their code, although i use separate color filter for more accuracy.
Using the code
The steps of work is very simple
- take videoframe from webcam
- use filtering by given color(here eucladianfiltering used)
- make greyscale
- find objects by given size
- find biggest object
- draw object position in bitmap
First how my software work first can start tracking by default color
black and color range of 120 but u can change in real time to color
change press that a color dialog will come , then select color, remember
to press OK and see the solidcolor box that Ur required color is
present or not.
To select the range and define minimum size of the object see next image, there are 3 numeric updown list for that. objectsize calculated in pixel now about the views,
there are 4 view, 3 of them is Aforge video source control and another one is a picturebox, first one show normal video, second one show all detected object, 3rd box show only the biggest object and fourth one just draw a ’0′ sign in biggest object location, see below image for more clear view
i also add a richtextbox which showing the pixel of biggestrectangle position .now about the code for connection i use normal aforge connection code,
for that u need to download aforge dll, and also add a very good videocontrol for showing video u can add it in ur toolbox. just click freespace on toolbox chooseitems-> browse the dll -> add the control
using AForge; using AForge.Video.DirectShow;
then initialize
videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice); if (videoDevices.Count == 0) throw new ApplicationException(); foreach (FilterInfo device in videoDevices) { VideoCaptureDevice videoSource = new VideoCaptureDevice(device.MonikerString); videoSource.DesiredFrameSize = new Size(320, 240); videoSource.DesiredFrameRate = 15; videoSourcePlayer1.VideoSource = videoSource; videoSourcePlayer1.Start(); }
for videoplayercontrol add a event in its misc
named
private void videoSourcePlayer1_NewFrame(object sender, ref Bitmap image) {//work with image }
in that function i apply my color detection code by writing eucladian filtering and then use blobcounter to extract data , here i m explaining it
So see EuclideanColorFiltering work first see
we are going to apply a color filter it is very simple code to use euclideanfiltering
// create filter EuclideanColorFiltering filter = new EuclideanColorFiltering( ); // set center colol and radius filter.CenterColor = Color.FromArgb( 215, 30, 30 ); filter.Radius = 100; // apply the filter filter.ApplyInPlace( image );
now see the effect
well to understand how it work look closely at the code
filter.CenterColor = Color.FromArgb( 215, 30, 30 ); filter.Radius = 100;
first line select the select color value. you all know color has a value 0 to 255.
by filter.CenterColor = Color.FromArgb( 215, 30, 30 ); i specified my center color will be a red effected color because here value of red is 215, green and blue is 30. and filter.Radius = 100 means that all color value near than 100 in my specified color.
now
my filter filters pixels, which color is inside/outside of RGB sphere
with specified center and radius – it keeps pixels with colors
inside/outside of the specified sphere and fills the rest with specified
color.
Now for detect objects i use bitmap data and use lockbits method to understand clearly this method see here . then we make it greyscale algorithom hten unlock it.
BitmapData objectsData = image.LockBits(new Rectangle(0, 0, image.Width, image.Height),ImageLockMode.ReadOnly, image.PixelFormat); // grayscaling UnmanagedImage grayImage = grayscaleFilter.Apply(new UnmanagedImage(objectsData)); // unlock image image.UnlockBits(objectsData);
now the object we use blobcounter for that. it is a very strong class that aforge provided.
blobCounter.MinWidth = 5; blobCounter.MinHeight = 5; blobCounter.FilterBlobs = true; blobCounter.ProcessImage(grayImage); Rectangle[] rects = blobCounter.GetObjectRectangles(); foreach(Rectangle recs in rects) if (rects.Length > 0) { foreach (Rectangle objectRect in rects) { Graphics g = Graphics.FromImage(image); using (Pen pen = new Pen(Color.FromArgb(160, 255, 160), 5)) { g.DrawRectangle(pen, objectRect); } g.Dispose(); } }
blobCounter.MinWidth and blobCounter.MinHeight define the smallest size of the object in pixel.
and blobCounter.GetObjectRectangles() return all the objects rectangle position. and using graphics class i draw rectangle over the images.
now if u want to take only the biggest object there is a method for that
blobCounter.MinWidth = 5; blobCounter.MinHeight = 5; blobCounter.FilterBlobs = true; blobCounter.ObjectsOrder = ObjectsOrder.Size; blobCounter.ProcessImage(grayImage); Rectangle[] rects = blobCounter.GetObjectRectangles(); foreach(Rectangle recs in rects) if (rects.Length > 0) { Rectangle objectRect = rects[0]; Graphics g = Graphics.FromImage(image); using (Pen pen = new Pen(Color.FromArgb(160, 255, 160), 5)) { g.DrawRectangle(pen, objectRect); } g.Dispose(); }
but if u want to extract u can use following code
Bitmap bmp = new Bitmap(rects[0].Width, rects[0].Height); Graphics g = Graphics.FromImage(bmp); g.DrawImage(c, 0, 0, rects[0], GraphicsUnit.Pixel);
so u will get ur object like that
For draw the bitmap i had to use threading the thread was called in videosurecplayer event where i called the thread.
void p(object r) { try {//create image Bitmap b = new Bitmap(pictureBox1.Image); Rectangle a = (Rectangle)r; Pen pen1 = new Pen(Color.FromArgb(160, 255, 160), 3); Graphics g2 = Graphics.FromImage(b); pen1 = new Pen(color, 3); SolidBrush b5 = new SolidBrush(color); Font f = new Font(Font, FontStyle.Bold); g2.DrawString("o", f, b5, a.Location);//draw the position g2.Dispose(); pictureBox1.Image = (System.Drawing.Image)b; this.Invoke((MethodInvoker)delegate { richTextBox1.Text = a.Location.ToString() + "\n" + richTextBox1.Text + "\n"; ; }); } catch (Exception faa) { Thread.CurrentThread.Abort(); } Thread.CurrentThread.Abort(); }
i have to use invoke to write in textbox because of cross threading. To send rectangle object i use parameterized thread. the thread 'aa' called the function "p()" to draw at bitmap and write in textbox.
if (rects.Length > 0) { Rectangle objectRect = rects[0]; // draw rectangle around derected object Graphics g = Graphics.FromImage(image); using (Pen pen = new Pen(Color.FromArgb(160, 255, 160), 5)) { g.DrawRectangle(pen, objectRect); } g.Dispose(); int objectX = objectRect.X + objectRect.Width / 2 - image.Width / 2; int objectY = image.Height / 2 - (objectRect.Y + objectRect.Height / 2); ParameterizedThreadStart t = new ParameterizedThreadStart(p); Thread aa = new Thread(t); aa.Start(rects[0]); }
Points of Interest
parameterized thrading, cross threading has to implement here, also there need to apply invoke method for write. u sing good threading we can increase the framerate. about filtering eucladian fltering is more accurate than HSLfiltering or Colorfiltering, yrbrcr filtering
thanks to andrew kirillov for his help.
发表评论
dk7QUa Your style is very unique in comparison to other folks I have read stuff from. I appreciate you for posting when you ave got the opportunity, Guess I all just bookmark this site.
36CXJe Updating your website frequently helps build your
RufMXH Woh I like your articles , saved to favorites !.
TLHL2t Really informative blog article.Really looking forward to read more. Cool.
Ueo8qh It as not that I want to duplicate your web site, but I really like the design. Could you tell me which style are you using? Or was it especially designed?
DWTk7d Im thankful for the article post.Much thanks again.
Wow! This could be one particular of the most beneficial blogs We ave ever arrive across on this subject. Basically Wonderful. I am also a specialist in this topic so I can understand your hard work.
吃和睡是猪的生活。人生的意义就在于获得幸福。
HevRuh Thanks for the article.Much thanks again. Much obliged.
xD3IZM Thanks for sharing, this is a fantastic blog post.Really looking forward to read more. Awesome.