带计划功能的摄像头应用程序
一个具有计划功能的摄像头应用程序,用于捕捉视频。
引言
这个应用程序使用摄像头捕捉视频到文件(.avi)。它还具有计划录制时间的功能,可以自动开始视频捕捉。我们可以使用任何摄像头,并设置各种属性来配合摄像头使用,例如视频大小、源和摄像头本身的设置。
背景
这段代码的基础是使用 avicap32 DLL。使用这个 DLL,你可以连接到摄像头并设置其设置。我们使用 SendMessage
向摄像头发送消息,例如连接和捕捉视频。关于这个主题已经有一些现有的文章,但我会尝试把它写得非常简单。
Using the Code
我们需要做的第一件事是设置我们的捕捉控件。我使用一个简单的 PictureBox
控件来托管摄像头的输出。
这只需要一行代码即可完成
mCapHwnd = capCreateCaptureWindowA("WebCap", WS_VISIBLE | WS_CHILD, 0, 0,
this.pictureBox1.Width, this.pictureBox1.Height,
this.pictureBox1.Handle.ToInt32(), 0);
接下来我们需要连接到我们的摄像头
SendMessage(mCapHwnd, WM_CAP_CONNECT, 0, 0);
接下来我们需要几行代码来设置摄像头设置
//Set the frame rate for the WebCam
SendMessage(mCapHwnd, WM_CAP_SET_PREVIEWRATE, 66, 0);
//Set the preview flag to true
SendMessage(mCapHwnd, WM_CAP_SET_PREVIEW, 1, 0);
//Set thisif you want to control the video compression for the output video
SendMessage(mCapHwnd, WM_CAP_DLG_VIDEOCOMPRESSION, 0, 0);
为了捕捉视频,你必须设置各种视频属性,例如是否要捕捉音频等。我们需要使用 CAPTUREPARMS
结构来实现这一点。你可以在源代码下载中找到它的声明。下一行使用 CAPTUREPARMS
结构来设置我们想要的摄像头设置
SendMessage2(mCapHwnd, WM_CAP_SET_SEQUENCE_SETUP,
new IntPtr(Marshal.SizeOf(CaptureParams)),ref CaptureParams);
CAPTUREPARMS
结构中的一个重要参数是 fYield
。如果希望在与表单不同的线程中捕捉视频,请将其设置为 true (1)。
接下来,我们想将视频捕捉到 PictureBox
控件中。我们通过调用此消息来做到这一点
SendMessage(mCapHwnd, WM_CAP_GRAB_FRAME_NOSTOP, 0, 0);
我们需要在计时器滴答事件中调用此行,以便获得连续的视频。我使用了 System.Threading.Timer
来实现这一点。
private void DoIt()
{
System.Threading.Timer t = null;
t = new System.Threading.Timer(delegate(object state)
{
t.Dispose();
CaptureImage();
DoIt();
}, null, 66, -1);
}
接下来我们需要将视频捕捉到文件(默认文件是使用 avicap32.dll 的 .avi 文件)
string file = DateTime.Now.ToShortDateString().Replace('/','_') +
"_" + DateTime.Now.ToLongTimeString().Replace(':','_') + ".avi";
SendMessageA(mCapHwnd, WM_CAP_FILE_SET_CAPTURE_FILEA, 0, dir +
Path.DirectorySeparatorChar + file);
SendMessage(mCapHwnd, WM_CAP_SEQUENCE, 0, 0);
接下来的两个方法用于配置摄像头源和格式。只有在你不想使用摄像头的默认设置时才使用它们。
private void btnConfig_Click(object sender, EventArgs e)
{
SendMessage(mCapHwnd, WM_CAP_DLG_VIDEOSOURCE, 0, 0);
}
private void btnFormat_Click(object sender, EventArgs e)
{
SendMessage(mCapHwnd, WM_CAP_DLG_VIDEOFORMAT, 0, 0);
}
代码的计划部分非常简单。我使用 app.config 文件来存储我想要开始捕捉的时间,并使用 Timer
控件来检查是否是开始捕捉的时间。你可以在源代码下载中查看此内容。
好的,剩下的唯一事情就是在完成工作后断开与摄像头的连接
SendMessage(mCapHwnd, WM_CAP_DISCONNECT, 0, 0);
就这样了。希望我成功地保持了它的简单性。
关注点
这是我第一次使用摄像头编写应用程序。你也可以使用 DirectX 来做同样的事情,但我发现这种方法既快速又简单。