FormMain.cs 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915
  1. using Emgu.CV.Face;
  2. using Emgu.CV.Structure;
  3. using Emgu.CV.Util;
  4. using Emgu.CV;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.ComponentModel;
  8. using System.Data;
  9. using System.Drawing;
  10. using System.Linq;
  11. using System.Text;
  12. using System.Threading.Tasks;
  13. using System.Windows.Forms;
  14. using System.IO;
  15. using System.Windows.Media.Imaging;
  16. using Emgu.CV.CvEnum;
  17. using System.Runtime.CompilerServices;
  18. using static System.Windows.Forms.VisualStyles.VisualStyleElement.StartPanel;
  19. using System.Data.SqlClient;
  20. using Emgu.CV.Ocl;
  21. using DirectShowLib;
  22. using System.Runtime.Serialization.Formatters.Binary;
  23. namespace T_FaceRecognizer
  24. {
  25. public partial class FormMain : Form
  26. {
  27. public FormMain()
  28. {
  29. InitializeComponent();
  30. }
  31. private void CaptureTimer_Tick(object sender, EventArgs e)
  32. {
  33. ProcessFrame();
  34. }
  35. #region <Переменные>
  36. SqlConnection SCon = new SqlConnection(@"Data Source=213.155.192.79,3002;Initial Catalog=FaceTrackApp;Persist Security Info=True;User ID=u20teresh;Password=bfg2");
  37. public int SelectedCameraID { get; set; } = 0;
  38. Rectangle CurrentFace;
  39. public string UserName { get; set; } = "Лицо не обнаружено";
  40. /// <summary>
  41. /// ID пользователя, который обнаружен
  42. /// </summary>
  43. private string CurrentUserID = string.Empty;
  44. /// <summary>
  45. /// тип операции 1 - вход, 0- выход
  46. /// </summary>
  47. private int TypeOperation = 0;
  48. private bool IsMenuOpened = true;
  49. //доступные видеокамеры
  50. private DsDevice[] WebCams = null;
  51. int CountCams = -1;
  52. HashSet<string> HtBefore = new HashSet<string>();
  53. //включена ли на данный момент камера
  54. #endregion
  55. #region <Свойства>
  56. public event PropertyChangedEventHandler PropertyChanged;
  57. private VideoCapture Capture;
  58. private CascadeClassifier HaarCascade;
  59. private Image<Bgr, Byte> BgrFrame = null;
  60. private Image<Gray, Byte> DetectedFace = null;
  61. private List<FaceData> FaceList = new List<FaceData>();
  62. private VectorOfMat ImageList = new VectorOfMat();
  63. private List<string> NameList = new List<string>();
  64. private VectorOfInt LabelList = new VectorOfInt();
  65. private EigenFaceRecognizer recognizer;
  66. private Timer CaptureTimer;
  67. private Timer CaptureTimerIdent;
  68. private bool IsRecognized = false;
  69. #region FaceName
  70. private string faceName;
  71. public string FaceName
  72. {
  73. get { return faceName; }
  74. set
  75. {
  76. faceName = value;
  77. if (faceName == "Лицо не обнаружено")
  78. {
  79. IsRecognized = false;
  80. }
  81. else
  82. {
  83. IsRecognized = true;
  84. }
  85. UserName = faceName;
  86. NotifyPropertyChanged();
  87. }
  88. }
  89. #endregion
  90. #region CameraCaptureImage
  91. private Bitmap cameraCapture;
  92. public Bitmap CameraCapture
  93. {
  94. get { return cameraCapture; }
  95. set
  96. {
  97. cameraCapture = value;
  98. if (TabPages.SelectedIndex == 1)
  99. {
  100. DrawName(cameraCapture, CurrentFace);
  101. PbxIdentification.Image = cameraCapture;
  102. }
  103. else
  104. {
  105. PbxFaces.Image = cameraCapture;
  106. }
  107. NotifyPropertyChanged();
  108. }
  109. }
  110. #endregion
  111. #region CameraCaptureFaceImage
  112. private Bitmap cameraCaptureFace;
  113. public Bitmap CameraCaptureFace
  114. {
  115. get { return cameraCaptureFace; }
  116. set
  117. {
  118. cameraCaptureFace = value;
  119. PbxFaces.Image = cameraCapture;
  120. NotifyPropertyChanged();
  121. }
  122. }
  123. #endregion
  124. #endregion
  125. /// <summary>
  126. /// отрисовка имени над прямоугольком
  127. /// </summary>
  128. private void DrawName(Bitmap cameraCapture, Rectangle face)
  129. {
  130. Pen PenForFace = new Pen(Brushes.Red, 5);
  131. Brush BrushForFace = Brushes.White;
  132. Font MyFont = new Font("Segoe UI Variable Small Semibol; 12pt; style=Bold", 12, FontStyle.Regular);
  133. Brush BrushInfo = Brushes.White;
  134. Pen PenInfo = new Pen(Brushes.White, 4);
  135. Graphics Graph = Graphics.FromImage(cameraCapture);
  136. //Graph.DrawRectangle(PenForFace, face.X, face.Y, face.Width, face.Height);
  137. //позиция отрисовки имени человека
  138. Point PointName = new Point(face.X, face.Y - 25);
  139. Graph.DrawString($"{UserName}", MyFont, BrushForFace, PointName);
  140. }
  141. /// <summary>
  142. /// получение данных с камеры и обработка изображени
  143. /// </summary>
  144. private void ProcessFrame()
  145. {
  146. try
  147. {
  148. BgrFrame = Capture.QueryFrame().ToImage<Bgr, Byte>().Flip(FlipType.Horizontal);
  149. }
  150. catch
  151. {
  152. return;
  153. }
  154. if (BgrFrame != null)
  155. {
  156. try
  157. {//for emgu cv bug
  158. Image<Gray, byte> grayframe = BgrFrame.Convert<Gray, byte>();
  159. Rectangle[] faces = HaarCascade.DetectMultiScale(grayframe, 1.2, 10, new System.Drawing.Size(50, 50), new System.Drawing.Size(200, 200));
  160. //detect face
  161. FaceName = "Лицо не обнаружено";
  162. foreach (var face in faces)
  163. {
  164. BgrFrame.Draw(face, new Bgr(0, 0, 255), 2);
  165. DetectedFace = BgrFrame.Copy(face).Convert<Gray, byte>();
  166. FaceRecognition();
  167. break;
  168. }
  169. CameraCapture = BgrFrame.ToBitmap();
  170. }
  171. catch (Exception ex)
  172. {
  173. //todo log
  174. }
  175. }
  176. }
  177. /// <summary>
  178. /// распознавание лица
  179. /// </summary>
  180. private void FaceRecognition()
  181. {
  182. if (ImageList.Size != 0)
  183. {
  184. FaceRecognizer.PredictionResult result = recognizer.Predict(DetectedFace.Resize(100, 100, Inter.Cubic));
  185. FaceName = NameList[result.Label];
  186. CurrentUserID = FaceList[result.Label].UserID;
  187. CameraCaptureFace = DetectedFace.ToBitmap();
  188. }
  189. else
  190. {
  191. FaceName = "Пожалуйста добавьте лицо";
  192. }
  193. }
  194. /// <summary>
  195. /// добавление лица в систему
  196. /// </summary>
  197. private void BtnAdd_Click(object sender, EventArgs e)
  198. {
  199. if (DetectedFace == null)
  200. {
  201. MessageBox.Show("Лица не обнаружены!\r\nУбедитесь что лицо находится в кадре и обведено красным прямоугольником.", "ImpulseVision", MessageBoxButtons.OK, MessageBoxIcon.Error);
  202. return;
  203. }
  204. string PhotoPath = string.Empty;
  205. //ProgressOperation.Value = 10;
  206. //TslStatus.Text = "Добавление нового пользователя...";
  207. bool Flag = TbxLastname.Text.Trim() == "" || TbxName.Text.Trim() == "" || TbxMaskPhone.Text.Trim() == "" || TbxMaskSnils.Text.Trim().Replace(" ","").Length < 11;
  208. if (Flag)
  209. {
  210. MessageBox.Show("Заполните все поля и повторите попытку!", "Ошибка добавления!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
  211. return;
  212. }
  213. SCon.Open();
  214. string QueryCheckPassport = $@"select UserID
  215. from Users
  216. where Snils = '{TbxMaskSnils.Text.Trim()}'";
  217. SqlCommand CmdCheck = new SqlCommand(QueryCheckPassport, SCon);
  218. SqlDataReader Res = CmdCheck.ExecuteReader();
  219. if (Res.HasRows)
  220. {
  221. MessageBox.Show("Такой пользователь уже зарегистрирован в системе!", "FaceTrack", MessageBoxButtons.OK, MessageBoxIcon.Error);
  222. SCon.Close();
  223. return;
  224. }
  225. SCon.Close();
  226. //изменить размеры изображения
  227. DetectedFace = DetectedFace.Resize(100, 100, Inter.Cubic);
  228. //сохранить изображение в папку
  229. DetectedFace.Save(Config.FacePhotosPath + $"{TbxName.Text.Trim()}{TbxMaskSnils.Text.Trim()}" + Config.ImageFileExtension);
  230. PhotoPath = Config.FacePhotosPath + $"{TbxName.Text.Trim()}{TbxMaskSnils.Text.Trim()}" + Config.ImageFileExtension;
  231. //добавление пользователя в БД
  232. SCon.Open();
  233. string QueryAdd = $@"insert into Users (Lastname,Firstname,Patronymic,Phone,Snils,Photo)
  234. values (@last,@first,@patr,@phone,@snils,@photo)
  235. ";
  236. SqlCommand Cmd = new SqlCommand(QueryAdd, SCon);
  237. Cmd.Parameters.AddWithValue("@last", TbxLastname.Text.Trim());
  238. Cmd.Parameters.AddWithValue("@first", TbxName.Text.Trim());
  239. Cmd.Parameters.AddWithValue("@patr", TbxPatronymic.Text.Trim());
  240. Cmd.Parameters.AddWithValue("@phone", TbxMaskPhone.Text.Trim());
  241. Cmd.Parameters.AddWithValue("@snils", TbxMaskSnils.Text.Trim());
  242. Cmd.Parameters.AddWithValue("@photo", PhotoPath);
  243. Cmd.ExecuteNonQuery();//выполнить запрос
  244. SCon.Close();
  245. MessageBox.Show("Успешно сохранено!", "FaceTrack", MessageBoxButtons.OK, MessageBoxIcon.Information);
  246. }
  247. /// <summary>
  248. /// получение данных об изображениях
  249. /// </summary>
  250. public void GetFacesList()
  251. {
  252. if (!File.Exists(Config.HaarCascadePath))
  253. {
  254. string text = "Файл каскада Хаара не обнаружен:\n\n";
  255. text += Config.HaarCascadePath;
  256. DialogResult result = MessageBox.Show(text, "Ошибка",
  257. MessageBoxButtons.OK, MessageBoxIcon.Error);
  258. }
  259. HaarCascade = new CascadeClassifier(Config.HaarCascadePath);
  260. FaceList.Clear();
  261. // Создать директорию, если она отсутствовала
  262. if (!Directory.Exists(Config.FacePhotosPath))
  263. {
  264. Directory.CreateDirectory(Config.FacePhotosPath);
  265. }
  266. // Тренировать изображения
  267. if (ImageList.Size > 0)
  268. {
  269. recognizer = new EigenFaceRecognizer(ImageList.Size);
  270. recognizer.Train(ImageList, LabelList);
  271. }
  272. }
  273. protected virtual void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
  274. {
  275. var handler = PropertyChanged;
  276. if (handler != null)
  277. handler(this, new PropertyChangedEventArgs(propertyName));
  278. }
  279. private void FormMain_Load(object sender, EventArgs e)
  280. {
  281. //скрытие заголовков вкладок в TabControl
  282. TabPages.Appearance = TabAppearance.FlatButtons;
  283. TabPages.ItemSize = new Size(0, 1);
  284. TabPages.SizeMode = TabSizeMode.Fixed;
  285. GetCams();
  286. SetFormParameters();
  287. TabPages.SelectTab(4);
  288. }
  289. private void PbxMenu_Click(object sender, EventArgs e)
  290. {
  291. IsMenuOpened = !IsMenuOpened;
  292. if(SplitContainer.Panel1.Width != 45)
  293. {
  294. SplitContainer.SplitterDistance = 45;
  295. PanHome.BackColor = Color.FromArgb(206, 208, 223);
  296. PanAdd.BackColor = Color.FromArgb(206, 208, 223);
  297. PanIdentification.BackColor = Color.FromArgb(206, 208, 223);
  298. PanJournal.BackColor = Color.FromArgb(206, 208, 223);
  299. PanSettings.BackColor = Color.FromArgb(206, 208, 223);
  300. }
  301. else
  302. {
  303. SplitContainer.SplitterDistance = 250;
  304. PanHome.BackColor = Color.FromArgb(58, 166, 64);
  305. PanAdd.BackColor = Color.FromArgb(58, 166, 64);
  306. PanIdentification.BackColor = Color.FromArgb(58, 166, 64);
  307. PanJournal.BackColor = Color.FromArgb(58, 166, 64);
  308. PanSettings.BackColor = Color.FromArgb(58, 166, 64);
  309. }
  310. }
  311. /// <summary>
  312. /// котроль размеров меню
  313. /// </summary>
  314. /// <param name="isMenuOpened">открыто меню или нет</param>
  315. private void ControlSizeMenu(bool isMenuOpened)
  316. {
  317. if (isMenuOpened)
  318. {
  319. SplitContainer.SplitterDistance = 250;
  320. }
  321. else
  322. {
  323. SplitContainer.SplitterDistance = 45;
  324. }
  325. }
  326. private void FormMain_Resize(object sender, EventArgs e)
  327. {
  328. ControlSizeMenu(IsMenuOpened);
  329. }
  330. private void BtnMain_Click(object sender, EventArgs e)
  331. {
  332. Task.Factory.StartNew(() =>
  333. {
  334. RecognizeOff();
  335. });
  336. TabPages.SelectTab(4);
  337. }
  338. private void BtnAddUser_Click(object sender, EventArgs e)
  339. {
  340. CaptureTimer = new Timer()
  341. {
  342. Interval = Config.TimerResponseValue
  343. };
  344. CaptureTimer.Tick += CaptureTimer_Tick;
  345. if (ImageList.Size == 0)
  346. {
  347. GetFacesList();
  348. }
  349. TabPages.SelectTab(0);
  350. Capture = new VideoCapture(SelectedCameraID);
  351. Capture.SetCaptureProperty(CapProp.Fps, 30);
  352. Capture.SetCaptureProperty(CapProp.FrameHeight, 450);
  353. Capture.SetCaptureProperty(CapProp.FrameWidth, 370);
  354. CaptureTimer.Start();
  355. }
  356. private void BtnIdent_Click(object sender, EventArgs e)
  357. {
  358. CaptureTimerIdent = new Timer()
  359. {
  360. Interval = Config.TimerResponseValue
  361. };
  362. CaptureTimerIdent.Tick += CaptureTimerIdent_Tick;
  363. GetFacesListForIdentification();
  364. Capture = new VideoCapture(SelectedCameraID);
  365. //настройка кадров
  366. Capture.SetCaptureProperty(CapProp.Fps, 30);
  367. Capture.SetCaptureProperty(CapProp.FrameHeight, 450);
  368. Capture.SetCaptureProperty(CapProp.FrameWidth, 370);
  369. CaptureTimerIdent.Start();
  370. TabPages.SelectTab(1);
  371. }
  372. /// <summary>
  373. /// отключение камеры и распознавания
  374. /// </summary>
  375. private void RecognizeOff()
  376. {
  377. if (BgrFrame != null)
  378. {
  379. if (Capture != null)
  380. {
  381. Capture.Dispose();
  382. Capture = null;
  383. }
  384. //BgrFrame = null;
  385. if (CaptureTimer != null)
  386. {
  387. CaptureTimer.Enabled = false;
  388. }
  389. if(CaptureTimerIdent != null)
  390. {
  391. CaptureTimerIdent.Enabled = false;
  392. }
  393. }
  394. }
  395. private void CaptureTimerIdent_Tick(object sender, EventArgs e)
  396. {
  397. ProcessFrameIndentification();
  398. }
  399. /// <summary>
  400. /// получение данных с камеры и распознавание
  401. /// </summary>
  402. private void ProcessFrameIndentification()
  403. {
  404. try
  405. {
  406. BgrFrame = Capture.QueryFrame().ToImage<Bgr, Byte>().Flip(FlipType.Horizontal);
  407. }
  408. catch
  409. {
  410. return;
  411. }
  412. if (BgrFrame != null)
  413. {
  414. try
  415. {
  416. Image<Gray, byte> grayframe = BgrFrame.Convert<Gray, byte>();
  417. Rectangle[] faces = HaarCascade.DetectMultiScale(grayframe, 1.2, 10, new System.Drawing.Size(50, 50), new System.Drawing.Size(200, 200));
  418. FaceName = "Лицо не обнаружено";
  419. foreach (var face in faces)
  420. {
  421. CurrentFace = face;
  422. BgrFrame.Draw(face, new Bgr(53, 23, 247), 2);
  423. DetectedFace = BgrFrame.Copy(face).Convert<Gray, byte>();
  424. FaceRecognition();
  425. break;
  426. }
  427. CameraCapture = BgrFrame.ToBitmap();
  428. }
  429. catch (Exception ex)
  430. {
  431. MessageBox.Show(ex.Message);
  432. }
  433. }
  434. }
  435. /// <summary>
  436. /// получение информации о пользователе и тренировка модели для распознавания
  437. /// </summary>
  438. private void GetFacesListForIdentification()
  439. {
  440. //файл Хаара
  441. if (!File.Exists(Config.HaarCascadePath))
  442. {
  443. string text = "Не удаётся найти файл данных - каскад Хаара:\n\n";
  444. text += Config.HaarCascadePath;
  445. DialogResult result = MessageBox.Show(text, "Ошибка",
  446. MessageBoxButtons.OK, MessageBoxIcon.Error);
  447. }
  448. HaarCascade = new CascadeClassifier(Config.HaarCascadePath);
  449. FaceList.Clear();
  450. FaceData FaceItem = null;
  451. //создать папку для фото, если она отсутствовала
  452. if (!Directory.Exists(Config.FacePhotosPath))
  453. {
  454. Directory.CreateDirectory(Config.FacePhotosPath);
  455. }
  456. //получить из БД инфо о пользователе (id, имя, фамилия, путь до фото)
  457. SCon.Open();
  458. string QueryGetInfoAboutUser = $@"select UserID ,Users.Lastname, Users.Firstname, Users.Patronymic, Photo
  459. from Users";
  460. SqlCommand Cmd = new SqlCommand(QueryGetInfoAboutUser, SCon);
  461. SqlDataReader Res = Cmd.ExecuteReader();
  462. if (Res.HasRows)
  463. {
  464. while (Res.Read())
  465. {
  466. try
  467. {
  468. FaceItem = new FaceData();
  469. FaceItem.FaceImage = new Image<Gray, byte>(Application.StartupPath + "\\" + Res["Photo"].ToString());
  470. FaceItem.PersonName = Res["Firstname"].ToString();
  471. FaceItem.LastName = Res["Lastname"].ToString();
  472. FaceItem.Patronymic = Res["Patronymic"].ToString();
  473. FaceItem.UserID = Res["UserID"].ToString();
  474. FaceList.Add(FaceItem);
  475. }
  476. catch (Exception ex)
  477. {
  478. MessageBox.Show(ex.Message, "FaceTrack", MessageBoxButtons.OK, MessageBoxIcon.Error);
  479. }
  480. }
  481. }
  482. else
  483. {
  484. SCon.Close();
  485. MessageBox.Show("Данные о пользователях отсутствуют!", "FaceTrack", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
  486. return;
  487. }
  488. SCon.Close();
  489. int i = 0;
  490. foreach (var face in FaceList)
  491. {
  492. ImageList.Push(face.FaceImage.Mat);
  493. NameList.Add(face.PersonName + " " + face.LastName);
  494. LabelList.Push(new[] { i++ });
  495. }
  496. // Тренировка модели
  497. if (ImageList.Size > 0)
  498. {
  499. recognizer = new EigenFaceRecognizer(ImageList.Size);
  500. recognizer.Train(ImageList, LabelList);
  501. }
  502. }
  503. private void BtnIn_Click(object sender, EventArgs e)
  504. {
  505. TypeOperation = 1;
  506. RegisterVisit(TypeOperation);
  507. }
  508. private void RegisterVisit(int typeOperation)
  509. {
  510. if (!IsRecognized)
  511. {
  512. MessageBox.Show("Убедитесь, что лицо находится в кадре и обведено красным прямоугольником!", "Ошибка распознавания!");
  513. return;
  514. }
  515. if (typeOperation == 1)
  516. {
  517. #region Предупреждение при попытке повторной идентификации пользователя за один день
  518. SCon.Open();
  519. string QueryCheckExistsVisit = $@"select Count(ID) as Cnt
  520. from Visits
  521. where UsersID = '{CurrentUserID}' and [Date] = CAST(GETDATE() as date)";
  522. SqlCommand CmdCheckVisit = new SqlCommand(QueryCheckExistsVisit, SCon);
  523. SqlDataReader Res = CmdCheckVisit.ExecuteReader();
  524. Res.Read();
  525. int n = int.Parse(Res["Cnt"].ToString());
  526. if (n >= 1)
  527. {
  528. MessageBox.Show("Сегодня данный пользователь уже прошёл идентификацию при входе!", "ImpulseVision", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
  529. SCon.Close();
  530. return;
  531. }
  532. SCon.Close();
  533. #endregion
  534. //регистрация посещения
  535. SCon.Open();
  536. string QueryAddVisit = $@"set dateformat dmy
  537. insert into Visits (UsersID,[Date],TimeEntrance)
  538. values ('{CurrentUserID}',CAST(GETDATE() as date),'{DateTime.Now.ToString("HH:mm:ss")}')
  539. ";
  540. SqlCommand Cmd = new SqlCommand(QueryAddVisit, SCon);
  541. Cmd.ExecuteNonQuery();
  542. SCon.Close();
  543. MessageBox.Show("Вход зарегистрирован!", "FaceTrack", MessageBoxButtons.OK, MessageBoxIcon.Information);
  544. }
  545. else
  546. {
  547. SCon.Open();
  548. string QueryCheckRecord = $@"set dateformat dmy
  549. select *
  550. from Visits
  551. where UsersID = '{CurrentUserID}' and [Date] = cast(GETDATE() as date) and TimeExit is null
  552. ";
  553. SqlCommand CmdCheck = new SqlCommand(QueryCheckRecord, SCon);
  554. SqlDataReader Res = CmdCheck.ExecuteReader();
  555. if (!Res.HasRows)
  556. {
  557. MessageBox.Show("Данный пользователь уже вышел!", "ImpulseVision", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
  558. SCon.Close();
  559. return;
  560. }
  561. SCon.Close();
  562. //!!! Выход пользователя, который не прошёл идентификацию не регистрируется
  563. SCon.Open();
  564. string QueryTimeExit = $@"update Visits
  565. set TimeExit = '{DateTime.Now.ToString("HH:mm:ss")}'
  566. where UsersID = '{CurrentUserID}' and [Date] = cast(GETDATE() as date)";
  567. SqlCommand Cmd = new SqlCommand(QueryTimeExit, SCon);
  568. Cmd.ExecuteNonQuery();
  569. SCon.Close();
  570. MessageBox.Show("Выход зарегистрирован!", "FaceTrack", MessageBoxButtons.OK, MessageBoxIcon.Information);
  571. }
  572. }
  573. private void BtnOut_Click(object sender, EventArgs e)
  574. {
  575. TypeOperation = 0;
  576. RegisterVisit(TypeOperation);
  577. }
  578. private void BtnJournal_Click(object sender, EventArgs e)
  579. {
  580. Task.Factory.StartNew(() =>
  581. {
  582. RecognizeOff();
  583. });
  584. GetInformationAboutVisiting();
  585. TabPages.SelectTab(2);
  586. }
  587. /// <summary>
  588. /// получение списка пользователей для журнала посещений
  589. /// </summary>
  590. private void GetInformationAboutVisiting()
  591. {
  592. DgbJournal.Rows.Clear();
  593. SCon.Open();
  594. string QueryGetVisits = $@"select UserID,Lastname +' '+Firstname+' '+Patronymic as FIO,(select MAX([Date])
  595. from Visits
  596. where UsersID = Users.UserID) as LastDateVisit
  597. from Users
  598. ";
  599. if(TbxSearch.Text.Trim() != string.Empty)
  600. {
  601. QueryGetVisits += $@" where Lastname +' '+Firstname+' '+Patronymic like '%{TbxSearch.Text.Trim()}%'";
  602. }
  603. SqlCommand CommandGetVisits = new SqlCommand(QueryGetVisits, SCon);
  604. SqlDataReader Res = CommandGetVisits.ExecuteReader();
  605. if(Res.HasRows)
  606. {
  607. string DateTemplate = string.Empty;
  608. while(Res.Read())
  609. {
  610. try
  611. {
  612. DateTemplate = DateTime.Parse(Res["LastDateVisit"].ToString()).ToString("dd.MM.yyyy");
  613. }
  614. catch(Exception ex)
  615. {
  616. DateTemplate = "нет";
  617. }
  618. DgbJournal.Rows.Add(Res["UserID"].ToString(), Res["FIO"].ToString(), DateTemplate);
  619. }
  620. }
  621. else
  622. {
  623. MessageBox.Show("Посещения пользователей отсутствуют!", "FaceTrack", MessageBoxButtons.OK, MessageBoxIcon.Error);
  624. SCon.Close();
  625. return;
  626. }
  627. SCon.Close();
  628. }
  629. private void DgbJournal_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
  630. {
  631. int RowIndex = e.RowIndex;
  632. int SelectedUserID = int.Parse(DgbJournal.Rows[RowIndex].Cells[0].Value.ToString());
  633. string SelectedUserName = DgbJournal.Rows[RowIndex].Cells[1].Value.ToString();
  634. FormVisiting FVisiting = new FormVisiting(SelectedUserID, SelectedUserName);
  635. this.Hide();
  636. FVisiting.ShowDialog();
  637. this.Show();
  638. }
  639. private void BtnSettings_Click(object sender, EventArgs e)
  640. {
  641. Task.Factory.StartNew(() =>
  642. {
  643. RecognizeOff();
  644. });
  645. GetCams();
  646. TabPages.SelectTab(3);
  647. }
  648. /// <summary>
  649. /// получение списка доступных камер
  650. /// </summary>
  651. private void GetCams()
  652. {
  653. WebCams = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice);
  654. CountCams = WebCams.Length;
  655. CmbCams.Items.Clear();
  656. for (int i = 0; i < CountCams; i++)
  657. {
  658. CmbCams.Items.Add(WebCams[i].Name);
  659. HtBefore.Add(WebCams[i].Name);
  660. }
  661. if (CountCams == 0)
  662. {
  663. MessageBox.Show("Камеры не обнаружены! Подключите камеру и перезапустите приложение.","FaceTrack",MessageBoxButtons.OK,MessageBoxIcon.Error);
  664. this.Close();
  665. }
  666. else
  667. {
  668. CmbCams.SelectedIndex = SelectedCameraID;
  669. }
  670. }
  671. /// <summary>
  672. /// обработка ситуации изменения количества подключённых камер
  673. /// </summary>
  674. private void CamsPreview()
  675. {
  676. DsDevice[] Cams = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice);
  677. int CountCams = Cams.Length;
  678. if(CountCams != HtBefore.Count)
  679. {
  680. GetCams();
  681. RecognizeOff();
  682. if (TabPages.SelectedIndex == 0)
  683. {
  684. BtnAddUser_Click(null, null);
  685. }
  686. else if (TabPages.SelectedIndex == 1)
  687. {
  688. BtnIdent_Click(null, null);
  689. }
  690. Application.Restart();
  691. }
  692. }
  693. private void PanelMenu_Paint(object sender, PaintEventArgs e)
  694. {
  695. Invalidate();
  696. }
  697. private void FormMain_FormClosing(object sender, FormClosingEventArgs e)
  698. {
  699. ApplyNewParameters();
  700. RecognizeOff();
  701. Application.ExitThread();
  702. }
  703. /// <summary>
  704. /// применение настроек для формы
  705. /// </summary>
  706. private void ApplyNewParameters()
  707. {
  708. LocalSettings LocalSet = new LocalSettings();
  709. LocalSet.SelectedCameraID = SelectedCameraID;
  710. if (CbxSaveLocationForm.Checked)
  711. {
  712. LocalSet.PositionLocationX = this.Location.X;
  713. LocalSet.PositionLocationY = this.Location.Y;
  714. }
  715. else
  716. {
  717. LocalSet.PositionLocationX = -1;
  718. LocalSet.PositionLocationY = -1;
  719. }
  720. if (CbxSaveSizeForm.Checked)
  721. {
  722. LocalSet.FormWidth = this.Width;
  723. LocalSet.FormHeight = this.Height;
  724. }
  725. else
  726. {
  727. LocalSet.FormWidth = -1;
  728. LocalSet.FormHeight = -1;
  729. }
  730. StreamWriter Sw = new StreamWriter(Application.StartupPath + "\\localSettings.txt");
  731. Sw.WriteLine(LocalSet.SelectedCameraID);
  732. Sw.WriteLine(LocalSet.FormWidth);
  733. Sw.WriteLine(LocalSet.FormHeight);
  734. Sw.WriteLine(LocalSet.PositionLocationX);
  735. Sw.WriteLine(LocalSet.PositionLocationY);
  736. Sw.Close();
  737. }
  738. /// <summary>
  739. /// получение ранее схранённых параметров формы
  740. /// </summary>
  741. private void SetFormParameters()
  742. {
  743. if (!File.Exists(Application.StartupPath + "\\localSettings.txt"))
  744. {
  745. return;
  746. }
  747. StreamReader Sr = new StreamReader(Application.StartupPath + "\\localSettings.txt");
  748. LocalSettings CurrentSettings = new LocalSettings();
  749. CurrentSettings.SelectedCameraID = int.Parse(Sr.ReadLine());
  750. CurrentSettings.FormWidth = int.Parse(Sr.ReadLine());
  751. CurrentSettings.FormHeight = int.Parse(Sr.ReadLine());
  752. CurrentSettings.PositionLocationX = int.Parse(Sr.ReadLine());
  753. CurrentSettings.PositionLocationY = int.Parse(Sr.ReadLine());
  754. Sr.Close();
  755. CbxSaveLocationForm.Checked = false;
  756. CbxSaveSizeForm.Checked = false;
  757. SelectedCameraID = CurrentSettings.SelectedCameraID;
  758. try
  759. {
  760. CmbCams.SelectedIndex = SelectedCameraID;
  761. }
  762. catch
  763. {
  764. SelectedCameraID = 0;
  765. }
  766. if (CurrentSettings.FormWidth != -1 && CurrentSettings.FormHeight != -1)
  767. {
  768. CbxSaveSizeForm.Checked = true;
  769. this.Size = new Size(CurrentSettings.FormWidth, CurrentSettings.FormHeight);
  770. }
  771. if (CurrentSettings.PositionLocationX != -1 && CurrentSettings.PositionLocationY != -1)
  772. {
  773. CbxSaveLocationForm.Checked = true;
  774. this.Location = new Point(CurrentSettings.PositionLocationX, CurrentSettings.PositionLocationY);
  775. }
  776. }
  777. private void CmbCams_SelectedIndexChanged(object sender, EventArgs e)
  778. {
  779. SelectedCameraID = CmbCams.SelectedIndex;
  780. }
  781. private void BtnSaveParameters_Click(object sender, EventArgs e)
  782. {
  783. ApplyNewParameters();
  784. MessageBox.Show("Выбранные параметры успешно применены!", "FaceTrack", MessageBoxButtons.OK, MessageBoxIcon.Information);
  785. }
  786. private void TbxSearch_TextChanged(object sender, EventArgs e)
  787. {
  788. GetInformationAboutVisiting();
  789. }
  790. private void TimerCamsControl_Tick(object sender, EventArgs e)
  791. {
  792. CamsPreview();
  793. }
  794. private void LblLinkHelp_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
  795. {
  796. if (!File.Exists(Application.StartupPath + "\\Source\\help.chm"))
  797. {
  798. MessageBox.Show("В данный момент времени справочная система приложения недоступна!", "Внимание!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
  799. return;
  800. }
  801. System.Diagnostics.Process.Start(Application.StartupPath + "\\Source\\help.chm");
  802. }
  803. private void label6_Click(object sender, EventArgs e)
  804. {
  805. }
  806. private void label8_Click(object sender, EventArgs e)
  807. {
  808. }
  809. private void label9_Click(object sender, EventArgs e)
  810. {
  811. }
  812. private void label10_Click(object sender, EventArgs e)
  813. {
  814. }
  815. }
  816. }