Перенос лица с изображения на лицо в видео с камеры

Когда я запускаю код и выбираю изображение, лицо переносится с изображения только на секунду, а затем рамка остается такой же, как и при запуске кода.

import cv2
import dlib
import numpy as np
import tkinter as tk
from tkinter import filedialog

# Загружаем модель для обнаружения ключевых точек на лице
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")

# Функция для обнаружения и отрисовки лиц на изображении
def highlightFaceOnImage(image):
    # Конвертируем изображение в оттенки серого для dlib
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    # Обнаруживаем лица на изображении
    faces = dlib.get_frontal_face_detector()(gray, 0)

    # Перебираем все обнаруженные лица
    for face in faces:
        # Получаем ключевые точки на лице
        landmarks = predictor(gray, face)

        # Получаем координаты ключевых точек
        x1 = min([landmarks.part(i).x for i in range(68)])
        y1 = min([landmarks.part(i).y for i in range(68)])
        x2 = max([landmarks.part(i).x for i in range(68)])
        y2 = max([landmarks.part(i).y for i in range(68)])

        # Отрисовываем ключевые точки на изображении
        for i in range(68):
            cv2.circle(image, (landmarks.part(i).x, landmarks.part(i).y), 2, (0, 0, 255), -1)

    return image

# Функция для переноса лица с изображения на лицо в видео
def transfer_face(frame, image, prev_face_img=None, prev_face_roi=None):
    # Конвертируем кадр и изображение в оттенки серого для dlib
    frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    # Обнаруживаем лица в кадре и на изображении
    frame_faces = dlib.get_frontal_face_detector()(frame_gray, 0)
    image_faces = dlib.get_frontal_face_detector()(image_gray, 0)

    if len(frame_faces) > 0 and len(image_faces) > 0:
        # Получаем ключевые точки на лице в кадре и на изображении
        frame_landmarks = predictor(frame_gray, frame_faces[0])
        image_landmarks = predictor(image_gray, image_faces[0])

        # Получаем координаты ключевых точек
        frame_x1 = min([frame_landmarks.part(i).x for i in range(68)])
        frame_y1 = min([frame_landmarks.part(i).y for i in range(68)])
        frame_x2 = max([frame_landmarks.part(i).x for i in range(68)])
        frame_y2 = max([frame_landmarks.part(i).y for i in range(68)])

        image_x1 = min([image_landmarks.part(i).x for i in range(68)])
        image_y1 = min([image_landmarks.part(i).y for i in range(68)])
        image_x2 = max([image_landmarks.part(i).x for i in range(68)])
        image_y2 = max([image_landmarks.part(i).y for i in range(68)])

        # Вырезаем область лица из изображения
        face_img = image[image_y1:image_y2, image_x1:image_x2]

        # Масштабируем вырезанное лицо, чтобы размер совпадал с лицом в кадре
        face_img = cv2.resize(face_img, (frame_x2 - frame_x1, frame_y2 - frame_y1))

        # Накладываем вырезанное лицо на кадр
        alpha = 0.5
        roi = frame[frame_y1:frame_y2, frame_x1:frame_x2]
        roi_bg = cv2.addWeighted(roi, 1 - alpha, np.zeros_like(roi), 0, 0)
        roi_fg = cv2.addWeighted(face_img, alpha, np.zeros_like(face_img), 0, 0)
        frame[frame_y1:frame_y2, frame_x1:frame_x2] = cv2.add(roi_bg, roi_fg)
    elif prev_face_img is not None and prev_face_roi is not None:
        # Если лицо не обнаружено, но есть предыдущий фрейм с перенесенным лицом, используем его
        frame[prev_face_roi[1]:prev_face_roi[1]+prev_face_roi[3], prev_face_roi[0]:prev_face_roi[0]+prev_face_roi[2]] = prev_face_img

    return frame, face_img, prev_face_roi

# Функция для выбора изображения
def select_image():
    root = tk.Tk()
    root.withdraw()
    try:
        file_path = filedialog.askopenfilename()
        if file_path:
            image = cv2.imread(file_path)
            image_with_landmarks = highlightFaceOnImage(image)
            cv2.imshow("Detecting faces on image", image_with_landmarks)
            return image
    finally:
        root.destroy()

# Запускаем камеру
video = cv2.VideoCapture(0)

prev_face_img = None
prev_face_roi = None
frame_x1 = frame_y1 = frame_x2 = frame_y2 = 0
while True:
    hasFrame, frame = video.read()
    if not hasFrame:
        cv2.waitKey()
        break

    # Обнаруживаем лица в кадре и рисуем ключевые точки
    frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    frame_faces = dlib.get_frontal_face_detector()(frame_gray, 0)
    if len(frame_faces) > 0:
        frame_landmarks = predictor(frame_gray, frame_faces[0])
        frame_pts = np.array([[p.x, p.y] for p in frame_landmarks.parts()], dtype=np.float32)
        for x, y in frame_pts.astype(int):
            cv2.circle(frame, (x, y), 2, (0, 0, 255), -1)
        frame_x1 = min([frame_landmarks.part(i).x for i in range(68)])
        frame_y1 = min([frame_landmarks.part(i).y for i in range(68)])
        frame_x2 = max([frame_landmarks.part(i).x for i in range(68)])
        frame_y2 = max([frame_landmarks.part(i).y for i in range(68)])
        prev_face_roi = (frame_x1, frame_y1, frame_x2 - frame_x1, frame_y2 - frame_y1)

    # Выбираем изображение
    image = None
    key = cv2.waitKey(1) & 0xFF
    if key == ord("i"):
        image = select_image()
        if image is not None:
            # Переносим лицо с изображения на кадр
            frame, prev_face_img, prev_face_roi = transfer_face(frame, image, prev_face_img, prev_face_roi)

    # Выводим итоговую картинку
    cv2.imshow("Face Transfer", frame)

Я попробовал использовать аффинное преобразование и триангуляцию Делоне для переноса лица с изображения на видео, но это не сработало. Также я попробовал оптимизировать код, но это тоже не сработало.


Ответы (0 шт):