MRECT LerpRect(MRECT lastRect, MRECT nextRect, float value) { MRECT ret = new MRECT() { top = (int)(lastRect.top + (nextRect.top - lastRect.top) * value), bottom = (int)(lastRect.bottom + (nextRect.bottom - lastRect.bottom) * value), left = (int)(lastRect.left + (nextRect.left - lastRect.left) * value), right = (int)(lastRect.right + (nextRect.right - lastRect.right) * value) }; return(ret); }
//刷新脸的核心事件 private void FaceTimer_Tick(object sender, EventArgs e) { if (faceTimerLock) { return; } if (timerLock) { return; } timerLock = true; Bitmap video = new Bitmap(showPhotoBox.Image); bool hasFace = faceFD.CheckFace(video, out AFD_FSDK_FACERES faceRes, out IntPtr offIntPtr, out IntPtr imageDataPtr); lastRect = hasFace ? nextRect : lastRect; //刷新矩形位置 nextRect = hasFace ? faceRes.DeIntPtr().rect : new MRECT(); if (hasFace) //找到了脸 { if (!compareLock) { compareLock = true; //在下一张脸解锁 byte[] data = faceFR.GetFaceData(faceRes, offIntPtr); if (CompareFace(data, out FaceDataStruct faceData)) { nowFace = faceData; } else { compareLock = false; nowFace = new FaceDataStruct(); } } } else { compareLock = false; nowFace = new FaceDataStruct(); } timerLock = false; Marshal.FreeHGlobal(imageDataPtr); //释放内存 }
public byte[] GetFaceData(Bitmap bitmap, Face_FD face_FD) { bool isFace = face_FD.CheckFace(bitmap, out AFD_FSDK_FACERES faceRes, out IntPtr offInputPtr, out IntPtr imageDataPtr); if (!isFace) { Error.Log(ErrorType.inputError); return(null); } AFR_FSDK_FaceInput faceinput = new AFR_FSDK_FaceInput(); faceinput.lOrient = (int)Marshal.PtrToStructure(faceRes.lfaceOrient, typeof(int)); MRECT rect = (MRECT)Marshal.PtrToStructure(faceRes.rcFace, typeof(MRECT)); faceinput.rcFace = rect; IntPtr faceInputPtr = Marshal.AllocHGlobal(Marshal.SizeOf(faceinput)); Marshal.StructureToPtr(faceinput, faceInputPtr, false); AFR_FSDK_FaceModel faceModel = new AFR_FSDK_FaceModel(); IntPtr faceModelPtr = Marshal.AllocHGlobal(Marshal.SizeOf(faceModel)); int ret = FaceAPI.AFR_FSDK_ExtractFRFeature(detectEngine, offInputPtr, faceInputPtr, faceModelPtr); if (ret != 0) //返回值为0代表获取成功 { Log.AddLog("获取不到人脸信息。"); return(null); } faceModel = (AFR_FSDK_FaceModel)Marshal.PtrToStructure(faceModelPtr, typeof(AFR_FSDK_FaceModel)); Marshal.FreeHGlobal(faceModelPtr); byte[] byteData = new byte[faceModel.lFeatureSize]; Marshal.Copy(faceModel.pbFeature, byteData, 0, faceModel.lFeatureSize); Marshal.FreeHGlobal(faceInputPtr); return(byteData); }
//刷新视频的事件 private void VideoTimer_Tick(object sender, EventArgs e) { if (timerLock) { return; } timerLock = true; //解除图片框的占用 if (showPhotoBox.Image != null) { showPhotoBox.Image.Dispose(); } Bitmap video = GetVideoPhoto(); //读取当前相机的照片 //对矩形进行插值 lastRect = LerpRect(lastRect, nextRect, videoInterval / faceInterval); if (isZeroRect(nextRect)) //为了显示更流畅,设置一个缓存时间 { if (nullNextFace++ % ((faceInterval / videoInterval + 1) * 2) == 0) { lastRect = new MRECT(); } } if (!isZeroRect(lastRect)) { video = video.DrawRect(lastRect); string information = nowFace._class + " " + nowFace._name; video = video.DrawString(lastRect, information); } showPhotoBox.Image = video; timerLock = false; faceTimerLock = false; }
//检查是否存在人脸,imageDataPtr必须在offInputPtr用完后释放掉 public bool CheckFace(Bitmap bitmap, out AFD_FSDK_FACERES faceRes, out IntPtr offInputPtr, out IntPtr imageDataPtr) { byte[] imageData = BitmapToBmp(bitmap, out int width, out int height, out int pitch); imageDataPtr = Marshal.AllocHGlobal(imageData.Length); Marshal.Copy(imageData, 0, imageDataPtr, imageData.Length); ASVLOFFSCREEN offInput = new ASVLOFFSCREEN(); offInput.u32PixelArrayFormat = 513; offInput.ppu8Plane = new IntPtr[4]; offInput.ppu8Plane[0] = imageDataPtr; offInput.i32Width = width; offInput.i32Height = height; offInput.pi32Pitch = new int[4]; offInput.pi32Pitch[0] = pitch; offInputPtr = Marshal.AllocHGlobal(Marshal.SizeOf(offInput)); Marshal.StructureToPtr(offInput, offInputPtr, false); faceRes = new AFD_FSDK_FACERES(); IntPtr faceResPtr = Marshal.AllocHGlobal(Marshal.SizeOf(faceRes)); int detectResult = FaceAPI.AFD_FSDK_StillImageFaceDetection(detectEngine, offInputPtr, ref faceResPtr); faceRes = (AFD_FSDK_FACERES)Marshal.PtrToStructure(faceResPtr, typeof(AFD_FSDK_FACERES)); MRECT rect = (MRECT)Marshal.PtrToStructure(faceRes.rcFace, typeof(MRECT)); bool ret = faceRes.nFace > 0; imageData = null; //Marshal.FreeHGlobal(imageDataPtr); //这个指针内存泄漏了 //Marshal.FreeHGlobal(faceResPtr); //GC.Collect(); return(ret); }
bool isZeroRect(MRECT rect) { return(rect.top == 0 && rect.bottom == 0 && rect.left == 0 && rect.right == 0); }