Как убрать имя в поле "Распознанные лица", когда 1 лицо добавлено и распознается, а 2 лицо не добавлено и тоже распознается как первое лицо? Получается у меня первое лицо добавлено - Face1, второе не добавлено и распознается, как Face1, а должно не распознаваться по имени, просто рамка вокруг лица должна быть. Также не понимаю почему после удаления лица в поле "Распознанные лица" остается имя распознанного лица. Получается я удаляю Face1, а имя остается. Это в кнопках "Удалить лицо" и "Удалить базу" 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 } } 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 } } Буду благодарен за помощь