Спонсор: Intel
Опубликован: 23.08.2014 | Уровень: для всех | Доступ: платный | ВУЗ: Северный (Арктический) федеральный университет им. М.В. Ломоносова
Лабораторная работа 2:

Интеграция возможностей модулей Intel Perceptual Computing SDK для реализации многоуровневой системы информационной безопасности, основанной на биометрической информации

< Лекция 4 || Лабораторная работа 2: 123 || Лекция 5 >

Реализация метода распознавания лица. Создание модели лица. Идентификация

При создании нового пользователя необходимо сделать несколько исходных моделей пользователя, с которыми будет происходить последующее сравнение при процессе авторизации. Для этого потребуется вызвать форму с модулем распознавания лица из нашего меню при нажатии кнопки button3 ("Добавить изображение").

private void button3_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrWhiteSpace(textBox1.Text)) //имя пользователя не задано
            {
                MessageBox.Show("Введите имя пользователя");
                return;
            }
 
            username = textBox1.Text;
            PXCMSession session;
            pxcmStatus sts = PXCMSession.CreateInstance(out session); //создаем сессию
            if (sts >= pxcmStatus.PXCM_STATUS_NO_ERROR) 
            {
                MainForm ft = new MainForm(session, username); //создаем форму
                ft.Show();        // вызываем форму
                session.Dispose();//удаляем сессию
            }
        }
    

Также необходимо добавить глобальные переменные для имени пользователя, режима запуска формы( создание нового пользователя или идентификации) и изменить конструктор формы MainForm в MainForm.cs:

private string username; 
private int mode; // 1 - режим создание пользователя , 2 - режим идентификации
public MainForm(PXCMSession session,string  username)        {
            InitializeComponent();
            this.session = session;
            this.username = username;
            this.mode = 1; // режим создания пользователя
            PopulateDeviceMenu();  //получить список камер
            PopulateModuleMenu();           
            button1.Show();            

            FormClosing += new FormClosingEventHandler(MainForm_FormClosing);
            Panel2.Paint += new PaintEventHandler(Panel_Paint);
        }
    

Добавим на форму MainForm еще одну кнопку button1 (назовем ее "сделать снимок"), при нажатии на которую будет браться текущее изображение с камеры и создаваться модель лица человека.

Реализуем метод создания модели лица человека на основе метода AdvancedPipeline в FaceTracking.cs создадим функцию CreatePerson(), тело функции скопируем из метода AdvancedPipeline и изменим некоторые части кода.

До:

/* Display Results */
DisplayPicture(capture.QueryImage(images,PXCMImage.ImageType.IMAGE_TYPE_COLOR)); DisplayLocation(face);
form.UpdatePanel();
    

После:

/* Display Results */
if (form.create_model_triger == true) 
{
 DisplayPicture(capture.QueryImage(images, PXCMImage.ImageType.IMAGE_TYPE_COLOR));
 DisplayLocation(face, 2);//вывести лицо и сделать модель лица человека из текущего кадра
 form.create_model_triger = false;
}
else
{
 DisplayPicture(capture.QueryImage(images, PXCMImage.ImageType.IMAGE_TYPE_COLOR));
 DisplayLocation(face, 1); //вывести лицо
}
form.UpdatePanel();
    

public volatile bool create_model_triger = false; - глобальная переменная в MainForm.cs, которая необходимо чтобы сделать модель лица человека в нужный момент.

Изменим функцию DispayLocation(). Во-первых, добавим в нее атрибут int mode, а тело изменим следующим образом.

До:

private void DisplayLocation(PXCMFaceAnalysis ft) {
for (uint i=0;;i++) {
   int fid; ulong ts;
   if (ft.QueryFace(i, out fid, out ts) < pxcmStatus.PXCM_STATUS_NO_ERROR) break;

   /* Retrieve face location data */
   PXCMFaceAnalysis.Detection ftd = ft.DynamicCast<PXCMFaceAnalysis.Detection>(PXCMFaceAnalysis.Detection.CUID);
   PXCMFaceAnalysis.Detection.Data ddata;
   if (ftd.QueryData(fid, out ddata) >= pxcmStatus.PXCM_STATUS_NO_ERROR)
      form.DrawLocation(ddata);              
   }
}
    

После:

private void DisplayLocation(PXCMFaceAnalysis ft, int mode)// mode = 1 вывод, 2 - вывод и //создание
        {
            for (uint i=0;;i++) {
            int fid; ulong ts;
            if (ft.QueryFace(i, out fid, out ts) < pxcmStatus.PXCM_STATUS_NO_ERROR) break;

            /* Retrieve face location data */
            PXCMFaceAnalysis.Detection ftd = ft.DynamicCast<PXCMFaceAnalysis.Detection>(PXCMFaceAnalysis.Detection.CUID);
            PXCMFaceAnalysis.Detection.Data ddata;

            if (mode == 2)
            {                
                /* Создание и настройка модуля распознавания лиц */
                PXCMFaceAnalysis.Recognition ftr = ft.DynamicCast<PXCMFaceAnalysis.Recognition>(PXCMFaceAnalysis.Recognition.CUID);
                PXCMFaceAnalysis.Recognition.ProfileInfo rec_pinfo;
                ftr.QueryProfile(0,out rec_pinfo);
                PXCMFaceAnalysis.Recognition.Model modelCurr; // иницилизация модели
                pxcmStatus sts = ftr.CreateModel(fid, out modelCurr); //создание модели

                if (sts < pxcmStatus.PXCM_STATUS_NO_ERROR)
                    break;     
 
                byte[] temp = new byte[rec_pinfo.modelSize];
                /* Нахождение строки источника данных БД для подключения, указываем ту, что появилась при создании БД.
Альтернативно можно прописать абсолютный путь к БД, например:
conString = @"Data Source=C:\Users\1\Desktop\intel perceptual computing sdk\practice 2\MyDB1.sdf"; */
                string conString = practice_2.cs.Properties.Settings.Default.MyDatabase_1ConnectionString;

                using (SqlCeConnection con = new SqlCeConnection(conString))
                {
                    con.Open(); //открываем подключение
                    sts = modelCurr.Serialize(temp); // преобразуем модель в массив //байтов
                    //string name = "Пользователь 1";
                    string name = form.getUsername(); // получаем имя пользователя
                    var rowId = new SqlCeCommand("SELECT TOP(1) id FROM models ORDER BY id DESC", con).ExecuteScalar();// выберем максимальный Id в таблице
                    using (SqlCeCommand com = new SqlCeCommand("INSERT INTO models VALUES(@id,@name,@image)", con))
                    {
                        int newid = Convert.ToInt32(rowId) + 1; 
                        //int newid = 1;
                        com.Parameters.AddWithValue("@id", newid);
                        com.Parameters.AddWithValue("@name", name);
                        com.Parameters.AddWithValue("@image", temp);
                        com.ExecuteNonQuery(); // выполняем запрос
                    } 
                }
            }
            if (ftd.QueryData(fid, out ddata) >= pxcmStatus.PXCM_STATUS_NO_ERROR)
                    form.DrawLocation(ddata); // отрисовываем лицо          
        }
}
    
Листинг .

Осталось добавить в MainForm.cs функцию получения имени пользователя getUsername и изменить в функции DoTracking строчку ft.AdvancedPipeline() на ft.CreatePerson() и обработать событие о нажатии на кнопку button1.

public string getUsername()
        {
            return this.username;
        }
private void button1_Click(object sender, EventArgs e)
        {
            create_model_triger = true;
        }
    

Теперь можно попробовать создать модель, убедиться, что она появилась можно, выбрав пункт меню "Показать таблицу данных" у таблицы в Обозревателе серверов. Чем больше моделей сделает пользователь, тем больше вероятность, что модуль распознавания его идентифицирует.

Создадим новую форму Form1.cs, которая будет открываться при нажатии на кнопку "Авторизоваться" формы mainmenu. Добавим на нее 2 textBox и 3 кнопки:

Форма авторизации Form1

Рис. 4.8. Форма авторизации Form1

Обработаем нажатие кнопки "Авторизоваться" button2 формы mainmenu:

private void button2_Click(object sender, EventArgs e)
        {
            Form1 f1 = new Form1(this);
            f1.Show();

        }
    

Тогда конструктор формы Form1 будет выглядеть следующим образом:

public Form1(mainmenu mainmenu1)
        {
            InitializeComponent();
            this.mm1 = mainmenu1;
        }
    

Объявим все глобальные переменные, которые понадобятся:

mainmenu mm1;
private string username = "Guest";
private string nameFromFaceRegognition;
private string wordFromVoiceRegognition;
private string password;
    

Обработаем событие нажатия на кнопку "Идентификация лица" button1 формы Form1, так чтобы при нажатии запускалась форма MainForm в режиме идентификации:

private void button1_Click(object sender, EventArgs e)
        {           
           PXCMSession session;
           pxcmStatus sts = PXCMSession.CreateInstance(out session);
           if (sts >= pxcmStatus.PXCM_STATUS_NO_ERROR)
           {
               MainForm ft = new MainForm(session,this); //создаем форму
               ft.Show();//вызываем форму
               session.Dispose();
           }
           
        }
    

Для этого потребуется определить дополнительный конструктор формы в MainForm.cs:

public MainForm(PXCMSession session, Form1 f1)
        {
            InitializeComponent();
            this.f1 = f1;  
            this.session = session;
            this.mode = 2; // режим идентификации
            PopulateDeviceMenu();
            PopulateModuleMenu();
            button1.Hide(); 
            FormClosing += new FormClosingEventHandler(MainForm_FormClosing);
            Panel2.Paint += new PaintEventHandler(Panel_Paint);

        }
    

button1.Hide() необходим, чтобы пользователь не мог создавать модели во время авторизации. Снова изменим фрагмент функцию DoTracking.

До: После:
ft.CreatePerson();
        
if (mode == 1)
            {
                ft.CreatePerson();
            }
else
            {
                ft.StartRecognition();
            }
        

Функция StartRecognition похожа на CreatePerson. CreatePerson выводит изображение с камеры, отслеживая лица в кадре, но в момент нажатия кнопки делает модель лица в текущем кадре и сохраняет его в базу данных. StartRecognition различается тем, что в начале забирает данные из базы данных, собирает список всех моделей, а затем выводит изображение с камеры, отслеживая лица в кадре, но в тоже время сравнивает их со списком всех моделей. При уровне совпадения больше заданного функция сообщает, что пользователь идентифицирован.

public void StartRecognition() {
...//объявляются переменные, точно также как в CreatePerson
PXCMFaceAnalysis.Recognition facer = face.DynamicCast<PXCMFaceAnalysis.Recognition>(PXCMFaceAnalysis.Recognition.CUID);
            PXCMFaceAnalysis.Recognition.ProfileInfo rec_pinfo;
            facer.QueryProfile(0, out rec_pinfo);
            facer.SetProfile(ref rec_pinfo);
form.UpdateStatus("Streaming");
            PXCMImage[] images = new PXCMImage[PXCMCapture.VideoStream.STREAM_LIMIT];
            PXCMScheduler.SyncPoint[] sps = new PXCMScheduler.SyncPoint[2];
            
            getListModel(face);  //получаем список моделей из БД      
            while (!form.stop)
            {
                      ...// точно также как в CreatePerson
            /* Display Results */
DisplayPicture(capture.QueryImage(images, PXCMImage.ImageType.IMAGE_TYPE_COLOR)); //вывод //изображения

                for (uint i = 0; ; i++) //для каждого найденного лица
                {
                    int fid; ulong ts;
                    if (face.QueryFace(i, out fid, out ts) < pxcmStatus.PXCM_STATUS_NO_ERROR) break; //если больше лиц не найдено, то выйти

                    /* Retrieve face location data */
                    PXCMFaceAnalysis.Detection ftd = face.DynamicCast<PXCMFaceAnalysis.Detection>(PXCMFaceAnalysis.Detection.CUID);
                    PXCMFaceAnalysis.Detection.Data ddata;
                   
                    PXCMFaceAnalysis.Recognition.Model modelCurr;
                    sts = facer.CreateModel(fid, out modelCurr); // создаем модель для //найденного лица
                    if (sts < pxcmStatus.PXCM_STATUS_NO_ERROR)
                        break;

                    int modelnumber = models.Count; //количество моделей
                    uint index;                  
                    Single[] scores = new Single[modelnumber]; // массив сходства моделей
                    sts = modelCurr.Compare(models.ToArray(), scores, out index); //сравниваем текущую модель со всеми моделями из списка, index - номер самой похожей
                    if (sts == pxcmStatus.PXCM_STATUS_NO_ERROR || sts == pxcmStatus.PXCM_STATUS_ITEM_UNAVAILABLE) 
                    {
                        if (scores[(int)index] > 0.99) //если сходство больше чем 99%
                        {                           
                            form.UpdateStatus("Пользователь "+namemodels[(int)index]+" идентифицирован"); // выводим сообщение о идентификации пользователя
                            if (ftd.QueryData(fid, out ddata) >= pxcmStatus.PXCM_STATUS_NO_ERROR)
                                form.DrawLocation(ddata); //выводим лицо
                        }
                    }
                }
                form.UpdatePanel();
            }
    
Листинг .

Подробнее остановимся на функции Compare. Ее можно использовать в нескольких видах:

pxcmStatus Compare(Model[] models, Single[] scores, out index);
pxcmStatus Compare(Model[] models, out index);
    

где models - массив моделей, scores - массив сходства моделей, он заполнится автоматически при выполнении функции, где scores[i] будет указывать на сходство текущей и i-ой модели, index - индекс наиболее похожей модели.

Осталось получить список всех моделей, то есть определить функцию getListModel:

List<PXCMFaceAnalysis.Recognition.Model> models = new List<PXCMFaceAnalysis.Recognition.Model>(); //коллекция моделей
       List<string> namemodels = new List<string>(); //коллекция имен пользователей, на // которые указывают модели
       
       public void getListModel(PXCMFaceAnalysis ft) //получение списка моделей
       {

           PXCMFaceAnalysis.Recognition facer = ft.DynamicCast<PXCMFaceAnalysis.Recognition>(PXCMFaceAnalysis.Recognition.CUID);
           PXCMFaceAnalysis.Recognition.ProfileInfo rec_pinfo;            
           facer.QueryProfile(out rec_pinfo);
           //facer.SetProfile(ref rec_pinfo);

           PXCMFaceAnalysis.Recognition.Model m;
           byte[] temp = new byte[rec_pinfo.modelSize];

            
               /* Нахождение строки источника данных БД для подключения, указываем ту, что появилась при создании БД.
Альтернативно можно прописать абсолютный путь к БД, например:
conString = @"Data Source=C:\Users\1\Desktop\intel perceptual computing sdk\practice 2\MyDB1.sdf"; */

        string conString = practice_2.cs.Properties.Settings.Default.MyDatabase_1ConnectionString;
        using (SqlCeConnection con = new SqlCeConnection(conString))
        {
            con.Open();//открываем подключение                
            using (SqlCeCommand com = new SqlCeCommand("SELECT name,buffer FROM models ORDER BY id DESC", con)) // 
            выбираем массив байтов модели и имя пользователя
            {
                SqlCeDataReader reader = com.ExecuteReader();
                while (reader.Read())
                {
                    string face_name = reader.GetString(0); //получить первый столбец //текущей строкий
                    reader.GetBytes(1, 0, temp, 0, (int)rec_pinfo.modelSize); //получить второй столбец текущей строки = в temp 
                    получаем считываемый массив байтов //модели
                    facer.DeserializeModel(temp, out m); //собираем модель из массива //байтов 
                    models.Add(m);
                    namemodels.Add(face_name);
                }
            }
        }

    }
    

Теперь после распознавания человека в статусной строке будет появляться надпись пользователь "имя пользователя" идентифицирован, изменим функцию обработчик кнопки Stop для того чтобы зафиксировать результат.

private void Stop_Click(object sender, EventArgs e)
        {
            if (mode == 2) //если режим идентификации
            {
                if (StatusLabel.Text.StartsWith("Пользователь") 
                && StatusLabel.Text.EndsWith("идентифицирован")) // пользователь идентифицирован
                {
                    int namelength = StatusLabel.Text.Length - 29;
                    username = StatusLabel.Text.Substring(13,namelength);
                    f1.UpdateDataFromFaceRecognition(username); //вернуть имя на форму f1
                }
            }
            stop = true;
            closing = true;
        }
    

Функция UpdateDataFromFaceRecognition просто запоминает имя пользователя:

public void UpdateDataFromFaceRecognition(string newUserName)
        {
            nameFromFaceRegognition = newUserName;
        }
    
< Лекция 4 || Лабораторная работа 2: 123 || Лекция 5 >
Дмитрий Юнушкин
Дмитрий Юнушкин

В лабораторной работе №2 (идентификация лица) сказано:

в FaceTracking.cs: удалим или закомментируем функцию SimplePipelineкласс MyUtilMPipeline и изменим функцию AdvancedPipeline...

Класса MyUtilMPipeline  нет в проекте вообще;

Функции AdvancedPipeline так же нет. Материалов к лабораторной  №2 в начале работы (по ссылке открывается та же страница) тоже нет.Это ошибки или используется другая версия примера?

Анатолий Федоров
Анатолий Федоров
Россия, Москва, Московский государственный университет им. М. В. Ломоносова, 1989
Дмитрий Юнушкин
Дмитрий Юнушкин
Россия, г. Пенза