基於PaddleHub的人臉檢測:AI人臉打飛機(第2版)
第 1 版鏈接如下:
第 2 版的改進:
- 大幅增加流暢度
- 採用新的動作偵測算法,代碼縮減 100 行 +
- 修改遊戲背景
- 修正音樂 bug
- 修改部分飛機參數
效果視頻請看 B 站,鏈接如下:
基於PaddleHub的人臉檢測:AI人臉打飛機(第2版)附代碼
所有代碼和素材文件請見 GitHub:
github: planegame_head_control
關於頭部角度的算法:
原來使用的是歐拉角的算法,來進行頭部的角度計算
但是分析了一下以這個項目的需求來看,不需要精度太高的角度計算,所有其實可以採用簡化的算法來代替複雜的歐拉角計算
頭部角度檢測部分的代碼片段如下
class HeadPostEstimation():
"""
頭部姿態識別
"""
def __init__(self, face_detector=None):
self.module = hub.Module(name="face_landmark_localization", face_detector_module=face_detector)
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=True)
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_lips_distance(self, face_landmark):
"""
從face_landmark_localization的檢測結果中查看上下嘴唇的距離
"""
lips_points = np.array([
face_landmark[52], face_landmark[58]
], dtype='float')
head_points = np.array([
face_landmark[25], face_landmark[8]
], dtype='float')
lips_distance = np.sum(np.square(lips_points[0] - lips_points[1]))
head_distance = np.sum(np.square(head_points[0] - head_points[1]))
relative_distance = lips_distance / head_distance
return relative_distance
def get_nose_distance(self,face_landmark):
"""
從face_landmark_localization的檢測結果中獲得鼻子的位置,以此判斷頭部運動
"""
nose_point = np.array([
face_landmark[31]
], dtype='float')
cheek_points = np.array([
face_landmark[3], face_landmark[15]
], dtype='float')
left_distance = np.sum(np.square(nose_point[0] - cheek_points[0]))
right_distance = np.sum(np.square(nose_point[0] - cheek_points[1]))
nose_position_h = left_distance/(left_distance+right_distance)
nose_position_v = nose_point[0][1]-cheek_points[0][1] # 獲得鼻子和臉頰定位點的高度相對值,以此作為抬頭/低頭的判斷
return nose_position_h, nose_position_v
def classify_pose(self, video):
"""
video 表示不斷產生圖片的生成器
"""
for index, img in enumerate(video(), start=1):
self.img_size = img.shape
success, face_landmark = self.get_face_landmark(img)
if not success:
logger.info("Get face landmark localization failed! Please check your image!")
continue
if not success:
logger.info("Get rotation and translation vectors failed!")
continue
# 計算嘴唇距離
lips_distance = self.get_lips_distance(face_landmark)
# 計算鼻子左右位置
nose_position_h, nose_position_v = self.get_nose_distance(face_landmark)
# 轉換成攝像頭可顯示的格式
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 本地顯示預測視頻框,AIStudio項目不支持顯示視頻框
#cv2.imshow('Pose Estimation', img_rgb)
return nose_position_h, nose_position_v, lips_distance