持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第二十天,点击查看活动详情
----20220625
聊天室更新了八篇,今天我们回到我们之前的头部动作姿态识别。关于姿态识别,我们前面的其实写过一篇关于这个的博客图片头部姿态检测(dlib+opencv) - 掘金 (juejin.cn),也就是我的项目笔记,我们项目主要是关于自闭症检测的,首先对于我们项目进行一个介绍吧
目前,自闭症是一种由多种生物因素引起的大脑广泛性发育障碍疾病,患有自闭症的儿童常常表现出不同程度的言语发育障碍、人际交往障碍、兴趣狭窄和行为方式刻板。这对自闭症儿童与同龄人的交流造成了很大困扰,甚至可能伴随患者终身。目前,针对于自闭症儿童的早期筛查,一直缺少可靠、便捷的测量和评估工具。传统的量表筛查方式,评估周期长,并且很大程度地依赖于家长或治疗师的主观意见,评估结果的准确性缺乏一定的保障。近年来,眼动追踪技术作为一种新兴技术,广泛地被应用在自闭症视觉模式的研究中。大量研究表明,自闭症儿童在面对社交等性质的刺激范式时,常常表现出异于正常儿童的头部动作模式。因此,头部姿态检测这项技术在自闭症的早筛与评估领域有着巨大的潜力。人工智能作为一种新兴技术,正释放出巨大的科技革命和产业变革能量,机器学习是人工智能的一个子集,在医疗保健行业,机器学习已经作为了某些病症的临床决策支持工具,能指导临床医生进行诊断和选择合适的治疗方法,提高护理人员的效率和提升治疗结果。但在自闭症筛查领域中,由于传统筛查方式的限制,整个过程不可避免需要依靠人力来完成,机器学习在该领域的应用显得有些缺乏。所以希望我的项目对于自闭症儿童的筛查有所帮助
在经过研究之后发现,自闭症儿童的yaw,picth,roll较正常儿童有一定的差别,所以重点检测这几个位置的数据值,之后通过监测数据建立模型
其实之前那篇文章,已经实现了头部姿态检测识别,但是存在一个问题,就是他只能通过照片来进行一个姿态的判定,判定结束之后,将结果输出在输出台,对于正常的自闭症儿童来说,一开始就进行一个拍照,其实不是很合理,于是我们这边现在改为了通过电脑自带摄像头进行识别,相应结果在屏幕上显示
源码部分
import cv2
import dlib
import numpy as np
from imutils import face_utils
# 脸部特征点模型
face_landmark_path = 'shape_predictor_68_face_landmarks.dat'
# 相机参数,用相机标定程序计算得到
K = [821.4438864, 0.0, 321.59586002,
0.0, 818.06766317, 222.64326701,
0.0, 0.0, 1.0]
D = [-1.21551899e-01, 8.80513056e-01, -7.98281873e-03, -3.46685305e-03, -3.83211727e+00]
# 相机矩阵
cam_matrix = np.array(K).reshape(3, 3).astype(np.float32)
dist_coeffs = np.array(D).reshape(5, 1).astype(np.float32)
# 14个特征点
object_pts = np.float32([[6.825897, 6.760612, 4.402142],
[1.330353, 7.122144, 6.903745],
[-1.330353, 7.122144, 6.903745],
[-6.825897, 6.760612, 4.402142],
[5.311432, 5.485328, 3.987654],
[1.789930, 5.393625, 4.413414],
[-1.789930, 5.393625, 4.413414],
[-5.311432, 5.485328, 3.987654],
[2.005628, 1.409845, 6.165652],
[-2.005628, 1.409845, 6.165652],
[2.774015, -2.080775, 5.048531],
[-2.774015, -2.080775, 5.048531],
[0.000000, -3.116408, 6.097667],
[0.000000, -7.415691, 4.070434]])
# 定义显示立方体的顶点
reprojectsrc = np.float32([[10.0, 10.0, 10.0],
[10.0, 10.0, -10.0],
[10.0, -10.0, -10.0],
[10.0, -10.0, 10.0],
[-10.0, 10.0, 10.0],
[-10.0, 10.0, -10.0],
[-10.0, -10.0, -10.0],
[-10.0, -10.0, 10.0]])
# 根据立方体顶点定义的边
line_pairs = [[0, 1], [1, 2], [2, 3], [3, 0],
[4, 5], [5, 6], [6, 7], [7, 4],
[0, 4], [1, 5], [2, 6], [3, 7]]
# 获得头部姿态
def get_head_pose(shape):
# 14个特征点
image_pts = np.float32([shape[17], shape[21], shape[22], shape[26], shape[36],
shape[39], shape[42], shape[45], shape[31], shape[35],
shape[48], shape[54], shape[57], shape[8]])
# 旋转向量与位移向量
_, rotation_vec, translation_vec = cv2.solvePnP(object_pts, image_pts, cam_matrix, dist_coeffs)
reprojectdst, _ = cv2.projectPoints(reprojectsrc, rotation_vec, translation_vec, cam_matrix,
dist_coeffs)
reprojectdst = tuple(map(tuple, reprojectdst.reshape(8, 2)))
# 计算欧拉角Euler
rotation_mat, _ = cv2.Rodrigues(rotation_vec)
pose_mat = cv2.hconcat((rotation_mat, translation_vec))
_, _, _, _, _, _, euler_angle = cv2.decomposeProjectionMatrix(pose_mat)
return reprojectdst, euler_angle
def main(index):
# 打开摄像头
cap = cv2.VideoCapture(index)
if not cap.isOpened():
print(f"[IO Error]无法连接至摄像头{index}.")
return
# 初始化检测器
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor(face_landmark_path)
while cap.isOpened():
ret, frame = cap.read()
if ret:
face_rects = detector(frame, 0)
if len(face_rects) > 0:
shape = predictor(frame, face_rects[0])
shape = face_utils.shape_to_np(shape)
reprojectdst, euler_angle = get_head_pose(shape)
if abs(euler_angle[1, 0]) < 5:
color = (0, 255, 0)
else:
color = (0, 0, 255)
for (x, y) in shape:
cv2.circle(frame, (x, y), 1, color, -1)
for start, end in line_pairs:
print(reprojectdst[start])
print(reprojectdst[end])
cv2.line(frame, (int(reprojectdst[start][0]),int(reprojectdst[start][1])), (int(reprojectdst[end][0]),int(reprojectdst[end][1])), color)
cv2.putText(frame, "X: " + "{:7.2f}".format(euler_angle[0, 0]), (20, 20), cv2.FONT_HERSHEY_SIMPLEX,
0.75, (0, 0, 0), thickness=2)
cv2.putText(frame, "Y: " + "{:7.2f}".format(euler_angle[1, 0]), (20, 50), cv2.FONT_HERSHEY_SIMPLEX,
0.75, (0, 0, 0), thickness=2)
cv2.putText(frame, "Z: " + "{:7.2f}".format(euler_angle[2, 0]), (20, 80), cv2.FONT_HERSHEY_SIMPLEX,
0.75, (0, 0, 0), thickness=2)
cv2.imshow("Camera Calibration", frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
if __name__ == '__main__':
temp = input("请输入待校准的相机编号(数字):")
temp = int(temp)
main(temp)