Напиши программу для анализа : Возраста , нации , ...
Criado em: 10 de março de 2025
Criado em: 10 de março de 2025
Напиши программу для анализа : Возраста , нации , пола, эмоций и уровня раздетости(как сильно). Программа с gui запрашивает видео и на каждом кадре ищет лицо если находит то обводит к квадрат и анализирует , результат анализа пишется около квадратика но так чтобы он был полностью виден и не вылезал за границы экрана. Также сделай чтобы была ещё вкладка для анализа картинок отдельно от видео. И сделай чтобы принимальсь видео любых форматов. И также чтобы программа сохраняла обработанные видео , фото и модели для анализа на диске G в сгенерированной папке
Ниже приведён пример кода на Python (с использованием PyQt) для решения описанной задачи. Код демонстрирует базовый подход к:
Обратите внимание, что в реальном проекте придётся:
Пример кода написан на PyQt5 + OpenCV. Для PyQt6 отличия будут минимальны (названия некоторых модулей и методы импорта).
bashpip install opencv-python PyQt5
(если используете виртуальное окружение, убедитесь, что эти команды выполняются в нём).
pythonimport sys import os import cv2 import time import numpy as np from PyQt5.QtWidgets import ( QApplication, QMainWindow, QWidget, QPushButton, QLabel, QVBoxLayout, QHBoxLayout, QFileDialog, QTabWidget, QMessageBox ) from PyQt5.QtGui import QPixmap, QImage from PyQt5.QtCore import Qt # ---------------------------- # Псевдо-функции для анализа # ---------------------------- def analyze_age(face_roi: np.ndarray) -> str: """ Заглушка. Вместо реального анализа возвращаем рандомный возраст или фейковый "25-30". В реальности тут вызывается предсказание модели. """ return "25-30" def analyze_gender(face_roi: np.ndarray) -> str: """ Заглушка. Возвращаем 'Муж' или 'Жен'. """ return "Муж" def analyze_emotion(face_roi: np.ndarray) -> str: """ Заглушка. Возвращаем 'Счастье'/'Грусть' и т.д. """ return "Счастье" def analyze_nationality(face_roi: np.ndarray) -> str: """ Заглушка. Возвращаем условную национальность. """ return "NA" def analyze_undress_level(face_roi: np.ndarray, full_frame: np.ndarray) -> str: """ Заглушка. Предположим, что уровень раздетости определяем по общей картинке. """ # В реальности это может быть отдельная модель (Image Classification, NSFW и т.д.) return "Лёгкая" # ------------------------------------- # Класс основного окна приложения (GUI) # ------------------------------------- class MainWindow(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("Анализ видео и изображений") # Создаем вкладки self.tabs = QTabWidget() self.setCentralWidget(self.tabs) self.video_tab = VideoTab() self.image_tab = ImageTab() self.tabs.addTab(self.video_tab, "Анализ Видео") self.tabs.addTab(self.image_tab, "Анализ Изображений") self.resize(800, 600) self.show() # ---------------------------------------- # Вкладка для анализа видео # ---------------------------------------- class VideoTab(QWidget): def __init__(self): super().__init__() self.layout = QVBoxLayout() # Кнопки self.btn_select_video = QPushButton("Выбрать видео для анализа") self.btn_process_video = QPushButton("Начать обработку") self.status_label = QLabel("Статус: Ожидание загрузки видео") self.layout.addWidget(self.btn_select_video) self.layout.addWidget(self.btn_process_video) self.layout.addWidget(self.status_label) # Соединяем сигналы self.btn_select_video.clicked.connect(self.select_video) self.btn_process_video.clicked.connect(self.process_video) # Путь к выбранному видео self.selected_video_path = None self.setLayout(self.layout) # Инициализация детектора лиц (Haar cascade) # (Можно заменить на другие, более современные модели) self.face_cascade = cv2.CascadeClassifier( cv2.data.haarcascades + "haarcascade_frontalface_default.xml" ) def select_video(self): """ Открываем диалог выбора видеофайла """ file_dialog = QFileDialog() file_dialog.setNameFilters(["Видео-файлы (*.mp4 *.avi *.mov *.mkv *.flv *.wmv);;Все файлы (*)"]) if file_dialog.exec_(): self.selected_video_path = file_dialog.selectedFiles()[0] self.status_label.setText(f"Выбрано видео: {self.selected_video_path}") def process_video(self): """ Анализ видео: покадровое чтение, детектирование лица, анализ, запись результатов. """ if not self.selected_video_path: QMessageBox.warning(self, "Ошибка", "Сначала выберите видеофайл.") return cap = cv2.VideoCapture(self.selected_video_path) if not cap.isOpened(): QMessageBox.critical(self, "Ошибка", "Не удалось открыть видео.") return # Создаем папку на диске G для сохранения результатов и моделей output_dir = create_output_dir_on_drive_g() # Формируем путь и имя для сохраненного видео video_name = os.path.basename(self.selected_video_path) output_video_path = os.path.join(output_dir, f"processed_{video_name}") # Параметры для записи выходного видео (кодек, FPS, размер) fourcc = cv2.VideoWriter_fourcc(*'XVID') fps = cap.get(cv2.CAP_PROP_FPS) width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) out = cv2.VideoWriter(output_video_path, fourcc, fps, (width, height)) frame_count = 0 total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) if cap.get(cv2.CAP_PROP_FRAME_COUNT) > 0 else 0 self.status_label.setText("Обработка видео...") while True: ret, frame = cap.read() if not ret: break frame_count += 1 # Детектируем лица gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) faces = self.face_cascade.detectMultiScale(gray, 1.3, 5) for (x, y, w, h) in faces: # Вырезаем ROI лица face_roi_color = frame[y:y+h, x:x+w] # Анализ (возраст, пол, эмоция, нация, уровень раздетости) age = analyze_age(face_roi_color) gender = analyze_gender(face_roi_color) emotion = analyze_emotion(face_roi_color) nationality = analyze_nationality(face_roi_color) undress_level = analyze_undress_level(face_roi_color, frame) # Строим строку для отображения result_str = f"{age} | {gender} | {emotion} | {nationality} | {undress_level}" # Рисуем квадрат на лице cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2) # Печатаем результат около квадратика # Проверяем, чтобы текст не вылезал за границы text_size, _ = cv2.getTextSize(result_str, cv2.FONT_HERSHEY_SIMPLEX, 0.6, 2) text_w, text_h = text_size text_x = x text_y = y - 10 # Если текст уходит вверх за границу, сдвинем его ниже лица if text_y - text_h < 0: text_y = y + h + text_h # То же самое по горизонтали if text_x + text_w > width: text_x = width - text_w cv2.putText(frame, result_str, (text_x, text_y), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 0, 0), 2, cv2.LINE_AA) # Записываем обработанный кадр out.write(frame) # Отображаем прогресс if total_frames > 0: progress_percent = int((frame_count / total_frames) * 100) self.status_label.setText(f"Обработка видео... {progress_percent}%") # (Опционально) можно вставить cv2.imshow('frame', frame), # но в PyQt это лучше делать иначе (через QLabel), # однако тогда нужен отдельный поток или QTimer. # Для избежания подвисания интерфейса: QApplication.processEvents() cap.release() out.release() self.status_label.setText(f"Обработка завершена. Результат: {output_video_path}") QMessageBox.information(self, "Готово", f"Видео сохранено: {output_video_path}") # ---------------------------------------- # Вкладка для анализа изображений # ---------------------------------------- class ImageTab(QWidget): def __init__(self): super().__init__() self.layout = QVBoxLayout() self.btn_select_image = QPushButton("Выбрать изображение") self.btn_process_image = QPushButton("Проанализировать") self.image_label = QLabel() self.image_label.setAlignment(Qt.AlignCenter) self.status_label = QLabel("Статус: Ожидание") self.layout.addWidget(self.btn_select_image) self.layout.addWidget(self.btn_process_image) self.layout.addWidget(self.image_label) self.layout.addWidget(self.status_label) self.setLayout(self.layout) self.btn_select_image.clicked.connect(self.select_image) self.btn_process_image.clicked.connect(self.process_image) self.selected_image_path = None # Инициализация детектора лиц self.face_cascade = cv2.CascadeClassifier( cv2.data.haarcascades + "haarcascade_frontalface_default.xml" ) def select_image(self): file_dialog = QFileDialog() file_dialog.setNameFilter("Изображения (*.png *.jpg *.jpeg *.bmp *.tiff);;Все файлы (*)") if file_dialog.exec_(): self.selected_image_path = file_dialog.selectedFiles()[0] self.status_label.setText(f"Выбрано изображение: {self.selected_image_path}") self.show_image(self.selected_image_path) def show_image(self, path): pixmap = QPixmap(path) self.image_label.setPixmap(pixmap.scaled(self.image_label.width(), self.image_label.height(), Qt.KeepAspectRatio, Qt.SmoothTransformation)) def process_image(self): if not self.selected_image_path: QMessageBox.warning(self, "Ошибка", "Сначала выберите изображение.") return image = cv2.imread(self.selected_image_path) if image is None: QMessageBox.critical(self, "Ошибка", "Не удалось открыть изображение.") return # Детектируем лица gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) faces = self.face_cascade.detectMultiScale(gray, 1.3, 5) for (x, y, w, h) in faces: face_roi_color = image[y:y+h, x:x+w] # Анализ (возраст, пол, эмоция, нация, уровень раздетости) age = analyze_age(face_roi_color) gender = analyze_gender(face_roi_color) emotion = analyze_emotion(face_roi_color) nationality = analyze_nationality(face_roi_color) undress_level = analyze_undress_level(face_roi_color, image) result_str = f"{age} | {gender} | {emotion} | {nationality} | {undress_level}" cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2) # Рисуем текст text_size, _ = cv2.getTextSize(result_str, cv2.FONT_HERSHEY_SIMPLEX, 0.6, 2) text_w, text_h = text_size text_x = x text_y = y - 10 # Проверка выхода за границы if text_y - text_h < 0: text_y = y + h + text_h if text_x + text_w > image.shape[1]: text_x = image.shape[1] - text_w cv2.putText(image, result_str, (text_x, text_y), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 0, 0), 2, cv2.LINE_AA) # Создаем папку на диске G для сохранения output_dir = create_output_dir_on_drive_g() # Генерируем имя файла base_name = os.path.basename(self.selected_image_path) output_image_path = os.path.join(output_dir, f"processed_{base_name}") cv2.imwrite(output_image_path, image) # Отобразим итоговое изображение в интерфейсе self.show_image(output_image_path) self.status_label.setText(f"Обработка завершена. Результат: {output_image_path}") # ---------------------------------------- # Вспомогательная функция для создания папки на диске G # ---------------------------------------- def create_output_dir_on_drive_g(): """ Создает (если нет) папку на диске G: с уникальным именем по времени, а также вложенную папку для сохранения моделей (пример). """ # Формируем путь к папке, например: G:/analysis_YYYYMMDD_HHMMSS folder_name = time.strftime("analysis_%Y%m%d_%H%M%S") base_path = "G:" # если диска G нет, нужно будет указать корректный путь output_dir = os.path.join(base_path, folder_name) try: os.makedirs(output_dir, exist_ok=True) # Можно также сохранить модели в подпапку, если нужно: models_dir = os.path.join(output_dir, "models") os.makedirs(models_dir, exist_ok=True) # Здесь можно сохранить скачанные или готовые модели, например: # save_some_models(models_dir) except Exception as e: print(f"Не удалось создать папку: {e}") return output_dir # ---------------------------------------- # Запуск приложения # ---------------------------------------- def main(): app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_()) if __name__ == "__main__": main()
GUI на PyQt
QTabWidget
для создания двух вкладок: VideoTab
(анализ видео) и ImageTab
(анализ изображений).Анализ лица
haarcascade_frontalface_default.xml
). Можно заменить на более продвинутые модели (например, DNN детектор лиц от OpenCV, blobFromImage + caffemodel).analyze_age()
, analyze_gender()
и т.д. сейчас возвращают заглушки. В реальном проекте там должны быть вызовы моделей машинного обучения (CNN, DNN, PyTorch, TensorFlow или другие).Обработка видео
cv2.VideoCapture
и cv2.VideoWriter
идёт чтение и запись покадрового видео.Проверка, чтобы текст не выходил за пределы кадра
cv2.getTextSize
), проверяем координаты и при необходимости сдвигаем надпись вниз/вправо.Сохранение обработанных данных
G:
создаётся папка с названием вида analysis_YYYYMMDD_HHMMSS
. Туда записываются:
models
(куда можно поместить нужные файлы моделей).Универсальность по форматам
Данный пример – это стартовый каркас приложения. Чтобы довести его до рабочего решения в реальном проекте, необходимо:
Надеюсь, этот пример послужит хорошей отправной точкой для вашей задачи!