FormMain.cs 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916
  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. if(Capture != null)
  407. BgrFrame = Capture.QueryFrame().ToImage<Bgr, Byte>().Flip(FlipType.Horizontal);
  408. }
  409. catch
  410. {
  411. return;
  412. }
  413. if (BgrFrame != null)
  414. {
  415. try
  416. {
  417. Image<Gray, byte> grayframe = BgrFrame.Convert<Gray, byte>();
  418. Rectangle[] faces = HaarCascade.DetectMultiScale(grayframe, 1.2, 10, new System.Drawing.Size(50, 50), new System.Drawing.Size(200, 200));
  419. FaceName = "Лицо не обнаружено";
  420. foreach (var face in faces)
  421. {
  422. CurrentFace = face;
  423. BgrFrame.Draw(face, new Bgr(53, 23, 247), 2);
  424. DetectedFace = BgrFrame.Copy(face).Convert<Gray, byte>();
  425. FaceRecognition();
  426. break;
  427. }
  428. CameraCapture = BgrFrame.ToBitmap();
  429. }
  430. catch (Exception ex)
  431. {
  432. MessageBox.Show(ex.Message);
  433. }
  434. }
  435. }
  436. /// <summary>
  437. /// получение информации о пользователе и тренировка модели для распознавания
  438. /// </summary>
  439. private void GetFacesListForIdentification()
  440. {
  441. //файл Хаара
  442. if (!File.Exists(Config.HaarCascadePath))
  443. {
  444. string text = "Не удаётся найти файл данных - каскад Хаара:\n\n";
  445. text += Config.HaarCascadePath;
  446. DialogResult result = MessageBox.Show(text, "Ошибка",
  447. MessageBoxButtons.OK, MessageBoxIcon.Error);
  448. }
  449. HaarCascade = new CascadeClassifier(Config.HaarCascadePath);
  450. FaceList.Clear();
  451. FaceData FaceItem = null;
  452. //создать папку для фото, если она отсутствовала
  453. if (!Directory.Exists(Config.FacePhotosPath))
  454. {
  455. Directory.CreateDirectory(Config.FacePhotosPath);
  456. }
  457. //получить из БД инфо о пользователе (id, имя, фамилия, путь до фото)
  458. SCon.Open();
  459. string QueryGetInfoAboutUser = $@"select UserID ,Users.Lastname, Users.Firstname, Users.Patronymic, Photo
  460. from Users";
  461. SqlCommand Cmd = new SqlCommand(QueryGetInfoAboutUser, SCon);
  462. SqlDataReader Res = Cmd.ExecuteReader();
  463. if (Res.HasRows)
  464. {
  465. while (Res.Read())
  466. {
  467. try
  468. {
  469. FaceItem = new FaceData();
  470. FaceItem.FaceImage = new Image<Gray, byte>(Application.StartupPath + "\\" + Res["Photo"].ToString());
  471. FaceItem.PersonName = Res["Firstname"].ToString();
  472. FaceItem.LastName = Res["Lastname"].ToString();
  473. FaceItem.Patronymic = Res["Patronymic"].ToString();
  474. FaceItem.UserID = Res["UserID"].ToString();
  475. FaceList.Add(FaceItem);
  476. }
  477. catch (Exception ex)
  478. {
  479. MessageBox.Show(ex.Message, "FaceTrack", MessageBoxButtons.OK, MessageBoxIcon.Error);
  480. }
  481. }
  482. }
  483. else
  484. {
  485. SCon.Close();
  486. MessageBox.Show("Данные о пользователях отсутствуют!", "FaceTrack", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
  487. return;
  488. }
  489. SCon.Close();
  490. int i = 0;
  491. foreach (var face in FaceList)
  492. {
  493. ImageList.Push(face.FaceImage.Mat);
  494. NameList.Add(face.PersonName + " " + face.LastName);
  495. LabelList.Push(new[] { i++ });
  496. }
  497. // Тренировка модели
  498. if (ImageList.Size > 0)
  499. {
  500. recognizer = new EigenFaceRecognizer(ImageList.Size);
  501. recognizer.Train(ImageList, LabelList);
  502. }
  503. }
  504. private void BtnIn_Click(object sender, EventArgs e)
  505. {
  506. TypeOperation = 1;
  507. RegisterVisit(TypeOperation);
  508. }
  509. private void RegisterVisit(int typeOperation)
  510. {
  511. if (!IsRecognized)
  512. {
  513. MessageBox.Show("Убедитесь, что лицо находится в кадре и обведено красным прямоугольником!", "Ошибка распознавания!");
  514. return;
  515. }
  516. if (typeOperation == 1)
  517. {
  518. #region Предупреждение при попытке повторной идентификации пользователя за один день
  519. SCon.Open();
  520. string QueryCheckExistsVisit = $@"select Count(ID) as Cnt
  521. from Visits
  522. where UsersID = '{CurrentUserID}' and [Date] = CAST(GETDATE() as date)";
  523. SqlCommand CmdCheckVisit = new SqlCommand(QueryCheckExistsVisit, SCon);
  524. SqlDataReader Res = CmdCheckVisit.ExecuteReader();
  525. Res.Read();
  526. int n = int.Parse(Res["Cnt"].ToString());
  527. if (n >= 1)
  528. {
  529. MessageBox.Show("Сегодня данный пользователь уже прошёл идентификацию при входе!", "ImpulseVision", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
  530. SCon.Close();
  531. return;
  532. }
  533. SCon.Close();
  534. #endregion
  535. //регистрация посещения
  536. SCon.Open();
  537. string QueryAddVisit = $@"set dateformat dmy
  538. insert into Visits (UsersID,[Date],TimeEntrance)
  539. values ('{CurrentUserID}',CAST(GETDATE() as date),'{DateTime.Now.ToString("HH:mm:ss")}')
  540. ";
  541. SqlCommand Cmd = new SqlCommand(QueryAddVisit, SCon);
  542. Cmd.ExecuteNonQuery();
  543. SCon.Close();
  544. MessageBox.Show("Вход зарегистрирован!", "FaceTrack", MessageBoxButtons.OK, MessageBoxIcon.Information);
  545. }
  546. else
  547. {
  548. SCon.Open();
  549. string QueryCheckRecord = $@"set dateformat dmy
  550. select *
  551. from Visits
  552. where UsersID = '{CurrentUserID}' and [Date] = cast(GETDATE() as date) and TimeExit is null
  553. ";
  554. SqlCommand CmdCheck = new SqlCommand(QueryCheckRecord, SCon);
  555. SqlDataReader Res = CmdCheck.ExecuteReader();
  556. if (!Res.HasRows)
  557. {
  558. MessageBox.Show("Данный пользователь уже вышел!", "ImpulseVision", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
  559. SCon.Close();
  560. return;
  561. }
  562. SCon.Close();
  563. //!!! Выход пользователя, который не прошёл идентификацию не регистрируется
  564. SCon.Open();
  565. string QueryTimeExit = $@"update Visits
  566. set TimeExit = '{DateTime.Now.ToString("HH:mm:ss")}'
  567. where UsersID = '{CurrentUserID}' and [Date] = cast(GETDATE() as date)";
  568. SqlCommand Cmd = new SqlCommand(QueryTimeExit, SCon);
  569. Cmd.ExecuteNonQuery();
  570. SCon.Close();
  571. MessageBox.Show("Выход зарегистрирован!", "FaceTrack", MessageBoxButtons.OK, MessageBoxIcon.Information);
  572. }
  573. }
  574. private void BtnOut_Click(object sender, EventArgs e)
  575. {
  576. TypeOperation = 0;
  577. RegisterVisit(TypeOperation);
  578. }
  579. private void BtnJournal_Click(object sender, EventArgs e)
  580. {
  581. Task.Factory.StartNew(() =>
  582. {
  583. RecognizeOff();
  584. });
  585. GetInformationAboutVisiting();
  586. TabPages.SelectTab(2);
  587. }
  588. /// <summary>
  589. /// получение списка пользователей для журнала посещений
  590. /// </summary>
  591. private void GetInformationAboutVisiting()
  592. {
  593. DgbJournal.Rows.Clear();
  594. SCon.Open();
  595. string QueryGetVisits = $@"select UserID,Lastname +' '+Firstname+' '+Patronymic as FIO,(select MAX([Date])
  596. from Visits
  597. where UsersID = Users.UserID) as LastDateVisit
  598. from Users
  599. ";
  600. if(TbxSearch.Text.Trim() != string.Empty)
  601. {
  602. QueryGetVisits += $@" where Lastname +' '+Firstname+' '+Patronymic like '%{TbxSearch.Text.Trim()}%'";
  603. }
  604. SqlCommand CommandGetVisits = new SqlCommand(QueryGetVisits, SCon);
  605. SqlDataReader Res = CommandGetVisits.ExecuteReader();
  606. if(Res.HasRows)
  607. {
  608. string DateTemplate = string.Empty;
  609. while(Res.Read())
  610. {
  611. try
  612. {
  613. DateTemplate = DateTime.Parse(Res["LastDateVisit"].ToString()).ToString("dd.MM.yyyy");
  614. }
  615. catch(Exception ex)
  616. {
  617. DateTemplate = "нет";
  618. }
  619. DgbJournal.Rows.Add(Res["UserID"].ToString(), Res["FIO"].ToString(), DateTemplate);
  620. }
  621. }
  622. else
  623. {
  624. MessageBox.Show("Посещения пользователей отсутствуют!", "FaceTrack", MessageBoxButtons.OK, MessageBoxIcon.Error);
  625. SCon.Close();
  626. return;
  627. }
  628. SCon.Close();
  629. }
  630. private void DgbJournal_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
  631. {
  632. int RowIndex = e.RowIndex;
  633. int SelectedUserID = int.Parse(DgbJournal.Rows[RowIndex].Cells[0].Value.ToString());
  634. string SelectedUserName = DgbJournal.Rows[RowIndex].Cells[1].Value.ToString();
  635. FormVisiting FVisiting = new FormVisiting(SelectedUserID, SelectedUserName);
  636. this.Hide();
  637. FVisiting.ShowDialog();
  638. this.Show();
  639. }
  640. private void BtnSettings_Click(object sender, EventArgs e)
  641. {
  642. Task.Factory.StartNew(() =>
  643. {
  644. RecognizeOff();
  645. });
  646. GetCams();
  647. TabPages.SelectTab(3);
  648. }
  649. /// <summary>
  650. /// получение списка доступных камер
  651. /// </summary>
  652. private void GetCams()
  653. {
  654. WebCams = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice);
  655. CountCams = WebCams.Length;
  656. CmbCams.Items.Clear();
  657. for (int i = 0; i < CountCams; i++)
  658. {
  659. CmbCams.Items.Add(WebCams[i].Name);
  660. HtBefore.Add(WebCams[i].Name);
  661. }
  662. if (CountCams == 0)
  663. {
  664. MessageBox.Show("Камеры не обнаружены! Подключите камеру и перезапустите приложение.","FaceTrack",MessageBoxButtons.OK,MessageBoxIcon.Error);
  665. this.Close();
  666. }
  667. else
  668. {
  669. CmbCams.SelectedIndex = SelectedCameraID;
  670. }
  671. }
  672. /// <summary>
  673. /// обработка ситуации изменения количества подключённых камер
  674. /// </summary>
  675. private void CamsPreview()
  676. {
  677. DsDevice[] Cams = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice);
  678. int CountCams = Cams.Length;
  679. if(CountCams != HtBefore.Count)
  680. {
  681. GetCams();
  682. RecognizeOff();
  683. if (TabPages.SelectedIndex == 0)
  684. {
  685. BtnAddUser_Click(null, null);
  686. }
  687. else if (TabPages.SelectedIndex == 1)
  688. {
  689. BtnIdent_Click(null, null);
  690. }
  691. Application.Restart();
  692. }
  693. }
  694. private void PanelMenu_Paint(object sender, PaintEventArgs e)
  695. {
  696. Invalidate();
  697. }
  698. private void FormMain_FormClosing(object sender, FormClosingEventArgs e)
  699. {
  700. ApplyNewParameters();
  701. RecognizeOff();
  702. Application.ExitThread();
  703. }
  704. /// <summary>
  705. /// применение настроек для формы
  706. /// </summary>
  707. private void ApplyNewParameters()
  708. {
  709. LocalSettings LocalSet = new LocalSettings();
  710. LocalSet.SelectedCameraID = SelectedCameraID;
  711. if (CbxSaveLocationForm.Checked)
  712. {
  713. LocalSet.PositionLocationX = this.Location.X;
  714. LocalSet.PositionLocationY = this.Location.Y;
  715. }
  716. else
  717. {
  718. LocalSet.PositionLocationX = -1;
  719. LocalSet.PositionLocationY = -1;
  720. }
  721. if (CbxSaveSizeForm.Checked)
  722. {
  723. LocalSet.FormWidth = this.Width;
  724. LocalSet.FormHeight = this.Height;
  725. }
  726. else
  727. {
  728. LocalSet.FormWidth = -1;
  729. LocalSet.FormHeight = -1;
  730. }
  731. StreamWriter Sw = new StreamWriter(Application.StartupPath + "\\localSettings.txt");
  732. Sw.WriteLine(LocalSet.SelectedCameraID);
  733. Sw.WriteLine(LocalSet.FormWidth);
  734. Sw.WriteLine(LocalSet.FormHeight);
  735. Sw.WriteLine(LocalSet.PositionLocationX);
  736. Sw.WriteLine(LocalSet.PositionLocationY);
  737. Sw.Close();
  738. }
  739. /// <summary>
  740. /// получение ранее схранённых параметров формы
  741. /// </summary>
  742. private void SetFormParameters()
  743. {
  744. if (!File.Exists(Application.StartupPath + "\\localSettings.txt"))
  745. {
  746. return;
  747. }
  748. StreamReader Sr = new StreamReader(Application.StartupPath + "\\localSettings.txt");
  749. LocalSettings CurrentSettings = new LocalSettings();
  750. CurrentSettings.SelectedCameraID = int.Parse(Sr.ReadLine());
  751. CurrentSettings.FormWidth = int.Parse(Sr.ReadLine());
  752. CurrentSettings.FormHeight = int.Parse(Sr.ReadLine());
  753. CurrentSettings.PositionLocationX = int.Parse(Sr.ReadLine());
  754. CurrentSettings.PositionLocationY = int.Parse(Sr.ReadLine());
  755. Sr.Close();
  756. CbxSaveLocationForm.Checked = false;
  757. CbxSaveSizeForm.Checked = false;
  758. SelectedCameraID = CurrentSettings.SelectedCameraID;
  759. try
  760. {
  761. CmbCams.SelectedIndex = SelectedCameraID;
  762. }
  763. catch
  764. {
  765. SelectedCameraID = 0;
  766. }
  767. if (CurrentSettings.FormWidth != -1 && CurrentSettings.FormHeight != -1)
  768. {
  769. CbxSaveSizeForm.Checked = true;
  770. this.Size = new Size(CurrentSettings.FormWidth, CurrentSettings.FormHeight);
  771. }
  772. if (CurrentSettings.PositionLocationX != -1 && CurrentSettings.PositionLocationY != -1)
  773. {
  774. CbxSaveLocationForm.Checked = true;
  775. this.Location = new Point(CurrentSettings.PositionLocationX, CurrentSettings.PositionLocationY);
  776. }
  777. }
  778. private void CmbCams_SelectedIndexChanged(object sender, EventArgs e)
  779. {
  780. SelectedCameraID = CmbCams.SelectedIndex;
  781. }
  782. private void BtnSaveParameters_Click(object sender, EventArgs e)
  783. {
  784. ApplyNewParameters();
  785. MessageBox.Show("Выбранные параметры успешно применены!", "FaceTrack", MessageBoxButtons.OK, MessageBoxIcon.Information);
  786. }
  787. private void TbxSearch_TextChanged(object sender, EventArgs e)
  788. {
  789. GetInformationAboutVisiting();
  790. }
  791. private void TimerCamsControl_Tick(object sender, EventArgs e)
  792. {
  793. CamsPreview();
  794. }
  795. private void LblLinkHelp_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
  796. {
  797. if (!File.Exists(Application.StartupPath + "\\Source\\help.chm"))
  798. {
  799. MessageBox.Show("В данный момент времени справочная система приложения недоступна!", "Внимание!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
  800. return;
  801. }
  802. System.Diagnostics.Process.Start(Application.StartupPath + "\\Source\\help.chm");
  803. }
  804. private void label6_Click(object sender, EventArgs e)
  805. {
  806. }
  807. private void label8_Click(object sender, EventArgs e)
  808. {
  809. }
  810. private void label9_Click(object sender, EventArgs e)
  811. {
  812. }
  813. private void label10_Click(object sender, EventArgs e)
  814. {
  815. }
  816. }
  817. }