diff --git a/.vs/SubCabinetSolution/v17/.suo b/.vs/SubCabinetSolution/v17/.suo
index c0c2566..12a3574 100644
--- a/.vs/SubCabinetSolution/v17/.suo
+++ b/.vs/SubCabinetSolution/v17/.suo
Binary files differ
diff --git a/.vs/SubCabinetSolution/v17/.suo b/.vs/SubCabinetSolution/v17/.suo
index c0c2566..12a3574 100644
--- a/.vs/SubCabinetSolution/v17/.suo
+++ b/.vs/SubCabinetSolution/v17/.suo
Binary files differ
diff --git a/SubCabinetSolution/Utils/NavigationService.cs b/SubCabinetSolution/Utils/NavigationService.cs
index 1e00f07..37bb787 100644
--- a/SubCabinetSolution/Utils/NavigationService.cs
+++ b/SubCabinetSolution/Utils/NavigationService.cs
@@ -20,7 +20,7 @@
public string CurrentPageKey
{
- get { return _currentPageKey; }
+ get => _currentPageKey;
private set { Set(() => CurrentPageKey, ref _currentPageKey, value); }
}
diff --git a/.vs/SubCabinetSolution/v17/.suo b/.vs/SubCabinetSolution/v17/.suo
index c0c2566..12a3574 100644
--- a/.vs/SubCabinetSolution/v17/.suo
+++ b/.vs/SubCabinetSolution/v17/.suo
Binary files differ
diff --git a/SubCabinetSolution/Utils/NavigationService.cs b/SubCabinetSolution/Utils/NavigationService.cs
index 1e00f07..37bb787 100644
--- a/SubCabinetSolution/Utils/NavigationService.cs
+++ b/SubCabinetSolution/Utils/NavigationService.cs
@@ -20,7 +20,7 @@
public string CurrentPageKey
{
- get { return _currentPageKey; }
+ get => _currentPageKey;
private set { Set(() => CurrentPageKey, ref _currentPageKey, value); }
}
diff --git a/SubCabinetSolution/ViewModel/CabinetViewModel.cs b/SubCabinetSolution/ViewModel/CabinetViewModel.cs
index 91b1f08..d6b4d96 100644
--- a/SubCabinetSolution/ViewModel/CabinetViewModel.cs
+++ b/SubCabinetSolution/ViewModel/CabinetViewModel.cs
@@ -71,7 +71,7 @@
private string _inputKeywords;
public RelayCommand SearchDataCommand { get; set; }
- private string _isTopSearchBarVisible;
+ private string _isTopSearchBarVisible = "Collapsed";
public string IsTopSearchBarVisible
{
diff --git a/.vs/SubCabinetSolution/v17/.suo b/.vs/SubCabinetSolution/v17/.suo
index c0c2566..12a3574 100644
--- a/.vs/SubCabinetSolution/v17/.suo
+++ b/.vs/SubCabinetSolution/v17/.suo
Binary files differ
diff --git a/SubCabinetSolution/Utils/NavigationService.cs b/SubCabinetSolution/Utils/NavigationService.cs
index 1e00f07..37bb787 100644
--- a/SubCabinetSolution/Utils/NavigationService.cs
+++ b/SubCabinetSolution/Utils/NavigationService.cs
@@ -20,7 +20,7 @@
public string CurrentPageKey
{
- get { return _currentPageKey; }
+ get => _currentPageKey;
private set { Set(() => CurrentPageKey, ref _currentPageKey, value); }
}
diff --git a/SubCabinetSolution/ViewModel/CabinetViewModel.cs b/SubCabinetSolution/ViewModel/CabinetViewModel.cs
index 91b1f08..d6b4d96 100644
--- a/SubCabinetSolution/ViewModel/CabinetViewModel.cs
+++ b/SubCabinetSolution/ViewModel/CabinetViewModel.cs
@@ -71,7 +71,7 @@
private string _inputKeywords;
public RelayCommand SearchDataCommand { get; set; }
- private string _isTopSearchBarVisible;
+ private string _isTopSearchBarVisible = "Collapsed";
public string IsTopSearchBarVisible
{
diff --git a/SubCabinetSolution/ViewModel/MainViewModel.cs b/SubCabinetSolution/ViewModel/MainViewModel.cs
index a7920e3..ddfd76c 100644
--- a/SubCabinetSolution/ViewModel/MainViewModel.cs
+++ b/SubCabinetSolution/ViewModel/MainViewModel.cs
@@ -5,8 +5,8 @@
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
+using System.Threading.Tasks;
using System.Windows;
-using AForge.Controls;
using AForge.Video.DirectShow;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
@@ -16,13 +16,17 @@
using SubCabinetSolution.Utils;
using SubCabinetSolution.Views;
using ViewFaceCore.Core;
+using Point = System.Drawing.Point;
+using Size = System.Drawing.Size;
namespace SubCabinetSolution.ViewModel
{
public class MainViewModel : ViewModelBase
{
- private FilterInfo _currentDevice;
+ private readonly FilterInfo _currentDevice;
private readonly FaceDetector _faceDetector = new FaceDetector();
+ private readonly FaceRecognizer _faceRecognizer = new FaceRecognizer();
+ private readonly FaceLandmarker _faceLandMarker = new FaceLandmarker();
/*
* TextBlock双向绑定
@@ -36,7 +40,7 @@
public string UserName
{
- get { return _userName; }
+ get => _userName;
set
{
_userName = value;
@@ -46,7 +50,7 @@
public string UserPassword
{
- get { return _userPassword; }
+ get => _userPassword;
set
{
_userPassword = value;
@@ -61,10 +65,20 @@
private readonly MySqlConnection _connection;
///
+ /// 本地人脸数据
+ ///
+ private readonly float[] _localeFaceFeatures;
+
+ ///
/// Initializes a new instance of the MainViewModel class.
///
public MainViewModel()
{
+ //加载本地人脸数据
+ var localeFaceTask = new Task(ExtractLocalePicture);
+ localeFaceTask.Start();
+ _localeFaceFeatures = localeFaceTask.Result;
+
var videoDevices = new ObservableCollection();
foreach (FilterInfo filter in new FilterInfoCollection(FilterCategory.VideoInputDevice))
{
@@ -118,8 +132,7 @@
// TODO 解码得到密码
if (account != _userName || secretKey != _userPassword) continue;
reader.Close();
- var cabinetWindow = new CabinetWindow();
- cabinetWindow.Show();
+ new CabinetWindow().Show();
//通过消息Messenger告诉MainWindow.xaml.cs关闭窗口
Messenger.Default.Send("CloseWindow", "2022093001");
return;
@@ -136,36 +149,73 @@
private void OpenCamera(MainWindow window)
{
- if (_currentDevice != null)
+ if (_currentDevice == null) return;
+ if (window.CameraPreviewPlayer.IsRunning)
{
- if (window.CameraPreviewPlayer.IsRunning)
+ window.CameraPreviewPlayer.SignalToStop();
+ window.CameraFormsHost.Visibility = Visibility.Collapsed;
+ }
+ else
+ {
+ window.CameraPreviewPlayer.VideoSource = new VideoCaptureDevice(_currentDevice.MonikerString);
+ window.CameraPreviewPlayer.Start();
+ window.CameraPreviewPlayer.NewFrame += delegate(object sender, ref Bitmap bitmap)
{
- window.CameraPreviewPlayer.SignalToStop();
- window.CameraFormsHost.Visibility = Visibility.Collapsed;
- }
- else
- {
- var videoSource = new VideoCaptureDevice(_currentDevice.MonikerString);
- window.CameraPreviewPlayer.VideoSource = videoSource;
- window.CameraPreviewPlayer.NewFrame += delegate(object sender, ref Bitmap bitmap)
+ //捕捉画面帧,人脸检测
+ var faceImage = SKBitmap.Decode(BitmapToBytes(bitmap)).ToFaceImage();
+ var faceInfos = _faceDetector.Detect(faceImage);
+ if (!faceInfos.Any()) return;
+ //画出人脸位置
+ using (var g = Graphics.FromImage(bitmap))
{
- //捕捉画面帧,人脸检测
- var skBitmap = SKBitmap.Decode(BitmapToBytes(bitmap));
- var faceInfos = _faceDetector.Detect(skBitmap);
- Debug.WriteLine($@"检测到的人脸数量:{faceInfos.Length} 个人脸信息");
foreach (var info in faceInfos)
{
- Debug.WriteLine($"{info.Score:f8}\t{info.Location}");
+ var faceRect = info.Location;
+ g.DrawRectangle(
+ new Pen(Color.Red, 3),
+ new Rectangle(
+ new Point(faceRect.X, faceRect.Y), new Size(faceRect.Width, faceRect.Height)
+ )
+ );
}
- };
- window.CameraPreviewPlayer.Start();
- window.CameraFormsHost.Visibility = Visibility.Visible;
+ }
- // Dispatcher.CurrentDispatcher.BeginInvoke(new ThreadStart(delegate { Debug.WriteLine(DateTime.Now); }));
- }
+ //比对人脸,只对比第一张人脸数据,新开线程处理,不然会卡
+ var task = new Task(() =>
+ {
+ var faceMarkPoints = _faceLandMarker.Mark(faceImage, faceInfos[0]);
+ var faceFeatures = _faceRecognizer.Extract(faceImage, faceMarkPoints);
+ Debug.WriteLine("相似度:" + _faceRecognizer.Compare(faceFeatures, _localeFaceFeatures));
+ return _faceRecognizer.IsSelf(faceFeatures, _localeFaceFeatures);
+ });
+ task.Start();
+ //切换为主线程
+ Application.Current.Dispatcher.Invoke(delegate
+ {
+ if (!task.Result) return;
+ window.CameraPreviewPlayer.SignalToStop();
+ window.CameraFormsHost.Visibility = Visibility.Collapsed;
+ new CabinetWindow().Show();
+ Messenger.Default.Send("CloseWindow", "2022093001");
+ });
+ };
+ window.CameraFormsHost.Visibility = Visibility.Visible;
}
}
+ ///
+ /// 读取本地人脸数据。暂时可以直接读取,后期可优化为后台线程长期读取图片数据
+ ///
+ /// float[]
+ private float[] ExtractLocalePicture()
+ {
+ var image = (Bitmap)Image.FromFile(@"D:\Android\IMG_20221008_155007.jpg");
+ var faceImage = SKBitmap.Decode(BitmapToBytes(image)).ToFaceImage();
+ var faceInfos = _faceDetector.Detect(faceImage);
+ var faceMarkPoints = new FaceLandmarker().Mark(faceImage, faceInfos[0]);
+ return _faceRecognizer.Extract(faceImage, faceMarkPoints);
+ }
+
private static byte[] BitmapToBytes(Bitmap bitmap)
{
var ms = new MemoryStream();