Spaces:
Paused
Paused
| """ | |
| @author: cuny | |
| @file: EulerX.py | |
| @time: 2022/4/1 13:54 | |
| @description: | |
| 寻找三维z轴旋转角roll,实现: | |
| 1. 输入一张三通道图片(四通道、单通道将默认转为三通道) | |
| 2. 输出人脸在x轴的转角roll,顺时针为正方向,角度制 | |
| """ | |
| import cv2 | |
| import numpy as np | |
| from math import asin, pi # -pi/2 ~ pi/2 | |
| # 获得人脸的关键点信息 | |
| def get_facePoints(src: np.ndarray, fd68): | |
| if len(src.shape) == 2: | |
| src = cv2.cvtColor(src, cv2.COLOR_GRAY2BGR) | |
| elif src.shape[2] == 4: | |
| src = cv2.cvtColor(src, cv2.COLOR_BGRA2BGR) | |
| status, dets, landmarks, _ = fd68.facePointsEuler(src) | |
| if status == 0: | |
| return 0, None, None | |
| elif status == 2: | |
| return 2, None, None | |
| else: | |
| return 1, dets, np.fliplr(landmarks) | |
| def eulerZ(landmark: np.matrix): | |
| # 我们规定顺时针为正方向 | |
| def get_pi_2(r): | |
| pi_2 = pi / 2. | |
| if r >= 0.0: | |
| return pi_2 | |
| else: | |
| return -pi_2 | |
| orbit_points = np.array([[landmark[21, 0], landmark[21, 1]], [landmark[71, 0], landmark[71, 1]], | |
| [landmark[25, 0], landmark[25, 1]], [landmark[67, 0], landmark[67, 1]]]) | |
| # [[cos a],[sin a],[point_x],[point_y]] | |
| # 前面两项是有关直线与Y正半轴夹角a的三角函数,所以对于眼睛部分来讲sin a应该接近1 | |
| # "我可以认为"cv2.fitLine的y轴正方向为竖直向下,且生成的拟合直线的方向为从起点指向终点 | |
| # 与y轴的夹角为y轴夹角与直线方向的夹角,方向从y指向直线,逆时针为正方向 | |
| # 所以最后对于鼻梁的计算结果需要取个负号 | |
| orbit_line = cv2.fitLine(orbit_points, cv2.DIST_L2, 0, 0.01, 0.01) | |
| orbit_a = asin(orbit_line[1][0]) | |
| nose_points = np.array([[landmark[55, 0], landmark[55, 1]], [landmark[69, 0], landmark[69, 1]]]) | |
| nose_line = cv2.fitLine(nose_points, cv2.DIST_L2, 0, 0.01, 0.01) | |
| nose_a = asin(nose_line[1][0]) | |
| return (orbit_a + nose_a) * (180.0 / (2 * pi)) | |