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();