private PointF[] GetProjected3DShape( CameraConfig videoCameraConfig, float zoomFactor, Point viewOffset, IntPtr shapeUnitCoeffPtr, uint shapeUnitCoeffCount, IntPtr animUnitCoeffPtr, uint animUnitCoeffCount, float scale, Vector3DF rotation, Vector3DF translation) { this.CheckPtrAndThrow(); PointF[] faceModelProjected3DShape = null; uint vertexCount = this.VertexCount; IntPtr faceModel3DVerticesPtr = IntPtr.Zero; if (shapeUnitCoeffPtr == IntPtr.Zero || shapeUnitCoeffCount == 0) { throw new ArgumentException("Invalid shape unit co-efficients", "shapeUnitCoeffPtr"); } if (animUnitCoeffPtr == IntPtr.Zero || animUnitCoeffCount == 0) { throw new ArgumentException("Invalid animation unit co-efficients", "animUnitCoeffPtr"); } if (vertexCount > 0) { try { faceModel3DVerticesPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Vector3DF)) * (int)vertexCount); this.faceTrackingModelPtr.GetProjectedShape( videoCameraConfig, zoomFactor, viewOffset, shapeUnitCoeffPtr, shapeUnitCoeffCount, animUnitCoeffPtr, animUnitCoeffCount, scale, ref rotation, ref translation, faceModel3DVerticesPtr, vertexCount); faceModelProjected3DShape = new PointF[vertexCount]; for (int i = 0; i < (int)vertexCount; i++) { IntPtr faceModel3DVerticesIthPtr; if (IntPtr.Size == 8) { // 64bit faceModel3DVerticesIthPtr = new IntPtr(faceModel3DVerticesPtr.ToInt64() + (i * Marshal.SizeOf(typeof(PointF)))); } else { // 32bit faceModel3DVerticesIthPtr = new IntPtr(faceModel3DVerticesPtr.ToInt32() + (i * Marshal.SizeOf(typeof(PointF)))); } faceModelProjected3DShape[i] = (PointF)Marshal.PtrToStructure(faceModel3DVerticesIthPtr, typeof(PointF)); } } finally { if (faceModel3DVerticesPtr != IntPtr.Zero) { Marshal.FreeHGlobal(faceModel3DVerticesPtr); } } } return faceModelProjected3DShape; }
/// <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); } }
private PointF[] GetProjected3DShape( CameraConfig videoCameraConfig, float zoomFactor, Point viewOffset, IntPtr shapeUnitCoeffPtr, uint shapeUnitCoeffCount, IntPtr animUnitCoeffPtr, uint animUnitCoeffCount, float scale, Vector3DF rotation, Vector3DF translation) { this.CheckPtrAndThrow(); PointF[] faceModelProjected3DShape = null; uint vertexCount = this.VertexCount; IntPtr faceModel3DVerticesPtr = IntPtr.Zero; if (shapeUnitCoeffPtr == IntPtr.Zero || shapeUnitCoeffCount == 0) { throw new ArgumentException("Invalid shape unit co-efficients", "shapeUnitCoeffPtr"); } if (animUnitCoeffPtr == IntPtr.Zero || animUnitCoeffCount == 0) { throw new ArgumentException("Invalid animation unit co-efficients", "animUnitCoeffPtr"); } if (vertexCount > 0) { try { faceModel3DVerticesPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Vector3DF)) * (int)vertexCount); this.faceTrackingModelPtr.GetProjectedShape( videoCameraConfig, zoomFactor, viewOffset, shapeUnitCoeffPtr, shapeUnitCoeffCount, animUnitCoeffPtr, animUnitCoeffCount, scale, ref rotation, ref translation, faceModel3DVerticesPtr, vertexCount); faceModelProjected3DShape = new PointF[vertexCount]; for (int i = 0; i < (int)vertexCount; i++) { IntPtr faceModel3DVerticesIthPtr; if (IntPtr.Size == 8) { // 64bit faceModel3DVerticesIthPtr = new IntPtr(faceModel3DVerticesPtr.ToInt64() + (i * Marshal.SizeOf(typeof(PointF)))); } else { // 32bit faceModel3DVerticesIthPtr = new IntPtr(faceModel3DVerticesPtr.ToInt32() + (i * Marshal.SizeOf(typeof(PointF)))); } faceModelProjected3DShape[i] = (PointF)Marshal.PtrToStructure(faceModel3DVerticesIthPtr, typeof(PointF)); } } finally { if (faceModel3DVerticesPtr != IntPtr.Zero) { Marshal.FreeHGlobal(faceModel3DVerticesPtr); } } } return(faceModelProjected3DShape); }
/// <summary> /// Initializes a new instance of the FaceTracker class from a reference of the Kinect device. /// <param name="sensor">Reference to kinect sensor instance</param> /// </summary> public FaceTracker(KinectSensor sensor) { if (sensor == null) { throw new ArgumentNullException("sensor"); } if (!sensor.ColorStream.IsEnabled) { throw new InvalidOperationException("Color stream is not enabled yet."); } if (!sensor.DepthStream.IsEnabled) { throw new InvalidOperationException("Depth stream is not enabled yet."); } this.operationMode = OperationMode.Kinect; this.sensor = sensor; this.initializationColorImageFormat = sensor.ColorStream.Format; this.initializationDepthImageFormat = sensor.DepthStream.Format; var newColorCameraConfig = new CameraConfig( (uint)sensor.ColorStream.FrameWidth, (uint)sensor.ColorStream.FrameHeight, sensor.ColorStream.NominalFocalLengthInPixels, FaceTrackingImageFormat.FTIMAGEFORMAT_UINT8_B8G8R8X8); var newDepthCameraConfig = new CameraConfig( (uint)sensor.DepthStream.FrameWidth, (uint)sensor.DepthStream.FrameHeight, sensor.DepthStream.NominalFocalLengthInPixels, FaceTrackingImageFormat.FTIMAGEFORMAT_UINT16_D13P3); this.Initialize(newColorCameraConfig, newDepthCameraConfig, IntPtr.Zero, IntPtr.Zero, this.DepthToColorCallback); }