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

使用 Kinect 传感器制作家庭监控

starIconstarIconstarIconstarIconstarIcon

5.00/5 (4投票s)

2018年3月16日

CPOL

5分钟阅读

viewsIcon

25854

downloadIcon

899

为 ThiefWatcher 应用程序添加对 Microsoft Kinect 的支持

引言

几个月前,我在本网站上发布了一篇题为《完整的防盗自制监控系统》的文章。顾名思义,这是一款用于家庭安全的软件,可以使用一个或多个摄像头、触发警报的入侵检测器、通知警报的通信设备以及用于访问警报瞬间摄像头拍摄照片的存储系统。

该系统是可扩展的,因此您可以轻松地为这些协议中的每一个编写自己的驱动程序,并几乎毫不费力地将它们添加到应用程序中。

Microsoft Kinect 传感器特别适合此应用程序。它提供彩色摄像头和红外传感器,可用作监控摄像头,并配备人体检测系统和深度传感器,可用于实现存在检测协议,通过两种不同方法触发警报。

该传感器有不同版本,Kinect SDK 也有不同版本。本文提供的代码使用 SDK 的 2.0 版本,该版本适用于 Xbox One 的 Kinect 传感器,但不适用于 Xbox 360 版本(至少在我的情况下是这样),因此,如果您想或需要使用其他 SDK 版本,您将不得不修改项目中的一个类以使其适应这些版本。

您可以下载 KinectProtocol 项目的源代码,或者仅下载必要的可执行文件,然后将存档的内容解压缩到安装 ThiefWatcher 应用程序的路径中。ThiefWatcher 应用程序可以从上述文章中下载。

要编译 KinectProtocol 项目,您必须在 ThiefWatcher 主解决方案中添加对 WatcherCommons 项目的引用。

代码使用 Visual Studio 2015 编写,语言为 C#

安装协议

Microsoft.Kinect.dllKinectProtocol.dll 文件以及包含西班牙语资源的 es 目录复制到 ThiefWatcher 目录后,您只需在 文件 菜单中使用 **安装协议** 选项选择 KinectProtocol.dll 文件,然后 KinectCamera 和 KinectTrigger 协议将添加到配置文件中。

由于传感器可以同时提供红外和彩色图像,您可以使用一个设备添加两种类型的摄像头,这样您就可以在有光或黑暗的情况下拍摄图像。要配置 Kinect 摄像头,请使用 **文件** 菜单中的 **新摄像头** 选项,然后在下拉列表中选择 **Kinect 摄像头**。

Select Kinect Camera protocol

在此情况下,无需在 **摄像头访问** 对话框中填写任何数据,将其留空即可。

Camera Access dialog box

在 **摄像头设置** 中,您只有两个选项:彩色图像或红外图像,选择其中一个并关闭对话框。

Camera Settings dialog box

最后一步是为摄像头命名,然后按保存按钮将其存储到配置文件中。

Give a name and save camera

您可以使用此窗口中的播放按钮测试摄像头。

关于触发协议,它在 **控制面板** 中进行配置。

Control Panel Window

在下拉列表中,选择 **Kinect Trigger** 作为触发协议。然后,您必须提供一个连接字符串来设置操作模式和设置。

在这种情况下,您有两个选项。使用身体检测功能非常适合有宠物的家庭,因为它只会检测到人类的存在。在这种情况下,连接字符串仅为 source=body

另一方面,您还可以使用深度传感器来检测环境中广泛的变化。使用此选项时,从 **Kinect** 获取的数据是图像中每个像素到传感器的距离(以毫米为单位)。用于检测变化的算法是计算两个连续帧之间的差异,将一个图像的每个像素减去另一个图像中对应的像素。如果距离大于某个阈值,则该差异被考虑在内。当差异的数量超过图像总像素的给定百分比时,触发器被激活。

在连接 string 中,您必须指示 source=depth,以及阈值(thres 参数)和差异百分比(sens 参数),例如:source=depth;thres=100;sens=15

Using the Code

摄像头和触发协议的实现已在关于 ThiefWatcher 应用程序的主文章中进行了说明。因此,让我们专注于 Sensor static 类,它封装了与 Kinect Sensor 交互所需的所有代码,并且是您必须修改才能将代码适配到其他 Kinect SDK 版本的唯一类。

SensorCaps enum 用于指示必须处理的输入类型,以优化工作。

[Flags]
public enum SensorCaps
{
    None = 0,
    Color = 1,
    Infrared = 2,
    Depth = 4,
    Body = 8
}

Sensor.Caps 属性中,您可以指示这些值的适当组合。

对于彩色图像,您有两个属性:Sensor.ColorFrameSize(只读),它返回图像的大小(一个 Size 结构体),以及 Sensor.ColorFrame 属性,它返回一个 Bitmap 对象,包含捕获的最后一张图像。

红外图像通过两个对应的属性进行处理:Sensor.InfraredFrameSizeSensor.InfraredFrame

通过 Sensor.BodyTracked 布尔属性执行身体检测,并且可以通过 Sensor.DepthFrame 属性以 ushort 数组的形式获取深度传感器数据。

传感器通过 OpenSensor 方法投入运行,该方法接收一个 SensorCaps 类型的参数。由于此方法由每个摄像头和触发协议调用,并且只需要启动一次传感器,因此我们通过全局变量 _instances 来计算调用该方法的实例数量。

public static void OpenSensor(SensorCaps caps)
{
    Caps |= caps;
    if (_sensor == null)
    {
        _instances = 1;
        _sensor = KinectSensor.GetDefault();
        if (!_sensor.IsOpen)
        {
            _sensor.Open();
        }
        Initialize();
        _reader = _sensor.OpenMultiSourceFrameReader(FrameSourceTypes.Color
            | FrameSourceTypes.Depth
            | FrameSourceTypes.Infrared
            | FrameSourceTypes.Body);
        _reader.MultiSourceFrameArrived +=
            new EventHandler<MultiSourceFrameArrivedEventArgs>(OnNewFrame);
    }
    else
    {
        _instances++;
    }
}

全局变量 _sensorKinectSensor 类型)在首次调用此方法时将为 null。在这种情况下,我们还在 _reader 变量中创建一个 MultiSourceFrameReader 帧读取器,它允许我们同时配置要读取的多种数据类型。在这种情况下,我们将始终读取彩色和红外图像、深度数据以及检测到的身体列表。

读取它们的方式是通过 MultiSourceFrameArrived 事件,该事件将在每次有新帧可用时触发。

停止使用 OpenSensor 打开的实例的方法是 CloseSensor,它将减少实例计数,直到达到最后一个实例,此时将系统恢复到初始状态并释放资源。

public static void CloseSensor()
{
    _instances--;
    if (_instances <= 0)
    {
        if (_sensor != null)
        {
            if (_sensor.IsOpen)
            {
                _sensor.Close();
                _reader.Dispose();
                _reader = null;
                _sensor = null;
            }
        }
        _instances = 0;
        Caps = SensorCaps.None;
    }
}

以上就是全部内容,感谢阅读!!

© . All rights reserved.