在R中实现人脸关键点坐标对齐:统一眼点Y与特定点X坐标
人脸关键点对齐的R语言实现
需求拆解
你需要实现两个核心对齐目标:
- 让关键点39和42的Y坐标一致(使眼睛连线水平)
- 让关键点27和8的X坐标相同(使鼻梁垂直)
下面是具体的实现步骤和代码,假设你的数据框名为face_landmarks,包含landmark_id、x_new_norm、y_new_norm三列。
步骤1:提取目标关键点坐标
先从数据中取出需要用于计算变换的四个关键点:
library(dplyr) library(tidyr) # 提取关键点位坐标 key_coords <- face_landmarks %>% filter(landmark_id %in% c(8, 27, 39, 42)) %>% pivot_wider( names_from = landmark_id, values_from = c(x_new_norm, y_new_norm) ) # 赋值到变量方便后续计算 x8 <- key_coords$x_new_norm_8 y8 <- key_coords$y_new_norm_8 x27 <- key_coords$x_new_norm_27 y27 <- key_coords$y_new_norm_27 x39 <- key_coords$x_new_norm_39 y39 <- key_coords$y_new_norm_39 x42 <- key_coords$x_new_norm_42 y42 <- key_coords$y_new_norm_42
步骤2:旋转变换让眼睛连线水平
计算眼睛连线的倾斜角度,对所有关键点做旋转变换,让39和42的Y坐标一致:
# 计算旋转弧度:让39-42的连线水平 rotate_angle <- atan2(y42 - y39, x42 - x39) # 定义旋转变换函数(以39点为旋转中心,减少整体偏移) rotate <- function(x, y, angle, cx, cy) { list( x_rot = (x - cx) * cos(-angle) - (y - cy) * sin(-angle) + cx, y_rot = (x - cx) * sin(-angle) + (y - cy) * cos(-angle) + cy ) } # 应用旋转到所有关键点 landmarks_rotated <- face_landmarks %>% rowwise() %>% mutate(rotate(x_new_norm, y_new_norm, rotate_angle, x39, y39)) %>% ungroup()
此时检查39和42的Y坐标,应该已经相等。
步骤3:平移调整让鼻梁垂直
旋转后,调整所有点的X坐标,让27和8的X值相同:
# 取旋转后的27和8点的X坐标 x27_rot <- landmarks_rotated %>% filter(landmark_id == 27) %>% pull(x_rot) x8_rot <- landmarks_rotated %>% filter(landmark_id == 8) %>% pull(x_rot) # 计算X方向偏移量,将8点对齐到27点的X位置 x_shift <- x27_rot - x8_rot # 应用平移得到最终对齐后的坐标 landmarks_aligned <- landmarks_rotated %>% mutate( x_aligned = x_rot + x_shift, y_aligned = y_rot )
验证效果
可以通过代码检查对齐是否达标,或者绘制关键点可视化:
# 检查眼睛Y坐标是否一致 landmarks_aligned %>% filter(landmark_id %in% c(39,42)) %>% select(landmark_id, y_aligned) # 检查鼻梁X坐标是否相同 landmarks_aligned %>% filter(landmark_id %in% c(27,8)) %>% select(landmark_id, x_aligned) # 绘制对齐后的关键点(可选) library(ggplot2) ggplot(landmarks_aligned, aes(x = x_aligned, y = y_aligned)) + geom_point(size = 2, aes(color = factor(landmark_id))) + coord_fixed() + theme_minimal() + theme(legend.position = "none")
可选优化
- 可以更换旋转中心(比如用人脸中心点),避免人脸整体偏移;
- 如果需要统一人脸大小,对齐后可以加入缩放步骤,比如将眼睛间距固定为某个值;
- 处理多个人脸数据时,将上述逻辑封装成函数,用
group_by按人脸分组处理。
内容的提问来源于stack exchange,提问作者Myriad
相关产品推荐
相关产品推荐

