Flask+人脸位姿检测—媒体大数据实验


前言

1.编写目的

一方面是分享思路(啥都搜不到真的好痛苦)
另一方面是记录一下,方便自己以后查(感谢提供资料的师哥师姐们和老师)

2.实验环境

操作系统:Win10
IDE:PyCharm 2021.3 (Community Edition)
Python:3.8

3.实现内容

捕捉面部关键点并实时视频展示,同时计算头部旋转角度并将数据存入mysql数据库;
通过flask驱动上述python程序运行,并读取其结果的mysql数据展示到前端页面,并添加echarts作图可视化。

4.实现过程

  1. 理解vtuber.py程序(捕捉面部关键点并视频绘制展示),为此给vtuber.py程序加了详细注释(数学计算方面的代码大脑自动略过了)
import cv2
import dlib
import numpy as np

DETECTOR = dlib.get_frontal_face_detector()  # 获得脸部位置检测器
PREDICTOR = dlib.shape_predictor('./data/shape_predictor_68_face_landmarks.dat')  # 获取人脸64关键点检测器


# 使⽤Dlib提取⾯部关键点

## 在img中寻找人脸,获取最大的人脸框的位置信息
def face_positioning(img):
    dets = DETECTOR(img, 0)  # 0表示采样(upsample)次数:0识别的人脸少点,1识别的多点,2识别的更多,小脸也可以识别
    if not dets:
        return None
    return max(dets, key=lambda det: (det.right() - det.left()) * (det.bottom() - det.top()))  # 返回面积最大的那张脸


## 提取面部关键点位置信息
def extract_key_points(img, position):
    landmark_shape = PREDICTOR(img, position)  # 寻找人脸的68个标定点
    key_points = []
    # 将68个关键点,每个点的x、y都以数组形式[x y]存入key_points中,并返回
    for i in range(68):
        pos = landmark_shape.part(i)
        key_points.append(np.array([pos.x, pos.y], dtype=np.float32))
    return key_points


# 计算面部特征

## 计算头部旋转三角形三个顶点(眉心、下巴、鼻子),每个点的中心位置
def generate_points(key_points):  # 生成构造点
    def center(array):
        return sum([key_points[i] for i in array]) / len(array)  # 得到相应部位的中点(应该是数组的计算吧,所以能够同时算出x和y的平均值,得到中点的数组[x y])

    left_brow = [18, 19, 20, 21]  # 左眉包含第18、19、20、21个特征点,下面同理
    right_brow = [22, 23, 24, 25]  # 右眉
    chin = [6, 7, 8, 9, 10]  # 下巴
    nose = [29, 30]  # 鼻子
    # 返回眉心、下巴、鼻子三个部位,每个部位的中点的位置数组
    return center(left_brow + right_brow), center(chin), center(nose)


## 计算头部旋转角度
def generate_features(contruction_points):  # 生成特征
    brow_center, chin_center, nose_center = contruction_points
    # 边向量
    mid_edge = brow_center - chin_center  # 眉心和下巴连线的连线
    bevel_edge = brow_center - nose_center  # 眉心和鼻子的连线
    # 计算长度
    mid_edge_length = np.linalg.norm(mid_edge)  # np.linalg.norm求范数
    # 计算头部水平旋转角度(计算 mid_edge 与 bevel_edge 向量积,可得到以这两个向量为边的平⾏四边形⾯积;⿐⼦转过的⾼度 = 平⾏四边形⾯积 / 中线⻓度)
    horizontal_rotation = np.cross(mid_edge, bevel_edge) / mid_edge_length ** 2  # 高与底的比值
    # 计算头部垂直旋转角度(计算 mid_edge 与 bevel_edge 数量积,再除以两次中线⻓度可以得到⽐值)
    vertical_rotation = mid_edge @ bevel_edge / mid_edge_length ** 2  # @ 点乘
    return np.array([horizontal_rotation, vertical_rotation])


# 绘图

## 手绘窗口
def draw_image(h_rotation, v_rotation):  # 画脸
    img = np.ones([512, 512], dtype=np.float32)  # [512,512]大小的画面
    face_length = 200
    center = 256, 256  # 画面中心
    left_eye = int(220 - h_rotation * face_length), int(
        249 + v_rotation * face_length)  # h_rotation: 水平旋转量,v_rotation: 垂直旋转量
    right_eye = int(292 - h_rotation * face_length), int(249 + v_rotation * face_length)
    month = int(256 - h_rotation * face_length / 2), int(310 + v_rotation * face_length / 2)
    # 画出脸和三个部位
    cv2.circle(img, center, 100, 0, 1)  # 参数分别为图片、圆心、半径、颜色、圆形轮廓的粗细(如果为正,负厚度表示要绘制实心圆)
    cv2.circle(img, left_eye, 15, 0, 1)
    cv2.circle(img, right_eye, 15, 0, 1)
    cv2.circle(img, month, 5, 0, 1)
    return img


## 摄像头窗口图像处理
def extract_img_features(img):  # 提取图片特征
    # 获取人脸位置信息
    face_position = face_positioning(img)

    # 如果没有获取到面部关键点(没有检测到脸)的时候,输出原图像(摄像头原画面)
    if not face_position:
        cv2.imshow('self', img)
        cv2.waitKey(1)
        return None

    # 如果获取了面部关键点(检测到脸)了的时候:
    key_points = extract_key_points(img, face_position)  # 根据人脸位置,获取面部关键点位置信息[x y]
    # 在图像上,每个关键点的位置上,绘制信息(第i个)
    for i, (p_x, p_y) in enumerate(key_points):  # enumerate使得key_points中每个元素具有索引i
        cv2.putText(img, str(i), (int(p_x), int(p_y)),
                    cv2.FONT_HERSHEY_COMPLEX, 0.25,
                    (255, 255, 255))  # cv2.FONT_HERSHEY_COMPLEX及其往后分别是字体样式、字体大小、字体颜色、(字体粗细)
    # 在图像上,绘制出头部旋转三角形三个点的位置(标上0,1,2)
    construction_points = generate_points(key_points)  # 获取头部旋转三角形三个部位的中点位置数组
    for i, (p_x, p_y) in enumerate(construction_points):
        cv2.putText(img, str(i), (int(p_x), int(p_y)),
                    cv2.FONT_HERSHEY_COMPLEX, 0.25, (255, 0, 0))
    # 计算头部水平、垂直旋转角度,并绘制在图上的鼻子位置
    rotation = generate_features(construction_points)
    cv2.putText(img, str(rotation),
                (int(construction_points[-1]
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值