基于Mediapipe:如何在旋转坐标系下计算人脸两点的斜率?
解决人脸旋转后斜率校正问题
首先,你当前的代码存在两个核心问题:
- 原点参考坐标计算错误:你错误地判断点8是否为(0,0,0),但实际上应该将所有点转换为相对于点8的局部坐标,而不是要求点8本身是原点。
- 斜率处理逻辑错误:旋转带来的角度变化不能用简单的斜率加减来修正,必须通过逆旋转变换将旋转后的向量转换回未旋转的坐标系。
正确的实现步骤
- 转换到局部坐标系:将所有关键点的坐标减去点8的坐标,得到以点8为原点的局部坐标。
- 计算人脸旋转角度:通过点8到点9的向量,计算该向量与原始x轴的夹角θ(这就是人脸的旋转角度)。
- 逆旋转目标向量:将目标两点的向量旋转-θ角度,还原到未旋转的坐标系,再计算斜率。
修正后的代码
import math def calculate_2D_slope(self, point1, point2): if not (point1 and point2): return None # 获取点8和点9的坐标 origin_point_no_8 = next((p for p in self.origin_points_coordinates if p["index"] == 8), None) origin_point_no_9 = next((p for p in self.origin_points_coordinates if p["index"] == 9), None) if not (origin_point_no_8 and origin_point_no_9): print("无法获取点8或点9的坐标") return None # 1. 转换到以点8为原点的局部坐标系 # 点9的局部坐标 p9_rel_x = origin_point_no_9["x"] - origin_point_no_8["x"] p9_rel_y = origin_point_no_9["y"] - origin_point_no_8["y"] # 计算人脸旋转角度θ(从原始x轴到点9向量的角度) theta = math.atan2(p9_rel_y, p9_rel_x) # 目标点的局部坐标 p1_rel_x = point1["x"] - origin_point_no_8["x"] p1_rel_y = point1["y"] - origin_point_no_8["y"] p2_rel_x = point2["x"] - origin_point_no_8["x"] p2_rel_y = point2["y"] - origin_point_no_8["y"] # 计算两点的向量 dx = p2_rel_x - p1_rel_x dy = p2_rel_y - p1_rel_y # 处理垂直情况(避免除以0) if abs(dx) < 1e-6: return float('inf') # 垂直直线斜率无穷大 # 2. 逆旋转向量:将向量旋转-θ角度,还原到未旋转坐标系 rotated_dx = dx * math.cos(theta) + dy * math.sin(theta) rotated_dy = -dx * math.sin(theta) + dy * math.cos(theta) # 处理旋转后垂直的情况 if abs(rotated_dx) < 1e-6: return float('inf') # 计算校正后的斜率 corrected_slope = rotated_dy / rotated_dx return corrected_slope
关键说明
- 旋转公式:逆旋转的本质是将旋转后的坐标系“转回去”,使用标准的2D旋转矩阵逆变换(旋转-θ角度)。
- 局部坐标系:必须先将所有点转换为相对于点8的坐标,才能确保旋转计算的准确性。
- 边界处理:加入了对dx接近0的判断,避免除以0的错误。
内容的提问来源于stack exchange,提问作者HiRelax
相关产品推荐
相关产品推荐

