From a774441fde00f0ce6c8387339c786e9e2f42f088 Mon Sep 17 00:00:00 2001 From: Stéphane Lenclud Date: Thu, 31 Jan 2019 10:32:17 +0100 Subject: Kinect: First draft. --- tracker-kinect-face/CMakeLists.txt | 6 + tracker-kinect-face/lang/nl_NL.ts | 22 ++ tracker-kinect-face/lang/ru_RU.ts | 22 ++ tracker-kinect-face/lang/stub.ts | 22 ++ tracker-kinect-face/lang/zh_CN.ts | 22 ++ tracker-kinect-face/test.cpp | 45 ++++ tracker-kinect-face/test.h | 28 +++ tracker-kinect-face/test.ui | 65 ++++++ tracker-kinect-face/test_dialog.cpp | 3 + tracker-kinect-face/tracker.cpp | 451 ++++++++++++++++++++++++++++++++++++ tracker-kinect-face/tracker.h | 90 +++++++ 11 files changed, 776 insertions(+) create mode 100644 tracker-kinect-face/CMakeLists.txt create mode 100644 tracker-kinect-face/lang/nl_NL.ts create mode 100644 tracker-kinect-face/lang/ru_RU.ts create mode 100644 tracker-kinect-face/lang/stub.ts create mode 100644 tracker-kinect-face/lang/zh_CN.ts create mode 100644 tracker-kinect-face/test.cpp create mode 100644 tracker-kinect-face/test.h create mode 100644 tracker-kinect-face/test.ui create mode 100644 tracker-kinect-face/test_dialog.cpp create mode 100644 tracker-kinect-face/tracker.cpp create mode 100644 tracker-kinect-face/tracker.h diff --git a/tracker-kinect-face/CMakeLists.txt b/tracker-kinect-face/CMakeLists.txt new file mode 100644 index 00000000..d139b445 --- /dev/null +++ b/tracker-kinect-face/CMakeLists.txt @@ -0,0 +1,6 @@ + +if(DEFINED ENV{KINECTSDK20_DIR}) + otr_module(tracker-kinect-face) + target_include_directories(opentrack-tracker-kinect-face SYSTEM PUBLIC $ENV{KINECTSDK20_DIR}inc) + target_link_libraries(opentrack-tracker-kinect-face $ENV{KINECTSDK20_DIR}lib/x86/kinect20.lib $ENV{KINECTSDK20_DIR}lib/x86/kinect20.face.lib) +endif() diff --git a/tracker-kinect-face/lang/nl_NL.ts b/tracker-kinect-face/lang/nl_NL.ts new file mode 100644 index 00000000..b6139882 --- /dev/null +++ b/tracker-kinect-face/lang/nl_NL.ts @@ -0,0 +1,22 @@ + + + + + test_metadata + + Kinect Face + + + + + test_ui + + Sine wave + + + + Pressing "Abort" will immediately crash the application. + + + + diff --git a/tracker-kinect-face/lang/ru_RU.ts b/tracker-kinect-face/lang/ru_RU.ts new file mode 100644 index 00000000..52aab9f3 --- /dev/null +++ b/tracker-kinect-face/lang/ru_RU.ts @@ -0,0 +1,22 @@ + + + + + test_metadata + + Kinect Face + + + + + test_ui + + Sine wave + + + + Pressing "Abort" will immediately crash the application. + + + + diff --git a/tracker-kinect-face/lang/stub.ts b/tracker-kinect-face/lang/stub.ts new file mode 100644 index 00000000..84a3c6af --- /dev/null +++ b/tracker-kinect-face/lang/stub.ts @@ -0,0 +1,22 @@ + + + + + test_metadata + + Kinect Face + + + + + test_ui + + Sine wave + + + + Pressing "Abort" will immediately crash the application. + + + + diff --git a/tracker-kinect-face/lang/zh_CN.ts b/tracker-kinect-face/lang/zh_CN.ts new file mode 100644 index 00000000..84a3c6af --- /dev/null +++ b/tracker-kinect-face/lang/zh_CN.ts @@ -0,0 +1,22 @@ + + + + + test_metadata + + Kinect Face + + + + + test_ui + + Sine wave + + + + Pressing "Abort" will immediately crash the application. + + + + diff --git a/tracker-kinect-face/test.cpp b/tracker-kinect-face/test.cpp new file mode 100644 index 00000000..c1ada177 --- /dev/null +++ b/tracker-kinect-face/test.cpp @@ -0,0 +1,45 @@ +/* Copyright (c) 2014, Stanislaw Halik + + * Permission to use, copy, modify, and/or distribute this + * software for any purpose with or without fee is hereby granted, + * provided that the above copyright notice and this permission + * notice appear in all copies. + */ + +#include "test.h" +#include "tracker.h" +#include "api/plugin-api.hpp" +#include "compat/math-imports.hpp" + +#include + +#include +#include + + +test_dialog::test_dialog() +{ + ui.setupUi(this); + + connect(ui.buttonBox, &QDialogButtonBox::clicked, [this](QAbstractButton* btn) { + if (btn == ui.buttonBox->button(QDialogButtonBox::Abort)) + // NOLINTNEXTLINE + *(volatile int*)nullptr = 0; + }); + + connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); + connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); +} + +void test_dialog::doOK() +{ + //s.b->save(); + close(); +} + +void test_dialog::doCancel() +{ + close(); +} + +OPENTRACK_DECLARE_TRACKER(KinectFaceTracker, test_dialog, test_metadata) diff --git a/tracker-kinect-face/test.h b/tracker-kinect-face/test.h new file mode 100644 index 00000000..2e105ae3 --- /dev/null +++ b/tracker-kinect-face/test.h @@ -0,0 +1,28 @@ +#pragma once +#include "ui_test.h" +#include "compat/macros.hpp" +#include "api/plugin-api.hpp" + + +class test_dialog : public ITrackerDialog +{ + Q_OBJECT + + Ui::test_ui ui; +public: + test_dialog(); + void register_tracker(ITracker *) override {} + void unregister_tracker() override {} +private slots: + void doOK(); + void doCancel(); +}; + +class test_metadata : public Metadata +{ + Q_OBJECT + + QString name() { return tr("Kinect Face"); } + QIcon icon() { return QIcon(":/images/opentrack.png"); } +}; + diff --git a/tracker-kinect-face/test.ui b/tracker-kinect-face/test.ui new file mode 100644 index 00000000..509eb819 --- /dev/null +++ b/tracker-kinect-face/test.ui @@ -0,0 +1,65 @@ + + + test_ui + + + Qt::NonModal + + + + 0 + 0 + 278 + 58 + + + + Sine wave + + + + ../gui/images/opentrack.png../gui/images/opentrack.png + + + Qt::LeftToRight + + + false + + + + + + + 0 + 0 + + + + Pressing "Abort" will immediately crash the application. + + + + + + + + 0 + 0 + + + + QDialogButtonBox::Abort|QDialogButtonBox::Close + + + + + + + + + startEngineClicked() + stopEngineClicked() + cameraSettingsClicked() + + diff --git a/tracker-kinect-face/test_dialog.cpp b/tracker-kinect-face/test_dialog.cpp new file mode 100644 index 00000000..5d33555b --- /dev/null +++ b/tracker-kinect-face/test_dialog.cpp @@ -0,0 +1,3 @@ +#include "test.h" +#include "api/plugin-api.hpp" + diff --git a/tracker-kinect-face/tracker.cpp b/tracker-kinect-face/tracker.cpp new file mode 100644 index 00000000..3fe3b8cc --- /dev/null +++ b/tracker-kinect-face/tracker.cpp @@ -0,0 +1,451 @@ + + +#include "tracker.h" + + +const double KinectFaceTracker::incr[6] = +{ + 50, 40, 80, + 70, 5, 3 +}; + +KinectFaceTracker::KinectFaceTracker(): + m_pKinectSensor(nullptr), + m_pCoordinateMapper(nullptr), + m_pColorFrameReader(nullptr), + m_pColorRGBX(nullptr), + m_pBodyFrameReader(nullptr) + +{ + for (int i = 0; i < BODY_COUNT; i++) + { + m_pFaceFrameSources[i] = nullptr; + m_pFaceFrameReaders[i] = nullptr; + } + + // create heap storage for color pixel data in RGBX format + m_pColorRGBX = new RGBQUAD[cColorWidth * cColorHeight]; +} + +KinectFaceTracker::~KinectFaceTracker() +{ + if (m_pColorRGBX) + { + delete[] m_pColorRGBX; + m_pColorRGBX = nullptr; + } + + // clean up Direct2D + //SafeRelease(m_pD2DFactory); + + // done with face sources and readers + for (int i = 0; i < BODY_COUNT; i++) + { + SafeRelease(m_pFaceFrameSources[i]); + SafeRelease(m_pFaceFrameReaders[i]); + } + + // done with body frame reader + SafeRelease(m_pBodyFrameReader); + + // done with color frame reader + SafeRelease(m_pColorFrameReader); + + // done with coordinate mapper + SafeRelease(m_pCoordinateMapper); + + // close the Kinect Sensor + if (m_pKinectSensor) + { + m_pKinectSensor->Close(); + } + + SafeRelease(m_pKinectSensor); +} + +module_status KinectFaceTracker::start_tracker(QFrame*) +{ + t.start(); + + if (SUCCEEDED(InitializeDefaultSensor())) + { + return status_ok(); + } + + return error("Kinect init failed!"); +} + +#ifdef EMIT_NAN +# include +#endif + +void KinectFaceTracker::data(double *data) +{ + const double dt = t.elapsed_seconds(); + t.start(); + +#ifdef EMIT_NAN + if ((rand() % 4) == 0) + { + for (int i = 0; i < 6; i++) + data[i] = 0. / 0.; + } + else +#endif + for (int i = 0; i < 6; i++) + { + double x = last_x[i] + incr[i] * dt; + if (x > 180) + x = -360 + x; + else if (x < -180) + x = 360 + x; + x = copysign(fmod(fabs(x), 360), x); + last_x[i] = x; + + if (i >= 3) + { + data[i] = x; + } + else + { + data[i] = x * 100 / 180.; + } + } + + + Update(); + //TODO: check if data is valid + data[0] = 0; + data[1] = 0; + data[2] = 0; + ExtractFaceRotationInDegrees(&faceRotation,&data[3], &data[4], &data[5]); + +} + + +/// +/// Converts rotation quaternion to Euler angles +/// And then maps them to a specified range of values to control the refresh rate +/// +/// face rotation quaternion +/// rotation about the X-axis +/// rotation about the Y-axis +/// rotation about the Z-axis +void KinectFaceTracker::ExtractFaceRotationInDegrees(const Vector4* pQuaternion, double* pYaw, double* pPitch, double* pRoll) +{ + double x = pQuaternion->x; + double y = pQuaternion->y; + double z = pQuaternion->z; + double w = pQuaternion->w; + + // convert face rotation quaternion to Euler angles in degrees + double dPitch, dYaw, dRoll; + dPitch = atan2(2 * (y * z + w * x), w * w - x * x - y * y + z * z) / M_PI * 180.0; + dYaw = asin(2 * (w * y - x * z)) / M_PI * 180.0; + dRoll = atan2(2 * (x * y + w * z), w * w + x * x - y * y - z * z) / M_PI * 180.0; + + // clamp rotation values in degrees to a specified range of values to control the refresh rate + /* + double increment = c_FaceRotationIncrementInDegrees; + *pPitch = static_cast(floor((dPitch + increment/2.0 * (dPitch > 0 ? 1.0 : -1.0)) / increment) * increment); + *pYaw = static_cast(floor((dYaw + increment/2.0 * (dYaw > 0 ? 1.0 : -1.0)) / increment) * increment); + *pRoll = static_cast(floor((dRoll + increment/2.0 * (dRoll > 0 ? 1.0 : -1.0)) / increment) * increment); + */ + + *pPitch = dPitch; + *pYaw = dYaw; + *pRoll = dRoll; + + +} + + +/// +/// Initializes the default Kinect sensor +/// +/// S_OK on success else the failure code +HRESULT KinectFaceTracker::InitializeDefaultSensor() +{ + HRESULT hr; + + hr = GetDefaultKinectSensor(&m_pKinectSensor); + if (FAILED(hr)) + { + return hr; + } + + if (m_pKinectSensor) + { + // Initialize Kinect and get color, body and face readers + IColorFrameSource* pColorFrameSource = nullptr; + IBodyFrameSource* pBodyFrameSource = nullptr; + + hr = m_pKinectSensor->Open(); + + if (SUCCEEDED(hr)) + { + hr = m_pKinectSensor->get_CoordinateMapper(&m_pCoordinateMapper); + } + + if (SUCCEEDED(hr)) + { + hr = m_pKinectSensor->get_ColorFrameSource(&pColorFrameSource); + } + + if (SUCCEEDED(hr)) + { + hr = pColorFrameSource->OpenReader(&m_pColorFrameReader); + } + + if (SUCCEEDED(hr)) + { + hr = m_pKinectSensor->get_BodyFrameSource(&pBodyFrameSource); + } + + if (SUCCEEDED(hr)) + { + hr = pBodyFrameSource->OpenReader(&m_pBodyFrameReader); + } + + if (SUCCEEDED(hr)) + { + // create a face frame source + reader to track each body in the fov + for (int i = 0; i < BODY_COUNT; i++) + { + if (SUCCEEDED(hr)) + { + // create the face frame source by specifying the required face frame features + hr = CreateFaceFrameSource(m_pKinectSensor, 0, c_FaceFrameFeatures, &m_pFaceFrameSources[i]); + } + if (SUCCEEDED(hr)) + { + // open the corresponding reader + hr = m_pFaceFrameSources[i]->OpenReader(&m_pFaceFrameReaders[i]); + } + } + } + + SafeRelease(pColorFrameSource); + SafeRelease(pBodyFrameSource); + } + + if (!m_pKinectSensor || FAILED(hr)) + { + //SetStatusMessage(L"No ready Kinect found!", 10000, true); + return E_FAIL; + } + + return hr; +} + +/// +/// Main processing function +/// +void KinectFaceTracker::Update() +{ + if (!m_pColorFrameReader || !m_pBodyFrameReader) + { + return; + } + + IColorFrame* pColorFrame = nullptr; + HRESULT hr = m_pColorFrameReader->AcquireLatestFrame(&pColorFrame); + + if (SUCCEEDED(hr)) + { + INT64 nTime = 0; + IFrameDescription* pFrameDescription = nullptr; + int nWidth = 0; + int nHeight = 0; + ColorImageFormat imageFormat = ColorImageFormat_None; + UINT nBufferSize = 0; + RGBQUAD *pBuffer = nullptr; + + hr = pColorFrame->get_RelativeTime(&nTime); + + if (SUCCEEDED(hr)) + { + hr = pColorFrame->get_FrameDescription(&pFrameDescription); + } + + if (SUCCEEDED(hr)) + { + hr = pFrameDescription->get_Width(&nWidth); + } + + if (SUCCEEDED(hr)) + { + hr = pFrameDescription->get_Height(&nHeight); + } + + if (SUCCEEDED(hr)) + { + hr = pColorFrame->get_RawColorImageFormat(&imageFormat); + } + + if (SUCCEEDED(hr)) + { + if (imageFormat == ColorImageFormat_Bgra) + { + hr = pColorFrame->AccessRawUnderlyingBuffer(&nBufferSize, reinterpret_cast(&pBuffer)); + } + else if (m_pColorRGBX) + { + pBuffer = m_pColorRGBX; + nBufferSize = cColorWidth * cColorHeight * sizeof(RGBQUAD); + hr = pColorFrame->CopyConvertedFrameDataToArray(nBufferSize, reinterpret_cast(pBuffer), ColorImageFormat_Bgra); + } + else + { + hr = E_FAIL; + } + } + + if (SUCCEEDED(hr)) + { + //DrawStreams(nTime, pBuffer, nWidth, nHeight); + ProcessFaces(); + } + + SafeRelease(pFrameDescription); + } + + SafeRelease(pColorFrame); +} + + +/// +/// Updates body data +/// +/// pointer to the body data storage +/// indicates success or failure +HRESULT KinectFaceTracker::UpdateBodyData(IBody** ppBodies) +{ + HRESULT hr = E_FAIL; + + if (m_pBodyFrameReader != nullptr) + { + IBodyFrame* pBodyFrame = nullptr; + hr = m_pBodyFrameReader->AcquireLatestFrame(&pBodyFrame); + if (SUCCEEDED(hr)) + { + hr = pBodyFrame->GetAndRefreshBodyData(BODY_COUNT, ppBodies); + } + SafeRelease(pBodyFrame); + } + + return hr; +} + + + +/// +/// Processes new face frames +/// +void KinectFaceTracker::ProcessFaces() +{ + HRESULT hr; + IBody* ppBodies[BODY_COUNT] = { 0 }; + bool bHaveBodyData = SUCCEEDED(UpdateBodyData(ppBodies)); + + // iterate through each face reader + for (int iFace = 0; iFace < BODY_COUNT; ++iFace) + { + // retrieve the latest face frame from this reader + IFaceFrame* pFaceFrame = nullptr; + hr = m_pFaceFrameReaders[iFace]->AcquireLatestFrame(&pFaceFrame); + + BOOLEAN bFaceTracked = false; + if (SUCCEEDED(hr) && nullptr != pFaceFrame) + { + // check if a valid face is tracked in this face frame + hr = pFaceFrame->get_IsTrackingIdValid(&bFaceTracked); + } + + if (SUCCEEDED(hr)) + { + if (bFaceTracked) + { + IFaceFrameResult* pFaceFrameResult = nullptr; + RectI faceBox = { 0 }; + PointF facePoints[FacePointType::FacePointType_Count]; + DetectionResult faceProperties[FaceProperty::FaceProperty_Count]; + //D2D1_POINT_2F faceTextLayout; + + hr = pFaceFrame->get_FaceFrameResult(&pFaceFrameResult); + + // need to verify if pFaceFrameResult contains data before trying to access it + if (SUCCEEDED(hr) && pFaceFrameResult != nullptr) + { + hr = pFaceFrameResult->get_FaceBoundingBoxInColorSpace(&faceBox); + + if (SUCCEEDED(hr)) + { + hr = pFaceFrameResult->GetFacePointsInColorSpace(FacePointType::FacePointType_Count, facePoints); + } + + if (SUCCEEDED(hr)) + { + hr = pFaceFrameResult->get_FaceRotationQuaternion(&faceRotation); + } + + if (SUCCEEDED(hr)) + { + hr = pFaceFrameResult->GetFaceProperties(FaceProperty::FaceProperty_Count, faceProperties); + } + + if (SUCCEEDED(hr)) + { + //hr = GetFaceTextPositionInColorSpace(ppBodies[iFace], &faceTextLayout); + } + + if (SUCCEEDED(hr)) + { + // draw face frame results + //m_pDrawDataStreams->DrawFaceFrameResults(iFace, &faceBox, facePoints, &faceRotation, faceProperties, &faceTextLayout); + } + } + + SafeRelease(pFaceFrameResult); + } + else + { + // face tracking is not valid - attempt to fix the issue + // a valid body is required to perform this step + if (bHaveBodyData) + { + // check if the corresponding body is tracked + // if this is true then update the face frame source to track this body + IBody* pBody = ppBodies[iFace]; + if (pBody != nullptr) + { + BOOLEAN bTracked = false; + hr = pBody->get_IsTracked(&bTracked); + + UINT64 bodyTId; + if (SUCCEEDED(hr) && bTracked) + { + // get the tracking ID of this body + hr = pBody->get_TrackingId(&bodyTId); + if (SUCCEEDED(hr)) + { + // update the face frame source with the tracking ID + m_pFaceFrameSources[iFace]->put_TrackingId(bodyTId); + } + } + } + } + } + } + + SafeRelease(pFaceFrame); + } + + if (bHaveBodyData) + { + for (int i = 0; i < _countof(ppBodies); ++i) + { + SafeRelease(ppBodies[i]); + } + } +} diff --git a/tracker-kinect-face/tracker.h b/tracker-kinect-face/tracker.h new file mode 100644 index 00000000..88243b1f --- /dev/null +++ b/tracker-kinect-face/tracker.h @@ -0,0 +1,90 @@ + + + +#include + +#include "api/plugin-api.hpp" +#include "compat/timer.hpp" +#include "compat/macros.hpp" + +// Kinect Header files +#include +#include + +#pragma once + +// Safe release for interfaces +template +inline void SafeRelease(Interface *& pInterfaceToRelease) +{ + if (pInterfaceToRelease != nullptr) + { + pInterfaceToRelease->Release(); + pInterfaceToRelease = nullptr; + } +} + + +class KinectFaceTracker : public ITracker +{ +public: + KinectFaceTracker(); + ~KinectFaceTracker() override; + module_status start_tracker(QFrame *) override; + void data(double *data) override; + +private: + static const double incr[6]; + double last_x[6]{}; + Timer t; + + // Kinect stuff + + // define the face frame features required to be computed by this application + static const DWORD c_FaceFrameFeatures = + FaceFrameFeatures::FaceFrameFeatures_BoundingBoxInColorSpace + | FaceFrameFeatures::FaceFrameFeatures_PointsInColorSpace + | FaceFrameFeatures::FaceFrameFeatures_RotationOrientation + | FaceFrameFeatures::FaceFrameFeatures_Happy + | FaceFrameFeatures::FaceFrameFeatures_RightEyeClosed + | FaceFrameFeatures::FaceFrameFeatures_LeftEyeClosed + | FaceFrameFeatures::FaceFrameFeatures_MouthOpen + | FaceFrameFeatures::FaceFrameFeatures_MouthMoved + | FaceFrameFeatures::FaceFrameFeatures_LookingAway + | FaceFrameFeatures::FaceFrameFeatures_Glasses + | FaceFrameFeatures::FaceFrameFeatures_FaceEngagement; + + static const int cColorWidth = 1920; + static const int cColorHeight = 1080; + + + void Update(); + HRESULT InitializeDefaultSensor(); + void ProcessFaces(); + HRESULT UpdateBodyData(IBody** ppBodies); + void ExtractFaceRotationInDegrees(const Vector4* pQuaternion, double* pPitch, double* pYaw, double* pRoll); + + // Current Kinect + IKinectSensor* m_pKinectSensor; + + // Coordinate mapper + ICoordinateMapper* m_pCoordinateMapper; + + // Color reader + IColorFrameReader* m_pColorFrameReader; + + // Body reader + IBodyFrameReader* m_pBodyFrameReader; + + // Face sources + IFaceFrameSource* m_pFaceFrameSources[BODY_COUNT]; + + // Face readers + IFaceFrameReader* m_pFaceFrameReaders[BODY_COUNT]; + + // + RGBQUAD* m_pColorRGBX; + + Vector4 faceRotation; + +}; -- cgit v1.2.3 From af286a3fa5e1460faad85b816149ad1309ef3584 Mon Sep 17 00:00:00 2001 From: Stéphane Lenclud Date: Thu, 31 Jan 2019 16:59:14 +0100 Subject: Kinect: Now using HD API --- tracker-kinect-face/tracker.cpp | 229 +++++++++++++++++++++++++++++----------- tracker-kinect-face/tracker.h | 18 ++-- 2 files changed, 177 insertions(+), 70 deletions(-) diff --git a/tracker-kinect-face/tracker.cpp b/tracker-kinect-face/tracker.cpp index 3fe3b8cc..9b03f492 100644 --- a/tracker-kinect-face/tracker.cpp +++ b/tracker-kinect-face/tracker.cpp @@ -3,11 +3,81 @@ #include "tracker.h" -const double KinectFaceTracker::incr[6] = + +/// +bool IsValidRect(const RectI& aRect) +{ + if (aRect.Bottom != 0) + { + return true; + } + + if (aRect.Left != 0) + { + return true; + } + + if (aRect.Right != 0) + { + return true; + } + + if (aRect.Top != 0) + { + return true; + } + + return false; +} + +/// +bool IsNullVetor(const Vector4& aVector) +{ + if (aVector.w != 0) + { + return false; + } + + if (aVector.y != 0) + { + return false; + } + + if (aVector.y != 0) + { + return false; + } + + if (aVector.z != 0) + { + return false; + } + + return true; +} + +/// +bool IsNullPoint(const CameraSpacePoint& aPoint) { - 50, 40, 80, - 70, 5, 3 -}; + if (aPoint.X != 0) + { + return false; + } + + if (aPoint.Y != 0) + { + return false; + } + + if (aPoint.Z != 0) + { + return false; + } + + + return true; +} + KinectFaceTracker::KinectFaceTracker(): m_pKinectSensor(nullptr), @@ -17,11 +87,8 @@ KinectFaceTracker::KinectFaceTracker(): m_pBodyFrameReader(nullptr) { - for (int i = 0; i < BODY_COUNT; i++) - { - m_pFaceFrameSources[i] = nullptr; - m_pFaceFrameReaders[i] = nullptr; - } + m_pFaceFrameSource = nullptr; + m_pFaceFrameReader = nullptr; // create heap storage for color pixel data in RGBX format m_pColorRGBX = new RGBQUAD[cColorWidth * cColorHeight]; @@ -39,11 +106,8 @@ KinectFaceTracker::~KinectFaceTracker() //SafeRelease(m_pD2DFactory); // done with face sources and readers - for (int i = 0; i < BODY_COUNT; i++) - { - SafeRelease(m_pFaceFrameSources[i]); - SafeRelease(m_pFaceFrameReaders[i]); - } + SafeRelease(m_pFaceFrameSource); + SafeRelease(m_pFaceFrameReader); // done with body frame reader SafeRelease(m_pBodyFrameReader); @@ -79,46 +143,43 @@ module_status KinectFaceTracker::start_tracker(QFrame*) # include #endif +bool KinectFaceTracker::center() +{ + iFacePositionCenter = iFacePosition; + iFaceRotationCenter = iFaceRotation; + //TODO: Rotation center too + return true; +} + + void KinectFaceTracker::data(double *data) { const double dt = t.elapsed_seconds(); t.start(); -#ifdef EMIT_NAN - if ((rand() % 4) == 0) + + Update(); + //TODO: check if data is valid + + ExtractFaceRotationInDegrees(&iFaceRotationQuaternion, &iFaceRotation.X, &iFaceRotation.Y, &iFaceRotation.Z); + + if (!IsNullPoint(iFacePosition) && !IsNullPoint(iFaceRotation)) { - for (int i = 0; i < 6; i++) - data[i] = 0. / 0.; + // We have valid tracking retain position and rotation + iLastFacePosition = iFacePosition; + iLastFaceRotation = iFaceRotation; } - else -#endif - for (int i = 0; i < 6; i++) - { - double x = last_x[i] + incr[i] * dt; - if (x > 180) - x = -360 + x; - else if (x < -180) - x = 360 + x; - x = copysign(fmod(fabs(x), 360), x); - last_x[i] = x; - - if (i >= 3) - { - data[i] = x; - } - else - { - data[i] = x * 100 / 180.; - } - } + + // Feed our framework our last valid position and rotation + data[0] = (iLastFacePosition.X - iFacePositionCenter.X) * 100; // Convert to centimer to be in a range that suites OpenTrack. + data[1] = (iLastFacePosition.Y - iFacePositionCenter.Y) * 100; + data[2] = (iLastFacePosition.Z - iFacePositionCenter.Z) * 100; + // Yaw, picth, Roll + data[3] = 0-(iLastFaceRotation.X - iFaceRotationCenter.X); // Invert to be compatible with ED out-of-the-box + data[4] = (iLastFaceRotation.Y - iFaceRotationCenter.Y); + data[5] = (iLastFaceRotation.Z - iFaceRotationCenter.Z); - Update(); - //TODO: check if data is valid - data[0] = 0; - data[1] = 0; - data[2] = 0; - ExtractFaceRotationInDegrees(&faceRotation,&data[3], &data[4], &data[5]); } @@ -131,7 +192,7 @@ void KinectFaceTracker::data(double *data) /// rotation about the X-axis /// rotation about the Y-axis /// rotation about the Z-axis -void KinectFaceTracker::ExtractFaceRotationInDegrees(const Vector4* pQuaternion, double* pYaw, double* pPitch, double* pRoll) +void KinectFaceTracker::ExtractFaceRotationInDegrees(const Vector4* pQuaternion, float* pYaw, float* pPitch, float* pRoll) { double x = pQuaternion->x; double y = pQuaternion->y; @@ -215,12 +276,12 @@ HRESULT KinectFaceTracker::InitializeDefaultSensor() if (SUCCEEDED(hr)) { // create the face frame source by specifying the required face frame features - hr = CreateFaceFrameSource(m_pKinectSensor, 0, c_FaceFrameFeatures, &m_pFaceFrameSources[i]); + hr = CreateHighDefinitionFaceFrameSource(m_pKinectSensor, &m_pFaceFrameSource); } if (SUCCEEDED(hr)) { // open the corresponding reader - hr = m_pFaceFrameSources[i]->OpenReader(&m_pFaceFrameReaders[i]); + hr = m_pFaceFrameSource->OpenReader(&m_pFaceFrameReader); } } } @@ -348,12 +409,43 @@ void KinectFaceTracker::ProcessFaces() IBody* ppBodies[BODY_COUNT] = { 0 }; bool bHaveBodyData = SUCCEEDED(UpdateBodyData(ppBodies)); + if (!bHaveBodyData) + { + return; + } + + // TODO: Select closest body + // Just use the first body we find + BOOLEAN tracked; + int i = 0; + while (i < BODY_COUNT) + { + hr = ppBodies[i]->get_IsTracked(&tracked); + UINT64 trackingId = 0; + + if (SUCCEEDED(hr) && tracked) + { + hr = ppBodies[i]->get_TrackingId(&trackingId); + + if (SUCCEEDED(hr)) + { + // Tell our face source to use the given body id + hr = m_pFaceFrameSource->put_TrackingId(trackingId); + break; + } + + } + + i++; + } + + // iterate through each face reader for (int iFace = 0; iFace < BODY_COUNT; ++iFace) { // retrieve the latest face frame from this reader - IFaceFrame* pFaceFrame = nullptr; - hr = m_pFaceFrameReaders[iFace]->AcquireLatestFrame(&pFaceFrame); + IHighDefinitionFaceFrame* pFaceFrame = nullptr; + hr = m_pFaceFrameReader->AcquireLatestFrame(&pFaceFrame); BOOLEAN bFaceTracked = false; if (SUCCEEDED(hr) && nullptr != pFaceFrame) @@ -366,47 +458,54 @@ void KinectFaceTracker::ProcessFaces() { if (bFaceTracked) { - IFaceFrameResult* pFaceFrameResult = nullptr; + OutputDebugStringA("Tracking face!\n"); + + //IFaceFrameResult* pFaceFrameResult = nullptr; + IFaceAlignment* pFaceAlignment = nullptr; + CreateFaceAlignment(&pFaceAlignment); // TODO: check return? RectI faceBox = { 0 }; - PointF facePoints[FacePointType::FacePointType_Count]; - DetectionResult faceProperties[FaceProperty::FaceProperty_Count]; - //D2D1_POINT_2F faceTextLayout; + //D2D1_POINT_2F faceTextLayout; + + //hr = pFaceFrame->get_FaceFrameResult(&pFaceFrameResult); - hr = pFaceFrame->get_FaceFrameResult(&pFaceFrameResult); + hr = pFaceFrame->GetAndRefreshFaceAlignmentResult(pFaceAlignment); // need to verify if pFaceFrameResult contains data before trying to access it - if (SUCCEEDED(hr) && pFaceFrameResult != nullptr) + if (SUCCEEDED(hr) && pFaceAlignment != nullptr) { - hr = pFaceFrameResult->get_FaceBoundingBoxInColorSpace(&faceBox); + hr = pFaceAlignment->get_FaceBoundingBox(&faceBox); + //pFaceFrameResult->get_FaceBoundingBoxInColorSpace(); if (SUCCEEDED(hr)) { - hr = pFaceFrameResult->GetFacePointsInColorSpace(FacePointType::FacePointType_Count, facePoints); + //hr = pFaceFrameResult->GetFacePointsInColorSpace(FacePointType::FacePointType_Count, facePoints); + hr = pFaceAlignment->get_HeadPivotPoint(&iFacePosition); } if (SUCCEEDED(hr)) { - hr = pFaceFrameResult->get_FaceRotationQuaternion(&faceRotation); + //hr = pFaceFrameResult->get_FaceRotationQuaternion(&faceRotation); + hr = pFaceAlignment->get_FaceOrientation(&iFaceRotationQuaternion); } if (SUCCEEDED(hr)) { - hr = pFaceFrameResult->GetFaceProperties(FaceProperty::FaceProperty_Count, faceProperties); + //hr = pFaceFrameResult->GetFaceProperties(FaceProperty::FaceProperty_Count, faceProperties); } if (SUCCEEDED(hr)) { - //hr = GetFaceTextPositionInColorSpace(ppBodies[iFace], &faceTextLayout); + //hr = GetFaceTextPositionInColorSpace(ppBodies[0], &faceTextLayout); } if (SUCCEEDED(hr)) { // draw face frame results - //m_pDrawDataStreams->DrawFaceFrameResults(iFace, &faceBox, facePoints, &faceRotation, faceProperties, &faceTextLayout); + //m_pDrawDataStreams->DrawFaceFrameResults(0, &faceBox, facePoints, &faceRotation, faceProperties, &faceTextLayout); } } - SafeRelease(pFaceFrameResult); + SafeRelease(pFaceAlignment); } else { @@ -430,7 +529,7 @@ void KinectFaceTracker::ProcessFaces() if (SUCCEEDED(hr)) { // update the face frame source with the tracking ID - m_pFaceFrameSources[iFace]->put_TrackingId(bodyTId); + m_pFaceFrameSource->put_TrackingId(bodyTId); } } } @@ -449,3 +548,5 @@ void KinectFaceTracker::ProcessFaces() } } } + + diff --git a/tracker-kinect-face/tracker.h b/tracker-kinect-face/tracker.h index 88243b1f..cfadf997 100644 --- a/tracker-kinect-face/tracker.h +++ b/tracker-kinect-face/tracker.h @@ -32,10 +32,9 @@ public: ~KinectFaceTracker() override; module_status start_tracker(QFrame *) override; void data(double *data) override; + bool center() override; private: - static const double incr[6]; - double last_x[6]{}; Timer t; // Kinect stuff @@ -62,7 +61,7 @@ private: HRESULT InitializeDefaultSensor(); void ProcessFaces(); HRESULT UpdateBodyData(IBody** ppBodies); - void ExtractFaceRotationInDegrees(const Vector4* pQuaternion, double* pPitch, double* pYaw, double* pRoll); + void ExtractFaceRotationInDegrees(const Vector4* pQuaternion, float* pPitch, float* pYaw, float* pRoll); // Current Kinect IKinectSensor* m_pKinectSensor; @@ -77,14 +76,21 @@ private: IBodyFrameReader* m_pBodyFrameReader; // Face sources - IFaceFrameSource* m_pFaceFrameSources[BODY_COUNT]; + IHighDefinitionFaceFrameSource* m_pFaceFrameSource; // Face readers - IFaceFrameReader* m_pFaceFrameReaders[BODY_COUNT]; + IHighDefinitionFaceFrameReader* m_pFaceFrameReader; // RGBQUAD* m_pColorRGBX; - Vector4 faceRotation; + CameraSpacePoint iLastFacePosition; + CameraSpacePoint iFacePosition; + CameraSpacePoint iFacePositionCenter; + Vector4 iFaceRotationQuaternion; + // As Yaw, Pitch, Roll + CameraSpacePoint iLastFaceRotation; + CameraSpacePoint iFaceRotation; + CameraSpacePoint iFaceRotationCenter; }; -- cgit v1.2.3 From e419e8056cd883d0c5465b20343d69eba8c255ae Mon Sep 17 00:00:00 2001 From: Stéphane Lenclud Date: Fri, 1 Feb 2019 17:11:43 +0100 Subject: Kinect: Initializing positions and rotations to zero. --- tracker-kinect-face/tracker.cpp | 11 ++++++++--- tracker-kinect-face/tracker.h | 15 --------------- 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/tracker-kinect-face/tracker.cpp b/tracker-kinect-face/tracker.cpp index 9b03f492..1ab14c87 100644 --- a/tracker-kinect-face/tracker.cpp +++ b/tracker-kinect-face/tracker.cpp @@ -84,8 +84,13 @@ KinectFaceTracker::KinectFaceTracker(): m_pCoordinateMapper(nullptr), m_pColorFrameReader(nullptr), m_pColorRGBX(nullptr), - m_pBodyFrameReader(nullptr) - + m_pBodyFrameReader(nullptr), + iLastFacePosition{0,0,0}, + iFacePositionCenter{ 0,0,0 }, + iFacePosition{ 0,0,0 }, + iLastFaceRotation{ 0,0,0 }, + iFaceRotationCenter{ 0,0,0 }, + iFaceRotation{ 0,0,0 } { m_pFaceFrameSource = nullptr; m_pFaceFrameReader = nullptr; @@ -175,7 +180,7 @@ void KinectFaceTracker::data(double *data) data[1] = (iLastFacePosition.Y - iFacePositionCenter.Y) * 100; data[2] = (iLastFacePosition.Z - iFacePositionCenter.Z) * 100; - // Yaw, picth, Roll + // Yaw, Picth, Roll data[3] = 0-(iLastFaceRotation.X - iFaceRotationCenter.X); // Invert to be compatible with ED out-of-the-box data[4] = (iLastFaceRotation.Y - iFaceRotationCenter.Y); data[5] = (iLastFaceRotation.Z - iFaceRotationCenter.Z); diff --git a/tracker-kinect-face/tracker.h b/tracker-kinect-face/tracker.h index cfadf997..162e1cff 100644 --- a/tracker-kinect-face/tracker.h +++ b/tracker-kinect-face/tracker.h @@ -38,21 +38,6 @@ private: Timer t; // Kinect stuff - - // define the face frame features required to be computed by this application - static const DWORD c_FaceFrameFeatures = - FaceFrameFeatures::FaceFrameFeatures_BoundingBoxInColorSpace - | FaceFrameFeatures::FaceFrameFeatures_PointsInColorSpace - | FaceFrameFeatures::FaceFrameFeatures_RotationOrientation - | FaceFrameFeatures::FaceFrameFeatures_Happy - | FaceFrameFeatures::FaceFrameFeatures_RightEyeClosed - | FaceFrameFeatures::FaceFrameFeatures_LeftEyeClosed - | FaceFrameFeatures::FaceFrameFeatures_MouthOpen - | FaceFrameFeatures::FaceFrameFeatures_MouthMoved - | FaceFrameFeatures::FaceFrameFeatures_LookingAway - | FaceFrameFeatures::FaceFrameFeatures_Glasses - | FaceFrameFeatures::FaceFrameFeatures_FaceEngagement; - static const int cColorWidth = 1920; static const int cColorHeight = 1080; -- cgit v1.2.3 From d528f282305b24484861d8913c96c222621cf18c Mon Sep 17 00:00:00 2001 From: Stéphane Lenclud Date: Sat, 2 Feb 2019 02:12:30 +0100 Subject: Kinect: Improved CMake configuration for Kinect SDK. --- tracker-kinect-face/CMakeLists.txt | 27 +++++++++++++++++++++++++-- tracker-kinect-face/tracker.cpp | 2 +- tracker-kinect-face/tracker.h | 2 +- 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/tracker-kinect-face/CMakeLists.txt b/tracker-kinect-face/CMakeLists.txt index d139b445..9a37f2d8 100644 --- a/tracker-kinect-face/CMakeLists.txt +++ b/tracker-kinect-face/CMakeLists.txt @@ -1,6 +1,29 @@ +# Setup cache variable to Kinect SDK path if(DEFINED ENV{KINECTSDK20_DIR}) + set(KINECTSDK20_DIR $ENV{KINECTSDK20_DIR} CACHE PATH $ENV{KINECTSDK20_DIR}) +else() + set(KINECTSDK20_DIR $ENV{KINECTSDK20_DIR} CACHE PATH "") +endif() + +# If we have a valid SDK path, try build that tracker +if(EXISTS ${KINECTSDK20_DIR}) + # Register our module otr_module(tracker-kinect-face) - target_include_directories(opentrack-tracker-kinect-face SYSTEM PUBLIC $ENV{KINECTSDK20_DIR}inc) - target_link_libraries(opentrack-tracker-kinect-face $ENV{KINECTSDK20_DIR}lib/x86/kinect20.lib $ENV{KINECTSDK20_DIR}lib/x86/kinect20.face.lib) + + # Add include path to Kinect SDK + target_include_directories(opentrack-tracker-kinect-face SYSTEM PUBLIC ${KINECTSDK20_DIR}/inc) + + # Check processor architecture + if(CMAKE_SIZEOF_VOID_P EQUAL 4) + # 32 bits + set (kinect-arch-dir "x86") + elseif(CMAKE_SIZEOF_VOID_P EQUAL 8) + # 64 bits + set (kinect-arch-dir "x64") + endif() + + # Link against Kinect SDK libraries + target_link_libraries(opentrack-tracker-kinect-face ${KINECTSDK20_DIR}/lib/${kinect-arch-dir}/kinect20.lib ${KINECTSDK20_DIR}/lib/${kinect-arch-dir}/kinect20.face.lib) + endif() diff --git a/tracker-kinect-face/tracker.cpp b/tracker-kinect-face/tracker.cpp index 1ab14c87..407557f0 100644 --- a/tracker-kinect-face/tracker.cpp +++ b/tracker-kinect-face/tracker.cpp @@ -132,7 +132,7 @@ KinectFaceTracker::~KinectFaceTracker() SafeRelease(m_pKinectSensor); } -module_status KinectFaceTracker::start_tracker(QFrame*) +module_status KinectFaceTracker::start_tracker(QFrame* aFrame) { t.start(); diff --git a/tracker-kinect-face/tracker.h b/tracker-kinect-face/tracker.h index 162e1cff..1f986e22 100644 --- a/tracker-kinect-face/tracker.h +++ b/tracker-kinect-face/tracker.h @@ -30,7 +30,7 @@ class KinectFaceTracker : public ITracker public: KinectFaceTracker(); ~KinectFaceTracker() override; - module_status start_tracker(QFrame *) override; + module_status start_tracker(QFrame* aFrame) override; void data(double *data) override; bool center() override; -- cgit v1.2.3 From fbdb4c9191f0b3b0aa0d62d706b1598706561170 Mon Sep 17 00:00:00 2001 From: Stéphane Lenclud Date: Sat, 2 Feb 2019 02:26:23 +0100 Subject: Adding Kinect V2 SDK EULA. --- 3rdparty-notices/Kinect-V2-SDK-Eula.rtf | 525 ++++++++++++++++++++++++++++++++ 1 file changed, 525 insertions(+) create mode 100644 3rdparty-notices/Kinect-V2-SDK-Eula.rtf diff --git a/3rdparty-notices/Kinect-V2-SDK-Eula.rtf b/3rdparty-notices/Kinect-V2-SDK-Eula.rtf new file mode 100644 index 00000000..c2e634f7 --- /dev/null +++ b/3rdparty-notices/Kinect-V2-SDK-Eula.rtf @@ -0,0 +1,525 @@ +{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff39\deff0\stshfdbch31505\stshfloch31506\stshfhich31506\stshfbi0\deflang1033\deflangfe1033\themelang1033\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f1\fbidi \fswiss\fcharset0\fprq2{\*\panose 020b0604020202020204}Arial;} +{\f2\fbidi \fmodern\fcharset0\fprq1{\*\panose 02070309020205020404}Courier New;}{\f3\fbidi \froman\fcharset2\fprq2{\*\panose 05050102010706020507}Symbol;}{\f10\fbidi \fnil\fcharset2\fprq2{\*\panose 05000000000000000000}Wingdings;} +{\f34\fbidi \froman\fcharset1\fprq2{\*\panose 02040503050406030204}Cambria Math;}{\f38\fbidi \fswiss\fcharset0\fprq2{\*\panose 020b0502040204020203}Segoe UI;}{\f39\fbidi \fswiss\fcharset0\fprq2{\*\panose 00000000000000000000}Tahoma;} +{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fdbmajor\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} +{\fhimajor\f31502\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0302020204030204}Calibri Light;}{\fbimajor\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} +{\flominor\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fdbminor\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} +{\fhiminor\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f40\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} +{\f41\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f43\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f44\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f45\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} +{\f46\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f47\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f48\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f50\fbidi \fswiss\fcharset238\fprq2 Arial CE;} +{\f51\fbidi \fswiss\fcharset204\fprq2 Arial Cyr;}{\f53\fbidi \fswiss\fcharset161\fprq2 Arial Greek;}{\f54\fbidi \fswiss\fcharset162\fprq2 Arial Tur;}{\f55\fbidi \fswiss\fcharset177\fprq2 Arial (Hebrew);} +{\f56\fbidi \fswiss\fcharset178\fprq2 Arial (Arabic);}{\f57\fbidi \fswiss\fcharset186\fprq2 Arial Baltic;}{\f58\fbidi \fswiss\fcharset163\fprq2 Arial (Vietnamese);}{\f60\fbidi \fmodern\fcharset238\fprq1 Courier New CE;} +{\f61\fbidi \fmodern\fcharset204\fprq1 Courier New Cyr;}{\f63\fbidi \fmodern\fcharset161\fprq1 Courier New Greek;}{\f64\fbidi \fmodern\fcharset162\fprq1 Courier New Tur;}{\f65\fbidi \fmodern\fcharset177\fprq1 Courier New (Hebrew);} +{\f66\fbidi \fmodern\fcharset178\fprq1 Courier New (Arabic);}{\f67\fbidi \fmodern\fcharset186\fprq1 Courier New Baltic;}{\f68\fbidi \fmodern\fcharset163\fprq1 Courier New (Vietnamese);}{\f430\fbidi \fswiss\fcharset238\fprq2 Tahoma CE;} +{\f431\fbidi \fswiss\fcharset204\fprq2 Tahoma Cyr;}{\f433\fbidi \fswiss\fcharset161\fprq2 Tahoma Greek;}{\f434\fbidi \fswiss\fcharset162\fprq2 Tahoma Tur;}{\f435\fbidi \fswiss\fcharset177\fprq2 Tahoma (Hebrew);} +{\f436\fbidi \fswiss\fcharset178\fprq2 Tahoma (Arabic);}{\f437\fbidi \fswiss\fcharset186\fprq2 Tahoma Baltic;}{\f438\fbidi \fswiss\fcharset163\fprq2 Tahoma (Vietnamese);}{\f439\fbidi \fswiss\fcharset222\fprq2 Tahoma (Thai);} +{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;} +{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} +{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbmajor\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} +{\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} +{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} +{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhimajor\f31528\fbidi \fswiss\fcharset238\fprq2 Calibri Light CE;}{\fhimajor\f31529\fbidi \fswiss\fcharset204\fprq2 Calibri Light Cyr;} +{\fhimajor\f31531\fbidi \fswiss\fcharset161\fprq2 Calibri Light Greek;}{\fhimajor\f31532\fbidi \fswiss\fcharset162\fprq2 Calibri Light Tur;}{\fhimajor\f31535\fbidi \fswiss\fcharset186\fprq2 Calibri Light Baltic;} +{\fhimajor\f31536\fbidi \fswiss\fcharset163\fprq2 Calibri Light (Vietnamese);}{\fbimajor\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbimajor\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} +{\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);} +{\flominor\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flominor\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flominor\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;} +{\flominor\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flominor\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flominor\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} +{\flominor\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flominor\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbminor\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} +{\fdbminor\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbminor\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbminor\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} +{\fdbminor\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbminor\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbminor\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} +{\fdbminor\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhiminor\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\fhiminor\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;} +{\fhiminor\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;} +{\fhiminor\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\fbiminor\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbiminor\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\fbiminor\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbiminor\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fbiminor\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} +{\fbiminor\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbiminor\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fbiminor\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}} +{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0; +\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;\caccentone\ctint255\cshade191\red46\green116\blue181;\caccentone\ctint255\cshade127\red31\green77\blue120;\red31\green73\blue125;} +{\*\defchp \fs22\loch\af31506\hich\af31506\dbch\af31505 }{\*\defpap \ql \li0\ri0\sa160\sl259\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{ +\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af39\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1033\loch\f39\hich\af39\dbch\af31505\cgrid\langnp1033\langfenp1033 \snext0 \sqformat \spriority0 Normal;}{ +\s1\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\outlinelevel0\rin0\lin0\itap0 \rtlch\fcs1 \af39\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1033\loch\f39\hich\af39\dbch\af31505\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 \slink15 \sqformat +heading 1;}{\s2\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\outlinelevel1\rin0\lin0\itap0 \rtlch\fcs1 \af39\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1033\loch\f39\hich\af39\dbch\af31505\cgrid\langnp1033\langfenp1033 +\sbasedon0 \snext0 \slink16 \sqformat heading 2;}{\s3\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\outlinelevel2\rin0\lin0\itap0 \rtlch\fcs1 \af39\afs24\alang1025 \ltrch\fcs0 +\fs24\lang1033\langfe1033\loch\f39\hich\af39\dbch\af31505\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext0 \slink17 \sqformat heading 3;}{\*\cs10 \additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\* +\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\sa160\sl259\slmult1 +\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 \snext11 \ssemihidden \sunhideused +Normal Table;}{\*\cs15 \additive \rtlch\fcs1 \af0\afs32 \ltrch\fcs0 \fs32\cf17\loch\f31502\hich\af31502\dbch\af31501 \sbasedon10 \slink1 \slocked \spriority9 Heading 1 Char;}{\*\cs16 \additive \rtlch\fcs1 \af0\afs26 \ltrch\fcs0 +\fs26\cf17\loch\f31502\hich\af31502\dbch\af31501 \sbasedon10 \slink2 \slocked \ssemihidden \spriority9 Heading 2 Char;}{\*\cs17 \additive \rtlch\fcs1 \af0\afs24 \ltrch\fcs0 \fs24\cf18\loch\f31502\hich\af31502\dbch\af31501 +\sbasedon10 \slink3 \slocked \ssemihidden \spriority9 Heading 3 Char;}{\s18\ql \li0\ri0\nowidctlpar\tqc\tx4680\tqr\tx9360\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af39\afs24\alang1025 \ltrch\fcs0 +\fs24\lang1033\langfe1033\loch\f39\hich\af39\dbch\af31505\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext18 \slink19 \sunhideused \styrsid1930808 header;}{\*\cs19 \additive \rtlch\fcs1 \af39\afs24 \ltrch\fcs0 \f39\fs24 +\sbasedon10 \slink18 \slocked \styrsid1930808 Header Char;}{\s20\ql \li0\ri0\nowidctlpar\tqc\tx4680\tqr\tx9360\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af39\afs24\alang1025 \ltrch\fcs0 +\fs24\lang1033\langfe1033\loch\f39\hich\af39\dbch\af31505\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext20 \slink21 \sunhideused \styrsid1930808 footer;}{\*\cs21 \additive \rtlch\fcs1 \af39\afs24 \ltrch\fcs0 \f39\fs24 +\sbasedon10 \slink20 \slocked \styrsid1930808 Footer Char;}{\*\cs22 \additive \rtlch\fcs1 \af0\afs16 \ltrch\fcs0 \fs16 \sbasedon10 \ssemihidden \sunhideused \styrsid4929922 annotation reference;}{ +\s23\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af39\afs20\alang1025 \ltrch\fcs0 \fs20\lang1033\langfe1033\loch\f39\hich\af39\dbch\af31505\cgrid\langnp1033\langfenp1033 +\sbasedon0 \snext23 \slink24 \ssemihidden \sunhideused \styrsid4929922 annotation text;}{\*\cs24 \additive \rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f39\fs20 \sbasedon10 \slink23 \slocked \ssemihidden \styrsid4929922 Comment Text Char;}{ +\s25\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \ab\af39\afs20\alang1025 \ltrch\fcs0 \b\fs20\lang1033\langfe1033\loch\f39\hich\af39\dbch\af31505\cgrid\langnp1033\langfenp1033 +\sbasedon23 \snext23 \slink26 \ssemihidden \sunhideused \styrsid4929922 annotation subject;}{\*\cs26 \additive \rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\f39\fs20 \sbasedon24 \slink25 \slocked \ssemihidden \styrsid4929922 Comment Subject Char;}{ +\s27\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af38\afs18\alang1025 \ltrch\fcs0 \fs18\lang1033\langfe1033\loch\f38\hich\af38\dbch\af31505\cgrid\langnp1033\langfenp1033 +\sbasedon0 \snext27 \slink28 \ssemihidden \sunhideused \styrsid4929922 Balloon Text;}{\*\cs28 \additive \rtlch\fcs1 \af38\afs18 \ltrch\fcs0 \f38\fs18 \sbasedon10 \slink27 \slocked \ssemihidden \styrsid4929922 Balloon Text Char;}{ +\s29\ql \li720\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin720\itap0\contextualspace \rtlch\fcs1 \af39\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1033\loch\f39\hich\af39\dbch\af31505\cgrid\langnp1033\langfenp1033 +\sbasedon0 \snext29 \sqformat \spriority34 \styrsid5338358 List Paragraph;}}{\*\listtable{\list\listtemplateid-1933036156\listsimple{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat0\levelspace0\levelindent0{\leveltext +\'01*;}{\levelnumbers;}}{\listname ;}\listid-2}{\list\listtemplateid1663739596\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\leveltemplateid67698693 +\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li1440\lin1440 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698691\'01o;}{\levelnumbers;}\f2\fbias0 +\fi-360\li2160\lin2160 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698693\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li2880\lin2880 }{\listlevel +\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698689\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li3600\lin3600 }{\listlevel\levelnfc23\levelnfcn23\leveljc0 +\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698691\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li4320\lin4320 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1 +\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698693\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li5040\lin5040 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0 +\levelindent0{\leveltext\leveltemplateid67698689\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li5760\lin5760 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext +\leveltemplateid67698691\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li6480\lin6480 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698693 +\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li7200\lin7200 }{\listname ;}\listid296491462}{\list\listtemplateid1166995046\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext +\leveltemplateid67698693\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li1440\lin1440 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698691 +\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li2160\lin2160 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698693\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 +\fi-360\li2880\lin2880 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698689\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li3600\lin3600 }{\listlevel +\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698691\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li4320\lin4320 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0 +\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698693\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li5040\lin5040 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1 +\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698689\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li5760\lin5760 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0 +\levelindent0{\leveltext\leveltemplateid67698691\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li6480\lin6480 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext +\leveltemplateid67698693\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li7200\lin7200 }{\listname ;}\listid728115947}{\list\listtemplateid-576179798\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0 +\levelindent0{\leveltext\leveltemplateid67698689\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li1260\lin1260 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext +\leveltemplateid67698691\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li1980\lin1980 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698693 +\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li2700\lin2700 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698689\'01\u-3913 ?;}{\levelnumbers;} +\f3\fbias0 \fi-360\li3420\lin3420 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698691\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li4140\lin4140 } +{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698693\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li4860\lin4860 }{\listlevel\levelnfc23\levelnfcn23 +\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698689\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li5580\lin5580 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0 +\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698691\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li6300\lin6300 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0 +\levelindent0{\leveltext\leveltemplateid67698693\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li7020\lin7020 }{\listname ;}\listid844515658}{\list\listtemplateid2023228974\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0 +\levelstartat1\levelspace0\levelindent0{\leveltext\leveltemplateid67698693\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li1800\lin1800 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0 +\levelindent0{\leveltext\leveltemplateid67698691\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li2520\lin2520 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext +\leveltemplateid67698693\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li3240\lin3240 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698689 +\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li3960\lin3960 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698691\'01o;}{\levelnumbers;}\f2\fbias0 +\fi-360\li4680\lin4680 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698693\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li5400\lin5400 }{\listlevel +\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698689\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li6120\lin6120 }{\listlevel\levelnfc23\levelnfcn23\leveljc0 +\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698691\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li6840\lin6840 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1 +\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698693\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li7560\lin7560 }{\listname ;}\listid1411999391}{\list\listtemplateid-926094602\listhybrid{\listlevel\levelnfc23\levelnfcn23 +\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\leveltemplateid67698689\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li1800\lin1800 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1 +\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698691\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li2520\lin2520 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0 +{\leveltext\leveltemplateid67698693\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li3240\lin3240 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698689 +\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li3960\lin3960 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698691\'01o;}{\levelnumbers;}\f2\fbias0 +\fi-360\li4680\lin4680 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698693\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li5400\lin5400 }{\listlevel +\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698689\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li6120\lin6120 }{\listlevel\levelnfc23\levelnfcn23\leveljc0 +\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698691\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li6840\lin6840 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1 +\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid67698693\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li7560\lin7560 }{\listname ;}\listid1653637060}{\list\listtemplateid11189262\listsimple{\listlevel\levelnfc4\levelnfcn4\leveljc0 +\leveljcn0\levelfollow0\levelstartat1\levelold\levelspace0\levelindent0{\leveltext\'02\'00.;}{\levelnumbers\'01;}\rtlch\fcs1 \af39 \ltrch\fcs0 \b\f39\fbias0 }{\listname ;}\listid1681809293}}{\*\listoverridetable{\listoverride\listid1681809293 +\listoverridecount0\ls1}{\listoverride\listid296491462\listoverridecount0\ls2}{\listoverride\listid-2\listoverridecount1{\lfolevel\listoverrideformat{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat0\levelold\levelspace0 +\levelindent360{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 }}\ls3}{\listoverride\listid1653637060\listoverridecount0\ls4}{\listoverride\listid1411999391\listoverridecount0\ls5}{\listoverride\listid728115947\listoverridecount0\ls6} +{\listoverride\listid844515658\listoverridecount0\ls7}}{\*\pgptbl {\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}}{\*\rsidtbl \rsid73750\rsid91414\rsid675470\rsid1909739\rsid1930808\rsid2042763\rsid3882049\rsid3949644\rsid4196885\rsid4796860\rsid4929922\rsid5338358 +\rsid6816407\rsid6969745\rsid7096959\rsid7297413\rsid7679777\rsid7695099\rsid8139599\rsid8222967\rsid8745415\rsid9392452\rsid9909308\rsid10056964\rsid10234499\rsid10296048\rsid10437656\rsid10570424\rsid10897255\rsid11022658\rsid11090850\rsid11808396 +\rsid11829074\rsid11871500\rsid11937711\rsid11949759\rsid13329978\rsid13781786\rsid14225958\rsid14551182\rsid14579304\rsid15495172\rsid15621282\rsid16385968\rsid16457108}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0 +\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\creatim\yr2014\mo8\dy27\hr11\min25}{\revtim\yr2014\mo8\dy27\hr11\min25}{\version1}{\edmins0}{\nofpages6}{\nofwords1938}{\nofchars11052}{\nofcharsws12965}{\vern57437}}{\*\xmlnstbl {\xmlns1 http://schemas. +microsoft.com/office/word/2003/wordml}}\paperw12240\paperh15840\margl1440\margr1440\margt1440\margb1440\gutter0\ltrsect +\widowctrl\ftnbj\aenddoc\trackmoves0\trackformatting1\donotembedsysfont0\relyonvml1\donotembedlingdata0\grfdocevents0\validatexml0\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors0\horzdoc\dghspace120\dgvspace120\dghorigin1701 +\dgvorigin1984\dghshow0\dgvshow3\jcompress\viewscale100\splytwnine\ftnlytwnine\htmautsp\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\nobrkwrptbl\snaptogridincell\rempersonalinfo\allowfieldendsel\wrppunct\asianbrkrule\rsidroot6816407 +\newtblstyruls\nogrowautofit\remdttm\usenormstyforlist\noindnmbrts\felnbrelev\nocxsptable\indrlsweleven\noafcnsttbl\afelev\utinl\hwelev\spltpgpar\notcvasp\notbrkcnstfrctbl\notvatxbx\krnprsnet\cachedcolbal \nouicompat \fet0{\*\wgrffmtfilter 2450} +\nofeaturethrottle1\ilfomacatclnup0{\*\ftnsep \ltrpar \pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid1930808 \rtlch\fcs1 \af39\afs24\alang1025 \ltrch\fcs0 +\fs24\lang1033\langfe1033\loch\af39\hich\af39\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid10296048 \chftnsep +\par }}{\*\ftnsepc \ltrpar \pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid1930808 \rtlch\fcs1 \af39\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1033\loch\af39\hich\af39\dbch\af31505\cgrid\langnp1033\langfenp1033 { +\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid10296048 \chftnsepc +\par }}{\*\aftnsep \ltrpar \pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid1930808 \rtlch\fcs1 \af39\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1033\loch\af39\hich\af39\dbch\af31505\cgrid\langnp1033\langfenp1033 { +\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid10296048 \chftnsep +\par }}{\*\aftnsepc \ltrpar \pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid1930808 \rtlch\fcs1 \af39\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1033\loch\af39\hich\af39\dbch\af31505\cgrid\langnp1033\langfenp1033 { +\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid10296048 \chftnsepc +\par }}\ltrpar \sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4 +\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (} +{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\ql \li0\ri0\sb120\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 +\af39\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1033\loch\af39\hich\af39\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 Microsoft Kinect for Windows}{ +\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\fs20\insrsid4929922 \hich\af39\dbch\af31505\loch\f39 v2}{\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 Software Development Kit (SDK) +\par }\pard \ltrpar\ql \li0\ri0\sa120\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\fs20\insrsid8745415 +\par }\pard \ltrpar\ql \li0\ri0\sb120\sa120\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 +These license terms are an agreement between Microsoft Corporation (or based on where you live, one of its affiliates) and you. Please read them. They apply to the software named above, \hich\af39\dbch\af31505\loch\f39 +which includes the media on which you received it, if any. It also applies to any Microsoft}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid8745415 +\par }\pard \ltrpar\ql \fi-360\li360\ri0\sb120\sa120\nowidctlpar\tx360\wrapdefault\faauto\rin0\lin360\itap0 {\rtlch\fcs1 \af3\afs20 \ltrch\fcs0 \f3\fs20\insrsid8745415 \loch\af3\dbch\af31505\hich\f3 \'b7}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\f1\fs20\insrsid8745415 \tab }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 updates}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid8745415 , +\par }\pard \ltrpar\ql \fi-360\li360\ri0\sb120\sa120\nowidctlpar\wrapdefault\faauto\rin0\lin360\itap0 {\rtlch\fcs1 \af3\afs20 \ltrch\fcs0 \f3\fs20\insrsid8745415 \loch\af3\dbch\af31505\hich\f3 \'b7}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid8745415 +\tab }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 supplements, +\par }{\rtlch\fcs1 \af3\afs20 \ltrch\fcs0 \f3\fs20\insrsid8745415 \loch\af3\dbch\af31505\hich\f3 \'b7}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid8745415 \tab }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 +documentation, and}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid8745415 +\par }{\rtlch\fcs1 \af3\afs20 \ltrch\fcs0 \f3\fs20\insrsid8745415 \loch\af3\dbch\af31505\hich\f3 \'b7}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid8745415 \tab }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 +support services}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid8745415 +\par }\pard \ltrpar\ql \li0\ri0\sb120\sa120\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 +for this software, unless other terms accompany those items. If so, those terms apply. +\par }{\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 The softwar\hich\af39\dbch\af31505\loch\f39 e is licensed, not sold.}{\rtlch\fcs1 \af39 \ltrch\fcs0 \insrsid8745415 \hich\af39\dbch\af31505\loch\f39 }{ +\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 \hich\f39 +By downloading, installing, accessing, or using the software, you accept all terms in this agreement. If you do not accept them, do not download, install, access, or use the software. \'93\loch\f39 \hich\f39 You\'94\loch\f39 \hich\f39 or \'93\loch\f39 +\hich\f39 you\'94\loch\f39 means the individual who downloa\hich\af39\dbch\af31505\loch\f39 +ds, installs, accesses, or uses the software (and, if you represent a legal entity, it also means that entity, and you represent and warrant that you are authorized to enter into this agreement for that entity).}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 +\par }{\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 If you comply with these license terms, you\hich\af39\dbch\af31505\loch\f39 have the rights below.}{\rtlch\fcs1 \ab\af1\afs20 \ltrch\fcs0 +\b\f1\fs20\insrsid8745415 +\par }\pard \ltrpar\ql \li0\ri0\sb200\sa100\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \ab\af1\afs20 \ltrch\fcs0 \b\f1\fs20\insrsid8745415 \hich\af1\dbch\af31505\loch\f1 1. }{\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\fs20\insrsid8745415 +\hich\af39\dbch\af31505\loch\f39 INSTALLATION AND USE RIGHTS. +\par {\pntext\pard\plain\ltrpar \rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\f39\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 a.\tab}}\pard \ltrpar\ql \fi-270\li450\ri0\sa100\nowidctlpar\tx540\wrapdefault{\*\pn \pnlvlbody\ilvl0\ls1\pnrnot0\pnlcltr\pnb1 +\pnf39\pnstart1 {\pntxta .}}\faauto\ls1\rin0\lin450\itap0\pararsid6816407 {\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 Installation and Use.}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 +\hich\af39\dbch\af31505\loch\f39 You may (i) install and use any number of copies of the software (only when installed using the accompanying software installer package) on your computer to design, develop, and \hich\af39\dbch\af31505\loch\f39 +test your programs that run specifically on a Microsoft Windows operating system, and that are intended for use solely in connection with }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid11871500 \hich\af39\dbch\af31505\loch\f39 the }{\rtlch\fcs1 +\af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 Microsoft Kinect for Windows}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid4929922 \hich\af39\dbch\af31505\loch\f39 }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\insrsid3882049 \hich\af39\dbch\af31505\loch\f39 v}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid4929922 \hich\af39\dbch\af31505\loch\f39 2}{\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 }{ +\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 sensor}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid4929922 \hich\af39\dbch\af31505\loch\f39 \hich\f39 (\'93\loch\f39 Kinect }{\rtlch\fcs1 \af39\afs20 +\ltrch\fcs0 \fs20\insrsid3882049 \hich\af39\dbch\af31505\loch\f39 v}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid4929922 \hich\af39\dbch\af31505\loch\f39 2}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid7679777 \hich\af39\dbch\af31505\loch\f39 + Sensor}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid4929922 \loch\af39\dbch\af31505\hich\f39 \'94\loch\f39 )}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 +, and its associated drivers and runtime software, and no other sensor }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid73750 \hich\af39\dbch\af31505\loch\f39 unless such sensor is supported by Microsoft }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 (}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid6969745 \hich\af39\dbch\af31505\loch\f39 collectively, the }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 +\loch\af39\dbch\af31505\hich\f39 \'93\loch\f39 Kinect }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid4929922 \hich\af39\dbch\af31505\loch\f39 V2}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 \hich\f39 + Applications\'94\loch\f39 ), and (ii) distribute your Kinect }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid3882049 \hich\af39\dbch\af31505\loch\f39 v}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid4929922 \hich\af39\dbch\af31505\loch\f39 2 }{ +\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 Applications, subject to the terms in this agreement. +\par {\pntext\pard\plain\ltrpar \rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \b\f39\fs20\insrsid7695099 \hich\af39\dbch\af31505\loch\f39 b.\tab}}\pard \ltrpar\ql \fi-270\li450\ri0\sa100\nowidctlpar\tx540\wrapdefault{\*\pn \pnlvlbody\ilvl0\ls1\pnrnot0\pnlcltr\pnb1 +\pnf39\pnstart1 {\pntxta .}}\faauto\ls1\rin0\lin450\itap0 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \b\fs20\insrsid7695099 \hich\af39\dbch\af31505\loch\f39 Tele\hich\af39\dbch\af31505\loch\f39 metry Data Collection. }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\insrsid7695099 \hich\af39\dbch\af31505\loch\f39 When in use by you, the software will provide Microsoft with telemetry data }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\lang9\langfe1033\langnp9\insrsid7695099 \hich\af39\dbch\af31505\loch\f39 +(e.g. operating system, number of processors, graphic chipset, memory, device type, locale, time) regarding your installation and use. }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\lang9\langfe1033\langnp9\insrsid14225958 \hich\af39\dbch\af31505\loch\f39 +The data will not be u\hich\af39\dbch\af31505\loch\f39 sed to identify specific individuals. }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\lang9\langfe1033\langnp9\insrsid7695099 \hich\af39\dbch\af31505\loch\f39 }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\lang9\langfe1033\langnp9\insrsid8222967 \hich\af39\dbch\af31505\loch\f39 Microsoft will}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\lang9\langfe1033\langnp9\insrsid7695099 \hich\af39\dbch\af31505\loch\f39 use the Telemetry Data for product and }{ +\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\lang9\langfe1033\langnp9\insrsid91414 \hich\af39\dbch\af31505\loch\f39 service}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\lang9\langfe1033\langnp9\insrsid7695099 \hich\af39\dbch\af31505\loch\f39 improvements. +}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid7695099\charrsid7695099 +\par {\pntext\pard\plain\ltrpar \rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\f39\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 c.\tab}}\pard \ltrpar\ql \fi-270\li450\ri0\sa100\nowidctlpar\tx540\wrapdefault{\*\pn \pnlvlbody\ilvl0\ls1\pnrnot0\pnlcltr\pnb1 +\pnf39\pnstart1 {\pntxta .}}\faauto\ls1\rin0\lin450\itap0\pararsid6816407 {\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 Included Microsoft Programs.}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 The software includes other Microsoft programs. The license terms with those programs apply to your use o\hich\af39\dbch\af31505\loch\f39 f them. +\par {\pntext\pard\plain\ltrpar \rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\f39\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 d.\tab}}\pard \ltrpar\ql \fi-270\li450\ri0\sa100\nowidctlpar\tx540\wrapdefault{\*\pn \pnlvlbody\ilvl0\ls1\pnrnot0\pnlcltr\pnb1 +\pnf39\pnstart1 {\pntxta .}}\faauto\ls1\rin0\lin450\itap0\pararsid6816407 {\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 No High Risk Use. WARNING:}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 The Kinect }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid3949644 \hich\af39\dbch\af31505\loch\f39 v}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid4929922 \hich\af39\dbch\af31505\loch\f39 2 }{ +\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid7679777 \hich\af39\dbch\af31505\loch\f39 S}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 ensor and the software are not fault-tolerant. The Kinect }{\rtlch\fcs1 +\af39\afs20 \ltrch\fcs0 \fs20\insrsid3949644 \hich\af39\dbch\af31505\loch\f39 v}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid4929922 \hich\af39\dbch\af31505\loch\f39 2}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid7679777 +\hich\af39\dbch\af31505\loch\f39 Sensor }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 and the software are not designed or intended for use with any program where failure or fault of any kind of the Kinect }{ +\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid3949644 \hich\af39\dbch\af31505\loch\f39 v}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid4929922 \hich\af39\dbch\af31505\loch\f39 2}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid7679777 +\hich\af39\dbch\af31505\loch\f39 Sensor}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid4929922 \hich\af39\dbch\af31505\loch\f39 }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 or soft +\hich\af39\dbch\af31505\loch\f39 \hich\f39 ware could lead to death or serious bodily injury of any person, or to severe physical or environmental damage (\'93\loch\f39 \hich\f39 High Risk Use\'94\loch\f39 +). You are not licensed to, and you agree not to, use, distribute or sublicense the use of the Kinect }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid11871500 \hich\af39\dbch\af31505\loch\f39 v2 }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 Sensor and/or software in, or in conjunction with, High Risk Use. High Risk Use is STRICTLY PROHIBITED. }{\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\fs20\insrsid8745415 +\hich\af39\dbch\af31505\loch\f39 High Risk Use includes, for example, the following: aircraft navigation and control of other modes of human mass transportation, nuclear or chemical f\hich\af39\dbch\af31505\loch\f39 acilities. }{\rtlch\fcs1 \ab\af1\afs20 +\ltrch\fcs0 \b\f1\fs20\insrsid8745415 +\par }\pard \ltrpar\ql \li0\ri0\sb200\sa100\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \ab\af1\afs20 \ltrch\fcs0 \b\f1\fs20\insrsid8745415 \hich\af1\dbch\af31505\loch\f1 2}{\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\fs20\insrsid8745415 +\hich\af39\dbch\af31505\loch\f39 . ADDITIONAL LICENSING REQUIREMENTS AND/OR USE RIGHTS +\par }\pard \ltrpar\ql \fi-183\li363\ri0\sa100\nowidctlpar\tx363\wrapdefault\faauto\rin0\lin363\itap0 {\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 a.\tab Distributable Code}{\rtlch\fcs1 \af39\afs20 +\ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 . The software contains code that you are permitted to distribute solely in Kinect }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid3949644 \hich\af39\dbch\af31505\loch\f39 v}{ +\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid4929922 \hich\af39\dbch\af31505\loch\f39 2}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 Applications if you comply with the terms below. +\par }\pard\plain \ltrpar\s3\ql \fi-357\li1077\ri0\sb120\sa120\nowidctlpar\tx1080\wrapdefault\faauto\outlinelevel2\rin0\lin1077\itap0 \rtlch\fcs1 \af39\afs24\alang1025 \ltrch\fcs0 +\fs24\lang1033\langfe1033\loch\af39\hich\af39\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 i.\tab Right to Use and \hich\af39\dbch\af31505\loch\f39 \hich\f39 +Distribute. The code and text files listed below are \'93\loch\f39 \hich\f39 Distributable Code.\'94 +\par }\pard\plain \ltrpar\ql \fi-358\li1435\ri0\sb120\sa120\nowidctlpar\tx1437\wrapdefault\faauto\rin0\lin1435\itap0 \rtlch\fcs1 \af39\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1033\loch\af39\hich\af39\dbch\af31505\cgrid\langnp1033\langfenp1033 { +\rtlch\fcs1 \af3\afs20 \ltrch\fcs0 \f3\fs20\insrsid8745415 \loch\af3\dbch\af31505\hich\f3 \'b7\tab }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\ul\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 REDIST.TXT Files}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 . You may copy and distribute the object code form of code listed in REDIST.TXT files}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid11871500 \hich\af39\dbch\af31505\loch\f39 + as part of your Kinect v2 Application}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 . +\par }\pard \ltrpar\ql \fi-358\li1435\ri0\sb120\sa120\nowidctlpar\wrapdefault\faauto\rin0\lin1435\itap0 {\rtlch\fcs1 \af3\afs20 \ltrch\fcs0 \f3\fs20\insrsid8745415 \loch\af3\dbch\af31505\hich\f3 \'b7\tab }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\ul\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 Sample Code}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 . You may modify, copy \hich\af39\dbch\af31505\loch\f39 +and distribute the source and object code form of code in the Samples subdirectory}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid11871500 \hich\af39\dbch\af31505\loch\f39 as part of your Kinect v2 Application}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 +\f1\fs20\insrsid8745415 .}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f0\fs20\insrsid8745415 +\par }{\rtlch\fcs1 \af3\afs20 \ltrch\fcs0 \f3\fs20\insrsid8745415 \loch\af3\dbch\af31505\hich\f3 \'b7\tab }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\ul\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 Third Party Distribution}{\rtlch\fcs1 \af39\afs20 +\ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 . You may permit distributors of your Kinect }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid3949644 \hich\af39\dbch\af31505\loch\f39 v2}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 Applications to copy and distribute the Distributable Code a\hich\af39\dbch\af31505\loch\f39 s part of those Kinect }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid3949644 +\hich\af39\dbch\af31505\loch\f39 v}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid4929922 \hich\af39\dbch\af31505\loch\f39 2}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 Applications. +\par {\listtext\pard\plain\ltrpar \s29 \rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f3\fs20\insrsid5338358\charrsid11829074 \loch\af3\dbch\af31505\hich\f3 \'b7\tab}}\pard\plain \ltrpar\s29\ql \fi-360\li1440\ri0\nowidctlpar +\tx900\wrapdefault\faauto\ls7\rin0\lin1440\itap0\pararsid11829074\contextualspace \rtlch\fcs1 \af39\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1033\loch\af39\hich\af39\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\ul\insrsid5338358\charrsid11829074 \hich\af39\dbch\af31505\loch\f39 Third Party Programs}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid5338358\charrsid11829074 \hich\af39\dbch\af31505\loch\f39 +. This software may contain certain third-party programs. You agree that your use of them is governed by the license terms provided with those programs. +\par }\pard\plain \ltrpar\ql \li0\ri0\sa100\nowidctlpar\tx1512\wrapdefault\faauto\rin0\lin0\itap0\pararsid11829074 \rtlch\fcs1 \af39\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1033\loch\af39\hich\af39\dbch\af31505\cgrid\langnp1033\langfenp1033 { +\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid8745415 +\par }\pard \ltrpar\ql \li720\ri0\sa100\nowidctlpar\wrapdefault\faauto\rin0\lin720\itap0 {\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 ii. Distribution Requirements.}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 }{\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 For any D\hich\af39\dbch\af31505\loch\f39 istributable Code you distribute, you must: }{\rtlch\fcs1 +\af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid8745415 +\par }\pard \ltrpar\ql \fi-360\li1440\ri0\sa100\nowidctlpar\wrapdefault\faauto\rin0\lin1440\itap0 {\rtlch\fcs1 \af10\afs20 \ltrch\fcs0 \f10\fs20\insrsid8745415 \loch\af10\dbch\af31505\hich\f10 \'a7\tab }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 add significant primary functionality to it in your Kinect }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid11871500 \hich\af39\dbch\af31505\loch\f39 v2}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 Applications; +\par }\pard \ltrpar\ql \fi-360\li1440\ri0\sa100\nowidctlpar\wrapdefault\faauto\rin0\lin1440\itap0\pararsid11829074 {\rtlch\fcs1 \af10\afs20 \ltrch\fcs0 \f10\fs20\insrsid8745415 \loch\af10\dbch\af31505\hich\f10 \'a7\tab }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 distribute Distributable Code included in a setup program only as part of that setup program without modification}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid10234499 +\hich\af39\dbch\af31505\loch\f39 ;}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid11808396 +\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f10\fs20\insrsid14225958 \loch\af10\dbch\af31505\hich\f10 \'a7\tab}}\pard \ltrpar\ql \fi-360\li1440\ri0\sa100\nowidctlpar\wrapdefault\faauto\ls6\rin0\lin1440\itap0\pararsid11829074 { +\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid14225958 \hich\af39\dbch\af31505\loch\f39 c}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid13329978 \hich\af39\dbch\af31505\loch\f39 learly state in your Kinect V2 }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\insrsid3949644 \hich\af39\dbch\af31505\loch\f39 A}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid13329978 \hich\af39\dbch\af31505\loch\f39 pplication (as well as require your licensees to do so) }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\insrsid15495172 \hich\af39\dbch\af31505\loch\f39 a privacy statement}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid13329978 \hich\af39\dbch\af31505\loch\f39 + regarding the collection and use of customer data as well as the following statement regarding Microsoft\hich\f39 \rquote \loch\f39 s }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid91414 \hich\af39\dbch\af31505\loch\f39 collection and }{\rtlch\fcs1 +\af39\afs20 \ltrch\fcs0 \fs20\insrsid13329978 \hich\af39\dbch\af31505\loch\f39 use of customer data}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid10234499 \hich\af39\dbch\af31505\loch\f39 \hich\f39 : \'93}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\ul\insrsid10234499\charrsid11829074 \hich\af39\dbch\af31505\loch\f39 No\hich\af39\dbch\af31505\loch\f39 te}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid10234499 \hich\af39\dbch\af31505\loch\f39 : When using }{\rtlch\fcs1 \af39\afs20 +\ltrch\fcs0 \fs20\insrsid3949644 \hich\af39\dbch\af31505\loch\f39 the _________________(insert name of Your}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid10234499 \hich\af39\dbch\af31505\loch\f39 Kinect }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\insrsid3949644 \hich\af39\dbch\af31505\loch\f39 v}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid10234499 \hich\af39\dbch\af31505\loch\f39 2 Application}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid3949644 \hich\af39\dbch\af31505\loch\f39 )} +{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid11871500 \hich\af39\dbch\af31505\loch\f39 with a Kinect for Windows v2 Sensor}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid14225958 ,}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid10234499 +\hich\af39\dbch\af31505\loch\f39 }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\lang9\langfe1033\langnp9\insrsid10234499 \hich\af39\dbch\af31505\loch\f39 +Microsoft will collect telemetry data (e.g. operating system, number of processors, graphic chipset, memory, device type, locale, time) in\hich\af39\dbch\af31505\loch\f39 order to improve }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\lang9\langfe1033\langnp9\insrsid91414 \hich\af39\dbch\af31505\loch\f39 Microsoft products and services}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\lang9\langfe1033\langnp9\insrsid10234499 \hich\af39\dbch\af31505\loch\f39 \hich\f39 +. The data will not be used to identify specific individuals.\'94\loch\f39 }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid13329978\charrsid11871500 \hich\af39\dbch\af31505\loch\f39 +\par }\pard \ltrpar\ql \fi-360\li1440\ri0\sa100\nowidctlpar\wrapdefault\faauto\rin0\lin1440\itap0 {\rtlch\fcs1 \af10\afs20 \ltrch\fcs0 \f10\fs20\insrsid8745415 \loch\af10\dbch\af31505\hich\f10 \'a7\tab }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 clearly state in marketing materials, documentation and other materials related to the Kinect }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid3949644 \hich\af39\dbch\af31505\loch\f39 v}{\rtlch\fcs1 +\af39\afs20 \ltrch\fcs0 \fs20\insrsid13329978 \hich\af39\dbch\af31505\loch\f39 2}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 Application (e.g. on the webpages on whi\hich\af39\dbch\af31505\loch\f39 +ch the Kinect }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid13329978 \hich\af39\dbch\af31505\loch\f39 V2 }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 Application is described or from which the Kinect }{ +\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid13329978 \hich\af39\dbch\af31505\loch\f39 V2}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 + Application may be downloaded or otherwise obtained), that it is intended for use only with the Kinect }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid13329978 \hich\af39\dbch\af31505\loch\f39 V2}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid16457108 \hich\af39\dbch\af31505\loch\f39 S}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 ensor; +\par }\pard \ltrpar\ql \fi-360\li1440\ri0\sb120\sa120\nowidctlpar\wrapdefault\faauto\rin0\lin1440\itap0 {\rtlch\fcs1 \af10\afs20 \ltrch\fcs0 \f10\fs20\insrsid8745415 \loch\af10\dbch\af31505\hich\f10 \'a7\tab }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 require }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid3949644 \hich\af39\dbch\af31505\loch\f39 licensees, }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 +\hich\af39\dbch\af31505\loch\f39 distributors and external end users to agree to }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid3949644 \hich\af39\dbch\af31505\loch\f39 license }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 +\hich\af39\dbch\af31505\loch\f39 terms that}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid3949644 \hich\af39\dbch\af31505\loch\f39 are as protective of Microsoft\hich\f39 \rquote \loch\f39 +s rights and interests in the Distributable Code as stated in this agreement; and }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f0\fs20\insrsid8745415 +\par }\pard \ltrpar\ql \fi-360\li1440\ri0\sa100\nowidctlpar\wrapdefault\faauto\rin0\lin1440\itap0 {\rtlch\fcs1 \af10\afs20 \ltrch\fcs0 \f10\fs20\insrsid8745415 \loch\af10\dbch\af31505\hich\f10 \'a7\tab }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 display your valid copyright notice on your Kinect }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid3949644 \hich\af39\dbch\af31505\loch\f39 v}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\insrsid13329978 \hich\af39\dbch\af31505\loch\f39 2}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 Applications}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid8745415 . +\par }\pard\plain \ltrpar\s3\ql \fi-357\li1077\ri0\sb120\sa120\nowidctlpar\tx1077\tx1440\wrapdefault\faauto\outlinelevel2\rin0\lin1077\itap0 \rtlch\fcs1 \af39\afs24\alang1025 \ltrch\fcs0 +\fs24\lang1033\langfe1033\loch\af39\hich\af39\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 iii.\tab Distribution Restrictions. You may not: +\par }\pard\plain \ltrpar\ql \fi-358\li1435\ri0\sb120\sa120\nowidctlpar\tx1437\wrapdefault\faauto\rin0\lin1435\itap0 \rtlch\fcs1 \af39\afs24\alang1025 \ltrch\fcs0 \fs24\lang1033\langfe1033\loch\af39\hich\af39\dbch\af31505\cgrid\langnp1033\langfenp1033 { +\rtlch\fcs1 \af3\afs20 \ltrch\fcs0 \f3\fs20\insrsid8745415 \loch\af3\dbch\af31505\hich\f3 \'b7\tab }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 alter\hich\af39\dbch\af31505\loch\f39 + any copyright, trademark or patent notice in the Distributable Code; +\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \f10\fs20\insrsid13329978 \loch\af10\dbch\af31505\hich\f10 \'a7\tab}}\pard \ltrpar\ql \fi-360\li1440\ri0\sb120\sa120\nowidctlpar +\tx1437\wrapdefault\faauto\ls2\rin0\lin1440\itap0\pararsid11829074 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid13329978 \hich\af39\dbch\af31505\loch\f39 +License the Microsoft Distributable Code in a manner inconsistent with the terms of this License. +\par }\pard \ltrpar\ql \fi-358\li1435\ri0\sb120\sa120\nowidctlpar\tx1437\wrapdefault\faauto\rin0\lin1435\itap0 {\rtlch\fcs1 \af3\afs20 \ltrch\fcs0 \f3\fs20\insrsid8745415 \loch\af3\dbch\af31505\hich\f3 \'b7\tab }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 use Microsoft\hich\f39 \rquote \loch\f39 s trademarks, including but not limited to Microsoft, Kinect and Window\hich\af39\dbch\af31505\loch\f39 s, in your Kinect }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\insrsid3949644 \hich\af39\dbch\af31505\loch\f39 v2}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 Applications\hich\f39 \rquote \loch\f39 names or in a way that suggests your Kinect for }{\rtlch\fcs1 +\af39\afs20 \ltrch\fcs0 \fs20\insrsid3949644 \hich\af39\dbch\af31505\loch\f39 v2 }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 Applications come from or are endorsed by Microsoft; +\par }\pard \ltrpar\ql \fi-358\li1435\ri0\sb120\sa120\nowidctlpar\wrapdefault\faauto\rin0\lin1435\itap0 {\rtlch\fcs1 \af3\afs20 \ltrch\fcs0 \f3\fs20\insrsid8745415 \loch\af3\dbch\af31505\hich\f3 \'b7\tab }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 distribute Distributable Code to run on a platform other than a Microsoft Windows operating system; +\par }\pard \ltrpar\ql \fi-360\li1437\ri0\sb120\sa120\nowidctlpar\wrapdefault\faauto\rin0\lin1437\itap0 {\rtlch\fcs1 \af3\afs20 \ltrch\fcs0 \f3\fs20\insrsid8745415 \loch\af3\dbch\af31505\hich\f3 \'b7\tab }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 include Distr\hich\af39\dbch\af31505\loch\f39 ibutable Code in malicious, obscene, deceptive or unlawful programs; +\par }\pard \ltrpar\ql \fi-358\li1435\ri0\sb120\sa120\nowidctlpar\tx1437\wrapdefault\faauto\rin0\lin1435\itap0 {\rtlch\fcs1 \af3\afs20 \ltrch\fcs0 \f3\fs20\insrsid8745415 \loch\af3\dbch\af31505\hich\f3 \'b7\tab }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 include Distributable Code for any programs designed or intended for High Risk Use; or}{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \f0\fs20\insrsid8745415 +\par }{\rtlch\fcs1 \af3\afs20 \ltrch\fcs0 \f3\fs20\insrsid8745415 \loch\af3\dbch\af31505\hich\f3 \'b7\tab }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 +modify or distribute the source code of any Distributable Code so that any part of it becomes su\hich\af39\dbch\af31505\loch\f39 +bject to an Excluded License. An Excluded License is one that requires, as a condition of use, modification or distribution, that}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid8745415 +\par }\pard \ltrpar\ql \fi-357\li1792\ri0\sb120\sa120\nowidctlpar\tx1795\wrapdefault\faauto\rin0\lin1792\itap0 {\rtlch\fcs1 \af3\afs20 \ltrch\fcs0 \f3\fs20\insrsid8745415 \loch\af3\dbch\af31505\hich\f3 \'b7\tab }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 the code be disclosed or distributed in source code form; or +\par }\pard \ltrpar\ql \fi-357\li1792\ri0\sb120\sa120\nowidctlpar\wrapdefault\faauto\rin0\lin1792\itap0 {\rtlch\fcs1 \af3\afs20 \ltrch\fcs0 \f3\fs20\insrsid8745415 \loch\af3\dbch\af31505\hich\f3 \'b7\tab }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 others have the right to modify it. +\par }\pard \ltrpar\ql \li0\ri0\sb200\sa100\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \ab\af1\afs20 \ltrch\fcs0 \b\f1\fs20\insrsid8745415 \hich\af1\dbch\af31505\loch\f1 3. }{\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\fs20\insrsid8745415 +\hich\af39\dbch\af31505\loch\f39 SCOPE OF LICENSE.}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 + The software is licensed, not sold. This agreement only gives you some rights to use the software. Microsoft reserves all other rights. Unless applicable law gives you more rights despite this limitation, you may use the software only as expressly permit +\hich\af39\dbch\af31505\loch\f39 t\hich\af39\dbch\af31505\loch\f39 ed in this agreement. In doing so, you must comply with any technical limitations in the software that only allow you to use it in certain ways. You may not:}{\rtlch\fcs1 \af1\afs20 +\ltrch\fcs0 \f1\fs20\insrsid8745415 +\par }\pard \ltrpar\ql \fi-360\li720\ri0\sa100\nowidctlpar\wrapdefault\faauto\rin0\lin720\itap0 {\rtlch\fcs1 \af3\afs20 \ltrch\fcs0 \f3\fs20\cf1\insrsid8745415 \loch\af3\dbch\af31505\hich\f3 \'b7\tab }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 +\hich\af39\dbch\af31505\loch\f39 access or use, or attempt to access or use, features of the Kinect }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid3949644 \hich\af39\dbch\af31505\loch\f39 v2 }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 +\hich\af39\dbch\af31505\loch\f39 Sensor that are not \hich\af39\dbch\af31505\loch\f39 exposed or enabled by the software; +\par }{\rtlch\fcs1 \af3\afs20 \ltrch\fcs0 \f3\fs20\cf1\insrsid8745415 \loch\af3\dbch\af31505\hich\f3 \'b7\tab }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415\charrsid1909739 \hich\af39\dbch\af31505\loch\f39 distribute Kinect }{\rtlch\fcs1 +\af39\afs20 \ltrch\fcs0 \fs20\insrsid3949644\charrsid1909739 \hich\af39\dbch\af31505\loch\f39 v2}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415\charrsid1909739 \hich\af39\dbch\af31505\loch\f39 Applications for use with any sensor other than }{ +\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid11871500\charrsid1909739 \hich\af39\dbch\af31505\loch\f39 the }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415\charrsid1909739 \hich\af39\dbch\af31505\loch\f39 Kinect }{\rtlch\fcs1 \af39\afs20 +\ltrch\fcs0 \fs20\insrsid3949644\charrsid1909739 \hich\af39\dbch\af31505\loch\f39 v2}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid16457108\charrsid1909739 \hich\af39\dbch\af31505\loch\f39 Sensor}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\insrsid14225958 \hich\af39\dbch\af31505\loch\f39 or }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415\charrsid1909739 \hich\af39\dbch\af31505\loch\f39 its associated drivers and runtime software;}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid8745415 +\par }\pard \ltrpar\ql \fi-360\li720\ri0\sb200\sa100\nowidctlpar\wrapdefault\faauto\rin0\lin720\itap0 {\rtlch\fcs1 \af3\afs20 \ltrch\fcs0 \f3\fs20\cf1\insrsid8745415 \loch\af3\dbch\af31505\hich\f3 \'b7\tab }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 use the software or any Kinect }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid3949644 \hich\af39\dbch\af31505\loch\f39 v2}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 +\hich\af39\dbch\af31505\loch\f39 Applications in any High Risk Use; }{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid8745415 +\par }\pard \ltrpar\ql \fi-360\li720\ri0\sa100\nowidctlpar\wrapdefault\faauto\rin0\lin720\itap0 {\rtlch\fcs1 \af3\afs20 \ltrch\fcs0 \f3\fs20\cf1\insrsid8745415 \loch\af3\dbch\af31505\hich\f3 \'b7\tab }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 +\hich\af39\dbch\af31505\loch\f39 work \hich\af39\dbch\af31505\loch\f39 around any technical limitations in the software; +\par }{\rtlch\fcs1 \af3\afs20 \ltrch\fcs0 \f3\fs20\cf1\insrsid8745415 \loch\af3\dbch\af31505\hich\f3 \'b7\tab }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 +reverse engineer, decompile, or disassemble any part of the software not provided in source code form, except and only to the extent that applicable law expressly permits, despite this limitation; +\par }\pard \ltrpar\ql \fi-360\li720\ri0\sb200\sa100\nowidctlpar\wrapdefault\faauto\rin0\lin720\itap0 {\rtlch\fcs1 \af3\afs20 \ltrch\fcs0 \f3\fs20\cf1\insrsid8745415 \loch\af3\dbch\af31505\hich\f3 \'b7\tab }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 publi\hich\af39\dbch\af31505\loch\f39 sh the software for others to copy; +\par }\pard \ltrpar\ql \fi-360\li720\ri0\sa100\nowidctlpar\wrapdefault\faauto\rin0\lin720\itap0 {\rtlch\fcs1 \af3\afs20 \ltrch\fcs0 \f3\fs20\cf1\insrsid8745415 \loch\af3\dbch\af31505\hich\f3 \'b7\tab }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 +\hich\af39\dbch\af31505\loch\f39 rent, lease, or lend the software; +\par }\pard \ltrpar\ql \fi-360\li720\ri0\sb200\sa100\nowidctlpar\wrapdefault\faauto\rin0\lin720\itap0 {\rtlch\fcs1 \af3\afs20 \ltrch\fcs0 \f3\fs20\cf1\insrsid8745415 \loch\af3\dbch\af31505\hich\f3 \'b7\tab }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 transfer the software or this agreement to any third party; or +\par }\pard \ltrpar\ql \fi-360\li720\ri0\sb200\sa100\nowidctlpar\wrapdefault\faauto\rin0\lin720\itap0\pararsid11829074 {\rtlch\fcs1 \af3\afs20 \ltrch\fcs0 \f3\fs20\cf1\insrsid8745415 \loch\af3\dbch\af31505\hich\f3 \'b7\tab }{\rtlch\fcs1 \af39\afs20 +\ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 use the software for commercial software hosting services.}{\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\insrsid8745415 +\par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 4. REGULATORY COMPLIANCE. }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 You agree that your developmen\hich\af39\dbch\af31505\loch\f39 t, marketing, sales, and distribution of Kinect }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid3949644 +\hich\af39\dbch\af31505\loch\f39 v2}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 + Applications shall be in compliance with all applicable legal requirements, including compliance with the medical device regulatory requirements of the U.S. Federal Food, Drug, and Cosmetic Act and any ass\hich\af39\dbch\af31505\loch\f39 +ociated requirements, or similar laws, regulations, or policies in other countries or territories.\~ + To the extent required by law, you are solely responsible for obtaining or filing any approval, clearance, registration, permit, or other regulatory author\hich\af39\dbch\af31505\loch\f39 i\hich\af39\dbch\af31505\loch\f39 +zation and shall comply with the requirements of such authorization. +\par }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\cf19\insrsid8745415 +\par }{\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 5. ACKNOWLEDGEMENT AND WAIVER. }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 +You acknowledge the software may allow you to control the Kinect }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid16457108 \hich\af39\dbch\af31505\loch\f39 v2 }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 +Sensor, which are mechanical hardware devices that include motors to move the device, \hich\af39\dbch\af31505\loch\f39 +a fan to cool it, and other mechanical components. Depending on how you elect to use the software, you could harm persons or damage or destroy the Kinect}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid2042763 \hich\af39\dbch\af31505\loch\f39 v2}{ +\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 Sensor, products incorporating the Kinect}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid2042763 \hich\af39\dbch\af31505\loch\f39 v2}{\rtlch\fcs1 \af39\afs20 +\ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 Sensor, or other property. In using the software, you must take steps to design and test your Kinect }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid2042763 +\hich\af39\dbch\af31505\loch\f39 v2 }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 +Applications to ensure that your applications do not present unreasonable risks of personal injury or death, property damage, or other losses. Kinect }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid2042763 \hich\af39\dbch\af31505\loch\f39 v +\hich\af39\dbch\af31505\loch\f39 2 }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 +Sensors utilize complex hardware and software technology that may not always function as intended. You must design your application so that any failure of a Kinect }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid2042763 +\hich\af39\dbch\af31505\loch\f39 v2 }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 Sensor and/or the software does not cause personal injury or death, property damage, or\hich\af39\dbch\af31505\loch\f39 + other losses. If you choose to use the software, you assume all risk that your use of the Kinect }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid2042763 \hich\af39\dbch\af31505\loch\f39 v2 }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 +\hich\af39\dbch\af31505\loch\f39 Sensors and/or the software causes any harm or loss, including to the end users of your Kinect }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid2042763 \hich\af39\dbch\af31505\loch\f39 v2}{\rtlch\fcs1 \af39\afs20 +\ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 Applications, and you agree to waive all claims against M\hich\af39\dbch\af31505\loch\f39 +icrosoft and its affiliates related to such use (including but not limited to any claim that a Kinect }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid2042763 \hich\af39\dbch\af31505\loch\f39 v2 }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 Sensor or the software is defective) and to hold Microsoft and its affiliates harmless from such claims. +\par }\pard \ltrpar\ql \li0\ri0\sb200\sa100\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 6. INDEMNIFICATION. }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 You agree to indemnify, \hich\af39\dbch\af31505\loch\f39 defend, and hold harmless Microsoft and its affiliates from any claims, including attorneys\hich\f39 \rquote \loch\f39 + fees, related to the distribution or use of your Kinect }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid2042763 \hich\af39\dbch\af31505\loch\f39 v2}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 + Applications. +\par }{\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 7. BACKUP COPY.}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 + You may make one backup copy of the software. You may use it only to reins\hich\af39\dbch\af31505\loch\f39 tall the software. +\par }{\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 8. DOCUMENTATION.}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 Any person }{\rtlch\fcs1 \af39\afs20 +\ltrch\fcs0 \fs20\insrsid1909739 \hich\af39\dbch\af31505\loch\f39 who }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 +has valid access to your computer or internal network may copy and use the documentation for your internal, reference purposes. +\par }\pard \ltrpar\ql \fi-360\li360\ri0\sb200\sa100\nowidctlpar\wrapdefault\faauto\rin0\lin360\itap0 {\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 9. SUPPORT SERVICES.}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 \hich\f39 Because this software is \'93\loch\f39 \hich\f39 as is,\'94\loch\f39 we may not provide\hich\af39\dbch\af31505\loch\f39 support services for it. +\par }\pard \ltrpar\ql \fi-360\li360\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin360\itap0 {\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 10.}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 +\hich\af39\dbch\af31505\loch\f39 }{\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 EXPORT RESTRICTIONS.}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 + The software is subject to United States export laws and regulations. You must comply with all domestic and international export laws and regulations that apply to the software. These laws include restrict\hich\af39\dbch\af31505\loch\f39 +ions on destinations, end users, and end use. For additional information, see }{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\ul\cf2\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 www.microsoft.com/exporting}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\insrsid8745415 .}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\ul\insrsid8745415 +\par }{\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 11. ENTIRE AGREEMENT.}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 + This agreement, and the terms for supplements, updates, Internet-based services and support services that you use, are the enti\hich\af39\dbch\af31505\loch\f39 re agreement for the software and support services. +\par }{\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 12. APPLICABLE LAW. +\par }\pard \ltrpar\ql \li360\ri0\sa100\nowidctlpar\wrapdefault\faauto\rin0\lin360\itap0 {\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 a. United States.}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 + If you acquired the software in the United States, Washington state law governs the interpretation of this agreement and applies to claims for breach of it, regardless of conflict of laws principles. The laws of the state where you live govern all other +\hich\af39\dbch\af31505\loch\f39 c\hich\af39\dbch\af31505\loch\f39 laims, including claims under state consumer protection laws, unfair competition laws, and in tort. +\par }{\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 b. Outside the United States.}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 + If you acquired the software in any other country, the laws of that country apply. +\par }\pard \ltrpar\ql \fi-360\li360\ri0\sb200\sa100\nowidctlpar\wrapdefault\faauto\rin0\lin360\itap0 {\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 13. LEGAL EFFECT.}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 +\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 This agreement describes \hich\af39\dbch\af31505\loch\f39 +certain legal rights. You may have other rights under the laws of your state, province or country. This agreement does not change your rights under the laws of your state, province or country if the laws of your state, province or country do not permit it +\hich\af39\dbch\af31505\loch\f39 \hich\af39\dbch\af31505\loch\f39 to do so. +\par }{\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 \hich\f39 14. DISCLAIMER OF WARRANTY. The software is licensed \'93\loch\f39 \hich\f39 as-is.\'94\loch\f39 + You bear all risk of using it. Microsoft gives no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws that this agreement cannot\hich\af39\dbch\af31505\loch\f39 + change. To the extent permitted under your local laws, Microsoft excludes the implied warranties of merchantability, fitness for a particular purpose, and non-infringement.}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 +\par }{\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 15. LIMITATION ON AND EXCLUSION OF REMEDIES AND DAMAGES. You can recover from Micr\hich\af39\dbch\af31505\loch\f39 +osoft and its suppliers only direct damages up to U.S. $5.00. You cannot recover any other damages, including consequential, lost profits, special, indirect or incidental damages.}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 +\par }\pard \ltrpar\ql \li360\ri0\sa100\nowidctlpar\wrapdefault\faauto\rin0\lin360\itap0 {\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 This limitation applies to +\par }{\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 a.}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 anything related to the software, services, co +\hich\af39\dbch\af31505\loch\f39 ntent (including code) on third party Internet sites, or third party programs; and +\par }{\rtlch\fcs1 \ab\af39\afs20 \ltrch\fcs0 \b\fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 b.}{\rtlch\fcs1 \af39\afs20 \ltrch\fcs0 \fs20\insrsid8745415 \hich\af39\dbch\af31505\loch\f39 + claims for breach of contract; breach of warranty, guarantee, or condition; strict liability, negligence, or other tort, to the extent permitted by applicable law. +\par \hich\af39\dbch\af31505\loch\f39 It als\hich\af39\dbch\af31505\loch\f39 +o applies even if Microsoft knew or should have known about the possibility of the damages. The above limitation or exclusion may not apply to you because your state, province or country may not allow the exclusion or limitation of incidental, consequenti +\hich\af39\dbch\af31505\loch\f39 a\hich\af39\dbch\af31505\loch\f39 l, or other damages. +\par }{\*\themedata 504b030414000600080000002100e9de0fbfff0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb4ec3301045f748fc83e52d4a +9cb2400825e982c78ec7a27cc0c8992416c9d8b2a755fbf74cd25442a820166c2cd933f79e3be372bd1f07b5c3989ca74aaff2422b24eb1b475da5df374fd9ad +5689811a183c61a50f98f4babebc2837878049899a52a57be670674cb23d8e90721f90a4d2fa3802cb35762680fd800ecd7551dc18eb899138e3c943d7e503b6 +b01d583deee5f99824e290b4ba3f364eac4a430883b3c092d4eca8f946c916422ecab927f52ea42b89a1cd59c254f919b0e85e6535d135a8de20f20b8c12c3b0 +0c895fcf6720192de6bf3b9e89ecdbd6596cbcdd8eb28e7c365ecc4ec1ff1460f53fe813d3cc7f5b7f020000ffff0300504b030414000600080000002100a5d6 +a7e7c0000000360100000b0000005f72656c732f2e72656c73848fcf6ac3300c87ef85bd83d17d51d2c31825762fa590432fa37d00e1287f68221bdb1bebdb4f +c7060abb0884a4eff7a93dfeae8bf9e194e720169aaa06c3e2433fcb68e1763dbf7f82c985a4a725085b787086a37bdbb55fbc50d1a33ccd311ba548b6309512 +0f88d94fbc52ae4264d1c910d24a45db3462247fa791715fd71f989e19e0364cd3f51652d73760ae8fa8c9ffb3c330cc9e4fc17faf2ce545046e37944c69e462 +a1a82fe353bd90a865aad41ed0b5b8f9d6fd010000ffff0300504b0304140006000800000021006b799616830000008a0000001c0000007468656d652f746865 +6d652f7468656d654d616e616765722e786d6c0ccc4d0ac3201040e17da17790d93763bb284562b2cbaebbf600439c1a41c7a0d29fdbd7e5e38337cedf14d59b +4b0d592c9c070d8a65cd2e88b7f07c2ca71ba8da481cc52c6ce1c715e6e97818c9b48d13df49c873517d23d59085adb5dd20d6b52bd521ef2cdd5eb9246a3d8b +4757e8d3f729e245eb2b260a0238fd010000ffff0300504b030414000600080000002100aa5225dfc60600008b1a0000160000007468656d652f7468656d652f +7468656d65312e786d6cec595d8bdb46147d2ff43f08bd3bfe92fcb1c41b6cd9ceb6d94d42eca4e4716c8fadc98e344633de8d0981923c160aa569e943037deb +43691b48a02fe9afd936a54d217fa17746b63c638fbb9b2585a5640d8b343af7ce997bafce1d4997afdc8fa87384134e58dc708b970aae83e3211b9178d2706f +f7bbb99aeb7081e211a22cc60d778eb97b65f7c30f2ea31d11e2083b601ff31dd4704321a63bf93c1fc230e297d814c7706dcc920809384d26f951828ec16f44 +f3a542a1928f10895d274611b8bd311e932176fad2a5bbbb74dea1701a0b2e078634e949d7d8b050d8d1615122f89c0734718e106db830cf881df7f17de13a14 +7101171a6e41fdb9f9ddcb79b4b330a2628bad66d7557f0bbb85c1e8b0a4e64c26836c52cff3bd4a33f3af00546ce23ad54ea553c9fc29001a0e61a52917dda7 +dfaab7dafe02ab81d2438bef76b55d2e1a78cd7f798373d3973f03af40a97f6f03dfed06104503af4029dedfc07b5eb51478065e81527c65035f2d34db5ed5c0 +2b5048497cb8812ef89572b05c6d061933ba6785d77daf5b2d2d9caf50500d5975c929c62c16db6a2d42f758d2058004522448ec88f9148fd110aa3840940c12 +e2ec93490885374531e3305c2815ba8532fc973f4f1da988a01d8c346bc90b98f08d21c9c7e1c3844c45c3fd18bcba1ae4cdcb1fdfbc7cee9c3c7a71f2e89793 +c78f4f1efd9c3a32acf6503cd1ad5e7fffc5df4f3f75fe7afeddeb275fd9f15cc7fffed367bffdfaa51d082b5d85e0d5d7cffe78f1ecd5379ffff9c3130bbc99 +a0810eef930873e73a3e766eb10816a6426032c783e4ed2cfa2122ba45339e701423398bc57f478406fafa1c5164c1b5b019c13b09488c0d787576cf20dc0b93 +9920168fd7c2c8001e30465b2cb146e19a9c4b0b737f164fec9327331d770ba123dbdc018a8dfc766653d05662731984d8a07993a258a0098eb170e4357688b1 +6575770931e27a408609e36c2c9cbbc46921620d499f0c8c6a5a19ed9108f232b711847c1bb139b8e3b418b5adba8d8f4c24dc15885ac8f73135c27815cd048a +6c2efb28a27ac0f791086d247bf364a8e33a5c40a6279832a733c29cdb6c6e24b05e2de9d7405eec693fa0f3c84426821cda7cee23c674649b1d06218aa6366c +8fc4a18efd881f428922e7261336f80133ef10790e7940f1d674df21d848f7e96a701b9455a7b42a107965965872791533a37e7b733a4658490d08bfa1e71189 +4f15f73559f7ff5b5907217df5ed53cbaa2eaaa0371362bda3f6d6647c1b6e5dbc03968cc8c5d7ee369ac53731dc2e9b0decbd74bf976ef77f2fdddbeee7772f +d82b8d06f9965bc574abae36eed1d67dfb9850da13738af7b9daba73e84ca32e0c4a3bf5cc8ab3e7b8690887f24e86090cdc2441cac64998f88488b017a229ec +ef8bae7432e10bd713ee4c19876dbf1ab6fa96783a8b0ed8287d5c2d16e5a3692a1e1c89d578c1cfc6e15143a4e84a75f50896b9576c27ea51794940dabe0d09 +6d329344d942a2ba1c9441520fe610340b09b5b277c2a26e615193ee97a9da6001d4b2acc0d6c9810d57c3f53d30012378a242148f649ed2542fb3ab92f92e33 +bd2d984605c03e625901ab4cd725d7adcb93ab4b4bed0c99364868e566925091513d8c87688417d52947cf42e36d735d5fa5d4a02743a1e683d25ad1a8d6fe8d +c579730d76ebda40635d2968ec1c37dc4ad9879219a269c31dc3633f1c4653a81d2eb7bc884ee0ddd95024e90d7f1e6599265cb4110fd3802bd149d520220227 +0e2551c395cbcfd24063a5218a5bb104827061c9d541562e1a3948ba99643c1ee3a1d0d3ae8dc848a7a7a0f0a95658af2af3f383a5259b41ba7be1e8d819d059 +720b4189f9d5a20ce0887078fb534ca33922f03a3313b255fdad35a685eceaef13550da5e3884e43b4e828ba98a77025e5191d7596c5403b5bac1902aa8564d1 +080713d960f5a01add34eb1a2987ad5df7742319394d34573dd35015d935ed2a66ccb06c036bb13c5f93d7582d430c9aa677f854bad725b7bed4bab57d42d625 +20e059fc2c5df70c0d41a3b69acca026196fcab0d4ecc5a8d93b960b3c85da599a84a6fa95a5dbb5b8653dc23a1d0c9eabf383dd7ad5c2d078b9af549156df3d +f44f136c700fc4a30d2f81675470954af8f09020d810f5d49e24950db845ee8bc5ad0147ce2c210df741c16f7a41c90f72859adfc97965af90abf9cd72aee9fb +e562c72f16daadd243682c228c8a7efacda50bafa2e87cf1e5458d6f7c7d89966fdb2e0d599467eaeb4a5e11575f5f8aa5ed5f5f1c02a2f3a052ead6cbf55625 +572f37bb39afddaae5ea41a5956b57826abbdb0efc5abdfbd0758e14d86b9603afd2a9e52ac520c8799582a45fabe7aa5ea9d4f4aacd5ac76b3e5c6c6360e5a9 +7c2c6201e155bc76ff010000ffff0300504b0304140006000800000021000dd1909fb60000001b010000270000007468656d652f7468656d652f5f72656c732f +7468656d654d616e616765722e786d6c2e72656c73848f4d0ac2301484f78277086f6fd3ba109126dd88d0add40384e4350d363f2451eced0dae2c082e8761be +9969bb979dc9136332de3168aa1a083ae995719ac16db8ec8e4052164e89d93b64b060828e6f37ed1567914b284d262452282e3198720e274a939cd08a54f980 +ae38a38f56e422a3a641c8bbd048f7757da0f19b017cc524bd62107bd5001996509affb3fd381a89672f1f165dfe514173d9850528a2c6cce0239baa4c04ca5b +babac4df000000ffff0300504b01022d0014000600080000002100e9de0fbfff0000001c0200001300000000000000000000000000000000005b436f6e74656e +745f54797065735d2e786d6c504b01022d0014000600080000002100a5d6a7e7c0000000360100000b00000000000000000000000000300100005f72656c732f +2e72656c73504b01022d00140006000800000021006b799616830000008a0000001c00000000000000000000000000190200007468656d652f7468656d652f74 +68656d654d616e616765722e786d6c504b01022d0014000600080000002100aa5225dfc60600008b1a00001600000000000000000000000000d6020000746865 +6d652f7468656d652f7468656d65312e786d6c504b01022d00140006000800000021000dd1909fb60000001b0100002700000000000000000000000000d00900007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73504b050600000000050005005d010000cb0a00000000} +{\*\colorschememapping 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d22796573223f3e0d0a3c613a636c724d +617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169 +6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363 +656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e} +{\*\latentstyles\lsdstimax371\lsdlockeddef0\lsdsemihiddendef0\lsdunhideuseddef0\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal;\lsdqformat1 \lsdlocked0 heading 1;\lsdqformat1 \lsdlocked0 heading 2; +\lsdqformat1 \lsdlocked0 heading 3;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5; +\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8; +\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 3; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 6;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 7; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 8;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 9;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 1;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 2; +\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 3;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 4;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 5; +\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 6;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 7;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 8; +\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 9;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal Indent;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footnote text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation text; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 header;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footer;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index heading;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority35 \lsdlocked0 caption; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 table of figures;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 envelope address;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 envelope return;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footnote reference; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation reference;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 line number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 page number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 endnote reference; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 endnote text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 table of authorities;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 macro;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 toa heading; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 2; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 2; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 2; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 5;\lsdqformat1 \lsdpriority10 \lsdlocked0 Title; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Closing;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Signature;\lsdsemihidden1 \lsdunhideused1 \lsdpriority1 \lsdlocked0 Default Paragraph Font;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 3; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Message Header;\lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Salutation;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Date;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text First Indent;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text First Indent 2; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Heading;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent 2; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Block Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Hyperlink;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 FollowedHyperlink; +\lsdqformat1 \lsdpriority22 \lsdlocked0 Strong;\lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Document Map;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Plain Text; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 E-mail Signature;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Top of Form;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Bottom of Form;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal (Web); +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Acronym;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Address;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Cite;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Code; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Definition;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Keyboard;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Preformatted;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Sample; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Typewriter;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Variable;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal Table;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation subject; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 No List;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 3; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Simple 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Simple 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Simple 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Classic 1; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Classic 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Classic 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Classic 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Colorful 1; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Colorful 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Colorful 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 2; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 1; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 5; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 6;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 8;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 1; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 5; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 6;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 8;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table 3D effects 1; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table 3D effects 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table 3D effects 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Contemporary;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Elegant; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Professional;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Subtle 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Subtle 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Web 1; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Web 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Web 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Balloon Text;\lsdpriority39 \lsdlocked0 Table Grid; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Theme;\lsdsemihidden1 \lsdlocked0 Placeholder Text;\lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing;\lsdpriority60 \lsdlocked0 Light Shading;\lsdpriority61 \lsdlocked0 Light List; +\lsdpriority62 \lsdlocked0 Light Grid;\lsdpriority63 \lsdlocked0 Medium Shading 1;\lsdpriority64 \lsdlocked0 Medium Shading 2;\lsdpriority65 \lsdlocked0 Medium List 1;\lsdpriority66 \lsdlocked0 Medium List 2;\lsdpriority67 \lsdlocked0 Medium Grid 1; +\lsdpriority68 \lsdlocked0 Medium Grid 2;\lsdpriority69 \lsdlocked0 Medium Grid 3;\lsdpriority70 \lsdlocked0 Dark List;\lsdpriority71 \lsdlocked0 Colorful Shading;\lsdpriority72 \lsdlocked0 Colorful List;\lsdpriority73 \lsdlocked0 Colorful Grid; +\lsdpriority60 \lsdlocked0 Light Shading Accent 1;\lsdpriority61 \lsdlocked0 Light List Accent 1;\lsdpriority62 \lsdlocked0 Light Grid Accent 1;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1; +\lsdpriority65 \lsdlocked0 Medium List 1 Accent 1;\lsdsemihidden1 \lsdlocked0 Revision;\lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;\lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;\lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote; +\lsdpriority66 \lsdlocked0 Medium List 2 Accent 1;\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;\lsdpriority70 \lsdlocked0 Dark List Accent 1; +\lsdpriority71 \lsdlocked0 Colorful Shading Accent 1;\lsdpriority72 \lsdlocked0 Colorful List Accent 1;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;\lsdpriority60 \lsdlocked0 Light Shading Accent 2;\lsdpriority61 \lsdlocked0 Light List Accent 2; +\lsdpriority62 \lsdlocked0 Light Grid Accent 2;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 2; +\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2;\lsdpriority70 \lsdlocked0 Dark List Accent 2;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 2; +\lsdpriority72 \lsdlocked0 Colorful List Accent 2;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 2;\lsdpriority60 \lsdlocked0 Light Shading Accent 3;\lsdpriority61 \lsdlocked0 Light List Accent 3;\lsdpriority62 \lsdlocked0 Light Grid Accent 3; +\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 3; +\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3;\lsdpriority70 \lsdlocked0 Dark List Accent 3;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 3; +\lsdpriority72 \lsdlocked0 Colorful List Accent 3;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 3;\lsdpriority60 \lsdlocked0 Light Shading Accent 4;\lsdpriority61 \lsdlocked0 Light List Accent 4;\lsdpriority62 \lsdlocked0 Light Grid Accent 4; +\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 4;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 4; +\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;\lsdpriority70 \lsdlocked0 Dark List Accent 4;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 4; +\lsdpriority72 \lsdlocked0 Colorful List Accent 4;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;\lsdpriority60 \lsdlocked0 Light Shading Accent 5;\lsdpriority61 \lsdlocked0 Light List Accent 5;\lsdpriority62 \lsdlocked0 Light Grid Accent 5; +\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 5; +\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5;\lsdpriority70 \lsdlocked0 Dark List Accent 5;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 5; +\lsdpriority72 \lsdlocked0 Colorful List Accent 5;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;\lsdpriority60 \lsdlocked0 Light Shading Accent 6;\lsdpriority61 \lsdlocked0 Light List Accent 6;\lsdpriority62 \lsdlocked0 Light Grid Accent 6; +\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 6; +\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;\lsdpriority70 \lsdlocked0 Dark List Accent 6;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 6; +\lsdpriority72 \lsdlocked0 Colorful List Accent 6;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 6;\lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;\lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis; +\lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;\lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference;\lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdsemihidden1 \lsdunhideused1 \lsdpriority37 \lsdlocked0 Bibliography; +\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;\lsdpriority41 \lsdlocked0 Plain Table 1;\lsdpriority42 \lsdlocked0 Plain Table 2;\lsdpriority43 \lsdlocked0 Plain Table 3;\lsdpriority44 \lsdlocked0 Plain Table 4; +\lsdpriority45 \lsdlocked0 Plain Table 5;\lsdpriority40 \lsdlocked0 Grid Table Light;\lsdpriority46 \lsdlocked0 Grid Table 1 Light;\lsdpriority47 \lsdlocked0 Grid Table 2;\lsdpriority48 \lsdlocked0 Grid Table 3;\lsdpriority49 \lsdlocked0 Grid Table 4; +\lsdpriority50 \lsdlocked0 Grid Table 5 Dark;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 1;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 1; +\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 1;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 1;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 1;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 1; +\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 1;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 2;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 2;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 2; +\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 2;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 2;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 2;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 2; +\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 3;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 3;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 3;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 3; +\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 3;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 3;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 3;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 4; +\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 4;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 4;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 4;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 4; +\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 4;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 4;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 5;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 5; +\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 5;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 5;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 5;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 5; +\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 5;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 6;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 6;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 6; +\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 6;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 6; +\lsdpriority46 \lsdlocked0 List Table 1 Light;\lsdpriority47 \lsdlocked0 List Table 2;\lsdpriority48 \lsdlocked0 List Table 3;\lsdpriority49 \lsdlocked0 List Table 4;\lsdpriority50 \lsdlocked0 List Table 5 Dark; +\lsdpriority51 \lsdlocked0 List Table 6 Colorful;\lsdpriority52 \lsdlocked0 List Table 7 Colorful;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 1;\lsdpriority47 \lsdlocked0 List Table 2 Accent 1;\lsdpriority48 \lsdlocked0 List Table 3 Accent 1; +\lsdpriority49 \lsdlocked0 List Table 4 Accent 1;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 1;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 1;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 1; +\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 2;\lsdpriority47 \lsdlocked0 List Table 2 Accent 2;\lsdpriority48 \lsdlocked0 List Table 3 Accent 2;\lsdpriority49 \lsdlocked0 List Table 4 Accent 2; +\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 2;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 2;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 2;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 3; +\lsdpriority47 \lsdlocked0 List Table 2 Accent 3;\lsdpriority48 \lsdlocked0 List Table 3 Accent 3;\lsdpriority49 \lsdlocked0 List Table 4 Accent 3;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 3; +\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 3;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 3;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 4;\lsdpriority47 \lsdlocked0 List Table 2 Accent 4; +\lsdpriority48 \lsdlocked0 List Table 3 Accent 4;\lsdpriority49 \lsdlocked0 List Table 4 Accent 4;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 4;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 4; +\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 4;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 5;\lsdpriority47 \lsdlocked0 List Table 2 Accent 5;\lsdpriority48 \lsdlocked0 List Table 3 Accent 5; +\lsdpriority49 \lsdlocked0 List Table 4 Accent 5;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 5;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 5;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 5; +\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 6;\lsdpriority47 \lsdlocked0 List Table 2 Accent 6;\lsdpriority48 \lsdlocked0 List Table 3 Accent 6;\lsdpriority49 \lsdlocked0 List Table 4 Accent 6; +\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 6;}}{\*\datastore 010500000200000018000000 +4d73786d6c322e534158584d4c5265616465722e362e3000000000000000000000060000 +d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff090006000000000000000000000001000000010000000000000000100000feffffff00000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +fffffffffffffffffdfffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffff0c6ad98892f1d411a65f0040963251e5000000000000000000000000f062 +dc4024c2cf01feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000105000000000000}} \ No newline at end of file -- cgit v1.2.3 From 388a876b68a83956b687100007aab7afafbb08ab Mon Sep 17 00:00:00 2001 From: Stéphane Lenclud Date: Sat, 2 Feb 2019 02:50:04 +0100 Subject: Kinect: Adding tracker icon. --- tracker-kinect-face/images/kinect.png | Bin 0 -> 217 bytes tracker-kinect-face/kinect.qrc | 5 +++++ tracker-kinect-face/lang/nl_NL.ts | 2 +- tracker-kinect-face/lang/ru_RU.ts | 2 +- tracker-kinect-face/lang/stub.ts | 2 +- tracker-kinect-face/lang/zh_CN.ts | 2 +- tracker-kinect-face/test.h | 4 ++-- 7 files changed, 11 insertions(+), 6 deletions(-) create mode 100644 tracker-kinect-face/images/kinect.png create mode 100644 tracker-kinect-face/kinect.qrc diff --git a/tracker-kinect-face/images/kinect.png b/tracker-kinect-face/images/kinect.png new file mode 100644 index 00000000..fd8f5f77 Binary files /dev/null and b/tracker-kinect-face/images/kinect.png differ diff --git a/tracker-kinect-face/kinect.qrc b/tracker-kinect-face/kinect.qrc new file mode 100644 index 00000000..8b27c81e --- /dev/null +++ b/tracker-kinect-face/kinect.qrc @@ -0,0 +1,5 @@ + + + images/kinect.png + + diff --git a/tracker-kinect-face/lang/nl_NL.ts b/tracker-kinect-face/lang/nl_NL.ts index b6139882..dec7a177 100644 --- a/tracker-kinect-face/lang/nl_NL.ts +++ b/tracker-kinect-face/lang/nl_NL.ts @@ -4,7 +4,7 @@ test_metadata - Kinect Face + Kinect Face - v0.1 diff --git a/tracker-kinect-face/lang/ru_RU.ts b/tracker-kinect-face/lang/ru_RU.ts index 52aab9f3..1634c0c2 100644 --- a/tracker-kinect-face/lang/ru_RU.ts +++ b/tracker-kinect-face/lang/ru_RU.ts @@ -4,7 +4,7 @@ test_metadata - Kinect Face + Kinect Face - v0.1 diff --git a/tracker-kinect-face/lang/stub.ts b/tracker-kinect-face/lang/stub.ts index 84a3c6af..bb36fb1e 100644 --- a/tracker-kinect-face/lang/stub.ts +++ b/tracker-kinect-face/lang/stub.ts @@ -4,7 +4,7 @@ test_metadata - Kinect Face + Kinect Face - v0.1 diff --git a/tracker-kinect-face/lang/zh_CN.ts b/tracker-kinect-face/lang/zh_CN.ts index 84a3c6af..bb36fb1e 100644 --- a/tracker-kinect-face/lang/zh_CN.ts +++ b/tracker-kinect-face/lang/zh_CN.ts @@ -4,7 +4,7 @@ test_metadata - Kinect Face + Kinect Face - v0.1 diff --git a/tracker-kinect-face/test.h b/tracker-kinect-face/test.h index 2e105ae3..1af0409b 100644 --- a/tracker-kinect-face/test.h +++ b/tracker-kinect-face/test.h @@ -22,7 +22,7 @@ class test_metadata : public Metadata { Q_OBJECT - QString name() { return tr("Kinect Face"); } - QIcon icon() { return QIcon(":/images/opentrack.png"); } + QString name() { return tr("Kinect Face - v0.1"); } + QIcon icon() { return QIcon(":/images/kinect.png"); } }; -- cgit v1.2.3 From ba8796acda06c9ae5f528dbbf655c714844d5429 Mon Sep 17 00:00:00 2001 From: Stéphane Lenclud Date: Sat, 2 Feb 2019 17:36:05 +0100 Subject: Various fixes from code review. --- tracker-kinect-face/CMakeLists.txt | 51 ++++++++++++++++++++------------------ tracker-kinect-face/lang/nl_NL.ts | 2 +- tracker-kinect-face/lang/ru_RU.ts | 2 +- tracker-kinect-face/lang/stub.ts | 2 +- tracker-kinect-face/lang/zh_CN.ts | 2 +- tracker-kinect-face/test.h | 2 +- tracker-kinect-face/tracker.cpp | 11 +++----- 7 files changed, 36 insertions(+), 36 deletions(-) diff --git a/tracker-kinect-face/CMakeLists.txt b/tracker-kinect-face/CMakeLists.txt index 9a37f2d8..fca1e495 100644 --- a/tracker-kinect-face/CMakeLists.txt +++ b/tracker-kinect-face/CMakeLists.txt @@ -1,29 +1,32 @@ +# Kinect SDK is Windows only +if (WIN32) + # Setup cache variable to Kinect SDK path + if(DEFINED ENV{KINECTSDK20_DIR}) + set(KINECTSDK20_DIR $ENV{KINECTSDK20_DIR} CACHE PATH $ENV{KINECTSDK20_DIR}) + else() + set(KINECTSDK20_DIR $ENV{KINECTSDK20_DIR} CACHE PATH "") + endif() -# Setup cache variable to Kinect SDK path -if(DEFINED ENV{KINECTSDK20_DIR}) - set(KINECTSDK20_DIR $ENV{KINECTSDK20_DIR} CACHE PATH $ENV{KINECTSDK20_DIR}) -else() - set(KINECTSDK20_DIR $ENV{KINECTSDK20_DIR} CACHE PATH "") -endif() + # If we have a valid SDK path, try build that tracker + if(EXISTS ${KINECTSDK20_DIR}) + # Register our module + otr_module(tracker-kinect-face) -# If we have a valid SDK path, try build that tracker -if(EXISTS ${KINECTSDK20_DIR}) - # Register our module - otr_module(tracker-kinect-face) - - # Add include path to Kinect SDK - target_include_directories(opentrack-tracker-kinect-face SYSTEM PUBLIC ${KINECTSDK20_DIR}/inc) + # Add include path to Kinect SDK + target_include_directories(opentrack-tracker-kinect-face SYSTEM PUBLIC ${KINECTSDK20_DIR}/inc) - # Check processor architecture - if(CMAKE_SIZEOF_VOID_P EQUAL 4) - # 32 bits - set (kinect-arch-dir "x86") - elseif(CMAKE_SIZEOF_VOID_P EQUAL 8) - # 64 bits - set (kinect-arch-dir "x64") - endif() + # Check processor architecture + if(CMAKE_SIZEOF_VOID_P EQUAL 4) + # 32 bits + set (kinect-arch-dir "x86") + elseif(CMAKE_SIZEOF_VOID_P EQUAL 8) + # 64 bits + set (kinect-arch-dir "x64") + endif() - # Link against Kinect SDK libraries - target_link_libraries(opentrack-tracker-kinect-face ${KINECTSDK20_DIR}/lib/${kinect-arch-dir}/kinect20.lib ${KINECTSDK20_DIR}/lib/${kinect-arch-dir}/kinect20.face.lib) + # Link against Kinect SDK libraries + target_link_libraries(opentrack-tracker-kinect-face ${KINECTSDK20_DIR}/lib/${kinect-arch-dir}/kinect20.lib ${KINECTSDK20_DIR}/lib/${kinect-arch-dir}/kinect20.face.lib) + + endif() -endif() +endif() \ No newline at end of file diff --git a/tracker-kinect-face/lang/nl_NL.ts b/tracker-kinect-face/lang/nl_NL.ts index dec7a177..f4fe07d8 100644 --- a/tracker-kinect-face/lang/nl_NL.ts +++ b/tracker-kinect-face/lang/nl_NL.ts @@ -4,7 +4,7 @@ test_metadata - Kinect Face - v0.1 + Kinect Face 0.1 diff --git a/tracker-kinect-face/lang/ru_RU.ts b/tracker-kinect-face/lang/ru_RU.ts index 1634c0c2..d4108ed3 100644 --- a/tracker-kinect-face/lang/ru_RU.ts +++ b/tracker-kinect-face/lang/ru_RU.ts @@ -4,7 +4,7 @@ test_metadata - Kinect Face - v0.1 + Kinect Face 0.1 diff --git a/tracker-kinect-face/lang/stub.ts b/tracker-kinect-face/lang/stub.ts index bb36fb1e..f82903a3 100644 --- a/tracker-kinect-face/lang/stub.ts +++ b/tracker-kinect-face/lang/stub.ts @@ -4,7 +4,7 @@ test_metadata - Kinect Face - v0.1 + Kinect Face 0.1 diff --git a/tracker-kinect-face/lang/zh_CN.ts b/tracker-kinect-face/lang/zh_CN.ts index bb36fb1e..f82903a3 100644 --- a/tracker-kinect-face/lang/zh_CN.ts +++ b/tracker-kinect-face/lang/zh_CN.ts @@ -4,7 +4,7 @@ test_metadata - Kinect Face - v0.1 + Kinect Face 0.1 diff --git a/tracker-kinect-face/test.h b/tracker-kinect-face/test.h index 1af0409b..0f8c170b 100644 --- a/tracker-kinect-face/test.h +++ b/tracker-kinect-face/test.h @@ -22,7 +22,7 @@ class test_metadata : public Metadata { Q_OBJECT - QString name() { return tr("Kinect Face - v0.1"); } + QString name() { return tr("Kinect Face 0.1"); } QIcon icon() { return QIcon(":/images/kinect.png"); } }; diff --git a/tracker-kinect-face/tracker.cpp b/tracker-kinect-face/tracker.cpp index 407557f0..c5517f89 100644 --- a/tracker-kinect-face/tracker.cpp +++ b/tracker-kinect-face/tracker.cpp @@ -38,7 +38,7 @@ bool IsNullVetor(const Vector4& aVector) return false; } - if (aVector.y != 0) + if (aVector.x != 0) { return false; } @@ -74,7 +74,6 @@ bool IsNullPoint(const CameraSpacePoint& aPoint) return false; } - return true; } @@ -150,9 +149,9 @@ module_status KinectFaceTracker::start_tracker(QFrame* aFrame) bool KinectFaceTracker::center() { + // Mark our center iFacePositionCenter = iFacePosition; iFaceRotationCenter = iFaceRotation; - //TODO: Rotation center too return true; } @@ -181,11 +180,9 @@ void KinectFaceTracker::data(double *data) data[2] = (iLastFacePosition.Z - iFacePositionCenter.Z) * 100; // Yaw, Picth, Roll - data[3] = 0-(iLastFaceRotation.X - iFaceRotationCenter.X); // Invert to be compatible with ED out-of-the-box + data[3] = -(iLastFaceRotation.X - iFaceRotationCenter.X); // Invert to be compatible with ED out-of-the-box data[4] = (iLastFaceRotation.Y - iFaceRotationCenter.Y); data[5] = (iLastFaceRotation.Z - iFaceRotationCenter.Z); - - } @@ -463,7 +460,7 @@ void KinectFaceTracker::ProcessFaces() { if (bFaceTracked) { - OutputDebugStringA("Tracking face!\n"); + //OutputDebugStringA("Tracking face!\n"); //IFaceFrameResult* pFaceFrameResult = nullptr; IFaceAlignment* pFaceAlignment = nullptr; -- cgit v1.2.3 From 32c809f5e0c6a9b6a5f202fffe5d034125957551 Mon Sep 17 00:00:00 2001 From: Stéphane Lenclud Date: Sat, 2 Feb 2019 18:17:05 +0100 Subject: Kinect: Installing SDK binaries. --- tracker-kinect-face/CMakeLists.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tracker-kinect-face/CMakeLists.txt b/tracker-kinect-face/CMakeLists.txt index fca1e495..cbdc2a97 100644 --- a/tracker-kinect-face/CMakeLists.txt +++ b/tracker-kinect-face/CMakeLists.txt @@ -25,7 +25,12 @@ if (WIN32) endif() # Link against Kinect SDK libraries - target_link_libraries(opentrack-tracker-kinect-face ${KINECTSDK20_DIR}/lib/${kinect-arch-dir}/kinect20.lib ${KINECTSDK20_DIR}/lib/${kinect-arch-dir}/kinect20.face.lib) + target_link_libraries(opentrack-tracker-kinect-face ${KINECTSDK20_DIR}/lib/${kinect-arch-dir}/Kinect20.lib ${KINECTSDK20_DIR}/lib/${kinect-arch-dir}/Kinect20.Face.lib) + + # Install Kinect Face DLL + install(FILES ${KINECTSDK20_DIR}/Redist/Face/${kinect-arch-dir}/Kinect20.Face.dll DESTINATION ./modules/ PERMISSIONS ${opentrack-perms-exec}) + # Install Kinect Face Database + install(DIRECTORY ${KINECTSDK20_DIR}/Redist/Face/${kinect-arch-dir}/NuiDatabase DESTINATION ./modules/) endif() -- cgit v1.2.3 From 997df9f3cbc9ef04c666e404b96ac4b02097b4f3 Mon Sep 17 00:00:00 2001 From: Stéphane Lenclud Date: Sat, 2 Feb 2019 21:51:27 +0100 Subject: Kinect: now with basic video preview. We have a massive memory leak, could have been there before though. --- tracker-kinect-face/CMakeLists.txt | 63 ++++++++++++++++++++------------------ tracker-kinect-face/tracker.cpp | 44 +++++++++++++++++++++----- tracker-kinect-face/tracker.h | 6 ++++ 3 files changed, 75 insertions(+), 38 deletions(-) diff --git a/tracker-kinect-face/CMakeLists.txt b/tracker-kinect-face/CMakeLists.txt index cbdc2a97..e12534b2 100644 --- a/tracker-kinect-face/CMakeLists.txt +++ b/tracker-kinect-face/CMakeLists.txt @@ -1,37 +1,40 @@ # Kinect SDK is Windows only if (WIN32) - # Setup cache variable to Kinect SDK path - if(DEFINED ENV{KINECTSDK20_DIR}) - set(KINECTSDK20_DIR $ENV{KINECTSDK20_DIR} CACHE PATH $ENV{KINECTSDK20_DIR}) - else() - set(KINECTSDK20_DIR $ENV{KINECTSDK20_DIR} CACHE PATH "") - endif() + find_package(OpenCV QUIET) + if(OpenCV_FOUND) + # Setup cache variable to Kinect SDK path + if(DEFINED ENV{KINECTSDK20_DIR}) + set(KINECTSDK20_DIR $ENV{KINECTSDK20_DIR} CACHE PATH $ENV{KINECTSDK20_DIR}) + else() + set(KINECTSDK20_DIR $ENV{KINECTSDK20_DIR} CACHE PATH "") + endif() - # If we have a valid SDK path, try build that tracker - if(EXISTS ${KINECTSDK20_DIR}) - # Register our module - otr_module(tracker-kinect-face) + # If we have a valid SDK path, try build that tracker + if(EXISTS ${KINECTSDK20_DIR}) + # Register our module + otr_module(tracker-kinect-face) - # Add include path to Kinect SDK - target_include_directories(opentrack-tracker-kinect-face SYSTEM PUBLIC ${KINECTSDK20_DIR}/inc) + # Add include path to Kinect SDK + target_include_directories(opentrack-tracker-kinect-face SYSTEM PUBLIC ${KINECTSDK20_DIR}/inc) - # Check processor architecture - if(CMAKE_SIZEOF_VOID_P EQUAL 4) - # 32 bits - set (kinect-arch-dir "x86") - elseif(CMAKE_SIZEOF_VOID_P EQUAL 8) - # 64 bits - set (kinect-arch-dir "x64") - endif() + # Check processor architecture + if(CMAKE_SIZEOF_VOID_P EQUAL 4) + # 32 bits + set (kinect-arch-dir "x86") + elseif(CMAKE_SIZEOF_VOID_P EQUAL 8) + # 64 bits + set (kinect-arch-dir "x64") + endif() - # Link against Kinect SDK libraries - target_link_libraries(opentrack-tracker-kinect-face ${KINECTSDK20_DIR}/lib/${kinect-arch-dir}/Kinect20.lib ${KINECTSDK20_DIR}/lib/${kinect-arch-dir}/Kinect20.Face.lib) - - # Install Kinect Face DLL - install(FILES ${KINECTSDK20_DIR}/Redist/Face/${kinect-arch-dir}/Kinect20.Face.dll DESTINATION ./modules/ PERMISSIONS ${opentrack-perms-exec}) - # Install Kinect Face Database - install(DIRECTORY ${KINECTSDK20_DIR}/Redist/Face/${kinect-arch-dir}/NuiDatabase DESTINATION ./modules/) - - endif() + # Link against Kinect SDK libraries + target_link_libraries(opentrack-tracker-kinect-face ${KINECTSDK20_DIR}/lib/${kinect-arch-dir}/Kinect20.lib ${KINECTSDK20_DIR}/lib/${kinect-arch-dir}/Kinect20.Face.lib) + # Link against OpenCV stuff, needed for video preview + target_link_libraries(opentrack-tracker-kinect-face opencv_imgproc opentrack-cv opencv_core) -endif() \ No newline at end of file + # Install Kinect Face DLL + install(FILES ${KINECTSDK20_DIR}/Redist/Face/${kinect-arch-dir}/Kinect20.Face.dll DESTINATION ./modules/ PERMISSIONS ${opentrack-perms-exec}) + # Install Kinect Face Database + install(DIRECTORY ${KINECTSDK20_DIR}/Redist/Face/${kinect-arch-dir}/NuiDatabase DESTINATION ./modules/) + endif(EXISTS ${KINECTSDK20_DIR}) + endif(OpenCV_FOUND) +endif(WIN32) \ No newline at end of file diff --git a/tracker-kinect-face/tracker.cpp b/tracker-kinect-face/tracker.cpp index c5517f89..073cf0be 100644 --- a/tracker-kinect-face/tracker.cpp +++ b/tracker-kinect-face/tracker.cpp @@ -2,6 +2,9 @@ #include "tracker.h" +#include +#include + /// @@ -137,6 +140,15 @@ module_status KinectFaceTracker::start_tracker(QFrame* aFrame) if (SUCCEEDED(InitializeDefaultSensor())) { + // Setup our video preview widget + iVideoWidget = std::make_unique(aFrame); + iLayout = std::make_unique(aFrame); + iLayout->setContentsMargins(0, 0, 0, 0); + iLayout->addWidget(iVideoWidget.get()); + aFrame->setLayout(iLayout.get()); + //video_widget->resize(video_frame->width(), video_frame->height()); + aFrame->show(); + return status_ok(); } @@ -161,12 +173,11 @@ void KinectFaceTracker::data(double *data) const double dt = t.elapsed_seconds(); t.start(); - Update(); - //TODO: check if data is valid ExtractFaceRotationInDegrees(&iFaceRotationQuaternion, &iFaceRotation.X, &iFaceRotation.Y, &iFaceRotation.Z); + //Check if data is valid if (!IsNullPoint(iFacePosition) && !IsNullPoint(iFaceRotation)) { // We have valid tracking retain position and rotation @@ -218,8 +229,6 @@ void KinectFaceTracker::ExtractFaceRotationInDegrees(const Vector4* pQuaternion, *pPitch = dPitch; *pYaw = dYaw; *pRoll = dRoll; - - } @@ -348,7 +357,8 @@ void KinectFaceTracker::Update() if (SUCCEEDED(hr)) { - if (imageFormat == ColorImageFormat_Bgra) + // Fetch color buffer + if (imageFormat == ColorImageFormat_Rgba) { hr = pColorFrame->AccessRawUnderlyingBuffer(&nBufferSize, reinterpret_cast(&pBuffer)); } @@ -356,12 +366,13 @@ void KinectFaceTracker::Update() { pBuffer = m_pColorRGBX; nBufferSize = cColorWidth * cColorHeight * sizeof(RGBQUAD); - hr = pColorFrame->CopyConvertedFrameDataToArray(nBufferSize, reinterpret_cast(pBuffer), ColorImageFormat_Bgra); + hr = pColorFrame->CopyConvertedFrameDataToArray(nBufferSize, reinterpret_cast(pBuffer), ColorImageFormat_Rgba); } else { hr = E_FAIL; } + } if (SUCCEEDED(hr)) @@ -370,6 +381,24 @@ void KinectFaceTracker::Update() ProcessFaces(); } + if (SUCCEEDED(hr)) + { + // Setup our image + QImage image((const unsigned char*)pBuffer, cColorWidth, cColorHeight, sizeof(RGBQUAD)*cColorWidth, QImage::Format_RGBA8888); + if (IsValidRect(iFaceBox)) + { + // Draw our face bounding box + QPainter painter(&image); + painter.setBrush(Qt::NoBrush); + painter.setPen(QPen(Qt::red, 8)); + painter.drawRect(iFaceBox.Left, iFaceBox.Top, iFaceBox.Right - iFaceBox.Left, iFaceBox.Bottom - iFaceBox.Top); + bool bEnd = painter.end(); + } + + // Update our video preview + iVideoWidget->update_image(image); + } + SafeRelease(pFrameDescription); } @@ -465,7 +494,6 @@ void KinectFaceTracker::ProcessFaces() //IFaceFrameResult* pFaceFrameResult = nullptr; IFaceAlignment* pFaceAlignment = nullptr; CreateFaceAlignment(&pFaceAlignment); // TODO: check return? - RectI faceBox = { 0 }; //D2D1_POINT_2F faceTextLayout; //hr = pFaceFrame->get_FaceFrameResult(&pFaceFrameResult); @@ -475,7 +503,7 @@ void KinectFaceTracker::ProcessFaces() // need to verify if pFaceFrameResult contains data before trying to access it if (SUCCEEDED(hr) && pFaceAlignment != nullptr) { - hr = pFaceAlignment->get_FaceBoundingBox(&faceBox); + hr = pFaceAlignment->get_FaceBoundingBox(&iFaceBox); //pFaceFrameResult->get_FaceBoundingBoxInColorSpace(); if (SUCCEEDED(hr)) diff --git a/tracker-kinect-face/tracker.h b/tracker-kinect-face/tracker.h index 1f986e22..5068f185 100644 --- a/tracker-kinect-face/tracker.h +++ b/tracker-kinect-face/tracker.h @@ -6,6 +6,7 @@ #include "api/plugin-api.hpp" #include "compat/timer.hpp" #include "compat/macros.hpp" +#include "cv/video-widget.hpp" // Kinect Header files #include @@ -69,6 +70,8 @@ private: // RGBQUAD* m_pColorRGBX; + RectI iFaceBox = { 0 }; + CameraSpacePoint iLastFacePosition; CameraSpacePoint iFacePosition; CameraSpacePoint iFacePositionCenter; @@ -78,4 +81,7 @@ private: CameraSpacePoint iLastFaceRotation; CameraSpacePoint iFaceRotation; CameraSpacePoint iFaceRotationCenter; + // + std::unique_ptr iVideoWidget; + std::unique_ptr iLayout; }; -- cgit v1.2.3 From fdc70ac7039d633b26f659e476681d99d45c685a Mon Sep 17 00:00:00 2001 From: Stéphane Lenclud Date: Sun, 3 Feb 2019 09:13:19 +0100 Subject: Kinect: Adding class to encapsulate Microsoft interface pointer. --- tracker-kinect-face/tracker.cpp | 26 +++++++++++++++++++------- tracker-kinect-face/tracker.h | 28 +++++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/tracker-kinect-face/tracker.cpp b/tracker-kinect-face/tracker.cpp index 073cf0be..8c2c164d 100644 --- a/tracker-kinect-face/tracker.cpp +++ b/tracker-kinect-face/tracker.cpp @@ -232,6 +232,7 @@ void KinectFaceTracker::ExtractFaceRotationInDegrees(const Vector4* pQuaternion, } + /// /// Initializes the default Kinect sensor /// @@ -248,9 +249,9 @@ HRESULT KinectFaceTracker::InitializeDefaultSensor() if (m_pKinectSensor) { - // Initialize Kinect and get color, body and face readers - IColorFrameSource* pColorFrameSource = nullptr; - IBodyFrameSource* pBodyFrameSource = nullptr; + // Initialize Kinect and get color, body and face readers + UniqueInterface pBodyFrameSource; + UniqueInterface pColorFrameSource; hr = m_pKinectSensor->Open(); @@ -261,17 +262,23 @@ HRESULT KinectFaceTracker::InitializeDefaultSensor() if (SUCCEEDED(hr)) { - hr = m_pKinectSensor->get_ColorFrameSource(&pColorFrameSource); + hr = m_pKinectSensor->get_ColorFrameSource(pColorFrameSource.PtrPtr()); + pColorFrameSource.Reset(); } + + //std::unique_ptr colorFrameSource(pColorFrameSource, SafeRelease); if (SUCCEEDED(hr)) { + //hr = (*pColorFrameSource.PtrPtr())->OpenReader(&m_pColorFrameReader); hr = pColorFrameSource->OpenReader(&m_pColorFrameReader); } + if (SUCCEEDED(hr)) { - hr = m_pKinectSensor->get_BodyFrameSource(&pBodyFrameSource); + hr = m_pKinectSensor->get_BodyFrameSource(pBodyFrameSource.PtrPtr()); + pBodyFrameSource.Reset(); } if (SUCCEEDED(hr)) @@ -297,8 +304,13 @@ HRESULT KinectFaceTracker::InitializeDefaultSensor() } } - SafeRelease(pColorFrameSource); - SafeRelease(pBodyFrameSource); + //pColorFrameSource.Free(); + //pBodyFrameSource.Free(); + //SafeRelease(pColorFrameSource); + //SafeRelease(pBodyFrameSource); + + //SafeRelease(*pBodyFrameSource.PtrPtr()); + //SafeRelease(*pColorFrameSource.PtrPtr()); } if (!m_pKinectSensor || FAILED(hr)) diff --git a/tracker-kinect-face/tracker.h b/tracker-kinect-face/tracker.h index 5068f185..220a126f 100644 --- a/tracker-kinect-face/tracker.h +++ b/tracker-kinect-face/tracker.h @@ -14,7 +14,7 @@ #pragma once -// Safe release for interfaces +// @deprecated Use UniqueInterface instead. Remove it at some point. template inline void SafeRelease(Interface *& pInterfaceToRelease) { @@ -25,6 +25,32 @@ inline void SafeRelease(Interface *& pInterfaceToRelease) } } +template +inline void ReleaseInterface(Interface* pInterfaceToRelease) +{ + if (pInterfaceToRelease != nullptr) + { + pInterfaceToRelease->Release(); + } +} + +// Safely use Microsoft interfaces. +template +class UniqueInterface : public std::unique_ptr)> ///**/ +{ +public: + UniqueInterface() : std::unique_ptr)>(nullptr, ReleaseInterface){} + // Access pointer, typically for creation + T** PtrPtr() { return &iPtr; }; + // Called this once the pointer was created + void Reset() { std::unique_ptr)>::reset(iPtr); } + // If ever you want to release that interface before the object is deleted + void Free() { iPtr = nullptr; Reset(); } +private: + T* iPtr = nullptr; +}; + + class KinectFaceTracker : public ITracker { -- cgit v1.2.3 From 70156963a8f65d21231de88460e6559bd78f770c Mon Sep 17 00:00:00 2001 From: Stéphane Lenclud Date: Sun, 3 Feb 2019 12:13:53 +0100 Subject: Kinect: Fixing massive memory leak after start/stop cycle. --- tracker-kinect-face/tracker.cpp | 89 +++++++++++++++-------------------------- 1 file changed, 32 insertions(+), 57 deletions(-) diff --git a/tracker-kinect-face/tracker.cpp b/tracker-kinect-face/tracker.cpp index 8c2c164d..54a716ac 100644 --- a/tracker-kinect-face/tracker.cpp +++ b/tracker-kinect-face/tracker.cpp @@ -241,82 +241,57 @@ HRESULT KinectFaceTracker::InitializeDefaultSensor() { HRESULT hr; + // Get and open Kinect sensor hr = GetDefaultKinectSensor(&m_pKinectSensor); - if (FAILED(hr)) + if (SUCCEEDED(hr)) { - return hr; + hr = m_pKinectSensor->Open(); } - if (m_pKinectSensor) + // TODO: check if we still need that guy + if (SUCCEEDED(hr)) { - // Initialize Kinect and get color, body and face readers - UniqueInterface pBodyFrameSource; - UniqueInterface pColorFrameSource; - - hr = m_pKinectSensor->Open(); + hr = m_pKinectSensor->get_CoordinateMapper(&m_pCoordinateMapper); + } - if (SUCCEEDED(hr)) - { - hr = m_pKinectSensor->get_CoordinateMapper(&m_pCoordinateMapper); - } + // Create color frame reader + if (SUCCEEDED(hr)) + { + UniqueInterface colorFrameSource; + hr = m_pKinectSensor->get_ColorFrameSource(colorFrameSource.PtrPtr()); + colorFrameSource.Reset(); if (SUCCEEDED(hr)) { - hr = m_pKinectSensor->get_ColorFrameSource(pColorFrameSource.PtrPtr()); - pColorFrameSource.Reset(); + hr = colorFrameSource->OpenReader(&m_pColorFrameReader); } + } - //std::unique_ptr colorFrameSource(pColorFrameSource, SafeRelease); - - if (SUCCEEDED(hr)) - { - //hr = (*pColorFrameSource.PtrPtr())->OpenReader(&m_pColorFrameReader); - hr = pColorFrameSource->OpenReader(&m_pColorFrameReader); - } - - - if (SUCCEEDED(hr)) - { - hr = m_pKinectSensor->get_BodyFrameSource(pBodyFrameSource.PtrPtr()); - pBodyFrameSource.Reset(); - } + // Create body frame reader + if (SUCCEEDED(hr)) + { + UniqueInterface bodyFrameSource; + hr = m_pKinectSensor->get_BodyFrameSource(bodyFrameSource.PtrPtr()); + bodyFrameSource.Reset(); if (SUCCEEDED(hr)) { - hr = pBodyFrameSource->OpenReader(&m_pBodyFrameReader); - } - - if (SUCCEEDED(hr)) - { - // create a face frame source + reader to track each body in the fov - for (int i = 0; i < BODY_COUNT; i++) - { - if (SUCCEEDED(hr)) - { - // create the face frame source by specifying the required face frame features - hr = CreateHighDefinitionFaceFrameSource(m_pKinectSensor, &m_pFaceFrameSource); - } - if (SUCCEEDED(hr)) - { - // open the corresponding reader - hr = m_pFaceFrameSource->OpenReader(&m_pFaceFrameReader); - } - } + hr = bodyFrameSource->OpenReader(&m_pBodyFrameReader); } + } - //pColorFrameSource.Free(); - //pBodyFrameSource.Free(); - //SafeRelease(pColorFrameSource); - //SafeRelease(pBodyFrameSource); - - //SafeRelease(*pBodyFrameSource.PtrPtr()); - //SafeRelease(*pColorFrameSource.PtrPtr()); + // Create HD face frame source + if (SUCCEEDED(hr)) + { + // create the face frame source by specifying the required face frame features + hr = CreateHighDefinitionFaceFrameSource(m_pKinectSensor, &m_pFaceFrameSource); } - if (!m_pKinectSensor || FAILED(hr)) + // Create HD face frame reader + if (SUCCEEDED(hr)) { - //SetStatusMessage(L"No ready Kinect found!", 10000, true); - return E_FAIL; + // open the corresponding reader + hr = m_pFaceFrameSource->OpenReader(&m_pFaceFrameReader); } return hr; -- cgit v1.2.3 From 1da2d0e71a03296a40b49316b5e23986de823a75 Mon Sep 17 00:00:00 2001 From: Stéphane Lenclud Date: Sun, 3 Feb 2019 12:28:12 +0100 Subject: Kinect: Renaming a few files. --- tracker-kinect-face/kinect_face_settings.cpp | 45 +++ tracker-kinect-face/kinect_face_settings.h | 28 ++ tracker-kinect-face/kinect_face_tracker.cpp | 569 +++++++++++++++++++++++++++ tracker-kinect-face/kinect_face_tracker.h | 113 ++++++ tracker-kinect-face/test.cpp | 45 --- tracker-kinect-face/test.h | 28 -- tracker-kinect-face/test_dialog.cpp | 2 +- tracker-kinect-face/tracker.cpp | 569 --------------------------- tracker-kinect-face/tracker.h | 113 ------ 9 files changed, 756 insertions(+), 756 deletions(-) create mode 100644 tracker-kinect-face/kinect_face_settings.cpp create mode 100644 tracker-kinect-face/kinect_face_settings.h create mode 100644 tracker-kinect-face/kinect_face_tracker.cpp create mode 100644 tracker-kinect-face/kinect_face_tracker.h delete mode 100644 tracker-kinect-face/test.cpp delete mode 100644 tracker-kinect-face/test.h delete mode 100644 tracker-kinect-face/tracker.cpp delete mode 100644 tracker-kinect-face/tracker.h diff --git a/tracker-kinect-face/kinect_face_settings.cpp b/tracker-kinect-face/kinect_face_settings.cpp new file mode 100644 index 00000000..53aada06 --- /dev/null +++ b/tracker-kinect-face/kinect_face_settings.cpp @@ -0,0 +1,45 @@ +/* Copyright (c) 2014, Stanislaw Halik + + * Permission to use, copy, modify, and/or distribute this + * software for any purpose with or without fee is hereby granted, + * provided that the above copyright notice and this permission + * notice appear in all copies. + */ + +#include "kinect_face_settings.h" +#include "kinect_face_tracker.h" +#include "api/plugin-api.hpp" +#include "compat/math-imports.hpp" + +#include + +#include +#include + + +test_dialog::test_dialog() +{ + ui.setupUi(this); + + connect(ui.buttonBox, &QDialogButtonBox::clicked, [this](QAbstractButton* btn) { + if (btn == ui.buttonBox->button(QDialogButtonBox::Abort)) + // NOLINTNEXTLINE + *(volatile int*)nullptr = 0; + }); + + connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); + connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); +} + +void test_dialog::doOK() +{ + //s.b->save(); + close(); +} + +void test_dialog::doCancel() +{ + close(); +} + +OPENTRACK_DECLARE_TRACKER(KinectFaceTracker, test_dialog, test_metadata) diff --git a/tracker-kinect-face/kinect_face_settings.h b/tracker-kinect-face/kinect_face_settings.h new file mode 100644 index 00000000..0f8c170b --- /dev/null +++ b/tracker-kinect-face/kinect_face_settings.h @@ -0,0 +1,28 @@ +#pragma once +#include "ui_test.h" +#include "compat/macros.hpp" +#include "api/plugin-api.hpp" + + +class test_dialog : public ITrackerDialog +{ + Q_OBJECT + + Ui::test_ui ui; +public: + test_dialog(); + void register_tracker(ITracker *) override {} + void unregister_tracker() override {} +private slots: + void doOK(); + void doCancel(); +}; + +class test_metadata : public Metadata +{ + Q_OBJECT + + QString name() { return tr("Kinect Face 0.1"); } + QIcon icon() { return QIcon(":/images/kinect.png"); } +}; + diff --git a/tracker-kinect-face/kinect_face_tracker.cpp b/tracker-kinect-face/kinect_face_tracker.cpp new file mode 100644 index 00000000..ccac8aa9 --- /dev/null +++ b/tracker-kinect-face/kinect_face_tracker.cpp @@ -0,0 +1,569 @@ + + +#include "kinect_face_tracker.h" + +#include +#include + + + +/// +bool IsValidRect(const RectI& aRect) +{ + if (aRect.Bottom != 0) + { + return true; + } + + if (aRect.Left != 0) + { + return true; + } + + if (aRect.Right != 0) + { + return true; + } + + if (aRect.Top != 0) + { + return true; + } + + return false; +} + +/// +bool IsNullVetor(const Vector4& aVector) +{ + if (aVector.w != 0) + { + return false; + } + + if (aVector.x != 0) + { + return false; + } + + if (aVector.y != 0) + { + return false; + } + + if (aVector.z != 0) + { + return false; + } + + return true; +} + +/// +bool IsNullPoint(const CameraSpacePoint& aPoint) +{ + if (aPoint.X != 0) + { + return false; + } + + if (aPoint.Y != 0) + { + return false; + } + + if (aPoint.Z != 0) + { + return false; + } + + return true; +} + + +KinectFaceTracker::KinectFaceTracker(): + m_pKinectSensor(nullptr), + m_pCoordinateMapper(nullptr), + m_pColorFrameReader(nullptr), + m_pColorRGBX(nullptr), + m_pBodyFrameReader(nullptr), + iLastFacePosition{0,0,0}, + iFacePositionCenter{ 0,0,0 }, + iFacePosition{ 0,0,0 }, + iLastFaceRotation{ 0,0,0 }, + iFaceRotationCenter{ 0,0,0 }, + iFaceRotation{ 0,0,0 } +{ + m_pFaceFrameSource = nullptr; + m_pFaceFrameReader = nullptr; + + // create heap storage for color pixel data in RGBX format + m_pColorRGBX = new RGBQUAD[cColorWidth * cColorHeight]; +} + +KinectFaceTracker::~KinectFaceTracker() +{ + if (m_pColorRGBX) + { + delete[] m_pColorRGBX; + m_pColorRGBX = nullptr; + } + + // clean up Direct2D + //SafeRelease(m_pD2DFactory); + + // done with face sources and readers + SafeRelease(m_pFaceFrameSource); + SafeRelease(m_pFaceFrameReader); + + // done with body frame reader + SafeRelease(m_pBodyFrameReader); + + // done with color frame reader + SafeRelease(m_pColorFrameReader); + + // done with coordinate mapper + SafeRelease(m_pCoordinateMapper); + + // close the Kinect Sensor + if (m_pKinectSensor) + { + m_pKinectSensor->Close(); + } + + SafeRelease(m_pKinectSensor); +} + +module_status KinectFaceTracker::start_tracker(QFrame* aFrame) +{ + t.start(); + + if (SUCCEEDED(InitializeDefaultSensor())) + { + // Setup our video preview widget + iVideoWidget = std::make_unique(aFrame); + iLayout = std::make_unique(aFrame); + iLayout->setContentsMargins(0, 0, 0, 0); + iLayout->addWidget(iVideoWidget.get()); + aFrame->setLayout(iLayout.get()); + //video_widget->resize(video_frame->width(), video_frame->height()); + aFrame->show(); + + return status_ok(); + } + + return error("Kinect init failed!"); +} + +#ifdef EMIT_NAN +# include +#endif + +bool KinectFaceTracker::center() +{ + // Mark our center + iFacePositionCenter = iFacePosition; + iFaceRotationCenter = iFaceRotation; + return true; +} + + +void KinectFaceTracker::data(double *data) +{ + const double dt = t.elapsed_seconds(); + t.start(); + + Update(); + + ExtractFaceRotationInDegrees(&iFaceRotationQuaternion, &iFaceRotation.X, &iFaceRotation.Y, &iFaceRotation.Z); + + //Check if data is valid + if (!IsNullPoint(iFacePosition) && !IsNullPoint(iFaceRotation)) + { + // We have valid tracking retain position and rotation + iLastFacePosition = iFacePosition; + iLastFaceRotation = iFaceRotation; + } + + // Feed our framework our last valid position and rotation + data[0] = (iLastFacePosition.X - iFacePositionCenter.X) * 100; // Convert to centimer to be in a range that suites OpenTrack. + data[1] = (iLastFacePosition.Y - iFacePositionCenter.Y) * 100; + data[2] = (iLastFacePosition.Z - iFacePositionCenter.Z) * 100; + + // Yaw, Picth, Roll + data[3] = -(iLastFaceRotation.X - iFaceRotationCenter.X); // Invert to be compatible with ED out-of-the-box + data[4] = (iLastFaceRotation.Y - iFaceRotationCenter.Y); + data[5] = (iLastFaceRotation.Z - iFaceRotationCenter.Z); +} + + +/// +/// Converts rotation quaternion to Euler angles +/// And then maps them to a specified range of values to control the refresh rate +/// +/// face rotation quaternion +/// rotation about the X-axis +/// rotation about the Y-axis +/// rotation about the Z-axis +void KinectFaceTracker::ExtractFaceRotationInDegrees(const Vector4* pQuaternion, float* pYaw, float* pPitch, float* pRoll) +{ + double x = pQuaternion->x; + double y = pQuaternion->y; + double z = pQuaternion->z; + double w = pQuaternion->w; + + // convert face rotation quaternion to Euler angles in degrees + double dPitch, dYaw, dRoll; + dPitch = atan2(2 * (y * z + w * x), w * w - x * x - y * y + z * z) / M_PI * 180.0; + dYaw = asin(2 * (w * y - x * z)) / M_PI * 180.0; + dRoll = atan2(2 * (x * y + w * z), w * w + x * x - y * y - z * z) / M_PI * 180.0; + + // clamp rotation values in degrees to a specified range of values to control the refresh rate + /* + double increment = c_FaceRotationIncrementInDegrees; + *pPitch = static_cast(floor((dPitch + increment/2.0 * (dPitch > 0 ? 1.0 : -1.0)) / increment) * increment); + *pYaw = static_cast(floor((dYaw + increment/2.0 * (dYaw > 0 ? 1.0 : -1.0)) / increment) * increment); + *pRoll = static_cast(floor((dRoll + increment/2.0 * (dRoll > 0 ? 1.0 : -1.0)) / increment) * increment); + */ + + *pPitch = dPitch; + *pYaw = dYaw; + *pRoll = dRoll; +} + + + +/// +/// Initializes the default Kinect sensor +/// +/// S_OK on success else the failure code +HRESULT KinectFaceTracker::InitializeDefaultSensor() +{ + HRESULT hr; + + // Get and open Kinect sensor + hr = GetDefaultKinectSensor(&m_pKinectSensor); + if (SUCCEEDED(hr)) + { + hr = m_pKinectSensor->Open(); + } + + // TODO: check if we still need that guy + if (SUCCEEDED(hr)) + { + hr = m_pKinectSensor->get_CoordinateMapper(&m_pCoordinateMapper); + } + + // Create color frame reader + if (SUCCEEDED(hr)) + { + UniqueInterface colorFrameSource; + hr = m_pKinectSensor->get_ColorFrameSource(colorFrameSource.PtrPtr()); + colorFrameSource.Reset(); + + if (SUCCEEDED(hr)) + { + hr = colorFrameSource->OpenReader(&m_pColorFrameReader); + } + } + + // Create body frame reader + if (SUCCEEDED(hr)) + { + UniqueInterface bodyFrameSource; + hr = m_pKinectSensor->get_BodyFrameSource(bodyFrameSource.PtrPtr()); + bodyFrameSource.Reset(); + + if (SUCCEEDED(hr)) + { + hr = bodyFrameSource->OpenReader(&m_pBodyFrameReader); + } + } + + // Create HD face frame source + if (SUCCEEDED(hr)) + { + // create the face frame source by specifying the required face frame features + hr = CreateHighDefinitionFaceFrameSource(m_pKinectSensor, &m_pFaceFrameSource); + } + + // Create HD face frame reader + if (SUCCEEDED(hr)) + { + // open the corresponding reader + hr = m_pFaceFrameSource->OpenReader(&m_pFaceFrameReader); + } + + return hr; +} + +/// +/// Main processing function +/// +void KinectFaceTracker::Update() +{ + if (!m_pColorFrameReader || !m_pBodyFrameReader) + { + return; + } + + IColorFrame* pColorFrame = nullptr; + HRESULT hr = m_pColorFrameReader->AcquireLatestFrame(&pColorFrame); + + if (SUCCEEDED(hr)) + { + INT64 nTime = 0; + IFrameDescription* pFrameDescription = nullptr; + int nWidth = 0; + int nHeight = 0; + ColorImageFormat imageFormat = ColorImageFormat_None; + UINT nBufferSize = 0; + RGBQUAD *pBuffer = nullptr; + + hr = pColorFrame->get_RelativeTime(&nTime); + + if (SUCCEEDED(hr)) + { + hr = pColorFrame->get_FrameDescription(&pFrameDescription); + } + + if (SUCCEEDED(hr)) + { + hr = pFrameDescription->get_Width(&nWidth); + } + + if (SUCCEEDED(hr)) + { + hr = pFrameDescription->get_Height(&nHeight); + } + + if (SUCCEEDED(hr)) + { + hr = pColorFrame->get_RawColorImageFormat(&imageFormat); + } + + if (SUCCEEDED(hr)) + { + // Fetch color buffer + if (imageFormat == ColorImageFormat_Rgba) + { + hr = pColorFrame->AccessRawUnderlyingBuffer(&nBufferSize, reinterpret_cast(&pBuffer)); + } + else if (m_pColorRGBX) + { + pBuffer = m_pColorRGBX; + nBufferSize = cColorWidth * cColorHeight * sizeof(RGBQUAD); + hr = pColorFrame->CopyConvertedFrameDataToArray(nBufferSize, reinterpret_cast(pBuffer), ColorImageFormat_Rgba); + } + else + { + hr = E_FAIL; + } + + } + + if (SUCCEEDED(hr)) + { + //DrawStreams(nTime, pBuffer, nWidth, nHeight); + ProcessFaces(); + } + + if (SUCCEEDED(hr)) + { + // Setup our image + QImage image((const unsigned char*)pBuffer, cColorWidth, cColorHeight, sizeof(RGBQUAD)*cColorWidth, QImage::Format_RGBA8888); + if (IsValidRect(iFaceBox)) + { + // Draw our face bounding box + QPainter painter(&image); + painter.setBrush(Qt::NoBrush); + painter.setPen(QPen(Qt::red, 8)); + painter.drawRect(iFaceBox.Left, iFaceBox.Top, iFaceBox.Right - iFaceBox.Left, iFaceBox.Bottom - iFaceBox.Top); + bool bEnd = painter.end(); + } + + // Update our video preview + iVideoWidget->update_image(image); + } + + SafeRelease(pFrameDescription); + } + + SafeRelease(pColorFrame); +} + + +/// +/// Updates body data +/// +/// pointer to the body data storage +/// indicates success or failure +HRESULT KinectFaceTracker::UpdateBodyData(IBody** ppBodies) +{ + HRESULT hr = E_FAIL; + + if (m_pBodyFrameReader != nullptr) + { + IBodyFrame* pBodyFrame = nullptr; + hr = m_pBodyFrameReader->AcquireLatestFrame(&pBodyFrame); + if (SUCCEEDED(hr)) + { + hr = pBodyFrame->GetAndRefreshBodyData(BODY_COUNT, ppBodies); + } + SafeRelease(pBodyFrame); + } + + return hr; +} + + + +/// +/// Processes new face frames +/// +void KinectFaceTracker::ProcessFaces() +{ + HRESULT hr; + IBody* ppBodies[BODY_COUNT] = { 0 }; + bool bHaveBodyData = SUCCEEDED(UpdateBodyData(ppBodies)); + + if (!bHaveBodyData) + { + return; + } + + // TODO: Select closest body + // Just use the first body we find + BOOLEAN tracked; + int i = 0; + while (i < BODY_COUNT) + { + hr = ppBodies[i]->get_IsTracked(&tracked); + UINT64 trackingId = 0; + + if (SUCCEEDED(hr) && tracked) + { + hr = ppBodies[i]->get_TrackingId(&trackingId); + + if (SUCCEEDED(hr)) + { + // Tell our face source to use the given body id + hr = m_pFaceFrameSource->put_TrackingId(trackingId); + break; + } + + } + + i++; + } + + + // iterate through each face reader + for (int iFace = 0; iFace < BODY_COUNT; ++iFace) + { + // retrieve the latest face frame from this reader + IHighDefinitionFaceFrame* pFaceFrame = nullptr; + hr = m_pFaceFrameReader->AcquireLatestFrame(&pFaceFrame); + + BOOLEAN bFaceTracked = false; + if (SUCCEEDED(hr) && nullptr != pFaceFrame) + { + // check if a valid face is tracked in this face frame + hr = pFaceFrame->get_IsTrackingIdValid(&bFaceTracked); + } + + if (SUCCEEDED(hr)) + { + if (bFaceTracked) + { + //OutputDebugStringA("Tracking face!\n"); + + //IFaceFrameResult* pFaceFrameResult = nullptr; + IFaceAlignment* pFaceAlignment = nullptr; + CreateFaceAlignment(&pFaceAlignment); // TODO: check return? + //D2D1_POINT_2F faceTextLayout; + + //hr = pFaceFrame->get_FaceFrameResult(&pFaceFrameResult); + + hr = pFaceFrame->GetAndRefreshFaceAlignmentResult(pFaceAlignment); + + // need to verify if pFaceFrameResult contains data before trying to access it + if (SUCCEEDED(hr) && pFaceAlignment != nullptr) + { + hr = pFaceAlignment->get_FaceBoundingBox(&iFaceBox); + //pFaceFrameResult->get_FaceBoundingBoxInColorSpace(); + + if (SUCCEEDED(hr)) + { + //hr = pFaceFrameResult->GetFacePointsInColorSpace(FacePointType::FacePointType_Count, facePoints); + hr = pFaceAlignment->get_HeadPivotPoint(&iFacePosition); + } + + if (SUCCEEDED(hr)) + { + //hr = pFaceFrameResult->get_FaceRotationQuaternion(&faceRotation); + hr = pFaceAlignment->get_FaceOrientation(&iFaceRotationQuaternion); + } + + if (SUCCEEDED(hr)) + { + //hr = pFaceFrameResult->GetFaceProperties(FaceProperty::FaceProperty_Count, faceProperties); + } + + if (SUCCEEDED(hr)) + { + //hr = GetFaceTextPositionInColorSpace(ppBodies[0], &faceTextLayout); + } + + if (SUCCEEDED(hr)) + { + // draw face frame results + //m_pDrawDataStreams->DrawFaceFrameResults(0, &faceBox, facePoints, &faceRotation, faceProperties, &faceTextLayout); + } + } + + SafeRelease(pFaceAlignment); + } + else + { + // face tracking is not valid - attempt to fix the issue + // a valid body is required to perform this step + if (bHaveBodyData) + { + // check if the corresponding body is tracked + // if this is true then update the face frame source to track this body + IBody* pBody = ppBodies[iFace]; + if (pBody != nullptr) + { + BOOLEAN bTracked = false; + hr = pBody->get_IsTracked(&bTracked); + + UINT64 bodyTId; + if (SUCCEEDED(hr) && bTracked) + { + // get the tracking ID of this body + hr = pBody->get_TrackingId(&bodyTId); + if (SUCCEEDED(hr)) + { + // update the face frame source with the tracking ID + m_pFaceFrameSource->put_TrackingId(bodyTId); + } + } + } + } + } + } + + SafeRelease(pFaceFrame); + } + + if (bHaveBodyData) + { + for (int i = 0; i < _countof(ppBodies); ++i) + { + SafeRelease(ppBodies[i]); + } + } +} + + diff --git a/tracker-kinect-face/kinect_face_tracker.h b/tracker-kinect-face/kinect_face_tracker.h new file mode 100644 index 00000000..220a126f --- /dev/null +++ b/tracker-kinect-face/kinect_face_tracker.h @@ -0,0 +1,113 @@ + + + +#include + +#include "api/plugin-api.hpp" +#include "compat/timer.hpp" +#include "compat/macros.hpp" +#include "cv/video-widget.hpp" + +// Kinect Header files +#include +#include + +#pragma once + +// @deprecated Use UniqueInterface instead. Remove it at some point. +template +inline void SafeRelease(Interface *& pInterfaceToRelease) +{ + if (pInterfaceToRelease != nullptr) + { + pInterfaceToRelease->Release(); + pInterfaceToRelease = nullptr; + } +} + +template +inline void ReleaseInterface(Interface* pInterfaceToRelease) +{ + if (pInterfaceToRelease != nullptr) + { + pInterfaceToRelease->Release(); + } +} + +// Safely use Microsoft interfaces. +template +class UniqueInterface : public std::unique_ptr)> ///**/ +{ +public: + UniqueInterface() : std::unique_ptr)>(nullptr, ReleaseInterface){} + // Access pointer, typically for creation + T** PtrPtr() { return &iPtr; }; + // Called this once the pointer was created + void Reset() { std::unique_ptr)>::reset(iPtr); } + // If ever you want to release that interface before the object is deleted + void Free() { iPtr = nullptr; Reset(); } +private: + T* iPtr = nullptr; +}; + + + +class KinectFaceTracker : public ITracker +{ +public: + KinectFaceTracker(); + ~KinectFaceTracker() override; + module_status start_tracker(QFrame* aFrame) override; + void data(double *data) override; + bool center() override; + +private: + Timer t; + + // Kinect stuff + static const int cColorWidth = 1920; + static const int cColorHeight = 1080; + + + void Update(); + HRESULT InitializeDefaultSensor(); + void ProcessFaces(); + HRESULT UpdateBodyData(IBody** ppBodies); + void ExtractFaceRotationInDegrees(const Vector4* pQuaternion, float* pPitch, float* pYaw, float* pRoll); + + // Current Kinect + IKinectSensor* m_pKinectSensor; + + // Coordinate mapper + ICoordinateMapper* m_pCoordinateMapper; + + // Color reader + IColorFrameReader* m_pColorFrameReader; + + // Body reader + IBodyFrameReader* m_pBodyFrameReader; + + // Face sources + IHighDefinitionFaceFrameSource* m_pFaceFrameSource; + + // Face readers + IHighDefinitionFaceFrameReader* m_pFaceFrameReader; + + // + RGBQUAD* m_pColorRGBX; + + RectI iFaceBox = { 0 }; + + CameraSpacePoint iLastFacePosition; + CameraSpacePoint iFacePosition; + CameraSpacePoint iFacePositionCenter; + + Vector4 iFaceRotationQuaternion; + // As Yaw, Pitch, Roll + CameraSpacePoint iLastFaceRotation; + CameraSpacePoint iFaceRotation; + CameraSpacePoint iFaceRotationCenter; + // + std::unique_ptr iVideoWidget; + std::unique_ptr iLayout; +}; diff --git a/tracker-kinect-face/test.cpp b/tracker-kinect-face/test.cpp deleted file mode 100644 index c1ada177..00000000 --- a/tracker-kinect-face/test.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright (c) 2014, Stanislaw Halik - - * Permission to use, copy, modify, and/or distribute this - * software for any purpose with or without fee is hereby granted, - * provided that the above copyright notice and this permission - * notice appear in all copies. - */ - -#include "test.h" -#include "tracker.h" -#include "api/plugin-api.hpp" -#include "compat/math-imports.hpp" - -#include - -#include -#include - - -test_dialog::test_dialog() -{ - ui.setupUi(this); - - connect(ui.buttonBox, &QDialogButtonBox::clicked, [this](QAbstractButton* btn) { - if (btn == ui.buttonBox->button(QDialogButtonBox::Abort)) - // NOLINTNEXTLINE - *(volatile int*)nullptr = 0; - }); - - connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); - connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); -} - -void test_dialog::doOK() -{ - //s.b->save(); - close(); -} - -void test_dialog::doCancel() -{ - close(); -} - -OPENTRACK_DECLARE_TRACKER(KinectFaceTracker, test_dialog, test_metadata) diff --git a/tracker-kinect-face/test.h b/tracker-kinect-face/test.h deleted file mode 100644 index 0f8c170b..00000000 --- a/tracker-kinect-face/test.h +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once -#include "ui_test.h" -#include "compat/macros.hpp" -#include "api/plugin-api.hpp" - - -class test_dialog : public ITrackerDialog -{ - Q_OBJECT - - Ui::test_ui ui; -public: - test_dialog(); - void register_tracker(ITracker *) override {} - void unregister_tracker() override {} -private slots: - void doOK(); - void doCancel(); -}; - -class test_metadata : public Metadata -{ - Q_OBJECT - - QString name() { return tr("Kinect Face 0.1"); } - QIcon icon() { return QIcon(":/images/kinect.png"); } -}; - diff --git a/tracker-kinect-face/test_dialog.cpp b/tracker-kinect-face/test_dialog.cpp index 5d33555b..fadf6084 100644 --- a/tracker-kinect-face/test_dialog.cpp +++ b/tracker-kinect-face/test_dialog.cpp @@ -1,3 +1,3 @@ -#include "test.h" +#include "kinect_face_settings.h" #include "api/plugin-api.hpp" diff --git a/tracker-kinect-face/tracker.cpp b/tracker-kinect-face/tracker.cpp deleted file mode 100644 index 54a716ac..00000000 --- a/tracker-kinect-face/tracker.cpp +++ /dev/null @@ -1,569 +0,0 @@ - - -#include "tracker.h" - -#include -#include - - - -/// -bool IsValidRect(const RectI& aRect) -{ - if (aRect.Bottom != 0) - { - return true; - } - - if (aRect.Left != 0) - { - return true; - } - - if (aRect.Right != 0) - { - return true; - } - - if (aRect.Top != 0) - { - return true; - } - - return false; -} - -/// -bool IsNullVetor(const Vector4& aVector) -{ - if (aVector.w != 0) - { - return false; - } - - if (aVector.x != 0) - { - return false; - } - - if (aVector.y != 0) - { - return false; - } - - if (aVector.z != 0) - { - return false; - } - - return true; -} - -/// -bool IsNullPoint(const CameraSpacePoint& aPoint) -{ - if (aPoint.X != 0) - { - return false; - } - - if (aPoint.Y != 0) - { - return false; - } - - if (aPoint.Z != 0) - { - return false; - } - - return true; -} - - -KinectFaceTracker::KinectFaceTracker(): - m_pKinectSensor(nullptr), - m_pCoordinateMapper(nullptr), - m_pColorFrameReader(nullptr), - m_pColorRGBX(nullptr), - m_pBodyFrameReader(nullptr), - iLastFacePosition{0,0,0}, - iFacePositionCenter{ 0,0,0 }, - iFacePosition{ 0,0,0 }, - iLastFaceRotation{ 0,0,0 }, - iFaceRotationCenter{ 0,0,0 }, - iFaceRotation{ 0,0,0 } -{ - m_pFaceFrameSource = nullptr; - m_pFaceFrameReader = nullptr; - - // create heap storage for color pixel data in RGBX format - m_pColorRGBX = new RGBQUAD[cColorWidth * cColorHeight]; -} - -KinectFaceTracker::~KinectFaceTracker() -{ - if (m_pColorRGBX) - { - delete[] m_pColorRGBX; - m_pColorRGBX = nullptr; - } - - // clean up Direct2D - //SafeRelease(m_pD2DFactory); - - // done with face sources and readers - SafeRelease(m_pFaceFrameSource); - SafeRelease(m_pFaceFrameReader); - - // done with body frame reader - SafeRelease(m_pBodyFrameReader); - - // done with color frame reader - SafeRelease(m_pColorFrameReader); - - // done with coordinate mapper - SafeRelease(m_pCoordinateMapper); - - // close the Kinect Sensor - if (m_pKinectSensor) - { - m_pKinectSensor->Close(); - } - - SafeRelease(m_pKinectSensor); -} - -module_status KinectFaceTracker::start_tracker(QFrame* aFrame) -{ - t.start(); - - if (SUCCEEDED(InitializeDefaultSensor())) - { - // Setup our video preview widget - iVideoWidget = std::make_unique(aFrame); - iLayout = std::make_unique(aFrame); - iLayout->setContentsMargins(0, 0, 0, 0); - iLayout->addWidget(iVideoWidget.get()); - aFrame->setLayout(iLayout.get()); - //video_widget->resize(video_frame->width(), video_frame->height()); - aFrame->show(); - - return status_ok(); - } - - return error("Kinect init failed!"); -} - -#ifdef EMIT_NAN -# include -#endif - -bool KinectFaceTracker::center() -{ - // Mark our center - iFacePositionCenter = iFacePosition; - iFaceRotationCenter = iFaceRotation; - return true; -} - - -void KinectFaceTracker::data(double *data) -{ - const double dt = t.elapsed_seconds(); - t.start(); - - Update(); - - ExtractFaceRotationInDegrees(&iFaceRotationQuaternion, &iFaceRotation.X, &iFaceRotation.Y, &iFaceRotation.Z); - - //Check if data is valid - if (!IsNullPoint(iFacePosition) && !IsNullPoint(iFaceRotation)) - { - // We have valid tracking retain position and rotation - iLastFacePosition = iFacePosition; - iLastFaceRotation = iFaceRotation; - } - - // Feed our framework our last valid position and rotation - data[0] = (iLastFacePosition.X - iFacePositionCenter.X) * 100; // Convert to centimer to be in a range that suites OpenTrack. - data[1] = (iLastFacePosition.Y - iFacePositionCenter.Y) * 100; - data[2] = (iLastFacePosition.Z - iFacePositionCenter.Z) * 100; - - // Yaw, Picth, Roll - data[3] = -(iLastFaceRotation.X - iFaceRotationCenter.X); // Invert to be compatible with ED out-of-the-box - data[4] = (iLastFaceRotation.Y - iFaceRotationCenter.Y); - data[5] = (iLastFaceRotation.Z - iFaceRotationCenter.Z); -} - - -/// -/// Converts rotation quaternion to Euler angles -/// And then maps them to a specified range of values to control the refresh rate -/// -/// face rotation quaternion -/// rotation about the X-axis -/// rotation about the Y-axis -/// rotation about the Z-axis -void KinectFaceTracker::ExtractFaceRotationInDegrees(const Vector4* pQuaternion, float* pYaw, float* pPitch, float* pRoll) -{ - double x = pQuaternion->x; - double y = pQuaternion->y; - double z = pQuaternion->z; - double w = pQuaternion->w; - - // convert face rotation quaternion to Euler angles in degrees - double dPitch, dYaw, dRoll; - dPitch = atan2(2 * (y * z + w * x), w * w - x * x - y * y + z * z) / M_PI * 180.0; - dYaw = asin(2 * (w * y - x * z)) / M_PI * 180.0; - dRoll = atan2(2 * (x * y + w * z), w * w + x * x - y * y - z * z) / M_PI * 180.0; - - // clamp rotation values in degrees to a specified range of values to control the refresh rate - /* - double increment = c_FaceRotationIncrementInDegrees; - *pPitch = static_cast(floor((dPitch + increment/2.0 * (dPitch > 0 ? 1.0 : -1.0)) / increment) * increment); - *pYaw = static_cast(floor((dYaw + increment/2.0 * (dYaw > 0 ? 1.0 : -1.0)) / increment) * increment); - *pRoll = static_cast(floor((dRoll + increment/2.0 * (dRoll > 0 ? 1.0 : -1.0)) / increment) * increment); - */ - - *pPitch = dPitch; - *pYaw = dYaw; - *pRoll = dRoll; -} - - - -/// -/// Initializes the default Kinect sensor -/// -/// S_OK on success else the failure code -HRESULT KinectFaceTracker::InitializeDefaultSensor() -{ - HRESULT hr; - - // Get and open Kinect sensor - hr = GetDefaultKinectSensor(&m_pKinectSensor); - if (SUCCEEDED(hr)) - { - hr = m_pKinectSensor->Open(); - } - - // TODO: check if we still need that guy - if (SUCCEEDED(hr)) - { - hr = m_pKinectSensor->get_CoordinateMapper(&m_pCoordinateMapper); - } - - // Create color frame reader - if (SUCCEEDED(hr)) - { - UniqueInterface colorFrameSource; - hr = m_pKinectSensor->get_ColorFrameSource(colorFrameSource.PtrPtr()); - colorFrameSource.Reset(); - - if (SUCCEEDED(hr)) - { - hr = colorFrameSource->OpenReader(&m_pColorFrameReader); - } - } - - // Create body frame reader - if (SUCCEEDED(hr)) - { - UniqueInterface bodyFrameSource; - hr = m_pKinectSensor->get_BodyFrameSource(bodyFrameSource.PtrPtr()); - bodyFrameSource.Reset(); - - if (SUCCEEDED(hr)) - { - hr = bodyFrameSource->OpenReader(&m_pBodyFrameReader); - } - } - - // Create HD face frame source - if (SUCCEEDED(hr)) - { - // create the face frame source by specifying the required face frame features - hr = CreateHighDefinitionFaceFrameSource(m_pKinectSensor, &m_pFaceFrameSource); - } - - // Create HD face frame reader - if (SUCCEEDED(hr)) - { - // open the corresponding reader - hr = m_pFaceFrameSource->OpenReader(&m_pFaceFrameReader); - } - - return hr; -} - -/// -/// Main processing function -/// -void KinectFaceTracker::Update() -{ - if (!m_pColorFrameReader || !m_pBodyFrameReader) - { - return; - } - - IColorFrame* pColorFrame = nullptr; - HRESULT hr = m_pColorFrameReader->AcquireLatestFrame(&pColorFrame); - - if (SUCCEEDED(hr)) - { - INT64 nTime = 0; - IFrameDescription* pFrameDescription = nullptr; - int nWidth = 0; - int nHeight = 0; - ColorImageFormat imageFormat = ColorImageFormat_None; - UINT nBufferSize = 0; - RGBQUAD *pBuffer = nullptr; - - hr = pColorFrame->get_RelativeTime(&nTime); - - if (SUCCEEDED(hr)) - { - hr = pColorFrame->get_FrameDescription(&pFrameDescription); - } - - if (SUCCEEDED(hr)) - { - hr = pFrameDescription->get_Width(&nWidth); - } - - if (SUCCEEDED(hr)) - { - hr = pFrameDescription->get_Height(&nHeight); - } - - if (SUCCEEDED(hr)) - { - hr = pColorFrame->get_RawColorImageFormat(&imageFormat); - } - - if (SUCCEEDED(hr)) - { - // Fetch color buffer - if (imageFormat == ColorImageFormat_Rgba) - { - hr = pColorFrame->AccessRawUnderlyingBuffer(&nBufferSize, reinterpret_cast(&pBuffer)); - } - else if (m_pColorRGBX) - { - pBuffer = m_pColorRGBX; - nBufferSize = cColorWidth * cColorHeight * sizeof(RGBQUAD); - hr = pColorFrame->CopyConvertedFrameDataToArray(nBufferSize, reinterpret_cast(pBuffer), ColorImageFormat_Rgba); - } - else - { - hr = E_FAIL; - } - - } - - if (SUCCEEDED(hr)) - { - //DrawStreams(nTime, pBuffer, nWidth, nHeight); - ProcessFaces(); - } - - if (SUCCEEDED(hr)) - { - // Setup our image - QImage image((const unsigned char*)pBuffer, cColorWidth, cColorHeight, sizeof(RGBQUAD)*cColorWidth, QImage::Format_RGBA8888); - if (IsValidRect(iFaceBox)) - { - // Draw our face bounding box - QPainter painter(&image); - painter.setBrush(Qt::NoBrush); - painter.setPen(QPen(Qt::red, 8)); - painter.drawRect(iFaceBox.Left, iFaceBox.Top, iFaceBox.Right - iFaceBox.Left, iFaceBox.Bottom - iFaceBox.Top); - bool bEnd = painter.end(); - } - - // Update our video preview - iVideoWidget->update_image(image); - } - - SafeRelease(pFrameDescription); - } - - SafeRelease(pColorFrame); -} - - -/// -/// Updates body data -/// -/// pointer to the body data storage -/// indicates success or failure -HRESULT KinectFaceTracker::UpdateBodyData(IBody** ppBodies) -{ - HRESULT hr = E_FAIL; - - if (m_pBodyFrameReader != nullptr) - { - IBodyFrame* pBodyFrame = nullptr; - hr = m_pBodyFrameReader->AcquireLatestFrame(&pBodyFrame); - if (SUCCEEDED(hr)) - { - hr = pBodyFrame->GetAndRefreshBodyData(BODY_COUNT, ppBodies); - } - SafeRelease(pBodyFrame); - } - - return hr; -} - - - -/// -/// Processes new face frames -/// -void KinectFaceTracker::ProcessFaces() -{ - HRESULT hr; - IBody* ppBodies[BODY_COUNT] = { 0 }; - bool bHaveBodyData = SUCCEEDED(UpdateBodyData(ppBodies)); - - if (!bHaveBodyData) - { - return; - } - - // TODO: Select closest body - // Just use the first body we find - BOOLEAN tracked; - int i = 0; - while (i < BODY_COUNT) - { - hr = ppBodies[i]->get_IsTracked(&tracked); - UINT64 trackingId = 0; - - if (SUCCEEDED(hr) && tracked) - { - hr = ppBodies[i]->get_TrackingId(&trackingId); - - if (SUCCEEDED(hr)) - { - // Tell our face source to use the given body id - hr = m_pFaceFrameSource->put_TrackingId(trackingId); - break; - } - - } - - i++; - } - - - // iterate through each face reader - for (int iFace = 0; iFace < BODY_COUNT; ++iFace) - { - // retrieve the latest face frame from this reader - IHighDefinitionFaceFrame* pFaceFrame = nullptr; - hr = m_pFaceFrameReader->AcquireLatestFrame(&pFaceFrame); - - BOOLEAN bFaceTracked = false; - if (SUCCEEDED(hr) && nullptr != pFaceFrame) - { - // check if a valid face is tracked in this face frame - hr = pFaceFrame->get_IsTrackingIdValid(&bFaceTracked); - } - - if (SUCCEEDED(hr)) - { - if (bFaceTracked) - { - //OutputDebugStringA("Tracking face!\n"); - - //IFaceFrameResult* pFaceFrameResult = nullptr; - IFaceAlignment* pFaceAlignment = nullptr; - CreateFaceAlignment(&pFaceAlignment); // TODO: check return? - //D2D1_POINT_2F faceTextLayout; - - //hr = pFaceFrame->get_FaceFrameResult(&pFaceFrameResult); - - hr = pFaceFrame->GetAndRefreshFaceAlignmentResult(pFaceAlignment); - - // need to verify if pFaceFrameResult contains data before trying to access it - if (SUCCEEDED(hr) && pFaceAlignment != nullptr) - { - hr = pFaceAlignment->get_FaceBoundingBox(&iFaceBox); - //pFaceFrameResult->get_FaceBoundingBoxInColorSpace(); - - if (SUCCEEDED(hr)) - { - //hr = pFaceFrameResult->GetFacePointsInColorSpace(FacePointType::FacePointType_Count, facePoints); - hr = pFaceAlignment->get_HeadPivotPoint(&iFacePosition); - } - - if (SUCCEEDED(hr)) - { - //hr = pFaceFrameResult->get_FaceRotationQuaternion(&faceRotation); - hr = pFaceAlignment->get_FaceOrientation(&iFaceRotationQuaternion); - } - - if (SUCCEEDED(hr)) - { - //hr = pFaceFrameResult->GetFaceProperties(FaceProperty::FaceProperty_Count, faceProperties); - } - - if (SUCCEEDED(hr)) - { - //hr = GetFaceTextPositionInColorSpace(ppBodies[0], &faceTextLayout); - } - - if (SUCCEEDED(hr)) - { - // draw face frame results - //m_pDrawDataStreams->DrawFaceFrameResults(0, &faceBox, facePoints, &faceRotation, faceProperties, &faceTextLayout); - } - } - - SafeRelease(pFaceAlignment); - } - else - { - // face tracking is not valid - attempt to fix the issue - // a valid body is required to perform this step - if (bHaveBodyData) - { - // check if the corresponding body is tracked - // if this is true then update the face frame source to track this body - IBody* pBody = ppBodies[iFace]; - if (pBody != nullptr) - { - BOOLEAN bTracked = false; - hr = pBody->get_IsTracked(&bTracked); - - UINT64 bodyTId; - if (SUCCEEDED(hr) && bTracked) - { - // get the tracking ID of this body - hr = pBody->get_TrackingId(&bodyTId); - if (SUCCEEDED(hr)) - { - // update the face frame source with the tracking ID - m_pFaceFrameSource->put_TrackingId(bodyTId); - } - } - } - } - } - } - - SafeRelease(pFaceFrame); - } - - if (bHaveBodyData) - { - for (int i = 0; i < _countof(ppBodies); ++i) - { - SafeRelease(ppBodies[i]); - } - } -} - - diff --git a/tracker-kinect-face/tracker.h b/tracker-kinect-face/tracker.h deleted file mode 100644 index 220a126f..00000000 --- a/tracker-kinect-face/tracker.h +++ /dev/null @@ -1,113 +0,0 @@ - - - -#include - -#include "api/plugin-api.hpp" -#include "compat/timer.hpp" -#include "compat/macros.hpp" -#include "cv/video-widget.hpp" - -// Kinect Header files -#include -#include - -#pragma once - -// @deprecated Use UniqueInterface instead. Remove it at some point. -template -inline void SafeRelease(Interface *& pInterfaceToRelease) -{ - if (pInterfaceToRelease != nullptr) - { - pInterfaceToRelease->Release(); - pInterfaceToRelease = nullptr; - } -} - -template -inline void ReleaseInterface(Interface* pInterfaceToRelease) -{ - if (pInterfaceToRelease != nullptr) - { - pInterfaceToRelease->Release(); - } -} - -// Safely use Microsoft interfaces. -template -class UniqueInterface : public std::unique_ptr)> ///**/ -{ -public: - UniqueInterface() : std::unique_ptr)>(nullptr, ReleaseInterface){} - // Access pointer, typically for creation - T** PtrPtr() { return &iPtr; }; - // Called this once the pointer was created - void Reset() { std::unique_ptr)>::reset(iPtr); } - // If ever you want to release that interface before the object is deleted - void Free() { iPtr = nullptr; Reset(); } -private: - T* iPtr = nullptr; -}; - - - -class KinectFaceTracker : public ITracker -{ -public: - KinectFaceTracker(); - ~KinectFaceTracker() override; - module_status start_tracker(QFrame* aFrame) override; - void data(double *data) override; - bool center() override; - -private: - Timer t; - - // Kinect stuff - static const int cColorWidth = 1920; - static const int cColorHeight = 1080; - - - void Update(); - HRESULT InitializeDefaultSensor(); - void ProcessFaces(); - HRESULT UpdateBodyData(IBody** ppBodies); - void ExtractFaceRotationInDegrees(const Vector4* pQuaternion, float* pPitch, float* pYaw, float* pRoll); - - // Current Kinect - IKinectSensor* m_pKinectSensor; - - // Coordinate mapper - ICoordinateMapper* m_pCoordinateMapper; - - // Color reader - IColorFrameReader* m_pColorFrameReader; - - // Body reader - IBodyFrameReader* m_pBodyFrameReader; - - // Face sources - IHighDefinitionFaceFrameSource* m_pFaceFrameSource; - - // Face readers - IHighDefinitionFaceFrameReader* m_pFaceFrameReader; - - // - RGBQUAD* m_pColorRGBX; - - RectI iFaceBox = { 0 }; - - CameraSpacePoint iLastFacePosition; - CameraSpacePoint iFacePosition; - CameraSpacePoint iFacePositionCenter; - - Vector4 iFaceRotationQuaternion; - // As Yaw, Pitch, Roll - CameraSpacePoint iLastFaceRotation; - CameraSpacePoint iFaceRotation; - CameraSpacePoint iFaceRotationCenter; - // - std::unique_ptr iVideoWidget; - std::unique_ptr iLayout; -}; -- cgit v1.2.3 From e2582c127addd7a3eaafb8cf8a63a5221c7aac20 Mon Sep 17 00:00:00 2001 From: Stéphane Lenclud Date: Sun, 3 Feb 2019 12:32:16 +0100 Subject: Kinect: Renaming more files. --- tracker-kinect-face/kinect.qrc | 5 --- tracker-kinect-face/kinect_face.qrc | 5 +++ tracker-kinect-face/kinect_face_settings.ui | 65 +++++++++++++++++++++++++++++ tracker-kinect-face/test.ui | 65 ----------------------------- tracker-kinect-face/test_dialog.cpp | 3 -- 5 files changed, 70 insertions(+), 73 deletions(-) delete mode 100644 tracker-kinect-face/kinect.qrc create mode 100644 tracker-kinect-face/kinect_face.qrc create mode 100644 tracker-kinect-face/kinect_face_settings.ui delete mode 100644 tracker-kinect-face/test.ui delete mode 100644 tracker-kinect-face/test_dialog.cpp diff --git a/tracker-kinect-face/kinect.qrc b/tracker-kinect-face/kinect.qrc deleted file mode 100644 index 8b27c81e..00000000 --- a/tracker-kinect-face/kinect.qrc +++ /dev/null @@ -1,5 +0,0 @@ - - - images/kinect.png - - diff --git a/tracker-kinect-face/kinect_face.qrc b/tracker-kinect-face/kinect_face.qrc new file mode 100644 index 00000000..8b27c81e --- /dev/null +++ b/tracker-kinect-face/kinect_face.qrc @@ -0,0 +1,5 @@ + + + images/kinect.png + + diff --git a/tracker-kinect-face/kinect_face_settings.ui b/tracker-kinect-face/kinect_face_settings.ui new file mode 100644 index 00000000..509eb819 --- /dev/null +++ b/tracker-kinect-face/kinect_face_settings.ui @@ -0,0 +1,65 @@ + + + test_ui + + + Qt::NonModal + + + + 0 + 0 + 278 + 58 + + + + Sine wave + + + + ../gui/images/opentrack.png../gui/images/opentrack.png + + + Qt::LeftToRight + + + false + + + + + + + 0 + 0 + + + + Pressing "Abort" will immediately crash the application. + + + + + + + + 0 + 0 + + + + QDialogButtonBox::Abort|QDialogButtonBox::Close + + + + + + + + + startEngineClicked() + stopEngineClicked() + cameraSettingsClicked() + + diff --git a/tracker-kinect-face/test.ui b/tracker-kinect-face/test.ui deleted file mode 100644 index 509eb819..00000000 --- a/tracker-kinect-face/test.ui +++ /dev/null @@ -1,65 +0,0 @@ - - - test_ui - - - Qt::NonModal - - - - 0 - 0 - 278 - 58 - - - - Sine wave - - - - ../gui/images/opentrack.png../gui/images/opentrack.png - - - Qt::LeftToRight - - - false - - - - - - - 0 - 0 - - - - Pressing "Abort" will immediately crash the application. - - - - - - - - 0 - 0 - - - - QDialogButtonBox::Abort|QDialogButtonBox::Close - - - - - - - - - startEngineClicked() - stopEngineClicked() - cameraSettingsClicked() - - diff --git a/tracker-kinect-face/test_dialog.cpp b/tracker-kinect-face/test_dialog.cpp deleted file mode 100644 index fadf6084..00000000 --- a/tracker-kinect-face/test_dialog.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "kinect_face_settings.h" -#include "api/plugin-api.hpp" - -- cgit v1.2.3 From 57285c2269f53bc7ae61f40289edc9083432bc8a Mon Sep 17 00:00:00 2001 From: Stéphane Lenclud Date: Sun, 3 Feb 2019 13:39:45 +0100 Subject: Kinect: Better body look-up algorithm that should allow someone to look over your shoulder without the tracker getting confused. --- tracker-kinect-face/kinect_face_tracker.cpp | 239 ++++++++++++++++------------ tracker-kinect-face/kinect_face_tracker.h | 5 + 2 files changed, 143 insertions(+), 101 deletions(-) diff --git a/tracker-kinect-face/kinect_face_tracker.cpp b/tracker-kinect-face/kinect_face_tracker.cpp index ccac8aa9..b7ccfecf 100644 --- a/tracker-kinect-face/kinect_face_tracker.cpp +++ b/tracker-kinect-face/kinect_face_tracker.cpp @@ -417,141 +417,178 @@ HRESULT KinectFaceTracker::UpdateBodyData(IBody** ppBodies) } +float VectorLengthSquared(CameraSpacePoint point) +{ + float lenghtSquared = pow(point.X, 2) + pow(point.Y, 2) + pow(point.Z, 2); + + //result = Math.Sqrt(result); + return lenghtSquared; +} + +// +// Finds the closest body from the sensor if any +// +IBody* KinectFaceTracker::FindClosestBody(IBody** aBodies) +{ + IBody* result = nullptr; + float closestBodyDistance = std::numeric_limits::max(); + + for(int i=0;iget_IsTracked(&tracked); + + if (tracked) + { + Joint joints[JointType_Count]; + HRESULT hr = aBodies[i]->GetJoints(JointType_Count,joints); + if (FAILED(hr)) + { + continue; + } + + auto currentLocation = joints[JointType_SpineBase].Position; + auto currentDistance = VectorLengthSquared(currentLocation); + + if (result == nullptr || currentDistance < closestBodyDistance) + { + result = aBodies[i]; + closestBodyDistance = currentDistance; + } + } + } + + return result; +} + +// +// Search our list of body for the one matching our id +// +IBody* KinectFaceTracker::FindTrackedBodyById(IBody** aBodies, UINT64 aTrackingId) +{ + float closestBodyDistance = std::numeric_limits::max(); + + for (int i = 0; i < BODY_COUNT; i++) + { + BOOLEAN tracked; + HRESULT hr = aBodies[i]->get_IsTracked(&tracked); + + if (tracked) + { + if (SUCCEEDED(hr) && tracked) + { + UINT64 trackingId = 0; + hr = aBodies[i]->get_TrackingId(&trackingId); + + if (SUCCEEDED(hr) && aTrackingId == trackingId) + { + return aBodies[i]; + } + } + } + } + + return nullptr; +} + /// /// Processes new face frames /// void KinectFaceTracker::ProcessFaces() { - HRESULT hr; - IBody* ppBodies[BODY_COUNT] = { 0 }; - bool bHaveBodyData = SUCCEEDED(UpdateBodyData(ppBodies)); - + HRESULT hr=0; + IBody* bodies[BODY_COUNT] = { 0 }; // Each bodies will need to be released + bool bHaveBodyData = SUCCEEDED(UpdateBodyData(bodies)); if (!bHaveBodyData) { return; } - // TODO: Select closest body - // Just use the first body we find - BOOLEAN tracked; - int i = 0; - while (i < BODY_COUNT) + // Try keep tracking the same body + IBody* body = FindTrackedBodyById(bodies, iTrackingId); + if (body == nullptr) { - hr = ppBodies[i]->get_IsTracked(&tracked); - UINT64 trackingId = 0; - - if (SUCCEEDED(hr) && tracked) + // The body we were tracking is gone, try tracking the closest body if any + body = FindClosestBody(bodies); + if (body != nullptr) { - hr = ppBodies[i]->get_TrackingId(&trackingId); - + // Update our face source with our new body id + hr = body->get_TrackingId(&iTrackingId); if (SUCCEEDED(hr)) { // Tell our face source to use the given body id - hr = m_pFaceFrameSource->put_TrackingId(trackingId); - break; + hr = m_pFaceFrameSource->put_TrackingId(iTrackingId); + //OutputDebugStringA("Tracking new body!\n"); } - } - - i++; } - - // iterate through each face reader - for (int iFace = 0; iFace < BODY_COUNT; ++iFace) + // retrieve the latest face frame from this reader + IHighDefinitionFaceFrame* pFaceFrame = nullptr; + if (SUCCEEDED(hr)) { - // retrieve the latest face frame from this reader - IHighDefinitionFaceFrame* pFaceFrame = nullptr; hr = m_pFaceFrameReader->AcquireLatestFrame(&pFaceFrame); + } - BOOLEAN bFaceTracked = false; - if (SUCCEEDED(hr) && nullptr != pFaceFrame) - { - // check if a valid face is tracked in this face frame - hr = pFaceFrame->get_IsTrackingIdValid(&bFaceTracked); - } + BOOLEAN bFaceTracked = false; + if (SUCCEEDED(hr) && nullptr != pFaceFrame) + { + // check if a valid face is tracked in this face frame + hr = pFaceFrame->get_IsTrackingIdValid(&bFaceTracked); + } - if (SUCCEEDED(hr)) + if (SUCCEEDED(hr)) + { + if (bFaceTracked) { - if (bFaceTracked) + //OutputDebugStringA("Tracking face!\n"); + + //IFaceFrameResult* pFaceFrameResult = nullptr; + IFaceAlignment* pFaceAlignment = nullptr; + CreateFaceAlignment(&pFaceAlignment); // TODO: check return? + //D2D1_POINT_2F faceTextLayout; + + //hr = pFaceFrame->get_FaceFrameResult(&pFaceFrameResult); + + hr = pFaceFrame->GetAndRefreshFaceAlignmentResult(pFaceAlignment); + + // need to verify if pFaceFrameResult contains data before trying to access it + if (SUCCEEDED(hr) && pFaceAlignment != nullptr) { - //OutputDebugStringA("Tracking face!\n"); + hr = pFaceAlignment->get_FaceBoundingBox(&iFaceBox); + //pFaceFrameResult->get_FaceBoundingBoxInColorSpace(); - //IFaceFrameResult* pFaceFrameResult = nullptr; - IFaceAlignment* pFaceAlignment = nullptr; - CreateFaceAlignment(&pFaceAlignment); // TODO: check return? - //D2D1_POINT_2F faceTextLayout; + if (SUCCEEDED(hr)) + { + //hr = pFaceFrameResult->GetFacePointsInColorSpace(FacePointType::FacePointType_Count, facePoints); + hr = pFaceAlignment->get_HeadPivotPoint(&iFacePosition); + } - //hr = pFaceFrame->get_FaceFrameResult(&pFaceFrameResult); + if (SUCCEEDED(hr)) + { + //hr = pFaceFrameResult->get_FaceRotationQuaternion(&faceRotation); + hr = pFaceAlignment->get_FaceOrientation(&iFaceRotationQuaternion); + } - hr = pFaceFrame->GetAndRefreshFaceAlignmentResult(pFaceAlignment); + if (SUCCEEDED(hr)) + { + //hr = pFaceFrameResult->GetFaceProperties(FaceProperty::FaceProperty_Count, faceProperties); + } - // need to verify if pFaceFrameResult contains data before trying to access it - if (SUCCEEDED(hr) && pFaceAlignment != nullptr) + if (SUCCEEDED(hr)) { - hr = pFaceAlignment->get_FaceBoundingBox(&iFaceBox); - //pFaceFrameResult->get_FaceBoundingBoxInColorSpace(); - - if (SUCCEEDED(hr)) - { - //hr = pFaceFrameResult->GetFacePointsInColorSpace(FacePointType::FacePointType_Count, facePoints); - hr = pFaceAlignment->get_HeadPivotPoint(&iFacePosition); - } - - if (SUCCEEDED(hr)) - { - //hr = pFaceFrameResult->get_FaceRotationQuaternion(&faceRotation); - hr = pFaceAlignment->get_FaceOrientation(&iFaceRotationQuaternion); - } - - if (SUCCEEDED(hr)) - { - //hr = pFaceFrameResult->GetFaceProperties(FaceProperty::FaceProperty_Count, faceProperties); - } - - if (SUCCEEDED(hr)) - { - //hr = GetFaceTextPositionInColorSpace(ppBodies[0], &faceTextLayout); - } - - if (SUCCEEDED(hr)) - { - // draw face frame results - //m_pDrawDataStreams->DrawFaceFrameResults(0, &faceBox, facePoints, &faceRotation, faceProperties, &faceTextLayout); - } + //hr = GetFaceTextPositionInColorSpace(ppBodies[0], &faceTextLayout); } - SafeRelease(pFaceAlignment); - } - else - { - // face tracking is not valid - attempt to fix the issue - // a valid body is required to perform this step - if (bHaveBodyData) + if (SUCCEEDED(hr)) { - // check if the corresponding body is tracked - // if this is true then update the face frame source to track this body - IBody* pBody = ppBodies[iFace]; - if (pBody != nullptr) - { - BOOLEAN bTracked = false; - hr = pBody->get_IsTracked(&bTracked); - - UINT64 bodyTId; - if (SUCCEEDED(hr) && bTracked) - { - // get the tracking ID of this body - hr = pBody->get_TrackingId(&bodyTId); - if (SUCCEEDED(hr)) - { - // update the face frame source with the tracking ID - m_pFaceFrameSource->put_TrackingId(bodyTId); - } - } - } + // draw face frame results + //m_pDrawDataStreams->DrawFaceFrameResults(0, &faceBox, facePoints, &faceRotation, faceProperties, &faceTextLayout); } } + + SafeRelease(pFaceAlignment); } SafeRelease(pFaceFrame); @@ -559,9 +596,9 @@ void KinectFaceTracker::ProcessFaces() if (bHaveBodyData) { - for (int i = 0; i < _countof(ppBodies); ++i) + for (int i = 0; i < _countof(bodies); ++i) { - SafeRelease(ppBodies[i]); + SafeRelease(bodies[i]); } } } diff --git a/tracker-kinect-face/kinect_face_tracker.h b/tracker-kinect-face/kinect_face_tracker.h index 220a126f..de71f081 100644 --- a/tracker-kinect-face/kinect_face_tracker.h +++ b/tracker-kinect-face/kinect_face_tracker.h @@ -74,6 +74,8 @@ private: void ProcessFaces(); HRESULT UpdateBodyData(IBody** ppBodies); void ExtractFaceRotationInDegrees(const Vector4* pQuaternion, float* pPitch, float* pYaw, float* pRoll); + static IBody* FindClosestBody(IBody** aBodies); + static IBody* FindTrackedBodyById(IBody** aBodies,UINT64 aTrackingId); // Current Kinect IKinectSensor* m_pKinectSensor; @@ -110,4 +112,7 @@ private: // std::unique_ptr iVideoWidget; std::unique_ptr iLayout; + + // Id of the body currently being tracked + UINT64 iTrackingId = 0; }; -- cgit v1.2.3 From ecaf8b6403f57e5813190f4ae1b89780c45339d8 Mon Sep 17 00:00:00 2001 From: Stéphane Lenclud Date: Sun, 3 Feb 2019 13:45:03 +0100 Subject: Kinect: Fixing tracking validity check. --- tracker-kinect-face/kinect_face_tracker.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tracker-kinect-face/kinect_face_tracker.cpp b/tracker-kinect-face/kinect_face_tracker.cpp index b7ccfecf..51990693 100644 --- a/tracker-kinect-face/kinect_face_tracker.cpp +++ b/tracker-kinect-face/kinect_face_tracker.cpp @@ -167,7 +167,9 @@ bool KinectFaceTracker::center() return true; } - +// +// +// void KinectFaceTracker::data(double *data) { const double dt = t.elapsed_seconds(); @@ -178,7 +180,7 @@ void KinectFaceTracker::data(double *data) ExtractFaceRotationInDegrees(&iFaceRotationQuaternion, &iFaceRotation.X, &iFaceRotation.Y, &iFaceRotation.Z); //Check if data is valid - if (!IsNullPoint(iFacePosition) && !IsNullPoint(iFaceRotation)) + if (IsValidRect(iFaceBox)) { // We have valid tracking retain position and rotation iLastFacePosition = iFacePosition; -- cgit v1.2.3 From 58cc914eb84cb4257904e401a91c0cd5fe3aebf7 Mon Sep 17 00:00:00 2001 From: Stéphane Lenclud Date: Sun, 3 Feb 2019 14:11:00 +0100 Subject: Kinect: CMake adjustments following code review. --- tracker-kinect-face/CMakeLists.txt | 20 +++++++++++--------- tracker-kinect-face/kinect_face_tracker.cpp | 5 +++++ 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/tracker-kinect-face/CMakeLists.txt b/tracker-kinect-face/CMakeLists.txt index e12534b2..690f82e7 100644 --- a/tracker-kinect-face/CMakeLists.txt +++ b/tracker-kinect-face/CMakeLists.txt @@ -4,18 +4,18 @@ if (WIN32) if(OpenCV_FOUND) # Setup cache variable to Kinect SDK path if(DEFINED ENV{KINECTSDK20_DIR}) - set(KINECTSDK20_DIR $ENV{KINECTSDK20_DIR} CACHE PATH $ENV{KINECTSDK20_DIR}) + set(SDK_KINECT20 $ENV{KINECTSDK20_DIR} CACHE PATH $ENV{KINECTSDK20_DIR}) else() - set(KINECTSDK20_DIR $ENV{KINECTSDK20_DIR} CACHE PATH "") + set(SDK_KINECT20 $ENV{KINECTSDK20_DIR} CACHE PATH "") endif() # If we have a valid SDK path, try build that tracker - if(EXISTS ${KINECTSDK20_DIR}) + if(EXISTS ${SDK_KINECT20}) # Register our module otr_module(tracker-kinect-face) # Add include path to Kinect SDK - target_include_directories(opentrack-tracker-kinect-face SYSTEM PUBLIC ${KINECTSDK20_DIR}/inc) + target_include_directories(opentrack-tracker-kinect-face SYSTEM PUBLIC "${SDK_KINECT20}/inc") # Check processor architecture if(CMAKE_SIZEOF_VOID_P EQUAL 4) @@ -23,18 +23,20 @@ if (WIN32) set (kinect-arch-dir "x86") elseif(CMAKE_SIZEOF_VOID_P EQUAL 8) # 64 bits - set (kinect-arch-dir "x64") + set (kinect-arch-dir "x64") + else() + message(FATAL_ERROR "Kinect: architecture not supported!") endif() # Link against Kinect SDK libraries - target_link_libraries(opentrack-tracker-kinect-face ${KINECTSDK20_DIR}/lib/${kinect-arch-dir}/Kinect20.lib ${KINECTSDK20_DIR}/lib/${kinect-arch-dir}/Kinect20.Face.lib) + target_link_libraries(opentrack-tracker-kinect-face "${SDK_KINECT20}/lib/${kinect-arch-dir}/Kinect20.lib" "${SDK_KINECT20}/lib/${kinect-arch-dir}/Kinect20.Face.lib") # Link against OpenCV stuff, needed for video preview target_link_libraries(opentrack-tracker-kinect-face opencv_imgproc opentrack-cv opencv_core) # Install Kinect Face DLL - install(FILES ${KINECTSDK20_DIR}/Redist/Face/${kinect-arch-dir}/Kinect20.Face.dll DESTINATION ./modules/ PERMISSIONS ${opentrack-perms-exec}) + install(FILES "${SDK_KINECT20}/Redist/Face/${kinect-arch-dir}/Kinect20.Face.dll" DESTINATION "./modules/" PERMISSIONS ${opentrack-perms-exec}) # Install Kinect Face Database - install(DIRECTORY ${KINECTSDK20_DIR}/Redist/Face/${kinect-arch-dir}/NuiDatabase DESTINATION ./modules/) - endif(EXISTS ${KINECTSDK20_DIR}) + install(DIRECTORY "${SDK_KINECT20}/Redist/Face/${kinect-arch-dir}/NuiDatabase" DESTINATION "./modules/") + endif(EXISTS ${SDK_KINECT20}) endif(OpenCV_FOUND) endif(WIN32) \ No newline at end of file diff --git a/tracker-kinect-face/kinect_face_tracker.cpp b/tracker-kinect-face/kinect_face_tracker.cpp index 51990693..0b7775bc 100644 --- a/tracker-kinect-face/kinect_face_tracker.cpp +++ b/tracker-kinect-face/kinect_face_tracker.cpp @@ -186,6 +186,11 @@ void KinectFaceTracker::data(double *data) iLastFacePosition = iFacePosition; iLastFaceRotation = iFaceRotation; } + else + { + //TODO: after like 5s without tracking reset position to zero + //TODO: Instead of hardcoding that delay add it to our settings + } // Feed our framework our last valid position and rotation data[0] = (iLastFacePosition.X - iFacePositionCenter.X) * 100; // Convert to centimer to be in a range that suites OpenTrack. -- cgit v1.2.3 From 7397242cb156ae0d1e942fba9d209b8627a2072e Mon Sep 17 00:00:00 2001 From: Stéphane Lenclud Date: Sun, 3 Feb 2019 14:17:38 +0100 Subject: Kinect: Removing dead code. --- tracker-kinect-face/kinect_face_tracker.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/tracker-kinect-face/kinect_face_tracker.cpp b/tracker-kinect-face/kinect_face_tracker.cpp index 0b7775bc..40571a28 100644 --- a/tracker-kinect-face/kinect_face_tracker.cpp +++ b/tracker-kinect-face/kinect_face_tracker.cpp @@ -155,9 +155,6 @@ module_status KinectFaceTracker::start_tracker(QFrame* aFrame) return error("Kinect init failed!"); } -#ifdef EMIT_NAN -# include -#endif bool KinectFaceTracker::center() { -- cgit v1.2.3 From 4508be24ef4adc4dac0c40ef316b07da75765b77 Mon Sep 17 00:00:00 2001 From: Stéphane Lenclud Date: Sun, 3 Feb 2019 15:03:57 +0100 Subject: Kinect: Limit actual frame rate to 30Hz. Fixing settings dialog. --- tracker-kinect-face/kinect_face_settings.cpp | 16 +++++++------ tracker-kinect-face/kinect_face_settings.h | 10 ++++---- tracker-kinect-face/kinect_face_settings.ui | 10 ++++---- tracker-kinect-face/kinect_face_tracker.cpp | 35 +++++++++++++++++----------- tracker-kinect-face/kinect_face_tracker.h | 4 +++- tracker-kinect-face/lang/nl_NL.ts | 8 +++---- tracker-kinect-face/lang/ru_RU.ts | 8 +++---- tracker-kinect-face/lang/stub.ts | 8 +++---- tracker-kinect-face/lang/zh_CN.ts | 8 +++---- 9 files changed, 59 insertions(+), 48 deletions(-) diff --git a/tracker-kinect-face/kinect_face_settings.cpp b/tracker-kinect-face/kinect_face_settings.cpp index 53aada06..238a3da6 100644 --- a/tracker-kinect-face/kinect_face_settings.cpp +++ b/tracker-kinect-face/kinect_face_settings.cpp @@ -17,29 +17,31 @@ #include -test_dialog::test_dialog() +KinectFaceSettings::KinectFaceSettings() { ui.setupUi(this); connect(ui.buttonBox, &QDialogButtonBox::clicked, [this](QAbstractButton* btn) { - if (btn == ui.buttonBox->button(QDialogButtonBox::Abort)) - // NOLINTNEXTLINE - *(volatile int*)nullptr = 0; + if (btn == ui.buttonBox->button(QDialogButtonBox::Abort)) + { + // NOLINTNEXTLINE + //*(volatile int*)nullptr = 0; + } }); connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); } -void test_dialog::doOK() +void KinectFaceSettings::doOK() { //s.b->save(); close(); } -void test_dialog::doCancel() +void KinectFaceSettings::doCancel() { close(); } -OPENTRACK_DECLARE_TRACKER(KinectFaceTracker, test_dialog, test_metadata) +OPENTRACK_DECLARE_TRACKER(KinectFaceTracker, KinectFaceSettings, KinectFaceMetadata) diff --git a/tracker-kinect-face/kinect_face_settings.h b/tracker-kinect-face/kinect_face_settings.h index 0f8c170b..647aa754 100644 --- a/tracker-kinect-face/kinect_face_settings.h +++ b/tracker-kinect-face/kinect_face_settings.h @@ -1,16 +1,16 @@ #pragma once -#include "ui_test.h" +#include "ui_kinect_face_settings.h" #include "compat/macros.hpp" #include "api/plugin-api.hpp" -class test_dialog : public ITrackerDialog +class KinectFaceSettings : public ITrackerDialog { Q_OBJECT - Ui::test_ui ui; + Ui::KinectFaceUi ui; public: - test_dialog(); + KinectFaceSettings(); void register_tracker(ITracker *) override {} void unregister_tracker() override {} private slots: @@ -18,7 +18,7 @@ private slots: void doCancel(); }; -class test_metadata : public Metadata +class KinectFaceMetadata : public Metadata { Q_OBJECT diff --git a/tracker-kinect-face/kinect_face_settings.ui b/tracker-kinect-face/kinect_face_settings.ui index 509eb819..a6192d9b 100644 --- a/tracker-kinect-face/kinect_face_settings.ui +++ b/tracker-kinect-face/kinect_face_settings.ui @@ -1,7 +1,7 @@ - test_ui - + KinectFaceUi + Qt::NonModal @@ -14,11 +14,11 @@ - Sine wave + Kinect Face Tracker - ../gui/images/opentrack.png../gui/images/opentrack.png + :/images/kinect.png:/images/kinect.png Qt::LeftToRight @@ -36,7 +36,7 @@ - Pressing "Abort" will immediately crash the application. + Start OpenTrack to check if Kinect Face Tracker is working. diff --git a/tracker-kinect-face/kinect_face_tracker.cpp b/tracker-kinect-face/kinect_face_tracker.cpp index 40571a28..ab568f1e 100644 --- a/tracker-kinect-face/kinect_face_tracker.cpp +++ b/tracker-kinect-face/kinect_face_tracker.cpp @@ -170,25 +170,32 @@ bool KinectFaceTracker::center() void KinectFaceTracker::data(double *data) { const double dt = t.elapsed_seconds(); - t.start(); - - Update(); - - ExtractFaceRotationInDegrees(&iFaceRotationQuaternion, &iFaceRotation.X, &iFaceRotation.Y, &iFaceRotation.Z); - //Check if data is valid - if (IsValidRect(iFaceBox)) + const double KMinDelayInSeconds = 1.0 / 30.0; // Pointless running faster than Kinect hardware itself + if (dt > KMinDelayInSeconds) { - // We have valid tracking retain position and rotation - iLastFacePosition = iFacePosition; - iLastFaceRotation = iFaceRotation; + t.start(); // Reset our timer + //OutputDebugStringA("Updating frame!\n"); + Update(); + ExtractFaceRotationInDegrees(&iFaceRotationQuaternion, &iFaceRotation.X, &iFaceRotation.Y, &iFaceRotation.Z); + //Check if data is valid + if (IsValidRect(iFaceBox)) + { + // We have valid tracking retain position and rotation + iLastFacePosition = iFacePosition; + iLastFaceRotation = iFaceRotation; + } + else + { + //TODO: after like 5s without tracking reset position to zero + //TODO: Instead of hardcoding that delay add it to our settings + } } else { - //TODO: after like 5s without tracking reset position to zero - //TODO: Instead of hardcoding that delay add it to our settings + //OutputDebugStringA("Skipping frame!\n"); } - + // Feed our framework our last valid position and rotation data[0] = (iLastFacePosition.X - iFacePositionCenter.X) * 100; // Convert to centimer to be in a range that suites OpenTrack. data[1] = (iLastFacePosition.Y - iFacePositionCenter.Y) * 100; @@ -344,7 +351,7 @@ void KinectFaceTracker::Update() if (SUCCEEDED(hr)) { hr = pColorFrame->get_RawColorImageFormat(&imageFormat); - } + } if (SUCCEEDED(hr)) { diff --git a/tracker-kinect-face/kinect_face_tracker.h b/tracker-kinect-face/kinect_face_tracker.h index de71f081..9f75507d 100644 --- a/tracker-kinect-face/kinect_face_tracker.h +++ b/tracker-kinect-face/kinect_face_tracker.h @@ -51,7 +51,9 @@ private: }; - +// +// +// class KinectFaceTracker : public ITracker { public: diff --git a/tracker-kinect-face/lang/nl_NL.ts b/tracker-kinect-face/lang/nl_NL.ts index f4fe07d8..a0a737ee 100644 --- a/tracker-kinect-face/lang/nl_NL.ts +++ b/tracker-kinect-face/lang/nl_NL.ts @@ -2,20 +2,20 @@ - test_metadata + KinectFaceMetadata Kinect Face 0.1 - test_ui + KinectFaceUi - Sine wave + Kinect Face Tracker - Pressing "Abort" will immediately crash the application. + Start OpenTrack to check if Kinect Face Tracker is working. diff --git a/tracker-kinect-face/lang/ru_RU.ts b/tracker-kinect-face/lang/ru_RU.ts index d4108ed3..72f91367 100644 --- a/tracker-kinect-face/lang/ru_RU.ts +++ b/tracker-kinect-face/lang/ru_RU.ts @@ -2,20 +2,20 @@ - test_metadata + KinectFaceMetadata Kinect Face 0.1 - test_ui + KinectFaceUi - Sine wave + Kinect Face Tracker - Pressing "Abort" will immediately crash the application. + Start OpenTrack to check if Kinect Face Tracker is working. diff --git a/tracker-kinect-face/lang/stub.ts b/tracker-kinect-face/lang/stub.ts index f82903a3..055ec4e1 100644 --- a/tracker-kinect-face/lang/stub.ts +++ b/tracker-kinect-face/lang/stub.ts @@ -2,20 +2,20 @@ - test_metadata + KinectFaceMetadata Kinect Face 0.1 - test_ui + KinectFaceUi - Sine wave + Kinect Face Tracker - Pressing "Abort" will immediately crash the application. + Start OpenTrack to check if Kinect Face Tracker is working. diff --git a/tracker-kinect-face/lang/zh_CN.ts b/tracker-kinect-face/lang/zh_CN.ts index f82903a3..055ec4e1 100644 --- a/tracker-kinect-face/lang/zh_CN.ts +++ b/tracker-kinect-face/lang/zh_CN.ts @@ -2,20 +2,20 @@ - test_metadata + KinectFaceMetadata Kinect Face 0.1 - test_ui + KinectFaceUi - Sine wave + Kinect Face Tracker - Pressing "Abort" will immediately crash the application. + Start OpenTrack to check if Kinect Face Tracker is working. -- cgit v1.2.3 From 1f82111bbee522c4d31372f9f64b903a08ccc11e Mon Sep 17 00:00:00 2001 From: Stéphane Lenclud Date: Sun, 3 Feb 2019 15:20:36 +0100 Subject: Kinect: Don't do video preview when not needed. --- tracker-kinect-face/kinect_face_tracker.cpp | 76 ++++++++++++++++------------- 1 file changed, 43 insertions(+), 33 deletions(-) diff --git a/tracker-kinect-face/kinect_face_tracker.cpp b/tracker-kinect-face/kinect_face_tracker.cpp index ab568f1e..5663de0f 100644 --- a/tracker-kinect-face/kinect_face_tracker.cpp +++ b/tracker-kinect-face/kinect_face_tracker.cpp @@ -5,6 +5,7 @@ #include #include +#include "compat/check-visible.hpp" /// @@ -308,6 +309,8 @@ HRESULT KinectFaceTracker::InitializeDefaultSensor() return hr; } + + /// /// Main processing function /// @@ -353,50 +356,57 @@ void KinectFaceTracker::Update() hr = pColorFrame->get_RawColorImageFormat(&imageFormat); } - if (SUCCEEDED(hr)) - { - // Fetch color buffer - if (imageFormat == ColorImageFormat_Rgba) - { - hr = pColorFrame->AccessRawUnderlyingBuffer(&nBufferSize, reinterpret_cast(&pBuffer)); - } - else if (m_pColorRGBX) - { - pBuffer = m_pColorRGBX; - nBufferSize = cColorWidth * cColorHeight * sizeof(RGBQUAD); - hr = pColorFrame->CopyConvertedFrameDataToArray(nBufferSize, reinterpret_cast(pBuffer), ColorImageFormat_Rgba); - } - else - { - hr = E_FAIL; - } - - } - if (SUCCEEDED(hr)) { //DrawStreams(nTime, pBuffer, nWidth, nHeight); ProcessFaces(); } - if (SUCCEEDED(hr)) - { - // Setup our image - QImage image((const unsigned char*)pBuffer, cColorWidth, cColorHeight, sizeof(RGBQUAD)*cColorWidth, QImage::Format_RGBA8888); - if (IsValidRect(iFaceBox)) + if (check_is_visible()) + { + //OutputDebugStringA("Widget visible!\n"); + // If our widget is visible we feed it our frame + if (SUCCEEDED(hr)) { - // Draw our face bounding box - QPainter painter(&image); - painter.setBrush(Qt::NoBrush); - painter.setPen(QPen(Qt::red, 8)); - painter.drawRect(iFaceBox.Left, iFaceBox.Top, iFaceBox.Right - iFaceBox.Left, iFaceBox.Bottom - iFaceBox.Top); - bool bEnd = painter.end(); + // Fetch color buffer + if (imageFormat == ColorImageFormat_Rgba) + { + hr = pColorFrame->AccessRawUnderlyingBuffer(&nBufferSize, reinterpret_cast(&pBuffer)); + } + else if (m_pColorRGBX) + { + pBuffer = m_pColorRGBX; + nBufferSize = cColorWidth * cColorHeight * sizeof(RGBQUAD); + hr = pColorFrame->CopyConvertedFrameDataToArray(nBufferSize, reinterpret_cast(pBuffer), ColorImageFormat_Rgba); + } + else + { + hr = E_FAIL; + } + + } + + if (SUCCEEDED(hr)) + { + // Setup our image + QImage image((const unsigned char*)pBuffer, cColorWidth, cColorHeight, sizeof(RGBQUAD)*cColorWidth, QImage::Format_RGBA8888); + if (IsValidRect(iFaceBox)) + { + // Draw our face bounding box + QPainter painter(&image); + painter.setBrush(Qt::NoBrush); + painter.setPen(QPen(Qt::red, 8)); + painter.drawRect(iFaceBox.Left, iFaceBox.Top, iFaceBox.Right - iFaceBox.Left, iFaceBox.Bottom - iFaceBox.Top); + bool bEnd = painter.end(); + } + + // Update our video preview + iVideoWidget->update_image(image); } - // Update our video preview - iVideoWidget->update_image(image); } + SafeRelease(pFrameDescription); } -- cgit v1.2.3 From 0011f928da90b6b7116f3c633a0a0cb855d75024 Mon Sep 17 00:00:00 2001 From: Stéphane Lenclud Date: Sun, 3 Feb 2019 15:35:16 +0100 Subject: Kinect: Tracker code cleaning. --- tracker-kinect-face/kinect_face_tracker.cpp | 86 +++++++++++++---------------- tracker-kinect-face/kinect_face_tracker.h | 38 ++++++------- 2 files changed, 56 insertions(+), 68 deletions(-) diff --git a/tracker-kinect-face/kinect_face_tracker.cpp b/tracker-kinect-face/kinect_face_tracker.cpp index 5663de0f..9f4f133b 100644 --- a/tracker-kinect-face/kinect_face_tracker.cpp +++ b/tracker-kinect-face/kinect_face_tracker.cpp @@ -7,6 +7,8 @@ #include "compat/check-visible.hpp" +static const int KColorWidth = 1920; +static const int KColorHeight = 1080; /// bool IsValidRect(const RectI& aRect) @@ -82,62 +84,48 @@ bool IsNullPoint(const CameraSpacePoint& aPoint) } -KinectFaceTracker::KinectFaceTracker(): - m_pKinectSensor(nullptr), - m_pCoordinateMapper(nullptr), - m_pColorFrameReader(nullptr), - m_pColorRGBX(nullptr), - m_pBodyFrameReader(nullptr), - iLastFacePosition{0,0,0}, - iFacePositionCenter{ 0,0,0 }, - iFacePosition{ 0,0,0 }, - iLastFaceRotation{ 0,0,0 }, - iFaceRotationCenter{ 0,0,0 }, - iFaceRotation{ 0,0,0 } +KinectFaceTracker::KinectFaceTracker() { - m_pFaceFrameSource = nullptr; - m_pFaceFrameReader = nullptr; - // create heap storage for color pixel data in RGBX format - m_pColorRGBX = new RGBQUAD[cColorWidth * cColorHeight]; + iColorRGBX = new RGBQUAD[KColorWidth * KColorHeight]; } KinectFaceTracker::~KinectFaceTracker() { - if (m_pColorRGBX) + if (iColorRGBX) { - delete[] m_pColorRGBX; - m_pColorRGBX = nullptr; + delete[] iColorRGBX; + iColorRGBX = nullptr; } // clean up Direct2D //SafeRelease(m_pD2DFactory); // done with face sources and readers - SafeRelease(m_pFaceFrameSource); - SafeRelease(m_pFaceFrameReader); + SafeRelease(iFaceFrameSource); + SafeRelease(iFaceFrameReader); // done with body frame reader - SafeRelease(m_pBodyFrameReader); + SafeRelease(iBodyFrameReader); // done with color frame reader - SafeRelease(m_pColorFrameReader); + SafeRelease(iColorFrameReader); // done with coordinate mapper - SafeRelease(m_pCoordinateMapper); + SafeRelease(iCoordinateMapper); // close the Kinect Sensor - if (m_pKinectSensor) + if (iKinectSensor) { - m_pKinectSensor->Close(); + iKinectSensor->Close(); } - SafeRelease(m_pKinectSensor); + SafeRelease(iKinectSensor); } module_status KinectFaceTracker::start_tracker(QFrame* aFrame) { - t.start(); + iTimer.start(); if (SUCCEEDED(InitializeDefaultSensor())) { @@ -170,12 +158,12 @@ bool KinectFaceTracker::center() // void KinectFaceTracker::data(double *data) { - const double dt = t.elapsed_seconds(); + const double dt = iTimer.elapsed_seconds(); const double KMinDelayInSeconds = 1.0 / 30.0; // Pointless running faster than Kinect hardware itself if (dt > KMinDelayInSeconds) { - t.start(); // Reset our timer + iTimer.start(); // Reset our timer //OutputDebugStringA("Updating frame!\n"); Update(); ExtractFaceRotationInDegrees(&iFaceRotationQuaternion, &iFaceRotation.X, &iFaceRotation.Y, &iFaceRotation.Z); @@ -254,28 +242,28 @@ HRESULT KinectFaceTracker::InitializeDefaultSensor() HRESULT hr; // Get and open Kinect sensor - hr = GetDefaultKinectSensor(&m_pKinectSensor); + hr = GetDefaultKinectSensor(&iKinectSensor); if (SUCCEEDED(hr)) { - hr = m_pKinectSensor->Open(); + hr = iKinectSensor->Open(); } // TODO: check if we still need that guy if (SUCCEEDED(hr)) { - hr = m_pKinectSensor->get_CoordinateMapper(&m_pCoordinateMapper); + hr = iKinectSensor->get_CoordinateMapper(&iCoordinateMapper); } // Create color frame reader if (SUCCEEDED(hr)) { UniqueInterface colorFrameSource; - hr = m_pKinectSensor->get_ColorFrameSource(colorFrameSource.PtrPtr()); + hr = iKinectSensor->get_ColorFrameSource(colorFrameSource.PtrPtr()); colorFrameSource.Reset(); if (SUCCEEDED(hr)) { - hr = colorFrameSource->OpenReader(&m_pColorFrameReader); + hr = colorFrameSource->OpenReader(&iColorFrameReader); } } @@ -283,12 +271,12 @@ HRESULT KinectFaceTracker::InitializeDefaultSensor() if (SUCCEEDED(hr)) { UniqueInterface bodyFrameSource; - hr = m_pKinectSensor->get_BodyFrameSource(bodyFrameSource.PtrPtr()); + hr = iKinectSensor->get_BodyFrameSource(bodyFrameSource.PtrPtr()); bodyFrameSource.Reset(); if (SUCCEEDED(hr)) { - hr = bodyFrameSource->OpenReader(&m_pBodyFrameReader); + hr = bodyFrameSource->OpenReader(&iBodyFrameReader); } } @@ -296,14 +284,14 @@ HRESULT KinectFaceTracker::InitializeDefaultSensor() if (SUCCEEDED(hr)) { // create the face frame source by specifying the required face frame features - hr = CreateHighDefinitionFaceFrameSource(m_pKinectSensor, &m_pFaceFrameSource); + hr = CreateHighDefinitionFaceFrameSource(iKinectSensor, &iFaceFrameSource); } // Create HD face frame reader if (SUCCEEDED(hr)) { // open the corresponding reader - hr = m_pFaceFrameSource->OpenReader(&m_pFaceFrameReader); + hr = iFaceFrameSource->OpenReader(&iFaceFrameReader); } return hr; @@ -316,13 +304,13 @@ HRESULT KinectFaceTracker::InitializeDefaultSensor() /// void KinectFaceTracker::Update() { - if (!m_pColorFrameReader || !m_pBodyFrameReader) + if (!iColorFrameReader || !iBodyFrameReader) { return; } IColorFrame* pColorFrame = nullptr; - HRESULT hr = m_pColorFrameReader->AcquireLatestFrame(&pColorFrame); + HRESULT hr = iColorFrameReader->AcquireLatestFrame(&pColorFrame); if (SUCCEEDED(hr)) { @@ -373,10 +361,10 @@ void KinectFaceTracker::Update() { hr = pColorFrame->AccessRawUnderlyingBuffer(&nBufferSize, reinterpret_cast(&pBuffer)); } - else if (m_pColorRGBX) + else if (iColorRGBX) { - pBuffer = m_pColorRGBX; - nBufferSize = cColorWidth * cColorHeight * sizeof(RGBQUAD); + pBuffer = iColorRGBX; + nBufferSize = KColorWidth * KColorHeight * sizeof(RGBQUAD); hr = pColorFrame->CopyConvertedFrameDataToArray(nBufferSize, reinterpret_cast(pBuffer), ColorImageFormat_Rgba); } else @@ -389,7 +377,7 @@ void KinectFaceTracker::Update() if (SUCCEEDED(hr)) { // Setup our image - QImage image((const unsigned char*)pBuffer, cColorWidth, cColorHeight, sizeof(RGBQUAD)*cColorWidth, QImage::Format_RGBA8888); + QImage image((const unsigned char*)pBuffer, KColorWidth, KColorHeight, sizeof(RGBQUAD)*KColorWidth, QImage::Format_RGBA8888); if (IsValidRect(iFaceBox)) { // Draw our face bounding box @@ -423,10 +411,10 @@ HRESULT KinectFaceTracker::UpdateBodyData(IBody** ppBodies) { HRESULT hr = E_FAIL; - if (m_pBodyFrameReader != nullptr) + if (iBodyFrameReader != nullptr) { IBodyFrame* pBodyFrame = nullptr; - hr = m_pBodyFrameReader->AcquireLatestFrame(&pBodyFrame); + hr = iBodyFrameReader->AcquireLatestFrame(&pBodyFrame); if (SUCCEEDED(hr)) { hr = pBodyFrame->GetAndRefreshBodyData(BODY_COUNT, ppBodies); @@ -539,7 +527,7 @@ void KinectFaceTracker::ProcessFaces() if (SUCCEEDED(hr)) { // Tell our face source to use the given body id - hr = m_pFaceFrameSource->put_TrackingId(iTrackingId); + hr = iFaceFrameSource->put_TrackingId(iTrackingId); //OutputDebugStringA("Tracking new body!\n"); } } @@ -549,7 +537,7 @@ void KinectFaceTracker::ProcessFaces() IHighDefinitionFaceFrame* pFaceFrame = nullptr; if (SUCCEEDED(hr)) { - hr = m_pFaceFrameReader->AcquireLatestFrame(&pFaceFrame); + hr = iFaceFrameReader->AcquireLatestFrame(&pFaceFrame); } BOOLEAN bFaceTracked = false; diff --git a/tracker-kinect-face/kinect_face_tracker.h b/tracker-kinect-face/kinect_face_tracker.h index 9f75507d..a6d4e89b 100644 --- a/tracker-kinect-face/kinect_face_tracker.h +++ b/tracker-kinect-face/kinect_face_tracker.h @@ -64,13 +64,9 @@ public: bool center() override; private: - Timer t; + // Kinect stuff - static const int cColorWidth = 1920; - static const int cColorHeight = 1080; - - void Update(); HRESULT InitializeDefaultSensor(); void ProcessFaces(); @@ -78,39 +74,43 @@ private: void ExtractFaceRotationInDegrees(const Vector4* pQuaternion, float* pPitch, float* pYaw, float* pRoll); static IBody* FindClosestBody(IBody** aBodies); static IBody* FindTrackedBodyById(IBody** aBodies,UINT64 aTrackingId); + + // + Timer iTimer; // Current Kinect - IKinectSensor* m_pKinectSensor; + IKinectSensor* iKinectSensor = nullptr; // Coordinate mapper - ICoordinateMapper* m_pCoordinateMapper; + ICoordinateMapper* iCoordinateMapper = nullptr; // Color reader - IColorFrameReader* m_pColorFrameReader; + IColorFrameReader* iColorFrameReader = nullptr; // Body reader - IBodyFrameReader* m_pBodyFrameReader; + IBodyFrameReader* iBodyFrameReader = nullptr; // Face sources - IHighDefinitionFaceFrameSource* m_pFaceFrameSource; + IHighDefinitionFaceFrameSource* iFaceFrameSource = nullptr; // Face readers - IHighDefinitionFaceFrameReader* m_pFaceFrameReader; + IHighDefinitionFaceFrameReader* iFaceFrameReader = nullptr; // - RGBQUAD* m_pColorRGBX; + RGBQUAD* iColorRGBX = nullptr; RectI iFaceBox = { 0 }; - CameraSpacePoint iLastFacePosition; - CameraSpacePoint iFacePosition; - CameraSpacePoint iFacePositionCenter; + // Face position + CameraSpacePoint iLastFacePosition = { 0 }; + CameraSpacePoint iFacePosition = { 0 }; + CameraSpacePoint iFacePositionCenter = { 0 }; - Vector4 iFaceRotationQuaternion; + Vector4 iFaceRotationQuaternion = { 0 }; // As Yaw, Pitch, Roll - CameraSpacePoint iLastFaceRotation; - CameraSpacePoint iFaceRotation; - CameraSpacePoint iFaceRotationCenter; + CameraSpacePoint iLastFaceRotation = { 0 }; + CameraSpacePoint iFaceRotation = { 0 }; + CameraSpacePoint iFaceRotationCenter = { 0 }; // std::unique_ptr iVideoWidget; std::unique_ptr iLayout; -- cgit v1.2.3 From 26ad3d2b154f9161cf577060f9b161e3312b5e76 Mon Sep 17 00:00:00 2001 From: Stéphane Lenclud Date: Thu, 7 Feb 2019 12:41:00 +0100 Subject: Kinect: Removing unused coordinate mapper. --- tracker-kinect-face/kinect_face_tracker.cpp | 9 --------- tracker-kinect-face/kinect_face_tracker.h | 3 --- 2 files changed, 12 deletions(-) diff --git a/tracker-kinect-face/kinect_face_tracker.cpp b/tracker-kinect-face/kinect_face_tracker.cpp index 9f4f133b..104ecda8 100644 --- a/tracker-kinect-face/kinect_face_tracker.cpp +++ b/tracker-kinect-face/kinect_face_tracker.cpp @@ -111,9 +111,6 @@ KinectFaceTracker::~KinectFaceTracker() // done with color frame reader SafeRelease(iColorFrameReader); - // done with coordinate mapper - SafeRelease(iCoordinateMapper); - // close the Kinect Sensor if (iKinectSensor) { @@ -248,12 +245,6 @@ HRESULT KinectFaceTracker::InitializeDefaultSensor() hr = iKinectSensor->Open(); } - // TODO: check if we still need that guy - if (SUCCEEDED(hr)) - { - hr = iKinectSensor->get_CoordinateMapper(&iCoordinateMapper); - } - // Create color frame reader if (SUCCEEDED(hr)) { diff --git a/tracker-kinect-face/kinect_face_tracker.h b/tracker-kinect-face/kinect_face_tracker.h index a6d4e89b..6273cba1 100644 --- a/tracker-kinect-face/kinect_face_tracker.h +++ b/tracker-kinect-face/kinect_face_tracker.h @@ -81,9 +81,6 @@ private: // Current Kinect IKinectSensor* iKinectSensor = nullptr; - // Coordinate mapper - ICoordinateMapper* iCoordinateMapper = nullptr; - // Color reader IColorFrameReader* iColorFrameReader = nullptr; -- cgit v1.2.3