自学内容网 自学内容网

社恐人群的社交新宠:实时人脸融合互动应用

目录

简介

实现思路

1. 引入所需库

2. 人脸检测器和特征点模型的初始化

3. 打开摄像头

4. 选择覆盖的图片

5. 获取图片的尺寸

6. FPS计算初始化

7. 主循环处理每一帧

8. 人脸检测和特征点识别

9. 处理每一张检测到的人脸

10. 调整图片大小并叠加到人脸上

11. FPS计算和显示

12. 显示画面和退出条件

13. 释放资源

整体代码

原版

 显示部分脸部关键点版本

效果展示


简介

        在这个数字化日益渗透生活的时代,对于社交恐惧(社恐)群体而言,传统面对面的交流往往伴随着不小的心理压力和不安。为此这篇文章旨在成为社恐人群的福音,让他们的表达与互动更加自如、有趣且富有创意。

应用简介

       通过OpenCV和Dlib,巧妙结合高清摄像头与实时图像处理技术,实现了人脸的精准识别与跟踪。用户只需简单几步,即可将预先选择或即时拍摄的图片、贴纸、甚至是动态表情包,实时叠加在自己或他人的脸部区域上。更令人兴奋的是,这些图像元素能够随着人脸的自然移动而动态调整位置,保持完美的贴合与同步,仿佛成为你面部的一部分,让每一次眨眼、微笑都充满无限可能。

社恐人群的福音

  1. 安全社交距离:无需近距离接触,通过手机屏幕即可展现自我,有效减少社恐人群在社交场合中的紧张感,享受安全舒适的交流体验。
  2. 创意表达:提供丰富多样的图像素材库,从趣味贴纸到个性滤镜,让用户能够轻松打造出独一无二的形象,展现自我风格,打破传统社交的局限。
  3. 趣味互动:无论是线上聚会、视频通话还是直播分享,这款应用都能为参与者带来前所未有的互动乐趣,让沟通变得更加生动有趣,增进彼此间的理解和亲近感。
  4. 增强自信:通过趣味的人脸融合效果,社恐人群可以在轻松愉快的氛围中逐渐克服对社交的恐惧,提升自信心,享受与人交流的乐趣。


实现思路

通过摄像头实时检测人脸,并将用户选择的图片叠加在人脸区域上,图片会随脸部移动。程序还实时计算并显示当前帧率(FPS)。下面是实现思路的详细讲解:

1. 引入所需库

 
import cv2
import dlib
from tkinter import filedialog, Tk
import numpy as np
import time

  • cv2: 用于处理视频流、图像操作和显示。
  • dlib: 用于人脸检测和特征点识别。
  • filedialog & Tk: 用于弹出文件选择对话框,允许用户选择图片。
  • numpy: 用于处理图像和矩阵操作。
  • time: 用于计算FPS(每秒帧数)。

2. 人脸检测器和特征点模型的初始化

 
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')

  • detector: dlib.get_frontal_face_detector() 初始化人脸检测器,用于检测摄像头画面中的人脸。
  • predictor: 加载 68 点面部特征模型,该模型可以在每个人脸上识别出68个特定的点,用于后续调整图像覆盖在脸上。

3. 打开摄像头

 
cap = cv2.VideoCapture(0)

  • 通过 cv2.VideoCapture(0) 打开默认的摄像头,用于实时获取视频画面。

4. 选择覆盖的图片

 
root = Tk()
root.withdraw()
image_path = filedialog.askopenfilename(title="选择一张图片")
overlay_image = cv2.imread(image_path, -1)

  • 使用 Tkfiledialog 生成文件选择对话框,用户可以从文件系统中选择一张图片。
  • cv2.imread(image_path, -1) 用于读取图片,-1表示读取图片的四个通道(包括透明度通道)。

5. 获取图片的尺寸

 
overlay_h, overlay_w = overlay_image.shape[:2]

  • 获取用户选择的图片的高和宽,用于后续调整图片大小以适应人脸区域。

6. FPS计算初始化

 
fps = 0
prev_time = 0

  • 初始化 fpsprev_time 用于计算每秒的帧率,后面会通过两帧之间的时间差来计算当前帧率。

7. 主循环处理每一帧

 
while True:
    cur_time = time.time()
    ret, frame = cap.read()
    if not ret:
        break

  • 开始主循环,程序不断从摄像头获取帧数据。
  • 使用 cap.read() 捕获当前帧,frame 是当前的图像,ret 表示是否成功读取。
  • cur_time = time.time() 记录当前帧的时间,用于之后计算FPS。

8. 人脸检测和特征点识别

 
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = detector(gray)

  • 将每一帧转换为灰度图像,因为人脸检测在灰度图中更为高效。
  • 使用 detector(gray) 在灰度图上检测人脸,faces 是一个包含检测到的所有人脸信息的列表。

9. 处理每一张检测到的人脸

 
for face in faces:
    landmarks = predictor(gray, face)
    x1, y1 = face.left(), face.top()
    x2, y2 = face.right(), face.bottom()
    face_w = x2 - x1
    face_h = y2 - y1

  • 对于每一张检测到的人脸,使用 predictor 通过68个点识别面部特征。
  • 通过 face.left()face.top()face.right()face.bottom() 获取人脸的边界框,并计算其宽度 face_w 和高度 face_h

10. 调整图片大小并叠加到人脸上

 
resized_overlay = cv2.resize(overlay_image, (face_w, face_h))

  • 使用 cv2.resize() 将用户选择的图片调整为与人脸相同的大小。
 
if resized_overlay.shape[2] == 4:
    overlay = resized_overlay[:, :, :3]
    mask = resized_overlay[:, :, 3]
    mask = cv2.merge([mask, mask, mask])
    mask = mask / 255.0
else:
    overlay = resized_overlay
    mask = np.ones(overlay.shape, dtype=np.float32)

  • 如果图片带有Alpha通道(第四个通道),将Alpha通道用作透明度掩码,mask 用于控制图片透明部分。
  • 如果没有Alpha通道,创建一个全1的掩码。
 
roi = frame[y_offset:y_offset + face_h, x_offset:x_offset + face_w]
result = roi * (1 - mask) + overlay * mask
frame[y_offset:y_offset + face_h, x_offset:x_offset + face_w] = result.astype(np.uint8)

  • roi 是摄像头帧中与人脸区域相对应的部分。
  • 将处理后的图片与人脸区域叠加,考虑透明度,最终结果覆盖在摄像头的原始画面中。

11. FPS计算和显示

 
fps = 1 / (cur_time - prev_time)
prev_time = cur_time
cv2.putText(frame, f"FPS: {int(fps)}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)

  • 通过当前帧与前一帧的时间差计算 fps
  • 使用 cv2.putText() 将帧率显示在屏幕上。

12. 显示画面和退出条件

 
cv2.imshow("Face Overlay with FPS", frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
    break

  • cv2.imshow() 用于显示摄像头画面,并将图片叠加在人脸上。
  • cv2.waitKey(1) 检测键盘输入,如果按下了 q 键,退出循环。

13. 释放资源

 
cap.release()
cv2.destroyAllWindows()

  • 释放摄像头资源并关闭所有OpenCV窗口。


整体代码

原版

import cv2
import dlib
from tkinter import filedialog, Tk
import numpy as np
import time

# 初始化人脸检测器
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')  # 下载并加载68点模型

# 打开摄像头
cap = cv2.VideoCapture(0)

# 用于选择图片
root = Tk()
root.withdraw()  # 隐藏主窗口
image_path = filedialog.askopenfilename(title="选择一张图片")

# 读取选择的图片
overlay_image = cv2.imread(image_path, -1)  # 读取为带透明通道的图片

# 获取图片的高宽
overlay_h, overlay_w = overlay_image.shape[:2]

# 初始化FPS相关变量
fps = 0
prev_time = 0

# 主循环:不断获取摄像头画面并检测人脸
while True:
    # 获取当前时间,用于计算FPS
    cur_time = time.time()

    ret, frame = cap.read()
    if not ret:
        break

    # 将图像转换为灰度图,便于检测
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # 检测人脸
    faces = detector(gray)

    for face in faces:
        # 使用68点检测器检测面部特征点
        landmarks = predictor(gray, face)

        # 获取人脸的矩形区域
        x1, y1 = face.left(), face.top()
        x2, y2 = face.right(), face.bottom()
        face_w = x2 - x1
        face_h = y2 - y1

        # 调整图片大小以适应人脸
        resized_overlay = cv2.resize(overlay_image, (face_w, face_h))

        # 获取图片的透明度通道 (如果存在)
        if resized_overlay.shape[2] == 4:  # 如果图片有4个通道 (带Alpha通道)
            overlay = resized_overlay[:, :, :3]  # 图片的RGB部分
            mask = resized_overlay[:, :, 3]  # 图片的Alpha通道作为掩膜
            mask = cv2.merge([mask, mask, mask])  # 将Alpha通道扩展为3个通道
            mask = mask / 255.0  # 归一化到[0, 1]
        else:
            overlay = resized_overlay
            mask = np.ones(overlay.shape, dtype=np.float32)

        # 计算图片的放置位置
        x_offset = x1
        y_offset = y1

        # 获取原始图像的同一区域
        roi = frame[y_offset:y_offset + face_h, x_offset:x_offset + face_w]

        # 将图片叠加到脸上,考虑透明度
        result = roi * (1 - mask) + overlay * mask

        # 将叠加的结果放回原图像
        frame[y_offset:y_offset + face_h, x_offset:x_offset + face_w] = result.astype(np.uint8)

    # 计算FPS
    fps = 1 / (cur_time - prev_time)
    prev_time = cur_time

    # 在图像上显示FPS
    cv2.putText(frame, f"FPS: {int(fps)}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)

    # 显示实时效果
    cv2.imshow("Face Overlay with FPS", frame)

    # 按下'q'键退出
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# 释放摄像头并关闭窗口
cap.release()
cv2.destroyAllWindows()

 显示部分脸部关键点版本

import cv2
import dlib
from tkinter import filedialog, Tk
import numpy as np
import time

# 初始化人脸检测器
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')  # 下载并加载68点模型

# 打开摄像头
cap = cv2.VideoCapture(0)

# 用于选择图片
root = Tk()
root.withdraw()  # 隐藏主窗口
image_path = filedialog.askopenfilename(title="选择一张图片")

# 读取选择的图片
overlay_image = cv2.imread(image_path, -1)  # 读取为带透明通道的图片

# 获取图片的高宽
overlay_h, overlay_w = overlay_image.shape[:2]

# 初始化FPS相关变量
fps = 0
prev_time = 0

# 定义需要显示的关键点索引
important_points = [36, 39, 42, 45, 30, 48, 54, 8]

# 主循环:不断获取摄像头画面并检测人脸
while True:
    # 获取当前时间,用于计算FPS
    cur_time = time.time()

    ret, frame = cap.read()
    if not ret:
        break

    # 将图像转换为灰度图,便于检测
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # 检测人脸
    faces = detector(gray)

    for face in faces:
        # 使用68点检测器检测面部特征点
        landmarks = predictor(gray, face)

        # 获取人脸的矩形区域
        x1, y1 = face.left(), face.top()
        x2, y2 = face.right(), face.bottom()
        face_w = x2 - x1
        face_h = y2 - y1

        # 调整图片大小以适应人脸
        resized_overlay = cv2.resize(overlay_image, (face_w, face_h))

        # 获取图片的透明度通道 (如果存在)
        if resized_overlay.shape[2] == 4:  # 如果图片有4个通道 (带Alpha通道)
            overlay = resized_overlay[:, :, :3]  # 图片的RGB部分
            mask = resized_overlay[:, :, 3]  # 图片的Alpha通道作为掩膜
            mask = cv2.merge([mask, mask, mask])  # 将Alpha通道扩展为3个通道
            mask = mask / 255.0  # 归一化到[0, 1]
        else:
            overlay = resized_overlay
            mask = np.ones(overlay.shape, dtype=np.float32)

        # 计算图片的放置位置
        x_offset = x1
        y_offset = y1

        # 获取原始图像的同一区域
        roi = frame[y_offset:y_offset + face_h, x_offset:x_offset + face_w]

        # 将图片叠加到脸上,考虑透明度
        result = roi * (1 - mask) + overlay * mask

        # 将叠加的结果放回原图像
        frame[y_offset:y_offset + face_h, x_offset:x_offset + face_w] = result.astype(np.uint8)

        # 只绘制最关键的几个点
        for n in important_points:
            x = landmarks.part(n).x
            y = landmarks.part(n).y
            cv2.circle(frame, (x, y), 2, (0, 0, 255), -1)  # 使用红色圆点标记

    # 计算FPS
    fps = 1 / (cur_time - prev_time)
    prev_time = cur_time

    # 在图像上显示FPS
    cv2.putText(frame, f"FPS: {int(fps)}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)

    # 显示实时效果
    cv2.imshow("Face Overlay with FPS and Important Landmarks", frame)

    # 按下'q'键退出
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# 释放摄像头并关闭窗口
cap.release()
cv2.destroyAllWindows()

 


 

效果展示

社恐神器效果展示


原文地址:https://blog.csdn.net/DDDDWJDDDD/article/details/142354161

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!