65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 OpenCVdotNet 在网络摄像头上捕获对象

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.71/5 (10投票s)

2009 年 7 月 27 日

CPOL

1分钟阅读

viewsIcon

78891

downloadIcon

5826

该程序使用网络摄像头,当图像发生变化时拍摄物体照片。

介绍 

此代码基于博客中的“Webcam Simple Frame Difference”(网络摄像头简单帧差):http://haryoktav.wordpress.com/2009/02/28/webcam-c-simple-frame-difference/

目标 

  • 使用网络摄像头监控房间
  • 无需保存长时间的视频,只需捕捉显示变化的图像
  • 易于查看结果,无需查看整个长时间的视频(可能没有任何变化) 

背景

此代码使用 OpenCVdotNet 库来

  1. 下载并安装 OpenCV 1.0 - http://sourceforge.net/projects/opencv/ (不要安装 1.1)
  2. 下载并安装 OpenCVDotNet 0.7 - http://code.google.com/p/opencvdotnet/

我使用 Visual Studio 2005 设计了一个如下所示的窗体

01.PNG

该窗体具有 2 个PictureBox,用于显示当前图像和捕获的图像;1 个 Timer,用于重复检查房间内图像的差异,并在需要时保存到文件;1 个按钮用于激活 Timer,1 个标签用于显示捕获的图像数量。

使用代码 

只有一个窗体,代码如下所示: 

安装 OpenCVDotnet 库后,将其添加到项目中

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

声明一些 private 变量

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 

构建一个 button1_Click 函数:用于激活 Timer: 

     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
        }        

主要函数在 timer1_tick

每次 Timer1 触发(在间隔属性中设置 = 500 -> 500 毫秒),我们需要将上一张图像(保存在 backgnd 中)与当前图像(frame)进行比较。
如果存在差异,则意味着房间内有物体进入或离开。因此,保存该图像。

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();
}

关注点

此代码运行良好。您可以运行该程序一个月,如果需要的话。
该程序将仅保存重要的图像,文件名称以保存日期命名。

程序运行时:(请记住创建一个文件夹:D:\Webcam

02.PNG

以及结果(保存的文件)

03.PNG

历史

我尝试改进它。现在它不再占用内存了。

© . All rights reserved.