一、摘要背景
随着科技的发展,对于人脸识别技术的应用已经影响到人们生活的方方面面,另外,PaddleHub 近期发布了人脸关键点检测模型face_landmark_localization,该模型转换自 https://github.com/lsy17096535/face-landmark ,支持同一张图中的多个人脸检测。它可以识别人脸中的68个关键点。这个模型成为这项技术的重要支撑。所以,我想利用这项技术做一个简单的头部姿态识别项目。
物体相对于相机的姿态可以使用旋转矩阵和平移矩阵表示。可以用世界坐标系,相机坐标系,像素坐标系等等。
得到旋转矩阵后就可以计算欧拉角。
二、项目主要代码
2.1安装paddlehub环境
import paddle.fluid
paddle.fluid.install_check.run_check()
2.2载入模块,加入所引用的目录
import cv2 import numpy as np import paddlehub as hub from paddlehub.common.logger import logger import time import math import os
2.3加载头部关键点坐标,头部投影点坐标以及投影点连线坐标
# 头部关键点坐标 self.model_points = np.array([ [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], [-7.308957, 0.913869, 0.000000], [7.308957, 0.913869, 0.000000], [0.746313,0.348381,6.263227], [0.000000,0.000000,6.763430], [-0.746313,0.348381,6.263227], ], dtype='float') # 头部投影点坐标 self.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]]) # 头部投影点连线坐标 self.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] ]
2.4预测人脸的68个关键点坐标,从face_landmark_localization的检测结果抽取姿态估计需要的点坐标
def get_face_landmark(self, image): """ 预测人脸的68个关键点坐标 images(ndarray): 单张图片的像素数据 """ try: # 选择GPU运行,use_gpu=True,并且在运行整个教程代码之前设置CUDA_VISIBLE_DEVICES环境变量 res = self.module.keypoint_detection(images=[image], use_gpu=False) return True, res[0]['data'][0] except Exception as e: logger.error("Get face landmark localization failed! Exception: %s " % e) return False, None def get_image_points_from_landmark(self, face_landmark): """ 从face_landmark_localization的检测结果抽取姿态估计需要的点坐标 """ image_points = np.array([ face_landmark[17], face_landmark[21], face_landmark[22], face_landmark[26], face_landmark[36], face_landmark[39], face_landmark[42], face_landmark[45], face_landmark[31], face_landmark[35], face_landmark[48], face_landmark[54], face_landmark[57], face_landmark[8], face_landmark[14], face_landmark[2], face_landmark[32], face_landmark[33], face_landmark[34], ], dtype='float') return image_points def caculate_pose_vector(self, image_points): """
2.5获取旋转向量和平移向量
# 相机视角 center = (self.img_size[1]/2, self.img_size[0]/2) focal_length = center[0] / np.tan(60/ 2 * np.pi / 180) camera_matrix = np.array([ [focal_length, 0, center[0]], [0, focal_length, center[1]], [0, 0, 1]], dtype = "float") dist_coeffs = np.zeros((4,1)) success, rotation_vector, translation_vector= cv2.solvePnP(self.model_points, image_points, camera_matrix, dist_coeffs) reprojectdst, _ = cv2.projectPoints(self.reprojectsrc, rotation_vector, translation_vector, camera_matrix, dist_coeffs) return success, rotation_vector, translation_vector, camera_matrix, dist_coeffs, reprojectdst def caculate_euler_angle(self, rotation_vector, translation_vector):
2.6将旋转向量转换为欧拉角
rvec_matrix = cv2.Rodrigues(rotation_vector)[0] proj_matrix = np.hstack((rvec_matrix, translation_vector)) euler_angles = cv2.decomposeProjectionMatrix(proj_matrix)[6] pitch, yaw, roll = [math.radians(_) for _ in euler_angles] return pitch, yaw, roll
2.7表示出投影立方体
alpha=0.3 if not hasattr(self, 'before'): self.before = reprojectdst else: reprojectdst = alpha * self.before + (1-alpha)* reprojectdst reprojectdst = tuple(map(tuple, reprojectdst.reshape(8, 2))) for start, end in self.line_pairs: cv2.line(img, reprojectdst[start], reprojectdst[end], (0, 0, 255))
2.8作品示例
三、收获与总结
经过这几周的暑期实践过程,我深感学习程序语言的不容易,以及我在这方面知识的匮乏。这几周我经常在mooc上面学习python这门语言的相关用法。即便如此,做出这个项目也是非常不容易。这个过程中出现了很多错误,语法不正确,无法显示坐标系等等。我询问同学,不断改进,才勉强运行。学习本来就不是一蹴而就的,我以后会多加练习,尝试着做一些简单的项目去增加自己的知识,提升自己撰写代码的能力。
参考文献:
https://aistudio.baidu.com/aistudio/projectdetail/369186
https://zhuanlan.zhihu.com/p/51208197
https://www.icourse163.org/search.htm?search=python%E5%9F%BA%E6%9C%AC%E7%94%A8%E6%B3%95#/
https://www.paddlepaddle.org.cn/