赠书 | Python人脸五官姿态检测


赠书 | Python人脸五官姿态检测文章插图
赠书 | Python人脸五官姿态检测文章插图
作者 | 李秋键
出品 | AI科技大本营
近几个月来由于疫情的影响使得网络授课得到了快速的发展 , 人工智能作为最有潜力的发展行业 , 同样可以应用于网络授课的监督 。 比如通过检测人脸姿态 , 眼睛是否张开 , 鼻子嘴巴等特征 , 来达到监测专注度等情绪特征 。 故本文主要是基于Github项目搭建pytorch项目实现人脸姿态监测 。
此源码地址:
*文末有赠书福利
并且该算法已应用于以下两种产品:儿童在线教育 , 用于识别儿童是否认真听讲;现场会议或学校教室 , 以判断演讲质量 。
人脸检测是指从复杂的背景当中提取我们感兴趣的人脸图像 。 脸部毛发、化妆品、光照、噪声、人脸倾斜和大小变化及各种遮挡等因素都会有导致人脸检测问题变得更为复杂 。 人脸识别技术主要目的在于输入的整幅图像上寻找特定人脸区域 , 从而为后续的人脸识别做准备 。 其中三大关键技术:基于特征的人脸检测技术;基于模板匹配人脸检测技术;基于统计的人脸检测技术
一般常用的算法特点如下:
1、Dlib:面部关键点识别不准确 , 旋转或滚动面部时误差很大 。
2、虚拟3D模型:将关键点的识别与“2D到3D虚拟修复模型”进行比较非常不准确 , 因为每个人的面孔都不一样 。
3、3DDFA:效果很差 , 我不知道为什么有那么多“github星星” 。
4、通过卷积网络统计出关键点位图 , 角度也很不准确 。
赠书 | Python人脸五官姿态检测文章插图
赠书 | Python人脸五官姿态检测文章插图
实验前的准备首先我们使用的python版本是3.6.5所用到的模块如下:

  • opencv是将用来进行图像处理和生成 。
  • numpy模块用来处理矩阵数据的运算 。
  • pytorch模块是常用的用来搭建模型和训练的深度学习框架 。
  • math是python中用来存储一些常见的数学函数库 。

赠书 | Python人脸五官姿态检测文章插图
网络模型的定义和训练(1)脸部特征提取:使用Retinaface提取面部框架 , 然后使用PFLD识别面部关键点 。 最后 , 关键点被跟踪以估计面部姿势 。
def calculate_pitch_yaw_roll(landmarks_2D, cam_w=256, cam_h=256,radians=False):""" Return thethe pitch yaw and roll angles associatedwith the input image.@param radians When True itreturns the angle in radians, otherwise in degrees."""assert landmarks_2D is not None,'landmarks_2D is None'# Estimated camera matrixvalues.c_x = cam_w / 2c_y = cam_h / 2f_x = c_x / np.tan(60 / 2 *np.pi / 180)f_y = f_xcamera_matrix =np.float32([[f_x, 0.0, c_x], [0.0, f_y, c_y],[0.0, 0.0, 1.0]])camera_distortion =np.float32([0.0, 0.0, 0.0, 0.0, 0.0])# dlib (68 landmark) trachedpoints# TRACKED_POINTS = [17, 21, 22,26, 36, 39, 42, 45, 31, 35, 48, 54, 57, 8]# wflw(98 landmark) trachedpoints# TRACKED_POINTS = [33, 38, 50,46, 60, 64, 68, 72, 55, 59, 76, 82, 85, 16]# X-Y-Z with X pointing forwardand Y on the left and Z up.# The X-Y-Z coordinates used arelike the standard coordinates of ROS (robotic operative system)# OpenCV uses the referenceusually used in computer vision:# X points to the right, Y down,Z to the frontlandmarks_3D = np.float32([[6.825897, 6.760612,4.402142], # LEFT_EYEBROW_LEFT,[1.330353, 7.122144,6.903745], # LEFT_EYEBROW_RIGHT,[-1.330353, 7.122144,6.903745], # RIGHT_EYEBROW_LEFT,[-6.825897, 6.760612,4.402142], # RIGHT_EYEBROW_RIGHT,[5.311432, 5.485328,3.987654], # LEFT_EYE_LEFT,[1.789930, 5.393625,4.413414], # LEFT_EYE_RIGHT,[-1.789930, 5.393625,4.413414], # RIGHT_EYE_LEFT,[-5.311432, 5.485328,3.987654], # RIGHT_EYE_RIGHT,[-2.005628, 1.409845,6.165652], # NOSE_LEFT,[-2.005628, 1.409845,6.165652], # NOSE_RIGHT,[2.774015, -2.080775,5.048531], # MOUTH_LEFT,[-2.774015, -2.080775,5.048531], # MOUTH_RIGHT,[0.000000, -3.116408, 6.097667], # LOWER_LIP,[0.000000, -7.415691,4.070434], # CHIN])landmarks_2D =np.asarray(landmarks_2D, dtype=np.float32).reshape(-1, 2)# Applying the PnP solver tofind the 3D pose of the head from the 2D position of the landmarks.# retval - bool# rvec - Output rotation vectorthat, together with tvec, brings points from the world coordinate system to thecamera coordinate system.# tvec - Output translationvector. It is the position of the world origin (SELLION) in camera co-ords_, rvec, tvec =cv2.solvePnP(landmarks_3D, landmarks_2D,camera_matrix, camera_distortion)#Get as input the rotationalvector, Return a rotational matrix# const double PI = 3.141592653;# double thetaz = atan2(r21,r11) / PI * 180;# double thetay = atan2(-1 *r31, sqrt(r32*r32 + r33*r33)) / PI * 180;# double thetax = atan2(r32,r33) / PI * 180;rmat, _ = cv2.Rodrigues(rvec)pose_mat = cv2.hconcat((rmat,tvec))_, _, _, _, _, _, euler_angles =cv2.decomposeProjectionMatrix(pose_mat)return map(lambda k: k[0], euler_angles) # euler_angles contain (pitch,yaw, roll)


推荐阅读