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

摄像头报警器 2.0 - 基于网络摄像头的报警系统

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.86/5 (33投票s)

2010年5月16日

CPOL

3分钟阅读

viewsIcon

89479

downloadIcon

9514

为预算有限的人们提供的简单报警系统..

main.jpg

只是一个小项目..

大约 4 年前,我用 VB6 编写了此程序的原始版本,并将其发布为免费软件(可能仍然在野外流传..),当我大约两年前开始迁移我的技能时,我决定这是学习 C# 的一个很好的入门应用程序。 所以,这个未完成的版本已经在我的开发机器上的一个文件夹中存放了一段时间,只是等待一些调整 - 前几天我终于有时间完成了。 我认为这是一个很好的目标免费软件,因为不幸的是,我们中的许多人一生中的某个时刻都遭受过被盗的厄运,学生、年轻的上班族或公寓里的人可能无法负担或安装合适的报警系统。

我使用 Creative 5.1 扬声器系统,当放大器调到最大时,它发出的警报声至少和传统的报警系统一样大,并且可能会导致入侵者逃跑,而不是试图找到来源并解除警报。

原始版本使用了 *avicap32.dll* 库,它在我的旧 Logitech 摄像头上运行良好,但在较新的设备上无法使用(已经在 Acer 笔记本电脑摄像头和 MS Lifecam 上进行了测试)。 在这一点上,我意识到我必须使用 DirectShow 库从更广泛的输入设备捕获视频。 在 CodeProject 上搜索发现了 Andrew Kirillov 的 运动检测 项目。 我删除了对 AForge 库的依赖,并重新设计了 AVI 读取器/写入器类,但 DirectShow 包装器和检测算法是他的工作(感谢 Andrew)。

亮点

当应用程序加载时,它会通过枚举已安装的编解码器来测试 WMV AVI 录制编解码器; 如果未找到,则会启动一个对话框,要求用户安装它。 安装可执行文件是一个嵌入式资源,它从资源程序集中提取并在临时目录中重新创建为文件,然后使用 ShellExecute API 启动。

private void codecTest()
{
    FilterCollection filters = new FilterCollection(FilterCategory.VideoCompressorCategory);
    bool found = false;
    foreach (Filter filter in filters)
    {
        found = filter.Name.Contains("Media Video 9");
        if (found)
            break;
    }
    if (!found)
    {
        if (MessageBox.Show("The video capture feature requires the Microsoft " + 
            "WMV9 codec. Do you want to install this now?", 
            "Codec Installation Required",
            MessageBoxButtons.OKCancel, 
            MessageBoxIcon.Question) == DialogResult.OK)
        {
            executeCodec();
        }
        else
        {
            _bCanRecord = false;
        }
    }
}

private bool executeCodec()
{
    try
    {
        Assembly assembly = Assembly.GetExecutingAssembly();
        using (Stream stream = assembly.GetManifestResourceStream(
                               "CamAlarm.Resources.wmv9VCMsetup.exe"))
        {
            if (stream != null)
            {
                BinaryReader br = new BinaryReader(stream);
                using (FileStream fs = new FileStream(
                       Environment.GetEnvironmentVariable("TEMP") + 
                       "\\wmv9VCMsetup.exe", FileMode.Create))
                {
                    BinaryWriter bw = new BinaryWriter(fs);
                    byte[] bt = new byte[stream.Length];
                    stream.Read(bt, 0, bt.Length);
                    bw.Write(bt);
                    br.Close();
                    bw.Close();
                    fs.Close();
                }
                executeProgram(Environment.GetEnvironmentVariable("TEMP") + 
                               "\\wmv9VCMsetup.exe");
            }
        }
        return true;
    }
    catch { return false; }
}

运行一个计时器,等待摄像头对焦,然后激活控制面板。 诸如密钥代码和选项控制状态之类的设置存储在应用程序的默认属性中。 首次运行时,或者如果密钥代码属性被清除,则“启动/停止”按钮充当密钥代码设置按钮。 应用程序中使用的声音是 System.Media.SoundPlayer 类的实例,在应用程序初始化时实例化并加载声音文件

private void loadWarning()
{
    if (_cWarningSound != null)
        _cWarningSound.Dispose();
    _cWarningSound = new SoundPlayer(CamAlarm.Resource1.beep);
    _cWarningSound.Load();
}

使用自定义计时器类定期轮询摄像头的运动触发状态; 如果发生运动,则会触发警报计时器,该计时器将循环直到警报被停用或发生最大警报超时

private void _cAlarmTimer_Tick(object sender)
{
    // timer starts 5 states: standby, armed, arming, triggered, sounding
    //1) if arming warning period elapses, optional beeps
    //2) if not arming, warning sounds and counts to min elapse
    //3) if min elapse and _activetick over threshhold, loops again
    //4) if standby -stop timer
    if (_eAlarmState == AlarmState.Arming)
    {
        _iTimerTick++;
        if (_iTimerTick > stringToInt(txtArmingDelay.Text))
            armAlarm();
        else
            updateStatus();
    }
    else if (_eAlarmState == AlarmState.Armed)
    {
        if (_iActiveTick > 5)
            triggerAlarm();
    }
    else if (_eAlarmState == AlarmState.Sounding)
    {
        _iTimerTick++;
        if (_iTimerTick > stringToInt(txtDuration.Text))
        {
            if (_iActiveTick < 5)
                disarmAlarm();
            else
                //loop again
                soundAlarm();
        }
        else
        {
            soundAlarm();
        }
    }
    else if (_eAlarmState == AlarmState.Standby)
    {
        stopAlarm();
    }
    else if (_eAlarmState == AlarmState.Triggered)
    {
        _iTimerTick++;
        if (_iTimerTick > stringToInt(txtAlarmDelay.Text))
        {
            soundAlarm();
        }
        else
        {
            if (!chkSilent.Checked)
                playWarning();
        }
    }
}

当警报处于 启动 模式时,除了键盘和停止开关之外的所有内容都被禁用。 这是通过禁用包含控件的 GroupBox 来完成的。 还需要停用主窗体关闭按钮。 这可以通过取消 FormClosing 事件中的窗体退出,以及使用 GetSystemMenu/EnableMenuItem API 禁用关闭按钮来完成

private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
{
    if (_bCloseDisabled)
    {
        e.Cancel = true;
    }
    else
    {
        closeCamera();
        closeFile();
        saveSettings();
        if (_cAlarmTimer != null)
            _cAlarmTimer.Dispose();
    }
}

private void enableClose(bool enable)
{
    if (enable)
        EnableMenuItem(GetSystemMenu(this.Handle, false), SC_CLOSE, MF_ENABLED);
    else
        EnableMenuItem(GetSystemMenu(this.Handle, false), SC_CLOSE, MF_GRAYED);
    
    _bCloseDisabled = !enable;
}

总而言之,这是一种相当简单的方法; 尽管我在代码中的注释并不多,但它相当简单..

使用应用程序..

将摄像头视图保持在宠物不会触发它的地方,并远离窗户。 将扬声器的音量调大,并通过混音器调整应用程序音量; CamAlarm 有一个在警报激活时将音量推到最大的选项,但如果主音量较低,这毫无意义。

好吧.. 享受吧! 如果您发现任何错误,请务必留言。

更改日志

2010年5月17日

  • 首次加载帮助页面会在用户应用程序文件夹中创建页面。
  • 触发警告蜂鸣声后,提高警报音量。
  • 修复了捕获视频时的锁定,在 *Camera.cs* 中从 Monitor.Enter 更改为 TryEnter
  • 为“清除”和“视频”按钮添加了工具提示。
  • 在激活警报时,为禁用的项目添加了菜单按钮。

2010 年 6 月 16 日

  • 修复了 executeCodec() 中的编解码器 URL。
  • 修复了设备选择窗体中禁用的“确定”按钮。
© . All rights reserved.