Skip to content

使用 Kinect 及其他兼容 OpenNI 的深度传感器

兼容 OpenNI 的深度传感器(Kinect、XtionPRO 等)通过 VideoCapture 类获得支持。借助熟悉的 VideoCapture 接口,可以获取深度图、BGR 图像以及其他一些格式的输出。

要在 OpenCV 中使用深度传感器,你需要完成以下预备步骤:

  1. 安装 OpenNI 库(从这里获取)以及用于 OpenNI 的 PrimeSensor 模块(从这里获取)。安装应按照这些产品说明书中列出的默认目录进行,例如:

    OpenNI:
    Linux & MacOSX:
    Libs into: /usr/lib
    Includes into: /usr/include/ni
    Windows:
    Libs into: c:/Program Files/OpenNI/Lib
    Includes into: c:/Program Files/OpenNI/Include
    PrimeSensor Module:
    Linux & MacOSX:
    Bins into: /usr/bin
    Windows:
    Bins into: c:/Program Files/Prime Sense/Sensor/Bin

    如果其中一种或两种产品安装到了其他目录,用户应当修改相应的 CMake 变量 OPENNI_LIB_DIR、OPENNI_INCLUDE_DIR 或/和 OPENNI_PRIME_SENSOR_MODULE_BIN_DIR。

  2. 在 CMake 中设置 WITH_OPENNI 标志,将 OpenCV 配置为支持 OpenNI。如果在安装目录中找到了 OpenNI,OpenCV 将连同 OpenNI 库一起编译(参见 CMake 日志中的 OpenNI 状态),但可能无法找到 PrimeSensor 模块(参见 CMake 日志中的 OpenNI PrimeSensor Modules 状态)。没有 PrimeSensor 模块时,OpenCV 仍能随 OpenNI 库成功编译,但 VideoCapture 对象将无法从 Kinect 传感器抓取数据。

  3. 编译 OpenCV。

VideoCapture 可以获取以下数据:

  1. 来自深度生成器的数据:

    • CAP_OPENNI_DEPTH_MAP —— 以 mm 为单位的深度值(CV_16UC1)
    • CAP_OPENNI_POINT_CLOUD_MAP —— 以米为单位的 XYZ 坐标(CV_32FC3)
    • CAP_OPENNI_DISPARITY_MAP —— 以像素为单位的视差(CV_8UC1)
    • CAP_OPENNI_DISPARITY_MAP_32F —— 以像素为单位的视差(CV_32FC1)
    • CAP_OPENNI_VALID_DEPTH_MASK —— 有效像素掩码(未被遮挡、未被阴影遮蔽等)(CV_8UC1)
  2. 来自 BGR 图像生成器的数据:

    • CAP_OPENNI_BGR_IMAGE —— 彩色图像(CV_8UC3)
    • CAP_OPENNI_GRAY_IMAGE —— 灰度图像(CV_8UC1)

要从深度传感器获取深度图,使用 VideoCapture::operator>>,例如:

VideoCapture capture( CAP_OPENNI );
for(;;)
{
Mat depthMap;
capture >> depthMap;
if( waitKey( 30 ) >= 0 )
break;
}

要获取多路数据图,使用 VideoCapture::grab 和 VideoCapture::retrieve,例如:

VideoCapture capture(0); // or CAP_OPENNI
for(;;)
{
Mat depthMap;
Mat bgrImage;
capture.grab();
capture.retrieve( depthMap, CAP_OPENNI_DEPTH_MAP );
capture.retrieve( bgrImage, CAP_OPENNI_BGR_IMAGE );
if( waitKey( 30 ) >= 0 )
break;
}

要设置和获取传感器数据生成器的某些属性,分别使用 VideoCapture::set 和 VideoCapture::get 方法,例如:

VideoCapture capture( CAP_OPENNI );
capture.set( CAP_OPENNI_IMAGE_GENERATOR_OUTPUT_MODE, CAP_OPENNI_VGA_30HZ );
cout << "FPS " << capture.get( CAP_OPENNI_IMAGE_GENERATOR+CAP_PROP_FPS ) << endl;

由于支持两类传感器数据生成器(图像生成器和深度生成器),因此有两个标志用于设置/获取所需生成器的属性:

  • CAP_OPENNI_IMAGE_GENERATOR —— 用于访问图像生成器属性的标志。
  • CAP_OPENNI_DEPTH_GENERATOR —— 用于访问深度生成器属性的标志。如果属性的两个可能值都未设置,则默认假定使用此标志值。

一些深度传感器(例如 XtionPRO)没有图像生成器。要检查这一点,可以获取 CAP_OPENNI_IMAGE_GENERATOR_PRESENT 属性:

bool isImageGeneratorPresent = capture.get( CAP_PROP_OPENNI_IMAGE_GENERATOR_PRESENT ) != 0; // or == 1

指定所需生成器类型的标志必须与具体的生成器属性结合使用。通过 OpenNI 接口可用的相机支持以下属性:

  • 对于图像生成器:

    • CAP_PROP_OPENNI_OUTPUT_MODE —— 支持三种输出模式:默认使用的 CAP_OPENNI_VGA_30HZ(图像生成器以 VGA 分辨率、30 FPS 返回图像)、CAP_OPENNI_SXGA_15HZ(图像生成器以 SXGA 分辨率、15 FPS 返回图像)以及 CAP_OPENNI_SXGA_30HZ(图像生成器以 SXGA 分辨率、30 FPS 返回图像,该模式由 XtionPRO Live 支持);深度生成器的数据图始终为 VGA 分辨率。
  • 对于深度生成器:

    • CAP_PROP_OPENNI_REGISTRATION —— 通过改变深度生成器的视点(当标志为 “on” 时)将重映射的深度图注册到图像图的标志,或(当标志为 “off” 时)将该视点恢复为正常视点。注册过程产生的图像是像素对齐的,这意味着图像中的每个像素都与深度图像中的一个像素对齐。

      以下属性仅支持获取:

    • CAP_PROP_OPENNI_FRAME_MAX_DEPTH —— Kinect 支持的最大深度,以 mm 为单位。

    • CAP_PROP_OPENNI_BASELINE —— 基线值,以 mm 为单位。

    • CAP_PROP_OPENNI_FOCAL_LENGTH —— 焦距,以像素为单位。

    • CAP_PROP_FRAME_WIDTH —— 帧宽度,以像素为单位。

    • CAP_PROP_FRAME_HEIGHT —— 帧高度,以像素为单位。

    • CAP_PROP_FPS —— 帧率,以 FPS 为单位。

  • 一些典型的「生成器类型 + 属性」标志组合被定义为单一标志:

    • CAP_OPENNI_IMAGE_GENERATOR_OUTPUT_MODE = CAP_OPENNI_IMAGE_GENERATOR + CAP_PROP_OPENNI_OUTPUT_MODE
    • CAP_OPENNI_DEPTH_GENERATOR_BASELINE = CAP_OPENNI_DEPTH_GENERATOR + CAP_PROP_OPENNI_BASELINE
    • CAP_OPENNI_DEPTH_GENERATOR_FOCAL_LENGTH = CAP_OPENNI_DEPTH_GENERATOR + CAP_PROP_OPENNI_FOCAL_LENGTH
    • CAP_OPENNI_DEPTH_GENERATOR_REGISTRATION = CAP_OPENNI_DEPTH_GENERATOR + CAP_PROP_OPENNI_REGISTRATION

更多信息请参考 opencv/samples/cpp 目录下的使用示例 videocapture_openni.cpp。