Skip to content

Commit

Permalink
添加项目文件。
Browse files Browse the repository at this point in the history
  • Loading branch information
LP authored and LP committed Sep 15, 2022
1 parent 15e7be1 commit fff5160
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 0 deletions.
103 changes: 103 additions & 0 deletions Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// See https://aka.ms/new-console-template for more information
using DlibDotNet;
using OpenCvSharp;
using System.Runtime.InteropServices;
using Point = OpenCvSharp.Point;
using System.Numerics;
using System.Diagnostics;

// define two constants, one for the eye aspect ratio to indicate
// blink and then a second constant for the number of consecutive
// frames the eye must be below the threshold
var EYE_AR_THRESH = 0.2;
var EYE_AR_CONSEC_FRAMES = 1;
// initialize the frame counters and the total number of blinks
var COUNTER = 0;
var TOTAL = 0;

VideoCapture cap = new(0);
using (var detector = Dlib.GetFrontalFaceDetector())
// 加载人脸68特征点检测模型
using (var sp = ShapePredictor.Deserialize("Resource/shape_predictor_68_face_landmarks.dat"))
while (cap.IsOpened())
{
using var frameMat = cap.RetrieveMat();
byte[] array = new byte[frameMat.Width * frameMat.Height * frameMat.ElemSize()];
Marshal.Copy(frameMat.Data, array, 0, array.Length);

using var cimg = Dlib.LoadImageData<RgbPixel>(array, (uint)frameMat.Height, (uint)frameMat.Width, (uint)(frameMat.Width * frameMat.ElemSize()));
var dets = detector.Operator(cimg);

var shapes = new List<FullObjectDetection>();
foreach (var rect in dets)
{
// 画出检测到的脸的矩形框
frameMat.Rectangle(new Rect(rect.Left, rect.Top, (int)rect.Width, (int)rect.Height), new Scalar(255, 0, 0));
var shape = sp.Detect(cimg, rect);
var eye1 = new Vector2[6];
var eye2 = new Vector2[6];
for (uint i = 0; i < shape.Parts; i++)
{
var point = shape.GetPart(i);
// 获取第一只眼睛
if (i >= 36 && i < 42)
{
eye1[i - 36] = new Vector2(point.X, point.Y);
}
// 获取第二只眼睛
if (i >= 42 && i < 48)
{
eye2[i - 42] = new Vector2(point.X, point.Y);
}

// 画出检测到的脸的68特征点
frameMat.Circle(point.X, point.Y, 1, new Scalar(0, 255, 0));
// frameMat.PutText(i.ToString(), new Point(point.X, point.Y), HersheyFonts.HersheySimplex, 0.3, new Scalar(0, 255, 0));
}

var EAR1 = eyeAspectRatio(eye1);
var EAR2 = eyeAspectRatio(eye2);
// average the eye aspect ratio together for both eyes
var ear = (EAR1 + EAR2) / 2.0;
frameMat.PutText(string.Format("EAR: {0:N2}", ear), new Point(300, 30), HersheyFonts.HersheySimplex, 0.7, new Scalar(0, 0, 255), 2);
// check to see if the eye aspect ratio is below the blink
// threshold, and if so, increment the blink frame counter
if (ear < EYE_AR_THRESH)
{
COUNTER += 1;
Debug.WriteLine(ear);
}
// otherwise, the eye aspect ratio is not below the blink
// threshold
else
{
//if the eyes were closed for a sufficient number of
// then increment the total number of blinks
if (COUNTER >= EYE_AR_CONSEC_FRAMES)
TOTAL += 1;
// reset the eye frame counter
COUNTER = 0;
}
}

frameMat.PutText(string.Format("Blinks: {0}", TOTAL), new Point(10, 30), HersheyFonts.HersheySimplex, 0.7, new Scalar(0, 0, 255), 2);

Cv2.ImShow("img", frameMat);

Cv2.WaitKey(50);
}

static double eyeAspectRatio(Vector2[] eye)
{
// compute the euclidean distances between the two sets of
// vertical eye landmarks (x, y)-coordinates
var A = Vector2.Distance(eye[1], eye[5]);
var B = Vector2.Distance(eye[2], eye[4]);
// compute the euclidean distance between the horizontal
// eye landmark (x, y)-coordinates
var C = Vector2.Distance(eye[0], eye[3]);
// compute the eye aspect ratio
var ear = (A + B) / (2.0 * C);
// return the eye aspect ratio
return ear;
}
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# 眨眼检测c#(.net6)
* 利用 [眼睛纵横比(EAR)](http://vision.fe.uni-lj.si/cvww2016/proceedings/papers/05.pdf?spm=a2c6h.12873639.article-detail.9.7cba3329OtWn6S&file=05.pdf)来进行眨眼算法
* 使用 [dlib](https://github.com/davisking/dlib) 进行人脸以及68特征点检测
Binary file added Resource/shape_predictor_68_face_landmarks.dat
Binary file not shown.
Binary file added Resource/动画.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 24 additions & 0 deletions blink.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="DlibDotNet" Version="19.21.0.20220724" />
<PackageReference Include="OpenCvSharp4.Windows" Version="4.6.0.20220608" />
</ItemGroup>

<ItemGroup>
<None Update="Resource\shape_predictor_68_face_landmarks.dat">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="shape_predictor_68_face_landmarks.dat.bz2">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
25 changes: 25 additions & 0 deletions blink.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.3.32825.248
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "blink", "blink.csproj", "{2D57E00A-0052-4A83-BE0C-92118E0A393D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{2D57E00A-0052-4A83-BE0C-92118E0A393D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2D57E00A-0052-4A83-BE0C-92118E0A393D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2D57E00A-0052-4A83-BE0C-92118E0A393D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2D57E00A-0052-4A83-BE0C-92118E0A393D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {5E7E598B-396F-4A6C-8C6B-6CB5FD4FBDAC}
EndGlobalSection
EndGlobal

0 comments on commit fff5160

Please sign in to comment.