最近突发奇想,有没一款电脑屏幕保护程序。
通过人脸识别,达到人在电脑面前,打开屏幕,人不在时自动锁屏。在网上搜索了一翻,并没有找到相关的软件。
网上发现了虹软这个人脸识别这个插件,于是下载下来,加功成了完整的程序。
1.屏避了360的屏保。
2.没有注册人脸情况下要打开屏幕,可以输入密码退出。
3.程序中有锁信键盘鼠标事件,原计划锁住,实际项目中没有必要这样做,锁屏窗口始终激活置顶就可以了。
4.解锁屏幕还原鼠标位置及激活窗口。
5.毫秒级响应速度,眨眼间,捂住嘴,眨眼都可以屏幕保护。
6.支持多人脸注册,可以用于一些公共场合,哪些人可以使用电脑。
7.可以扩展为指定开启,或锁定某一个程序,即程序使用保护。
以下三张图是原生程序扫描人脸时总是红色边框,没有美感,用gdi绘制出格子边框带科技感。
为了程序,第一次露脸。
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using ArcSoftFace.SDKModels;
using ArcSoftFace.SDKUtil;
using ArcSoftFace.Utils;
using ArcSoftFace.Entity;
using System.IO;
using System.Configuration;
using System.Threading;
using AForge.Video.DirectShow;
using System.Text.RegularExpressions;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;
using System.Runtime.InteropServices;
namespace ArcSoftFace
{
public partial class GuardScreenForm : Form
{
//引擎Handle
private IntPtr pImageEngine = IntPtr.Zero;
//保存右侧图片路径
private string image1Path;
//右侧图片人脸特征
private IntPtr image1Feature;
//保存对比图片的列表
private List imagePathList = new List();
//左侧图库人脸特征列表
private List imagesFeatureList = new List();
//相似度
private float threshold = 0.8f;
//用于标记是否需要清除比对结果
private bool isCompare = false;
#region 视频模式下相关
//视频引擎Handle
private IntPtr pVideoEngine = IntPtr.Zero;
//视频引擎 FR Handle 处理 FR和图片引擎分开,减少强占引擎的问题
private IntPtr pVideoImageEngine = IntPtr.Zero;
///
/// 视频输入设备信息
///
private FilterInfoCollection filterInfoCollection;
private VideoCaptureDevice deviceVideo;
#endregion
public GuardScreenForm()
{
InitializeComponent();
WindowMaxState();
this.ShowInTaskbar = false;///使窗体不显示在任务栏
InitEngines();
videoSource.Hide();
btnStartVideo_Click(null, null);
RegFace();
//txtThreshold.Enabled = false;
}
private void WindowMaxState()
{
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.WindowState = System.Windows.Forms.FormWindowState.Maximized;
this.BackColor = Color.Black;//.Blue;//蓝屏,设置背景颜色 jihua.cnblogs.com
this.Opacity = 1;
}
private void WindowSmallState()
{
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.WindowState = System.Windows.Forms.FormWindowState.Normal;
this.Opacity = 0.0;
this.Height = 50;
this.Width = 50;
//this.BackColor = Color.Black;//.Blue;//蓝屏,设置背景颜色 jihua.cnblogs.com
}
///
/// 初始化引擎
///
private void InitEngines()
{
//读取配置文件
AppSettingsReader reader = new AppSettingsReader();
string appId = (string)reader.GetValue("APP_ID", typeof(string));
string sdkKey64 = (string)reader.GetValue("SDKKEY64", typeof(string));
string sdkKey32 = (string)reader.GetValue("SDKKEY32", typeof(string));
var is64CPU = Environment.Is64BitProcess;
if (is64CPU)
{
if (string.IsNullOrWhiteSpace(appId) || string.IsNullOrWhiteSpace(sdkKey64))
{
//chooseMultiImgBtn.Enabled = false;
//matchBtn.Enabled = false;
//btnClearFaceList.Enabled = false;
//chooseImgBtn.Enabled = false;
MessageBox.Show("请在App.config配置文件中先配置APP_ID和SDKKEY64!");
return;
}
}
else
{
if (string.IsNullOrWhiteSpace(appId) || string.IsNullOrWhiteSpace(sdkKey32))
{
//chooseMultiImgBtn.Enabled = false;
//matchBtn.Enabled = false;
//btnClearFaceList.Enabled = false;
//chooseImgBtn.Enabled = false;
MessageBox.Show("请在App.config配置文件中先配置APP_ID和SDKKEY32!");
return;
}
}
//激活引擎 如出现错误,1.请先确认从官网下载的sdk库已放到对应的bin中,2.当前选择的CPU为x86或者x64
int retCode = 0;
try
{
retCode = ASFFunctions.ASFActivation(appId, is64CPU ? sdkKey64 : sdkKey32);
}
catch (Exception ex)
{
//chooseMultiImgBtn.Enabled = false;
//matchBtn.Enabled = false;
//btnClearFaceList.Enabled = false;
//chooseImgBtn.Enabled = false;
if (ex.Message.IndexOf("无法加载 DLL") > -1)
{
MessageBox.Show("请将sdk相关DLL放入bin对应的x86或x64下的文件夹中!");
}
else
{
MessageBox.Show("激活引擎失败!");
}
return;
}
Console.WriteLine("Activate Result:" + retCode);
//初始化引擎
uint detectMode = DetectionMode.ASF_DETECT_MODE_IMAGE;
//检测脸部的角度优先值
int detectFaceOrientPriority = ASF_OrientPriority.ASF_OP_0_HIGHER_EXT;
//人脸在图片中所占比例,如果需要调整检测人脸尺寸请修改此值,有效数值为2-32
int detectFaceScaleVal = 16;
//最大需要检测的人脸个数
int detectFaceMaxNum = 5;
//引擎初始化时需要初始化的检测功能组合
int combinedMask = FaceEngineMask.ASF_FACE_DETECT | FaceEngineMask.ASF_FACERECOGNITION | FaceEngineMask.ASF_AGE | FaceEngineMask.ASF_GENDER | FaceEngineMask.ASF_FACE3DANGLE;
//初始化引擎,正常值为0,其他返回值请参考http://ai.arcsoft.com.cn/bbs/forum.php?mod=viewthread&tid=19&_dsign=dbad527e
retCode = ASFFunctions.ASFInitEngine(detectMode, detectFaceOrientPriority, detectFaceScaleVal, detectFaceMaxNum, combinedMask, ref pImageEngine);
Console.WriteLine("InitEngine Result:" + retCode);
//AppendText((retCode == 0) ? "引擎初始化成功!\n" : string.Format("引擎初始化失败!错误码为:{0}\n", retCode));
//if (retCode != 0)
//{
// chooseMultiImgBtn.Enabled = false;
// matchBtn.Enabled = false;
// btnClearFaceList.Enabled = false;
// chooseImgBtn.Enabled = false;
//}
//初始化视频模式下人脸检测引擎
uint detectModeVideo = DetectionMode.ASF_DETECT_MODE_VIDEO;
int combinedMaskVideo = FaceEngineMask.ASF_FACE_DETECT | FaceEngineMask.ASF_FACERECOGNITION;
retCode = ASFFunctions.ASFInitEngine(detectModeVideo, detectFaceOrientPriority, detectFaceScaleVal, detectFaceMaxNum, combinedMaskVideo, ref pVideoEngine);
//视频专用FR引擎
detectFaceMaxNum = 1;
combinedMask = FaceEngineMask.ASF_FACERECOGNITION | FaceEngineMask.ASF_FACE3DANGLE;
retCode = ASFFunctions.ASFInitEngine(detectMode, detectFaceOrientPriority, detectFaceScaleVal, detectFaceMaxNum, combinedMask, ref pVideoImageEngine);
Console.WriteLine("InitVideoEngine Result:" + retCode);
initVideo();
}
///
/// 摄像头初始化
///
private void initVideo()
{
filterInfoCollection = new FilterInfoCollection(FilterCategory.VideoInputDevice);
if (filterInfoCollection.Count == 0)
{
//btnStartVideo.Enabled = false;
}
else
{
//btnStartVideo.Enabled = true;
}
}
private void RegFace()
{
List imagePathListTemp = new List();
var numStart = imagePathList.Count;
int isGoodImage = 0;
//保存图片路径并显示
string path = Environment.CurrentDirectory + @"\ArcFaceImgPath\";
string[] fileNames = Directory.GetFiles(path, "*.jpg");
//.Union(Directory.GetFiles(path, "*.png")).ToArray();
//string[] fileNames = Directory.GetFiles(path, "(*.jpg|*.bmp)");
//string[] fileNames = Directory.GetFiles("c:\\","*.jpg | *.bmp");
for (int i = 0; i < fileNames.Length; i++)
{
imagePathListTemp.Add(fileNames[i]);
}
//人脸检测以及提取人脸特征
ThreadPool.QueueUserWorkItem(new WaitCallback(delegate
{
//人脸检测和剪裁
for (int i = 0; i < imagePathListTemp.Count; i++)
{
Image image = Image.FromFile(imagePathListTemp[i]);
if (image.Width % 4 != 0)
{
image = ImageUtil.ScaleImage(image, image.Width - (image.Width % 4), image.Height);
}
ASF_MultiFaceInfo multiFaceInfo = FaceUtil.DetectFace(pImageEngine, image);
if (multiFaceInfo.faceNum > 0)
{
imagePathList.Add(imagePathListTemp[i]);
MRECT rect = MemoryUtil.PtrToStructure(multiFaceInfo.faceRects);
image = ImageUtil.CutImage(image, rect.left, rect.top, rect.right, rect.bottom);
}
else
{
continue;
}
this.Invoke(new Action(delegate
{
if (image == null)
{
image = Image.FromFile(imagePathListTemp[i]);
}
imageLists.Images.Add(imagePathListTemp[i], image);
//imageList.Items.Add((numStart + isGoodImage) + "号", imagePathListTemp[i]);
isGoodImage += 1;
image = null;
}));
}
//提取人脸特征
for (int i = numStart; i < imagePathList.Count; i++)
{
ASF_SingleFaceInfo singleFaceInfo = new ASF_SingleFaceInfo();
IntPtr feature = FaceUtil.ExtractFeature(pImageEngine, Image.FromFile(imagePathList[i]), out singleFaceInfo);
this.Invoke(new Action(delegate
{
if (singleFaceInfo.faceRect.left == 0 && singleFaceInfo.faceRect.right == 0)
{
//AppendText(string.Format("{0}号未检测到人脸\r\n", i));
}
else
{
//AppendText(string.Format("已提取{0}号人脸特征值,[left:{1},right:{2},top:{3},bottom:{4},orient:{5}]\r\n", i, singleFaceInfo.faceRect.left, singleFaceInfo.faceRect.right, singleFaceInfo.faceRect.top, singleFaceInfo.faceRect.bottom, singleFaceInfo.faceOrient));
imagesFeatureList.Add(feature);
}
}));
}
}));
}
//引入API函数
[DllImport("user32 ")]
//这个是调用windows的系统锁定
public static extern bool LockWorkStation();
[DllImport("user32.dll")]
static extern void BlockInput(bool Block);
private void lockTaskmgr()//锁定任务管理器
{
FileStream fs = new FileStream(Environment.ExpandEnvironmentVariables("%windir%\\system32\\taskmgr.exe"), FileMode.Open);
//byte[] Mybyte = new byte[(int)MyFs.Length];
//MyFs.Write(Mybyte, 0, (int)MyFs.Length);
//MyFs.Close();
//用文件流打开任务管理器应用程序而不关闭文件流就会阻止打开任务管理器
}
private void lockAll()
{
BlockInput(true);//锁定鼠标及键盘
}
private void Form1_Load(object sender, EventArgs e)
{
//this.lockAll();
//this.lockTaskmgr();
}
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
int x = (int)(0.5 * (this.Width - panel1.Width));
int y = (int)(0.5 * (this.Height - panel1.Height)); //panel1.Location.Y;
panel1.Location = new System.Drawing.Point(x, y);
}
private void txtPwd_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)Keys.Enter)
{
//btnUnlock_Click(null, null);
if (txtPwd.Text == "123456")
{
Close();
//btnStartVideo_Click(null, null);
//BlockInput(false);
//Close();
//Application.Exit();
}
else
{
MessageBox.Show("密码错误!", "消息",
MessageBoxButtons.OK, MessageBoxIcon.Information);
txtPwd.Text = "";
txtPwd.Focus();
}
}
}
private void btnStartVideo_Click(object sender, EventArgs e)
{
//必须保证有可用摄像头
if (filterInfoCollection.Count == 0)
{
MessageBox.Show("未检测到摄像头,请确保已安装摄像头或驱动!");
}
if (videoSource.IsRunning)
{
btnStartVideo.Text = "启用摄像头";
videoSource.SignalToStop(); //关闭摄像头
//chooseImgBtn.Enabled = true;
//matchBtn.Enabled = true;
//txtThreshold.Enabled = false;
videoSource.Hide();
}
else
{
if (isCompare)
{
//比对结果清除
for (int i = 0; i < imagesFeatureList.Count; i++)
{
//imageList.Items[i].Text = string.Format("{0}号", i);
}
//lblCompareInfo.Text = "";
isCompare = false;
}
//txtThreshold.Enabled = true;
videoSource.Show();
//chooseImgBtn.Enabled = false;
//matchBtn.Enabled = false;
btnStartVideo.Text = "关闭摄像头";
deviceVideo = new VideoCaptureDevice(filterInfoCollection[0].MonikerString);
deviceVideo.VideoResolution = deviceVideo.VideoCapabilities[0];
videoSource.VideoSource = deviceVideo;
videoSource.Start();
}
}
private FaceTrackUnit trackUnit = new FaceTrackUnit();
private Font font = new Font(FontFamily.GenericSerif, 10f);
private SolidBrush brush = new SolidBrush(Color.Red);
private Pen pen = new Pen(Color.Red);
private bool isLock = false;
///
/// 图像显示到窗体上,得到每一帧图像,并进行处理
///
///
///
private void videoSource_Paint(object sender, PaintEventArgs e)
{
if (videoSource.IsRunning)
{
//得到当前摄像头下的图片
Bitmap bitmap = videoSource.GetCurrentVideoFrame();
if (bitmap == null)
{
return;
}
Graphics g = e.Graphics;
float offsetX = videoSource.Width * 1f / bitmap.Width;
float offsetY = videoSource.Height * 1f / bitmap.Height;
//检测人脸,得到Rect框
ASF_MultiFaceInfo multiFaceInfo = FaceUtil.DetectFace(pVideoEngine, bitmap);
//得到最大人脸
ASF_SingleFaceInfo maxFace = FaceUtil.GetMaxFace(multiFaceInfo);
//得到Rect
MRECT rect = maxFace.faceRect;
float x = rect.left * offsetX;
float width = rect.right * offsetX - x;
float y = rect.top * offsetY;
float height = rect.bottom * offsetY - y;
//根据Rect进行画框
//g.DrawRectangle(pen, x, y, width, height);
DrawFaceFrame(x, y, width, height, 8, g);
if (trackUnit.message != "" && x > 0 && y > 0)
{
//将上一帧检测结果显示到页面上
g.DrawString(trackUnit.message, font, brush, x, y + 5);
}
//保证只检测一帧,防止页面卡顿以及出现其他内存被占用情况
if (isLock == false)
{
isLock = true;
//异步处理提取特征值和比对,不然页面会比较卡
ThreadPool.QueueUserWorkItem(new WaitCallback(delegate
{
if (rect.left != 0 && rect.right != 0 && rect.top != 0 && rect.bottom != 0)
{
try
{
//提取人脸特征
IntPtr feature = FaceUtil.ExtractFeature(pVideoImageEngine, bitmap, maxFace);
float similarity = 0f;
//得到比对结果
int result = compareFeature(feature, out similarity);
if (result > -1)
{
//将比对结果放到显示消息中,用于最新显示
trackUnit.message = string.Format(" {0}号 {1}", result, similarity);
this.Invoke(new Action(delegate
{
this.Opacity = 0;
this.OnDeactivate(new EventArgs());
}));
}
else
{
//重置显示消息
trackUnit.message = "";
this.Invoke(new Action(delegate
{
this.Opacity = 1;
this.Activate();
}));
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
isLock = false;
}
}
isLock = false;
}));
}
}
}
///
/// 得到feature比较结果
///
///
///
private int compareFeature(IntPtr feature, out float similarity)
{
int result = -1;
similarity = 0f;
//如果人脸库不为空,则进行人脸匹配
if (imagesFeatureList != null && imagesFeatureList.Count > 0)
{
for (int i = 0; i < imagesFeatureList.Count; i++)
{
//调用人脸匹配方法,进行匹配
ASFFunctions.ASFFaceFeatureCompare(pVideoImageEngine, feature, imagesFeatureList[i], ref similarity);
if (similarity >= threshold)
{
result = i;
break;
}
}
}
return result;
}
private void timerLockProcess_Tick(object sender, EventArgs e)
{
if (videoSource.IsRunning)
{
//得到当前摄像头下的图片
Bitmap bitmap = videoSource.GetCurrentVideoFrame();
if (bitmap == null)
{
return;
}
Graphics g = this.videoSource.CreateGraphics();
float offsetX = videoSource.Width * 1f / bitmap.Width;
float offsetY = videoSource.Height * 1f / bitmap.Height;
//检测人脸,得到Rect框
ASF_MultiFaceInfo multiFaceInfo = FaceUtil.DetectFace(pVideoEngine, bitmap);
//得到最大人脸
ASF_SingleFaceInfo maxFace = FaceUtil.GetMaxFace(multiFaceInfo);
//得到Rect
MRECT rect = maxFace.faceRect;
float x = rect.left * offsetX;
float width = rect.right * offsetX - x;
float y = rect.top * offsetY;
float height = rect.bottom * offsetY - y;
//根据Rect进行画框
g.DrawRectangle(pen, x, y, width, height);
if (trackUnit.message != "" && x > 0 && y > 0)
{
//将上一帧检测结果显示到页面上
g.DrawString(trackUnit.message, font, brush, x, y + 5);
}
//保证只检测一帧,防止页面卡顿以及出现其他内存被占用情况
if (isLock == false)
{
isLock = true;
//异步处理提取特征值和比对,不然页面会比较卡
ThreadPool.QueueUserWorkItem(new WaitCallback(delegate
{
if (rect.left != 0 && rect.right != 0 && rect.top != 0 && rect.bottom != 0)
{
try
{
//提取人脸特征
IntPtr feature = FaceUtil.ExtractFeature(pVideoImageEngine, bitmap, maxFace);
float similarity = 0f;
//得到比对结果
int result = compareFeature(feature, out similarity);
if (result > -1)
{
//将比对结果放到显示消息中,用于最新显示
trackUnit.message = string.Format(" {0}号 {1}", result, similarity);
this.Invoke(new Action(delegate
{
WindowSmallState();
//this.Left = -this.Width - 10;
//this.Visible = false;
}));
}
else
{
//重置显示消息
trackUnit.message = "";
this.Invoke(new Action(delegate
{
WindowMaxState();
//this.Visible = true;
}));
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
isLock = false;
}
}
isLock = false;
}));
}
}
}
private void LockScreenForm_FormClosed(object sender, FormClosedEventArgs e)
{
//销毁引擎
int retCode = ASFFunctions.ASFUninitEngine(pImageEngine);
Console.WriteLine("UninitEngine pImageEngine Result:" + retCode);
//销毁引擎
retCode = ASFFunctions.ASFUninitEngine(pVideoEngine);
Console.WriteLine("UninitEngine pVideoEngine Result:" + retCode);
if (videoSource.IsRunning)
{
videoSource.SignalToStop(); //关闭摄像头
}
}
private void ToolStripMenuItem_Click(object sender, EventArgs e)
{
if (sender is ToolStripMenuItem)
{
ToolStripMenuItem tsmItem = sender as ToolStripMenuItem;
switch (tsmItem.Text)
{
#region 打开spy++
case "打开spy++":
if (Directory.Exists(Environment.CurrentDirectory + string.Format("\\Tools\\")) == false)//如果不存在就创建file文件夹
{
Directory.CreateDirectory(Environment.CurrentDirectory + string.Format("\\Tools\\"));
}
//IntPtr mainHandle = FindWindow(null, "Microsoft Spy++ - Windows 1");
//if (mainHandle != IntPtr.Zero)
//{
// SetForegroundWindow(mainHandle);
// SendMessage(mainHandle, WM_SYSCOMMAND, SC_MAXIMIZE, 0); // 最大化
// SendKeys.SendWait("%{F3}");
//}
//else
//{
// string file = Environment.CurrentDirectory + string.Format("\\Tools\\spyxx.exe");
// if (File.Exists(file))
// {
// System.Diagnostics.Process spyxx = System.Diagnostics.Process.Start(file);
// spyxx.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
// spyxx.WaitForInputIdle(1000);
// if (spyxx.Responding)
// {
// SetForegroundWindow(spyxx.Handle);
// SendMessage(spyxx.Handle, WM_SYSCOMMAND, SC_RESTORE, 0); // 最大化
// SendKeys.SendWait("%{F3}");
// }
// }
//}
break;
#endregion
#region 发送程序到屏幕
case "发送程序到屏幕":
//设置到粘贴板
break;
#endregion
#region 为屏幕指定程序
case "复制为屏幕指定程序":
//设置到粘贴板
break;
#endregion
#region 显示主界面
case "显示主界面":
this.Visible = true;
this.WindowState = FormWindowState.Normal;
break;
#endregion
#region 启动服务
case "启动服务":
btnStartVideo_Click(null, null);
break;
#endregion
#region 停止服务
case "停止服务":
btnStartVideo_Click(null, null);
break;
#endregion
#region 退出
case "退出":
this.Close();
break;
#endregion
}
}
}
private void button1_Click(object sender, EventArgs e)
{
Graphics g = CreateGraphics();
Pen MyPen = new Pen(Color.Blue, 2);
int x = 100;
for (int i = 0; i <= 10; i++) //绘制纵向线条
{
g.DrawLine(MyPen, x, 400, x, 100);
x += 40;
}
Thread.Sleep(200); //线程休眠200毫秒,便于观察绘制情况
int y = 400;
for (int i = 0; i < +10; i++) //绘制横向线条
{
g.DrawLine(MyPen, 100, y, 550, y);
y -= 30;
}
Thread.Sleep(200);
x = 110;
y = 400;
Brush MyBrush = new SolidBrush(Color.BlueViolet);
int[] saleNum = { 120, 178, 263, 215, 99, 111, 265, 171, 136, 100, 129 };
for (int i = 0; i < saleNum.Length; i++)
{
g.FillRectangle(MyBrush, x, y - saleNum[i], 20, saleNum[i]); //绘制填充矩形
x += 40;
}
}
private void button2_Click(object sender, EventArgs e)
{
float x = 50;
float y = 20;
float width = 140;
float height = 160;
int pointCnt = 14;//点个数
Graphics g = CreateGraphics();
DrawFaceFrame(x, y, width, height, pointCnt, g);
}
}
}