Загрузка...

Помощь с распознаванием лица

Тема в разделе C# создана пользователем zerro5 23 апр 2024. (поднята 25 апр 2024) 302 просмотра

  1. zerro5
    zerro5 Автор темы 23 апр 2024 4 14 июн 2019
    Как убрать имя в поле "Распознанные лица", когда 1 лицо добавлено и распознается, а 2 лицо не добавлено и тоже распознается как первое лицо?
    Получается у меня первое лицо добавлено - Face1, второе не добавлено и распознается, как Face1, а должно не распознаваться по имени, просто рамка вокруг лица должна быть.
    [IMG]

    [IMG]
    Также не понимаю почему после удаления лица в поле "Распознанные лица" остается имя распознанного лица. Получается я удаляю Face1, а имя остается.
    Это в кнопках "Удалить лицо" и "Удалить базу"
    [IMG]
    CSHARP
    using System;
    using System.Collections.Generic;
    using System.Drawing;
    using System.Windows.Forms;
    using Emgu.CV;
    using Emgu.CV.Structure;
    using Emgu.CV.CvEnum;
    using System.IO;


    namespace MultiFaceRec
    {
    public partial class FrmPrincipal : Form
    {
    #region Переменные и свойства

    private Image<Bgr, Byte> _currentFrame; // Текущий захваченный кадр из видеопотока
    private Capture _grabber; // Объект захвата видео
    private HaarCascade _face; // Каскад Хаара для обнаружения лиц
    private MCvFont _font = new MCvFont(FONT.CV_FONT_HERSHEY_TRIPLEX, 1d, 0.5d); // Шрифт для отображения текста на изображении
    private Image<Gray, byte> _result, _trainedFace = null; // Результат обработки изображения, обученное лицо
    private Image<Gray, byte> _gray = null; // Изображение в оттенках серого
    private List<Image<Gray, byte>> _trainingImages = new List<Image<Gray, byte>>(); // Список обучающих изображений
    private List<string> _labels = new List<string>(); // Список меток для обучения
    private List<string> _namePersons = new List<string>(); // Список имен, соответствующих обнаруженным лицам
    private int _contTrain, _numLabels, _t; // Счетчики для обучения лиц
    private string _name, _names = null; // Имя лица, строки с именами лиц


    #endregion

    #region Конструктор и инициализация формы

    public FrmPrincipal() // Конструктор инициализирует форму
    {
    InitializeComponent(); // Метод инициализирует компоненты формы
    InitializeFaceRecognizer(); // Метод для инициализации распознавания лиц
    }

    private void FrmPrincipal_Load(object sender, EventArgs e)
    {
    // Можно добавить дополнительную инициализацию при загрузке формы
    }

    #endregion

    #region Методы


    // Метод InitializeFaceRecognizer() инициализирует распознавание лиц.
    private void InitializeFaceRecognizer()
    {
    // Создаем объект HaarCascade для определения лиц на изображении.
    _face = new HaarCascade("haarcascade_frontalface_default.xml");

    try
    {
    // Пытаемся загрузить информацию о метках и обученных лицах из файловой системы.
    string labelsInfo = File.ReadAllText(Application.StartupPath + "/TrainedFaces/TrainedLabels.txt");
    string[] labels = labelsInfo.Split('%');
    _numLabels = Convert.ToInt16(labels[0]);
    _contTrain = _numLabels;

    // Проходимся по каждой метке и соответствующему изображению и добавляем их в коллекции.
    for (int i = 1; i < _numLabels + 1; i++)
    {
    string loadFaces = "face" + i + ".bmp";
    _trainingImages.Add(new Image<Gray, byte>(Application.StartupPath + "/TrainedFaces/" + loadFaces));
    _labels.Add(labels[i]);
    }
    }
    catch (Exception)
    {
    // Если произошла ошибка загрузки или отсутствуют данные, выводим сообщение об ошибке.
    MessageBox.Show("Ничего не найдено в базе данных, пожалуйста, добавьте лицо.", "Загрузка обученных лиц", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
    }
    }


    // Метод StartCam() запускает камеру для захвата видеопотока.
    private void StartCam()
    {
    // Создаем объект Capture для захвата видеопотока.
    _grabber = new Capture();

    // Захватываем кадр, чтобы инициализировать камеру.
    _grabber.QueryFrame();

    // Добавляем обработчик события Idle приложения, который будет вызывать метод FrameGrabber() для обработки кадров.
    Application.Idle += new EventHandler(FrameGrabber);

    // Отключаем кнопку 1, чтобы избежать возможности запуска камеры несколько раз.
    button1.Enabled = false;
    }

    // Метод StopCam() останавливает камеру для захвата видеопотока.
    private void StopCam()
    {
    if (_grabber != null)
    {
    Application.Idle -= FrameGrabber; // Отписываемся от события обработки кадров
    _grabber.Dispose(); // Освобождаем ресурсы камеры
    _grabber = null;
    button1.Enabled = true; // Включаем кнопку "Захватить кадр"

    // Очистка места для вывода информации
    imageBoxFrameGrabber.Image = null; // Очистка изображения
    imageBox1.Image = null; // Очистка обучения
    label3.Text = ""; // Очистка имени
    label4.Text = ""; // Очистка количества лиц

    }
    }

    // Метод AddInBase() добавляет лицо в базу данных для обучения распознаванию.
    private void AddInBase()
    {
    try
    {
    // Проверяем, было ли введено имя для добавления лица.
    if (string.IsNullOrEmpty(textBox1.Text))
    {
    MessageBox.Show("Пожалуйста, введите ваше имя для добавления лица");
    }
    else
    {
    // Увеличиваем счетчик обучающих изображений.
    _contTrain++;

    // Захватываем кадр с камеры и преобразуем его в черно-белое изображение.
    _gray = _grabber.QueryGrayFrame().Resize(320, 240, Emgu.CV.CvEnum.INTER.CV_INTER_CUBIC);

    // Обнаруживаем лицо на кадре.
    MCvAvgComp[][] facesDetected = _gray.DetectHaarCascade(
    _face,
    1.2,
    10,
    Emgu.CV.CvEnum.HAAR_DETECTION_TYPE.DO_CANNY_PRUNING,
    new Size(20, 20));

    // Обрабатываем каждое обнаруженное лицо.
    foreach (MCvAvgComp f in facesDetected[0])
    {
    // Копируем область лица.
    _trainedFace = _currentFrame.Copy(f.rect).Convert<Gray, byte>();
    break;
    }

    // Преобразуем изображение лица к размеру 100x100.
    _trainedFace = _result.Resize(100, 100, Emgu.CV.CvEnum.INTER.CV_INTER_CUBIC);

    // Добавляем изображение лица и метку в соответствующие коллекции.
    _trainingImages.Add(_trainedFace);
    _labels.Add(textBox1.Text);

    // Отображаем изображение лица на форме.
    imageBox1.Image = _trainedFace;

    // Обновляем файл с метками обученных лиц.
    File.WriteAllText(Application.StartupPath + "/TrainedFaces/TrainedLabels.txt", _trainingImages.ToArray().Length.ToString() + "%");

    // Сохраняем изображения лиц и соответствующие метки в файловую систему.
    for (int i = 1; i < _trainingImages.ToArray().Length + 1; i++)
    {
    _trainingImages.ToArray()[i - 1].Save(Application.StartupPath + "/TrainedFaces/face" + i + ".bmp");
    File.AppendAllText(Application.StartupPath + "/TrainedFaces/TrainedLabels.txt", _labels.ToArray()[i - 1] + "%");
    }

    // Выводим сообщение об успешном добавлении лица в базу данных.
    MessageBox.Show(textBox1.Text + " - лицо обнаружено и добавлено", "Обучение выполнено успешно", MessageBoxButtons.OK, MessageBoxIcon.Information);
    }
    }
    catch
    {
    // Выводим сообщение об ошибке при обнаружении лица.
    MessageBox.Show("Лицо не обнаружено. Пожалуйста, проверьте вашу камеру или подойдите ближе.", "Ошибка обучения", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
    }
    }

    // Метод DeleteInBase() удаляет лица и связанные с ними файлы из базы данных.
    private void DeleteInBase()
    {
    try
    {
    // Удаляем файлы с лицами из папки TrainedFaces.
    DirectoryInfo trainedFacesDir = new DirectoryInfo(Application.StartupPath + "/TrainedFaces/");
    foreach (FileInfo file in trainedFacesDir.GetFiles())
    {
    file.Delete();
    }

    // Удаляем файл с метками лиц.
    File.Delete(Application.StartupPath + "/TrainedFaces/TrainedLabels.txt");

    // Очищаем списки лиц и меток.
    _trainingImages.Clear();
    _labels.Clear();

    MessageBox.Show("Сохраненные лица и имена удалены успешно.", "Успех", MessageBoxButtons.OK, MessageBoxIcon.Information);
    }
    catch (Exception ex)
    {
    // Выводим сообщение об ошибке при удалении лиц и меток.
    MessageBox.Show($"Ошибка при удалении сохраненных лиц и имен: {ex.Message}", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
    }

    // Метод RemoveFromBase() удаляет последнее добавленное лицо из базы данных обученных лиц.
    private void RemoveFromBase()
    {
    try
    {
    // Проверяем, есть ли что удалять.
    if (_contTrain > 0)
    {
    // Удаляем последнее добавленное лицо из списков обучающих изображений и меток.
    _trainingImages.RemoveAt(_trainingImages.Count - 1);
    _labels.RemoveAt(_labels.Count - 1);

    // Уменьшаем счетчик обучающих изображений.
    _contTrain--;

    // Обновляем файл с метками обученных лиц.
    File.WriteAllText(Application.StartupPath + "/TrainedFaces/TrainedLabels.txt", _trainingImages.ToArray().Length.ToString() + "%");

    // Перезаписываем файлы изображений лиц с учетом обновленных списков.
    for (int i = 1; i <= _trainingImages.Count; i++)
    {
    _trainingImages[i - 1].Save(Application.StartupPath + "/TrainedFaces/face" + i + ".bmp");
    File.AppendAllText(Application.StartupPath + "/TrainedFaces/TrainedLabels.txt", _labels[i - 1] + "%");
    }

    MessageBox.Show("Последнее добавленное лицо успешно удалено из базы данных.", "Успех", MessageBoxButtons.OK, MessageBoxIcon.Information);
    }
    else
    {
    // Выводим сообщение, если база данных пуста.
    MessageBox.Show("База данных обученных лиц пуста.", "Пусто", MessageBoxButtons.OK, MessageBoxIcon.Information);
    }
    }
    catch (Exception ex)
    {
    // Выводим сообщение об ошибке при удалении лица из базы данных.
    MessageBox.Show($"Ошибка при удалении последнего добавленного лица: {ex.Message}", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }

    }



    // Метод FrameGrabber выполняется при захвате каждого кадра с камеры.
    private void FrameGrabber(object sender, EventArgs e)
    {
    // Сбрасываем счетчик обнаруженных лиц и список имен лиц.
    label3.Text = "0";
    _namePersons.Add("");

    // Захватываем текущий кадр с камеры и преобразуем его в черно-белое изображение.
    _currentFrame = _grabber.QueryFrame().Resize(320, 240, Emgu.CV.CvEnum.INTER.CV_INTER_CUBIC);
    _gray = _currentFrame.Convert<Gray, Byte>();

    // Обнаруживаем лица на кадре.
    MCvAvgComp[][] facesDetected = _gray.DetectHaarCascade(
    _face,
    1.2,
    10,
    Emgu.CV.CvEnum.HAAR_DETECTION_TYPE.DO_CANNY_PRUNING,
    new Size(20, 20));

    // Обрабатываем каждое обнаруженное лицо.
    foreach (MCvAvgComp f in facesDetected[0])
    {
    _t++;
    // Выделяем лицо на текущем кадре.
    _result = _currentFrame.Copy(f.rect).Convert<Gray, byte>().Resize(100, 100, Emgu.CV.CvEnum.INTER.CV_INTER_CUBIC);
    _currentFrame.Draw(f.rect, new Bgr(Color.Yellow), 1); // Рамка лица

    // Если есть обученные лица, выполняем распознавание.
    if (_trainingImages.ToArray().Length != 0)
    {
    MCvTermCriteria termCrit = new MCvTermCriteria(_contTrain, 0.001);
    EigenObjectRecognizer recognizer = new EigenObjectRecognizer(
    _trainingImages.ToArray(),
    _labels.ToArray(),
    3000,
    ref termCrit);

    _name = recognizer.Recognize(_result);
    _currentFrame.Draw(_name, ref _font, new Point(f.rect.X - 2, f.rect.Y - 2), new Bgr(Color.DarkOrange)); // Имя над рамкой
    }

    _namePersons[_t - 1] = _name;
    _namePersons.Add("");

    label3.Text = facesDetected[0].Length.ToString();
    }

    _t = 0;

    // Собираем имена всех обнаруженных лиц.
    for (int nnn = 0; nnn < facesDetected[0].Length; nnn++)
    {
    _names = _names + _namePersons[nnn] + " "; // имена***
    }

    // Отображаем текущий кадр с выделенными лицами и именами на форме.
    imageBoxFrameGrabber.Image = _currentFrame;
    label4.Text = _names;
    _names = "";
    _namePersons.Clear();
    }




    #endregion

    #region Обработчики событий

    private void button1_Click(object sender, EventArgs e)
    {
    StartCam();
    }

    private void button2_Click(object sender, EventArgs e)
    {
    AddInBase();
    }
    private void button3_Click(object sender, EventArgs e)
    {
    StopCam();
    }
    private void button4_Click(object sender, EventArgs e)
    {
    DeleteInBase();
    }

    private void button5_Click(object sender, EventArgs e)
    {
    RemoveFromBase();
    }


    #endregion
    }
    }
    Буду благодарен за помощь :catmeow:
     
  2. Network
    Network 23 апр 2024 1549 2 май 2023
    Хуево обучена мб?
     
    1. zerro5 Автор темы
  3. vtlstolyarov
    vtlstolyarov 23 апр 2024 468 8 янв 2022
    Не стыдно просить людей исправить то что написала ChatGPT?
     
    1. Посмотреть предыдущие комментарии (2)
    2. sovanedev
      zerro5, индус комменты на русском не пишет))
    3. vtlstolyarov
      sovanedev, точно, значит всё же chatgpt :)
Загрузка...
Top