/// <summary> /// Gets the 3D shape associated with the result /// </summary> /// <param name="faceTrackFrame"> /// result object /// </param> /// <returns> /// the 3d shape /// </returns> public Vector3DF[] Get3DShape(FaceTrackFrame faceTrackFrame) { IntPtr shapeUnitCoeffPtr; uint shapeUnitCount = 0; IntPtr animUnitCoeffPtr; uint animUnitPointsCount; bool hasSuConverged; float scale; faceTrackFrame.ResultPtr.GetAUCoefficients(out animUnitCoeffPtr, out animUnitPointsCount); this.faceTracker.FaceTrackerPtr.GetShapeUnits(out scale, out shapeUnitCoeffPtr, ref shapeUnitCount, out hasSuConverged); return this.Get3DShape( shapeUnitCoeffPtr, shapeUnitCount, animUnitCoeffPtr, animUnitPointsCount, faceTrackFrame.Scale, faceTrackFrame.Rotation, faceTrackFrame.Translation); }
public PointF[] GetProjected3DShape(float zoomFactor, Point viewOffset, FaceTrackFrame faceTrackFrame) { this.CheckPtrAndThrow(); IntPtr shapeUnitCoeffPtr; uint shapeUnitCount = 0; IntPtr animUnitCoeffPtr; uint animUnitPointsCount; bool hasSuConverged; float scale; faceTrackFrame.ResultPtr.GetAUCoefficients(out animUnitCoeffPtr, out animUnitPointsCount); this.faceTracker.FaceTrackerPtr.GetShapeUnits(out scale, out shapeUnitCoeffPtr, ref shapeUnitCount, out hasSuConverged); return this.GetProjected3DShape( this.faceTracker.ColorCameraConfig, zoomFactor, viewOffset, shapeUnitCoeffPtr, shapeUnitCount, animUnitCoeffPtr, animUnitPointsCount, faceTrackFrame.Scale, faceTrackFrame.Rotation, faceTrackFrame.Translation); }
/// <summary> /// Helper method that does the core instantiation & initialization of face tracking engine /// </summary> /// <param name="newColorCameraConfig">Color camera configuration</param> /// <param name="newDepthCameraConfig">Depth camera configuration</param> /// <param name="colorImagePtr">Allows face tracking engine to read color image from native memory pointer. /// If set to IntPtr.Zero, image data needs to be provided for tracking to this instance. </param> /// <param name="depthImagePtr">Allows face tracking engine to read depth image from native memory pointer. /// If set to IntPtr.Zero, image data needs to be provided for tracking to this instance.</param> /// <param name="newRegisterDepthToColorDelegate">Callback which maps of depth to color pixels</param> private void Initialize( CameraConfig newColorCameraConfig, CameraConfig newDepthCameraConfig, IntPtr colorImagePtr, IntPtr depthImagePtr, FaceTrackingRegisterDepthToColor newRegisterDepthToColorDelegate) { if (newColorCameraConfig == null) { throw new ArgumentNullException("newColorCameraConfig"); } if (newDepthCameraConfig == null) { throw new ArgumentNullException("newDepthCameraConfig"); } if (newRegisterDepthToColorDelegate == null) { throw new ArgumentNullException("newRegisterDepthToColorDelegate"); } // initialize perf counters this.totalTracks = 0; this.trackStopwatch.Reset(); // get configuration & trace settings this.traceLevel = new TraceSwitch(FaceTrackTraceSwitchName, FaceTrackTraceSwitchName).Level; this.videoCameraConfig = newColorCameraConfig; this.depthCameraConfig = newDepthCameraConfig; this.registerDepthToColorDelegate = newRegisterDepthToColorDelegate; this.faceTrackerInteropPtr = NativeMethods.FTCreateFaceTracker(IntPtr.Zero); if (this.faceTrackerInteropPtr == null) { throw new InsufficientMemoryException("Cannot create face tracker."); } IntPtr funcPtr = Marshal.GetFunctionPointerForDelegate(this.registerDepthToColorDelegate); if (funcPtr == IntPtr.Zero) { throw new InsufficientMemoryException("Cannot setup callback for retrieving color to depth pixel mapping"); } int hr = this.faceTrackerInteropPtr.Initialize(this.videoCameraConfig, this.depthCameraConfig, funcPtr, null); if (hr != 0) { throw new InvalidOperationException( string.Format(CultureInfo.CurrentCulture, "Failed to initialize face tracker - Error code from native=0x{0:X}", hr)); } this.frame = this.CreateResult(out hr); if (this.frame == null || hr != 0) { throw new InvalidOperationException( string.Format(CultureInfo.CurrentCulture, "Failed to create face tracking result. Error code from native=0x{0:X}", hr)); } this.colorFaceTrackingImage = new Image(); if (colorImagePtr == IntPtr.Zero) { this.colorFaceTrackingImage.Allocate( this.videoCameraConfig.Width, this.videoCameraConfig.Height, this.videoCameraConfig.ImageFormat); } else { this.colorFaceTrackingImage.Attach( this.videoCameraConfig.Width, this.videoCameraConfig.Height, colorImagePtr, this.videoCameraConfig.ImageFormat, this.videoCameraConfig.Stride); } this.depthFaceTrackingImage = new Image(); if (depthImagePtr == IntPtr.Zero) { this.depthFaceTrackingImage.Allocate( this.depthCameraConfig.Width, this.depthCameraConfig.Height, this.depthCameraConfig.ImageFormat); } else { this.depthFaceTrackingImage.Attach( this.depthCameraConfig.Width, this.depthCameraConfig.Height, depthImagePtr, this.depthCameraConfig.ImageFormat, this.depthCameraConfig.Stride); } }
/// <summary> /// Allows calling dispose explicitly or from the finalizer /// </summary> /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources</param> protected virtual void Dispose(bool disposing) { if (!this.disposed) { string traceStr = string.Format( CultureInfo.InvariantCulture, "FaceTracker::Dispose() - TotalTracks={0}, TotalSuccessTracks={1}, TimePerTrack={2:F3}ms, TimePerSuccessTrack={3:F3}ms, TimePerDataCopy={4:F3}ms, TimePerStartOrContinueTracking={5:F3}ms", this.totalTracks, this.totalSuccessTracks, this.totalTracks > 0 ? (double)this.trackStopwatch.ElapsedMilliseconds / this.totalTracks : 0, this.totalSuccessTracks > 0 ? (double)this.totalSuccessTrackMs / this.totalSuccessTracks : 0, this.totalTracks > 0 ? (double)this.copyStopwatch.ElapsedMilliseconds / this.totalTracks : 0, this.totalTracks > 0 ? (double)this.startOrContinueTrackingStopwatch.ElapsedMilliseconds / this.totalTracks : 0); #if DEBUG Debug.WriteLine(traceStr); #else Trace.WriteLineIf(traceLevel >= TraceLevel.Info, traceStr); #endif if (this.faceModel != null) { this.faceModel.Dispose(); this.faceModel = null; } if (this.frame != null) { this.frame.Dispose(); this.frame = null; } if (this.colorFaceTrackingImage != null) { this.colorFaceTrackingImage.Dispose(); this.colorFaceTrackingImage = null; } if (this.depthFaceTrackingImage != null) { this.depthFaceTrackingImage.Dispose(); this.depthFaceTrackingImage = null; } if (this.faceTrackerInteropPtr != null) { Marshal.FinalReleaseComObject(this.faceTrackerInteropPtr); this.faceTrackerInteropPtr = null; } this.disposed = true; } }
/// <summary> /// Creates a frame object instance. Can be used for caching of the face tracking /// frame. FaceTrackFrame should be disposed after use. /// </summary> /// <returns> /// newly created frame object /// </returns> internal FaceTrackFrame CreateResult(out int hr) { IFTResult faceTrackResultPtr; FaceTrackFrame faceTrackFrame = null; this.CheckPtrAndThrow(); hr = this.faceTrackerInteropPtr.CreateFTResult(out faceTrackResultPtr); if (faceTrackResultPtr != null) { faceTrackFrame = new FaceTrackFrame(faceTrackResultPtr, this); } return faceTrackFrame; }