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:
- download and install OpenCV 1.0 - http://sourceforge.net/projects/opencv/ (do not install 1.1)
- download and install OpenCVDotNet 0.7 - http://code.google.com/p/opencvdotnet/
I use Visual Studio 2005 to design a form like this:
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:
using System;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Text;
using System.Windows.Forms;
using OpenCVDotNet;
Declare some private
variables:
namespace Objcap
{
public partial class Form1 : Form
{
private CVCapture capture;
private CVImage backgnd;
private byte threshold=30;
private bool only_first = false;
private int filename = 0;
Build a function for button1_Click
: to active timer:
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
timer1.Enabled = !(timer1.Enabled);
if (timer1.Enabled)
capture = new CVCapture(0);
else
capture.Release();
}
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.
private void timer1_Tick(object sender, EventArgs e)
{
using (CVImage frame = capture.QueryFrame())
{
frame.Resize(160, 120);
if (only_first == false)
{
backgnd = new CVImage(frame);
only_first = true;
}
for (int row = 0; row < frame.Height; ++row)
{
for (int col = 0; col < frame.Width; ++col)
{
CVRgbPixel pixel = frame[row, col];
byte bwValue = pixel.BwValue;
frame[row, col] = new CVRgbPixel(bwValue, bwValue, bwValue);
}
}
int pixelnum = 0;
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];
}
}
pictureBox1.Image = frame.ToBitmap();
int objsize = 500;
if (pixelnum > objsize)
{
using (CVImage frame2 = capture.QueryFrame())
{
filename++;
string path = "D:/webcam/";
path += DateTime.Today.Day.ToString()+"."+
filename.ToString() + ".jpg";
frame2.ToBitmap().Save(path, ImageFormat.Jpeg);
frame2.Resize(160, 120);
pictureBox3.Image = frame2.ToBitmap();
}
}
label5.Text = "Pictures: " + filename.ToString();
}
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):
And the result (saved files):
History
I tried to improve it. Now it does not cost memory any more.