Kinect面部模型(2D)

本文是参考这篇博客高清面部帧-面部模型2D而来,对博主的资源加以整理归纳。

主要通过IFaceModel接口获得面形的94个浮点值和面部1347个特征点,其中面形的94个浮点值,官方文档有介绍面形数据描述

基本步骤如下:

  1. 创建资源与事件(主要是高清面部资源);
  2. 在高清面部临帧事件里更新面部对齐,计算面部模型,将面部模型顶点映射至彩色空间;
  3. 在刻画时画出这些点即可;

对应的主要代码:

  1. 初始化部分,也即是创建资源和事件
// 初始化Kinect
HRESULT ThisApp::init_kinect(){
    IBodyFrameSource* pBodyFrameSource = nullptr;
    IColorFrameSource* pColorFrameSource = nullptr;
    // 查找当前默认Kinect
    HRESULT hr = ::GetDefaultKinectSensor(&m_pKinect);
    // 绅士地打开Kinect
    if (SUCCEEDED(hr)){
        hr = m_pKinect->Open();
    }
    // 获取彩色帧源(ColorFrameSource)
    if (SUCCEEDED(hr)){
        hr = m_pKinect->get_ColorFrameSource(&pColorFrameSource);
    }
    // 再获取彩色帧读取器
    if (SUCCEEDED(hr)){
        hr = pColorFrameSource->OpenReader(&m_pColorFrameReader);
    }
    // 注册临帧事件
    if (SUCCEEDED(hr)){
        m_pColorFrameReader->SubscribeFrameArrived(&m_hColorFrameArrived);
    }
    // 获取骨骼帧源
    if (SUCCEEDED(hr)) {
        hr = m_pKinect->get_BodyFrameSource(&pBodyFrameSource);
    }
    // 获取骨骼帧读取器
    if (SUCCEEDED(hr)) {
        hr = pBodyFrameSource->OpenReader(&m_pBodyFrameReader);
    }
    // 注册临帧事件
    if (SUCCEEDED(hr)){
        m_pBodyFrameReader->SubscribeFrameArrived(&m_hBodyFrameArrived);
    }
    // 创建高清面部帧源
    if (SUCCEEDED(hr)){
        hr = CreateHighDefinitionFaceFrameSource(m_pKinect, &m_pHDFaceFrameSource);
    }
    // 创建面部模型构建器 之前常试从文件中读取数据
    if (SUCCEEDED(hr) && !read_fsdfile_data()){
        hr = m_pHDFaceFrameSource->OpenModelBuilder(FaceModelBuilderAttributes_None, &m_pFaceModelBuilder);
    }
    // 开始数据收集
    if (SUCCEEDED(hr) && m_pFaceModelBuilder){
        hr = m_pFaceModelBuilder->BeginFaceDataCollection();
    }
    // 创建高清面部帧读取器
    if (SUCCEEDED(hr)){
        hr = m_pHDFaceFrameSource->OpenReader(&m_pHDFaceFrameReader);
    }
    // 注册临帧事件
    if (SUCCEEDED(hr)){
        hr = m_pHDFaceFrameReader->SubscribeFrameArrived(&m_hHDFFrameArrived);
    }
    // 创建面部特征对齐
    if (SUCCEEDED(hr)){
        hr = CreateFaceAlignment(&m_pFaceAlignment);
    }
    // 创建面部模型
    if (SUCCEEDED(hr)){
        hr = CreateFaceModel(1.f, FaceShapeDeformations::FaceShapeDeformations_Count, m_ImagaRenderer.data.sd, &m_pFaceModel);
    }
    // 获取映射器
    if (SUCCEEDED(hr)){
        hr = m_pKinect->get_CoordinateMapper(&m_pMapper);
    }
    // 获取面部定点数,1347
    if (SUCCEEDED(hr)){
        hr = GetFaceModelVertexCount(&m_cFaceVerticeCount);
    }
    // 创建顶点缓存,为顶点数组分配内存
    if (SUCCEEDED(hr)){
        m_pFaceVertices = reinterpret_cast<CameraSpacePoint*>(malloc(
            (sizeof(CameraSpacePoint) + sizeof(ColorSpacePoint)) * m_cFaceVerticeCount)
            );
        if (!m_pFaceVertices) hr = E_OUTOFMEMORY;
    }
    // 修改数据,即数组转换,省去单个转换中虚函数的开销
    if (SUCCEEDED(hr)){
        const_cast<const ColorSpacePoint*>(m_ImagaRenderer.data.face_points) =
            reinterpret_cast<const ColorSpacePoint*>(m_pFaceVertices + m_cFaceVerticeCount);
        const_cast<UINT&>(m_ImagaRenderer.data.face_points_count) = m_cFaceVerticeCount;
    }
    SafeRelease(pColorFrameSource);
    SafeRelease(pBodyFrameSource);
    return hr;
}
  1. 高清面部帧的处理
// 检查高清面部帧
void ThisApp::check_hd_face_frame(){
    m_ImagaRenderer.data.tracked = FALSE;
    // 高清面部临帧事件参数
    IHighDefinitionFaceFrameArrivedEventArgs* pArgs = nullptr;
    // 高清面部帧引用
    IHighDefinitionFaceFrameReference* pHDFFrameRef = nullptr;
    // 高清面部帧
    IHighDefinitionFaceFrame* pHDFaceFrame = nullptr;

    // 获取参数
    HRESULT hr = m_pHDFaceFrameReader->GetFrameArrivedEventData(m_hHDFFrameArrived, &pArgs);
    // 获取引用
    if (SUCCEEDED(hr)) {
        hr = pArgs->get_FrameReference(&pHDFFrameRef);
    }
    // 获取高清面部帧
    if (SUCCEEDED(hr)) {
        hr = pHDFFrameRef->AcquireFrame(&pHDFaceFrame);
    }
    // 更新面部特征对齐
    if (SUCCEEDED(hr)){
        hr = pHDFaceFrame->GetAndRefreshFaceAlignmentResult(m_pFaceAlignment);
    }
    // 检查面部模型构建器
    if (SUCCEEDED(hr) && !m_bProduced){
        IFaceModelData* pFaceModelData = nullptr;
        // 检查收集状态
        hr = m_pFaceModelBuilder->get_CollectionStatus(&m_ImagaRenderer.data.co_status);
        // 检查采集状态
        if (SUCCEEDED(hr)){
            hr = m_pFaceModelBuilder->get_CaptureStatus(&m_ImagaRenderer.data.ca_status);
        }
        // 采集成功 获取数据
        if (SUCCEEDED(hr) && m_ImagaRenderer.data.co_status == FaceModelBuilderCollectionStatus_Complete){
            hr = m_pFaceModelBuilder->GetFaceData(&pFaceModelData);
        }
        // 生成面部模型
        if (SUCCEEDED(hr) && pFaceModelData){
            SafeRelease(m_pFaceModel);
            hr = pFaceModelData->ProduceFaceModel(&m_pFaceModel);
        }
        // 检查结果
        if (SUCCEEDED(hr) && pFaceModelData){
            m_bProduced = TRUE;
            // 顺便输出面形数据
            m_pFaceModel->GetFaceShapeDeformations(lengthof(m_ImagaRenderer.data.sd), m_ImagaRenderer.data.sd);
        }
        // 释放掉
        SafeRelease(pFaceModelData);
    }
    // 获取面部顶点
    if (SUCCEEDED(hr)){
        hr = m_pFaceModel->CalculateVerticesForAlignment(m_pFaceAlignment, m_cFaceVerticeCount, m_pFaceVertices);
    }
    // 成功,将面部模型顶点映射为彩色空间
    if (SUCCEEDED(hr)){
        for (UINT i = 0U; i < m_cFaceVerticeCount; ++i){
            m_pMapper->MapCameraPointsToColorSpace(m_cFaceVerticeCount, m_pFaceVertices,
                m_ImagaRenderer.data.face_points_count,
                const_cast<ColorSpacePoint*>(m_ImagaRenderer.data.face_points)
                );
        }
        m_ImagaRenderer.data.tracked = TRUE;
    }
    // 安全释放
    SafeRelease(pHDFaceFrame);
    SafeRelease(pHDFFrameRef);
    SafeRelease(pArgs);
}

txt文件中保存的是94个面部特征点的模拟值,比如鼻子的高度模拟值等等,详细的官方SDK还未给出解释,对同一个人进行多次采样会发现,数据波动较大,解决办法可以是多次采样抵消,比如平均法。

展开阅读全文

没有更多推荐了,返回首页