Задать вопрос
@NIKITATR

Как сделать лицо в анфас?

Пытаюсь нормализировать изображение, а именно сделать так, чтобы оно смотрело в анфас. Прочитал идею в статье, в которой говорится, что лицо пользователя можно выровнять по глазам:
1) Координаты средних точек левого и правого глаз (Left и Right):
XL = (X45 + X42) /2 ;
YL = (Y45 + Y42) /2 ;
XR = (X39 + X 36) /2;
YR = (Y39 + Y 36) /2;
623b04a597b27952392131.png
2) Начало ПСК:
X0 =( XL + XR)/2;
Y0 =( YL + YR)/2;
Расстояния между средними точками глаз вдоль осей Х и Y:
DX = XR — XL
DY = YR — YL;
Действительное расстояние L между средними точками глаз (по теореме Пифагора):
L = sqrt ( DX** 2 + DY**2)
Тригонометрические функции угла поворота ПСК:
sin_AL = DY/L
cos_AL = DX/L
623b2ebd88706414573646.png
3) Переходим от координат в оконной СК к координатам в ПСК, используя параметры X0,Y0, L, sin AL, cos AL:
X_User_0 = 2 (X_Window — X0 ) / L;
Y_User_0 = — 2 (Y_Window — Y0 ) / L ;
X_User = X_User_0 * cos_AL — Y_User_0 * sin_AL;
Y_User = X_User_0 * sin_AL + Y_User_0 * cos_AL;
KOD
import math

import cv2
import dlib
def face(roi_gray,cos_AL,sin_AL,X_o,Y_o):
    weight, height, RGB = roi_gray.shape
    for x in range(weight):
        for y in range(height):
            X_USER_0 = 2 * (x - X_o) / L
            Y_USER_0 = 2 * (y - Y_o) / L
            X_NEW = int((X_USER_0) * cos_AL - Y_USER_0 * sin_AL)
            Y_NEW = int(X_USER_0 * sin_AL + Y_USER_0 * cos_AL)
            roi_gray[x][y] = roi_gray[X_NEW][Y_NEW]
    cv2.imwrite('result.jpg', cv2.resize(roi_gray, (400, 400)))

# Для детектирования лиц используем каскады Хаара
Path = "haarcascade_frontalface_default.xml"
faceCascade = cv2.CascadeClassifier(Path)

# Запуск видео потока
cap = cv2.VideoCapture(0)

# Модель для поиска ключевых точек
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
cos_AL,sin_AL, X_o,Y_o=0,0,0,0

while True:
    # Получение изображения из видео потока
    ret, frame = cap.read()
    #Мы  это сделали, т.к. если лица не будет , не сможем получить roi_gray, будет ошибка
    if ret == 0:
        break
    # Конвертирование изображения в черно-белое
    grayFrame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    # Обнаружение лиц и построение прямоугольного контура
    faces =faceCascade.detectMultiScale(grayFrame, minNeighbors = 10)
    for x, y, width, height in faces:
        cv2.rectangle(frame, (x, y), (x + width, y + height), color=(255, 255, 255), thickness=1)
        face=dlib.rectangle(x, y , x+width, y+height)
        landmarks = predictor(grayFrame, face)
        #left_eys
        x_r_36 = landmarks.part(36).x
        y_r_36 = landmarks.part(36).y
        x_r_39 = landmarks.part(39).x
        y_r_39 = landmarks.part(39).y
        X_r=(x_r_39 + x_r_36)/2
        Y_r=(y_r_39 + y_r_36)/2
        #rigth_eys
        x_l_42 = landmarks.part(42).x
        y_l_42 = landmarks.part(42).y
        x_l_45 = landmarks.part(45).x
        y_l_45 = landmarks.part(45).y
        X_l = (x_l_42 + x_l_45) / 2
        Y_l = (y_l_42 + y_l_45) / 2
        #nachalo_psk
        X_o=(X_l+X_r)/2
        Y_o=(Y_l+Y_r)/2
        #Расстояния между средними точками глаз вдоль осей Х и Y:
        DX=X_r-X_l
        DY=Y_r-Y_l
        #Действительное расстояние L между средними точками глаз (по теореме Пифагора):
        L=pow((DX**2)+(DY**2),0.5)
        #Тригонометрические функции угла поворота ПСК
        sin_AL=DY/L
        cos_AL=DX/L
    cv2.imshow("FACE IN IMAGE", frame)
    if cv2.waitKey(10) & 0xFF == ord('e'):  # <<<<< 0xFF
        break
roi_gray = frame[y:y + height, x:x + width]
cv2.imwrite('result.jpg', cv2.resize(roi_gray, (400, 400)))

L=round(math.degrees(math.asin(sin_AL)))
rotation_matrix =cv2.getRotationMatrix2D((X_o,Y_o),L, 0.5)
anfas=cv2.warpAffine(roi_gray,rotation_matrix,(400,400))
cv2.imshow('ANFAS',anfas)
cv2.waitKey()
#ПОПЫТКА СДЕЛАТЬ ЛИЦО В АНФАС без cv2.getRotationMatrix2 и warpAffine
#face(roi_gray,cos_AL,sin_AL,X_o,Y_o)

cap.release()
cv2.destroyAllWindows()


ИНТЕРЕСУЕТ ВОПРОС: КАК СДЕЛАТЬ ТАК, ЧТОБЫ ЛИЦО БЫЛО НЕ ПОД УГЛОМ?
Для чего это. Я хочу вырезать лицо(с размером, например, 400*400), которое зафиксировала камера(последний зафиксированный кадр ), затем его выровнять для дальнейшей обработки.
  • Вопрос задан
  • 204 просмотра
Подписаться 1 Средний 1 комментарий
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы