Kinect面部模型(2D)

来源:互联网 发布:照片换发型软件 编辑:程序博客网 时间:2024/05/17 07:17

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

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

基本步骤如下:

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

对应的主要代码:

  1. 初始化部分,也即是创建资源和事件
// 初始化KinectHRESULT 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还未给出解释,对同一个人进行多次采样会发现,数据波动较大,解决办法可以是多次采样抵消,比如平均法。

0 0