Advertisement
hataketsu

main

Sep 23rd, 2018
164
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 12.24 KB | None | 0 0
  1. /*
  2.  * Created by SharpDevelop.
  3.  * User: Worker
  4.  * Date: 8/9/2018
  5.  * Time: 9:45 AM
  6.  *
  7.  * To change this template use Tools | Options | Coding | Edit Standard Headers.
  8.  */
  9. using System;
  10. using System.Collections.Generic;
  11. using System.Diagnostics;
  12. using System.Drawing;
  13. using System.IO.Ports;
  14. using System.Windows.Forms;
  15. using Emgu.CV;
  16. using Emgu.CV.CvEnum;
  17. using Emgu.CV.Face;
  18. using Emgu.CV.Structure;
  19. using Emgu.CV.UI;
  20. using System.IO;
  21. using Emgu.CV.Util;
  22. namespace FaceUnlocker
  23. {
  24.    
  25.     public partial class MainForm : Form
  26.     {
  27.         Mat frame = new Mat();
  28.         //lưu các khung hình nhận được từ camera
  29.         VideoCapture capture;
  30.         //đối tượng ghi hình từ camera
  31.         private object lockObject = new object();
  32.         Mat faceOnly = null;
  33.         //lưu hình ảnh khuôn mặt
  34.         Mat capturedFace = null;
  35.         //lưu hình huôn mặt ghi lại
  36.         CascadeClassifier faceDetetor;
  37.         //đối tượng phát hiện khuôn mặt
  38.         EigenFaceRecognizer recog = new EigenFaceRecognizer();
  39.         //đối tượng nhận diện khuôn mặt
  40.        
  41.         const String PASSWORD_FILE = "password.txt";
  42.         //file lưu mật khẩu
  43.         const String RECOG_FILE = "face.xml";
  44.         //file lưu dữ liệu các khuôn mặt đã huấn luyện
  45.         const String FACE_DIR = "./faces/";
  46.         //thư mục lưu các khuô mặt
  47.         const String ALLOWED_FILE = "./allowed.txt";
  48.         //file lưu những người mở được cửa
  49.         Boolean isTraining = true;
  50.         //trạng thái đang huấn luyện hay không
  51.         String password = "123456";
  52.         //mật khuẩ mặc định
  53.         Dictionary<int,string> labelToName = new Dictionary<int, string>();
  54.         //ánh xạ từ nhãn sang tên
  55.         long checkFaceStartTime = -1;
  56.         //lần cuối cùng kiểm
  57.         int failed = 0;
  58.         //số lần mở cửa thất bại
  59.         String[] allAllowed;
  60.         //tên người mở được cửa
  61.         int openThreshold = 0;
  62.         public MainForm() //hàm khởi đầu chương trình
  63.         {
  64.             InitializeComponent();
  65.             capture = new Emgu.CV.VideoCapture(); //kết nối camera
  66.             capture.ImageGrabbed += ProcessFrame; //lắng nghe mỗi khi có hình ảnh từ camera
  67.             capture.Start(); //bắt đầu ghi hình
  68.            
  69.             faceDetetor = new CascadeClassifier("lbpcascade_frontalface_improved.xml"); //đọc file phát hiện khuôn mặt
  70.             foreach (var port in SerialPort.GetPortNames()) { //lấy danh sách cổng Serial
  71.                 portsBox.Items.Add(port); //thêm vào danh sách chọn
  72.                 portsBox.Text = port;
  73.             }
  74.             serialPort1.DataReceived += port_DataReceived; //lắng nghe dữ liệu từ cổng serial
  75.             if (File.Exists(PASSWORD_FILE)) //đọc mật khẩu cũ nếu có
  76.                 password = File.ReadAllText(PASSWORD_FILE);
  77.             if (File.Exists(RECOG_FILE)) { //đọc dữ leiu65 huấn luyện nếu có
  78.                 recog.Read(RECOG_FILE);
  79.                 print("Read recog file.");
  80.             }
  81.             readAllowed(); //đọc danh sách cho phép mở cửa
  82.             reloadData(); //đọc lại dữ liệu khuôn mặt
  83.         }
  84.  
  85.         void readAllowed()
  86.         {
  87.             if (File.Exists(ALLOWED_FILE)) { //đọc danh sách mở cửa nếu có
  88.                 var text = File.ReadAllText(ALLOWED_FILE);
  89.                 allowedUsers.Text = text;
  90.             }
  91.             loadAllow();
  92.         }
  93.  
  94.         void ProcessFrame(object sender, EventArgs e) //xử lý các khung hình từ camera
  95.         {
  96.            
  97.             if (isTraining) //nếu đang huấn luyện thì không xử lý
  98.                 return;
  99.             var shouldOpen = false; //không mở cửa
  100.             capture.Retrieve(frame);      //đọc khung hình từ camera
  101.             using (var gray = new Mat()) {
  102.                 CvInvoke.CvtColor(frame, gray, ColorConversion.Bgr2Gray); //chuyển hình ảnh thành màu xám
  103.                 var faces = faceDetetor.DetectMultiScale(gray); //tìm các khuôn mặt
  104.                 foreach (var face in faces) { //duyệt qua danh sách các khuôn mặt
  105.                     CvInvoke.Rectangle(gray, face, new MCvScalar(255, 0, 255)); //vẽ hình chữ nhật quanh khuôn mặt đã phát hiện
  106.                     faceOnly = new Mat(gray, face);//lưu khuôn mặt ra đối tượng riêng
  107.                     faceOnly = faceOnly.Clone();
  108.                     CvInvoke.Resize(faceOnly, faceOnly, new Size(160, 160)); //co giãn về kích cỡ chuẩn 160x160
  109.                     var result = recog.Predict(faceOnly); //thử dự đoán khuôn mặt
  110.                     var label = result.Label; //nhãn của khuôn mặt nhận diện được
  111.                     if (label != -1) {  //nếu nhận ra người đó
  112.                         var name = labelToName[label].Trim(); //lấy ra tên người đó
  113.                         if (Array.IndexOf(allAllowed, name) != -1) { //nếu trong danh sách mở cửa
  114.                             shouldOpen = true; //có thể mở cửa
  115.                         }
  116.                         CvInvoke.PutText(gray, name + ":" + Math.Ceiling(result.Distance), face.Location, FontFace.HersheyPlain, 1, new MCvScalar(255, 0, 255));
  117.                     } else
  118.                         CvInvoke.PutText(gray, "Người lạ", face.Location, FontFace.HersheyPlain, 1, new MCvScalar(255, 0, 255));
  119.                 }
  120.                
  121.                 try {
  122.                     pictureBox1.Image = gray.Bitmap; //hiển thị hình ảnh camera
  123.                 } catch {
  124.                 }
  125.             }
  126.             if (checkFaceStartTime != -1) { //nếu đang kiểm tra khuôn mặt
  127.                 var now = getCurrentSecond(); //lấy thời gian hiện tại
  128.                 if (now - checkFaceStartTime > 5) { //nếu quá 5s
  129.                     checkFaceStartTime = -1; //hủy kiểm tra khuôn mặt
  130.                     failed++; //cộng số lần thất bại
  131.                     if (failed >= 5) { //nếu thất bại quá 5 lần
  132.                         sendToArduino("alert=5;"); //báo động arduino
  133.                     }
  134.                     print("Face checking failed!");
  135.                 } else { //chưa quá 5s
  136.                     if (shouldOpen) { //nếu có thể mở
  137.                         openThreshold++; //cộng dồn
  138.                         if (openThreshold > 10) { //nếu đủ 10 lần kiểm tra thành công trong 5s
  139.                             checkFaceStartTime = -1;  //hủy kiểm tra khuôn mặt
  140.                             failed = 0; //reset số lần thất bại
  141.                             openThreshold = 0; //reset
  142.                             print("Face checking success!!");
  143.                             sendToArduino("door=open;echo=Unlocked by face;"); //mở cửa arduino
  144.                         }
  145.                     }
  146.                 }
  147.                 tries.Invoke((MethodInvoker)delegate {
  148.                     tries.Text = "Đã thử nhận diện: " + failed + " lần"; //hiển thị số lần thất bại
  149.                 });
  150.             }
  151.            
  152.         }
  153.        
  154.         long getCurrentSecond() //lấy thời gian hiện tại
  155.         {
  156.             return (long)(Math.Ceiling((double)DateTime.Now.ToFileTime() / 10000000));
  157.         }
  158.        
  159.         void MainFormLoad(object sender, EventArgs e)
  160.         {
  161.             print("ok");
  162.         }
  163.        
  164.         void ChangePasswordClick(object sender, EventArgs e) //sự kiện đồi mật khẩu
  165.         {
  166.             var newPWForm = new NewPassword(); //gọi form đổi mật khẩu
  167.             newPWForm.ShowDialog(); //hiển thị form
  168.             if (newPWForm.DialogResult == DialogResult.OK) { //nếu bấm ok
  169.                 password = newPWForm.getPassword(); //lấy mật khẩu mới
  170.                 File.WriteAllText(PASSWORD_FILE, password); //lưu lại
  171.                 MessageBox.Show("Đã lưu mật khẩu mới!");//thông báo thành công
  172.             } else {
  173.                 MessageBox.Show("Mật khẩu không hợp lệ!");
  174.             }
  175.         }
  176.         void ConnectClick(object sender, EventArgs e) //bấm nút kết nối arduino
  177.         {
  178.             if (serialPort1.IsOpen) { //nếu cổng đã mở
  179.                 serialPort1.Close(); //đóng cổng
  180.                 connect.Text = "Kết nối";
  181.             } else {
  182.                 connect.Text = "Ngắt kết nối";
  183.                 serialPort1.PortName = "" + portsBox.SelectedItem;
  184.                 serialPort1.Open(); //mở cổng
  185.             }
  186.         }
  187.        
  188.         private void port_DataReceived(object sender, SerialDataReceivedEventArgs e) //dữ liệu từ arduino tới
  189.         {
  190.             while (serialPort1.BytesToRead > 0) { //nếu có dữ liệu
  191.                 var command = serialPort1.ReadTo("="); //đọc lệnh
  192.                 var value = serialPort1.ReadTo(";");//đọc giá trị của lệnh
  193.                 print("Receive: " + command + "=" + value);
  194.                 if (command.Equals("password")) { //lệnh kiểm tra mật khẩu
  195.                     if (value.Equals(password)) { //mật khuẩ đúng
  196.                         sendToArduino("door=open;"); //mở cửa
  197.                         sendToArduino("echo=   Unlocked!!   ;");
  198.                     } else {
  199.                         sendToArduino("door=close;"); //đóng cửa
  200.                         sendToArduino("echo=  Password is     incorrect!!  ;");
  201.                     }
  202.                 } else if (command.Equals("check") & value.Equals("face")) { //lệnh kiểm tra khuôn mặt
  203.                     startCheckingFace(); //bắt đầu kiểm tra khuôn mặt
  204.                 }
  205.             }
  206.         }
  207.         void startCheckingFace()
  208.         {
  209.             checkFaceStartTime = getCurrentSecond(); //bắt đầu kiểm tra từ thời điểm này
  210.             print("Start checking face");
  211.             openThreshold = 0;
  212.         }
  213.         void print(String s)
  214.         {
  215.             System.Diagnostics.Debug.WriteLine(s);
  216.         }
  217.         void sendToArduino(String s) //lệnh gửi dữ liệu tới arduino
  218.         {
  219.             if (serialPort1.IsOpen) { //nếu cỗng mở
  220.                 serialPort1.Write(s); //thì gửi
  221.                 print("Sent command: " + s);
  222.             } else {
  223.                 print("Serial is not opened yet"); //báo lỗi
  224.             }
  225.         }
  226.         void AddImageClick(object sender, EventArgs e) //thêm ảnh vào thư viện
  227.         {
  228.            
  229.             var userName = currentUser.Text.Trim(); //lấy tên người hiện tại
  230.             if (userName.Length > 0) {  //nếu tên không rỗng
  231.                 if (capturedFace != null) { //nếu đã chụp được khuôn mặt
  232.                     Directory.CreateDirectory(FACE_DIR + "/" + userName); //tại thư mục cho người đó
  233.                     print("Add new image to " + userName); 
  234.                     CvInvoke.Imwrite(FACE_DIR + "/" + userName + "/" + DateTime.Now.ToFileTime() + ".jpg", capturedFace); //lưu ảnh vào đó
  235.                 } else
  236.                     MessageBox.Show("Chưa có hình ảnh!");
  237.             } else
  238.                 MessageBox.Show("Chưa có tên!");
  239.         }
  240.        
  241.         void OpenDoorClick(object sender, EventArgs e) //bấm nút mỡ cửa
  242.         {
  243.             sendToArduino("door=open;");
  244.         }
  245.        
  246.         void CloseDoorClick(object sender, EventArgs e) //bấm nút đóng cửa
  247.         {
  248.             sendToArduino("door=close;");
  249.         }
  250.        
  251.         void retrain() //huấn luyện lại dữ liệu
  252.         {
  253.             isTraining = true;
  254.             MessageBox.Show("Start retraining");
  255.             recog = new EigenFaceRecognizer(30, 5000); //tạo đối tượng nhận diện với 30 đặc trưng và ngưỡng nhận diện là 5000
  256.             var imgs = new VectorOfMat();
  257.             var labels = new VectorOfInt();
  258.             var count = 1; //biến đếm nhãn
  259.             labelToName.Clear();
  260.             foreach (var userPath in Directory.GetDirectories(FACE_DIR)) { //duyệt qua danh sách thư mục trong /faces
  261.                 var userName = Path.GetFileName(userPath).Trim(); //lấy tên thư mục, chính là tên người
  262.                 foreach (var file in Directory.GetFiles(userPath)) { //lấy danh sách file trong đó
  263.                     var img = CvInvoke.Imread(file, ImreadModes.Grayscale); //đọc hình ảnh
  264.                     imgs.Push(img); //cho vào danh sách huấn luyện
  265.                     labels.Push(new []{ count }); //gán nhãn
  266.                 }
  267.                 labelToName.Add(count, userName); //thêm vào danh sách ánh xạ nhãn tới tên
  268.                 count++; //tăng biến đếm nhãn
  269.             }
  270.             try {
  271.                 recog.Train(imgs, labels); //huấn luyện
  272.                 recog.Write(RECOG_FILE); //lưu file huấn luyện
  273.             } catch {
  274.             }
  275.             isTraining = false;
  276.             MessageBox.Show("Done retraining");
  277.         }
  278.        
  279.         void Button1Click(object sender, EventArgs e) //chụp hình ảnh
  280.         {
  281.             if (faceOnly != null)
  282.                 try {
  283.                     pictureBox2.Image = faceOnly.Bitmap;
  284.                     capturedFace = faceOnly;
  285.                 } catch {
  286.                 }
  287.         }
  288.         void GroupBox2Enter(object sender, EventArgs e)
  289.         {
  290.    
  291.         }
  292.         void Button2Click(object sender, EventArgs e)
  293.         {
  294.             sendToArduino("alert=5;");
  295.         }
  296.         void ComboBox1SelectedIndexChanged(object sender, EventArgs e)
  297.         {
  298.    
  299.         }
  300.  
  301.         void reloadData()
  302.         {
  303.             currentUser.Items.Clear();
  304.             if (Directory.Exists(FACE_DIR)) {
  305.                 foreach (var user in Directory.GetDirectories(FACE_DIR)) { //đọc danh sách người có trong thư mục faces
  306.                     print(user);
  307.                     var userName = Path.GetFileName(user);
  308.                     currentUser.Items.Add(userName);
  309.                     currentUser.Text = userName;
  310.                 }
  311.             } else {
  312.                 MessageBox.Show("Không có dữ liệu!");
  313.             }
  314.             retrain();
  315.            
  316.         }
  317.        
  318.         void saveData()
  319.         {
  320.             File.WriteAllText(ALLOWED_FILE, allowedUsers.Text);
  321.         }
  322.  
  323.         void RefreshButtonClick(object sender, EventArgs e)
  324.         {
  325.             reloadData();
  326.             saveData();
  327.         }
  328.         void TextBox1TextChanged(object sender, EventArgs e)
  329.         {
  330.    
  331.         }
  332.         void CheckFaceClick(object sender, EventArgs e)
  333.         {
  334.             startCheckingFace();
  335.         }
  336.        
  337.         void loadAllow()
  338.         {
  339.             allAllowed = allowedUsers.Text.Split(',');
  340.             for (int i = 0; i < allAllowed.Length; i++) {
  341.                 allAllowed[i] = allAllowed[i].Trim();
  342.             }
  343.         }
  344.         void AllowedUsersTextChanged(object sender, EventArgs e)
  345.         {
  346.            
  347.             loadAllow();
  348.         }
  349.     }
  350. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement