using System;
|
using System.Runtime.InteropServices;
|
using System.Collections.Generic;
|
using OpenCvSharp;
|
|
// 人脸跟踪
|
namespace FaceAI
|
{
|
// 人脸跟踪配置结构体
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
struct BDFaceTrackConf
|
{
|
public float detect_intv_before_track; // 未跟踪到人脸前的检测时间间隔
|
public float detect_intv_during_track; // 已跟踪到人脸后的检测时间间隔
|
};
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
public struct BDFaceBBox
|
{
|
public int index; // 人脸索引值
|
public float center_x; // 人脸中心点x坐标
|
public float center_y; // 人脸中心点y坐标
|
public float width; // 人脸宽度
|
public float height; // 人脸高度
|
public float score; // 人脸置信度
|
}
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
public struct BDFaceLandmark
|
{
|
public int index; // 人脸关键点索引值
|
public int size; // 人脸关键点数量
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 144)]
|
public float[] data;// = new float[144];
|
public float score; // 人脸关键点置信度
|
}
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
public struct BDFaceTrackInfo
|
{
|
public int face_id;
|
[MarshalAs(UnmanagedType.Struct)]
|
public BDFaceBBox box;
|
[MarshalAs(UnmanagedType.Struct)]
|
public BDFaceLandmark landmark;
|
}
|
|
// 人脸跟踪
|
class FaceTrack
|
{
|
[DllImport("BaiduFaceApi.dll", EntryPoint = "track", CharSet = CharSet.Ansi
|
, CallingConvention = CallingConvention.Cdecl)]
|
// type 为0时候执行RGB人脸跟踪,1时候执行NIR人脸跟踪
|
public static extern int track(IntPtr ptr, IntPtr mat, int type);
|
|
[DllImport("BaiduFaceApi.dll", EntryPoint = "clear_track_history", CharSet = CharSet.Ansi
|
, CallingConvention = CallingConvention.Cdecl)]
|
// type 为0时候执行RGB人脸跟踪,1时候执行NIR人脸跟踪
|
public static extern void clear_track_history(int type);
|
|
// 测试人脸跟踪
|
public void image_track()
|
{
|
Console.WriteLine("test_track");
|
int max_track_num = 50; // 设置最多检测跟踪人数(多人脸检测),默认为1,最多可设为50
|
|
BDFaceTrackInfo[] track_info = new BDFaceTrackInfo[max_track_num];
|
for (int i = 0; i < max_track_num; i++)
|
{
|
track_info[i] = new BDFaceTrackInfo();
|
track_info[i].box = new BDFaceBBox();
|
track_info[i].box.score = 0;
|
track_info[i].box.width = 0;
|
track_info[i].landmark.data = new float[144];
|
track_info[i].face_id = 0;
|
}
|
int sizeTrack = Marshal.SizeOf(typeof(BDFaceTrackInfo));
|
IntPtr ptT = Marshal.AllocHGlobal(sizeTrack * max_track_num);
|
Mat mat = Cv2.ImRead("../images/2.jpg");
|
// faceNum为返回的检测到的人脸个数
|
int type = 0;
|
int faceNum = track(ptT, mat.CvPtr, type);
|
Console.WriteLine("faceSize is:" + faceNum);
|
// 因为需预分配内存,所以返回的人脸数若大于预先分配的内存数,则仅仅显示预分配的人脸数
|
if (faceNum > max_track_num)
|
{
|
faceNum = max_track_num;
|
}
|
for (int index = 0; index < faceNum; index++) {
|
|
IntPtr ptr = new IntPtr();
|
if (8 == IntPtr.Size)
|
{
|
ptr = (IntPtr)(ptT.ToInt64() + sizeTrack * index);
|
}
|
else if (4 == IntPtr.Size)
|
{
|
ptr = (IntPtr)(ptT.ToInt32() + sizeTrack * index);
|
}
|
|
track_info[index] = (BDFaceTrackInfo)Marshal.PtrToStructure(ptr, typeof(BDFaceTrackInfo));
|
Console.WriteLine("track face_id is {0}:", track_info[index].face_id);
|
Console.WriteLine("track landmarks is:");
|
|
for(int i = 0; i < 144; i++)
|
{
|
Console.WriteLine("lanmark data is {0}:", track_info[index].landmark.data[i]);
|
}
|
Console.WriteLine("track landmarks score is:{0}", track_info[index].landmark.score);
|
Console.WriteLine("track landmarks index is:{0}", track_info[index].landmark.index);
|
|
// 索引值
|
Console.WriteLine("track score is:{0}", track_info[index].box.index);
|
// 置信度
|
Console.WriteLine("track score is:{0}", track_info[index].box.score);
|
// 人脸宽度
|
Console.WriteLine("track mWidth is:{0}", track_info[index].box.width);
|
// 中心点X,Y坐标
|
Console.WriteLine("track mCenter_x is:{0}", track_info[index].box.center_x);
|
Console.WriteLine("track mCenter_y is:{0}", track_info[index].box.center_y);
|
}
|
// 画人脸框
|
FaceDraw.draw_rects(ref mat, faceNum, track_info);
|
// 图片画框保存
|
mat.ImWrite("track.jpg");
|
Marshal.FreeHGlobal(ptT);
|
}
|
|
//usb摄像头实时人脸检测示例
|
public void usb_video_track()
|
{
|
// 默认电脑自带摄像头,device可能为0,若外接usb摄像头,则device可能为1.
|
int dev = 0;
|
using (var window = new Window("face"))
|
using (VideoCapture cap = VideoCapture.FromCamera(dev))
|
{
|
if (!cap.IsOpened())
|
{
|
Console.WriteLine("open camera error");
|
return;
|
}
|
// Frame image buffer
|
Mat image = new Mat();
|
// When the movie playback reaches end, Mat.data becomes NULL.
|
while (true)
|
{
|
cap.Read(image); // same as cvQueryFrame
|
if (!image.Empty())
|
{
|
int ilen = 10;//传入的人脸数
|
BDFaceTrackInfo[] track_info = new BDFaceTrackInfo[ilen];
|
for (int i = 0; i < ilen; i++)
|
{
|
track_info[i].box = new BDFaceBBox();
|
track_info[i].box.score = 0;
|
track_info[i].box.width = 0;
|
track_info[i].landmark.data = new float[144];
|
track_info[i].face_id = 0;
|
}
|
int sizeTrack = Marshal.SizeOf(typeof(BDFaceTrackInfo));
|
IntPtr ptT = Marshal.AllocHGlobal(sizeTrack* ilen);
|
//Cv2.ImWrite("usb_track_Cv2.jpg", image);
|
/* trackMat
|
* 传入参数: maxTrackObjNum:检测到的最大人脸数,传入外部分配人脸数,需要分配对应的内存大小。
|
* 传出检测到的最大人脸数
|
* 返回值: 传入的人脸数 和 检测到的人脸数 中的最小值,实际返回的人脸。
|
****/
|
int faceSize = ilen;//返回人脸数 分配人脸数和检测到人脸数的最小值
|
int curSize = ilen;//当前人脸数 输入分配的人脸数,输出实际检测到的人脸数
|
int type = 0;
|
faceSize = track(ptT, image.CvPtr, type);
|
for (int index = 0; index < faceSize; index++)
|
{
|
IntPtr ptr = new IntPtr();
|
if( 8 == IntPtr.Size)
|
{
|
ptr = (IntPtr)(ptT.ToInt64() + sizeTrack * index);
|
}
|
else if(4 == IntPtr.Size)
|
{
|
ptr = (IntPtr)(ptT.ToInt32() + sizeTrack * index);
|
}
|
|
track_info[index] = (BDFaceTrackInfo)Marshal.PtrToStructure(ptr, typeof(BDFaceTrackInfo));
|
//face_info[index] = (BDFaceBBox)Marshal.PtrToStructure(info_ptr, typeof(BDFaceBBox));
|
Console.WriteLine("in Liveness::usb_track face_id is {0}:",track_info[index].face_id);
|
Console.WriteLine("in Liveness::usb_track landmarks is:");
|
|
Console.WriteLine("in Liveness::usb_track score is:{0:f}", track_info[index].box.score);
|
// 人脸宽度
|
Console.WriteLine("in Liveness::usb_track mWidth is:{0:f}", track_info[index].box.width);
|
// 中心点X,Y坐标
|
Console.WriteLine("in Liveness::usb_track mCenter_x is:{0:f}", track_info[index].box.center_x);
|
Console.WriteLine("in Liveness::usb_track mCenter_y is:{0:f}", track_info[index].box.center_y);
|
|
}
|
|
FaceDraw.draw_rects(ref image, faceSize, track_info);
|
// FaceDraw.draw_shape(ref image, faceSize, track_info);
|
Marshal.FreeHGlobal(ptT);
|
window.ShowImage(image);
|
Cv2.WaitKey(1);
|
Console.WriteLine("mat not empty");
|
}
|
else
|
{
|
Console.WriteLine("mat is empty");
|
}
|
}
|
}
|
}
|
|
// 清除跟踪的人脸信息
|
public void test_clear_tracked_faces()
|
{
|
int type = 0;
|
clear_track_history(type);
|
Console.WriteLine("after clear tracked faces");
|
}
|
|
}
|
}
|