Пытаюсь нормализировать изображение, а именно сделать так, чтобы оно смотрело в анфас. Прочитал идею в статье, в которой говорится, что лицо пользователя можно выровнять по глазам:
1) Координаты средних точек левого и правого глаз (Left и Right):
XL = (X45 + X42) /2 ;
YL = (Y45 + Y42) /2 ;
XR = (X39 + X 36) /2;
YR = (Y39 + Y 36) /2;
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
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), которое зафиксировала камера(последний зафиксированный кадр ), затем его выровнять для дальнейшей обработки.