Загрузка...

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

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

Загрузка...
  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 1551 2 май 2023
    Хуево обучена мб?
     
    1. zerro5 Автор темы
  3. vtlstolyarov
    vtlstolyarov 23 апр 2024 474 8 янв 2022
    Не стыдно просить людей исправить то что написала ChatGPT?
     
    1. Посмотреть предыдущие комментарии (1)
    2. vtlstolyarov
      zerro5, а он, ты думаешь, где взял?
    3. sovanedev
      zerro5, индус комменты на русском не пишет))
Top