Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / WinForms

Use OpenCVdotNet to Capture Object on Webcam

4.71/5 (10 votes)
27 Jul 2009CPOL1 min read 78.3K   5.8K  
This program uses a webcam to take a picture of an object if there is a change in picture.

Introduction 

This code is based on "Webcam Simple Frame Difference" at the blog: http://haryoktav.wordpress.com/2009/02/28/webcam-c-simple-frame-difference/.

Objectives 

  • Monitoring a room with a webcam
  • No need to save a long movie, just capture pictures showing the change
  • Easy to view the result, no need to view the entire long movie (maybe it does not have any change) 

Background

This code uses OpenCVdotNet library to:

  1. download and install OpenCV 1.0 - http://sourceforge.net/projects/opencv/ (do not install 1.1)
  2. download and install OpenCVDotNet 0.7 - http://code.google.com/p/opencvdotnet/

I use Visual Studio 2005 to design a form like this:

01.PNG

The form has 2 pictureboxes to show the current image and the captured image; 1 timer to repeat checking the difference of image in the room and save to file if needed; 1 button to active timer, 1 label to show the number of captured images.

Using the Code 

There is only one form, and the code is as given below: 

After installing OpenCVDotnet library, add it to the project:

C#
using System;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Text;
using System.Windows.Forms;
using OpenCVDotNet; 	//don't forget to add opencvdotnel.dll as Reference

Declare some private variables:

C#
namespace Objcap
{
    public partial class Form1 : Form
    {
        private CVCapture capture;            //buffer for captured image from webcam
        private CVImage backgnd;              //buffer for previous image, 
					//subtracts result and captured image
        private byte threshold=30;            //threshold value = 30
        private bool only_first = false;      //flag
        private int filename = 0//to make file name change after each save 

Build a function for button1_Click: to active timer: 

C#
public Form1()
   {
       InitializeComponent();
   }
   private void button1_Click(object sender, EventArgs e)
   {
       timer1.Enabled = !(timer1.Enabled); //toggle start/stop
       if (timer1.Enabled)
           capture = new CVCapture(0);     //start camera when timer enabled
       else
           capture.Release();              //stop camera when timer disabled
   }        

The main function is in timer1_tick:

Every time Timer1 ticks (set in interval properties = 500 ->500 milliseconds), we need to compare the previous image (saved in backgnd) with current image (frame).
If there is a difference, it means there is an object in or out of your room. So save that image.

C#
private void timer1_Tick(object sender, EventArgs e)
{
    using (CVImage frame = capture.QueryFrame())  //get camera frame
    {
        frame.Resize(160, 120);             	//resize image to 160x120 pixel
        if (only_first == false)            	//only first time
        {
            backgnd = new CVImage(frame);   	//copy buffer to get the same size
            only_first = true;              	//disable flag forever
        }
        //gray scale conversion
        for (int row = 0; row < frame.Height; ++row)
        {
            for (int col = 0; col < frame.Width; ++col)
            {
                CVRgbPixel pixel = frame[row, col]; 	//get current pixel
                byte bwValue = pixel.BwValue;   	//get the gray color
                frame[row, col] = new CVRgbPixel(bwValue, bwValue, bwValue);//set current
								// pixel to gray
            }
        }
        int pixelnum = 0; // number of different pixel
        for (int row = 0; row < frame.Height; ++row)
        {
            for (int col = 0; col < frame.Width; ++col)
            {
                if (Math.Abs(frame[row, col].BwValue - 
			backgnd[row, col].BwValue) > threshold)
                {                       
                    pixelnum++;
                }
                backgnd[row, col] = frame[row, col];  	// save current frame to 
						// background frame for next time
            }
        } 
         pictureBox1.Image = frame.ToBitmap();  //display image
         int objsize = 500;  	// depends on Size of Object to be captured
                             	// if number of different pixels > 
				// objsize then save image to hard drive
        if (pixelnum > objsize)
        {
            using (CVImage frame2 = capture.QueryFrame())
            {                              
                // Capture color image
                filename++;                      	//change file name   
                string path = "D:/webcam/";        	// Path to save file
                path += DateTime.Today.Day.ToString()+"."+
                	filename.ToString() + ".jpg";   	// Full path - file name with 
						// added day saved         
                frame2.ToBitmap().Save(path, ImageFormat.Jpeg);   // Save image file 
						// with max resolution of webcam
                frame2.Resize(160, 120);               // Resize image to show on 
						// picturebox3
                pictureBox3.Image = frame2.ToBitmap();	//Show captured image
            }
        }      
         label5.Text = "Pictures: " + filename.ToString();   	// Show number of 
							// captured images
    }
    GC.Collect();
}

Points of Interest

This code runs well. You can run the program for a month if you want.
The program will save only important images with file named by saving day.

The program when run: (remember to create a folder: D:\Webcam):

02.PNG

And the result (saved files):

03.PNG

History

I tried to improve it. Now it does not cost memory any more.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)