Mediapipe+OpenCV图像识别技术与Unity引擎的结合-Part2

2023-11-13

前言

之前写了一篇文章:# Mediapipe+OpenCV图像识别技术与Unity引擎的结合

其中的技术是Python利用OpenCV图像捕捉,配合强大的Mediapipe库来实现人体动作检测与识别;将识别结果实时同步至Unity中,实现人物模型在Unity中运动身体结构识别

技术更新

因为之前的人物动作捕捉是先通过PythonMediapipe先将人物动作进行捕捉,将捕捉到的数据format后写入到txt中,在Unity端对txt进行数据读取,进而实现Unity人物运动;其中的缺点是:没有时效性

而本次的改进:通过利用socket和UPD通信,在localhost中数据传输,让动捕数据实时传输,到达实时动捕的效果

Demo演示

之前的Demo展示:https://hackathon2022.juejin.cn/#/works/detail?unique=WJoYomLPg0JOYs8GazDVrw
在这里插入图片描述
在这里插入图片描述

更新后效果

在这里插入图片描述

可以和珈乐同步互动…

YouCut_20220528_225044263_1.gif

本篇文章所用的技术会整理后开源,后续可以持续关注:
项目地址:https://github.com/BIGBOSS-dedsec/OpenCV-Unity-To-Build-3DPerson

GitHub:https://github.com/BIGBOSS-dedsec

CSDN: https://blog.csdn.net/weixin_50679163?type=edu

同时本篇文章实现的技术参加了稀土掘金2022编程挑战赛-游戏赛道-优秀奖
作品展示:https://hackathon2022.juejin.cn/#/works/detail?unique=WJoYomLPg0JOYs8GazDVrw
alt

认识Mediapipe

项目的实现,核心是强大的Mediapipe ,它是google的一个开源项目:

功能 详细
人脸检测 FaceMesh 从图像/视频中重建出人脸的3D Mesh
人像分离 从图像/视频中把人分离出来
手势跟踪 21个关键点的3D坐标
人体3D识别 33个关键点的3D坐标
物体颜色识别 可以把头发检测出来,并图上颜色

Mediapipe Dev
在这里插入图片描述
以上是Mediapipe的几个常用功能 ,这几个功能我们会在后续一一讲解实现
Python安装Mediapipe

pip install mediapipe==0.8.9.1

也可以用 setup.py 安装
https://github.com/google/mediapipe

项目环境

Python 3.7
Mediapipe 0.8.9.1
Numpy 1.21.6
OpenCV-Python 4.5.5.64
OpenCV-contrib-Python 4.5.5.64

在这里插入图片描述
实测也支持Python3.8-3.9

身体动作捕捉部分

身体数据文件

这部分是我们通过读取视频中人物计算出每个特征点信息进行数据保存,这些信息很重要,后续在untiy中导入这些动作数据
**加粗样式**
关于身体特征点
**加粗样式**

核心代码

摄像头捕捉部分:

import cv2

cap = cv2.VideoCapture(0)       #OpenCV摄像头调用:0=内置摄像头(笔记本)   1=USB摄像头-1  2=USB摄像头-2

while True:
    success, img = cap.read()
    imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)       #cv2图像初始化
    cv2.imshow("HandsImage", img)       #CV2窗体
    cv2.waitKey(1)      #关闭窗体

视频帧率计算

import time

#帧率时间计算
pTime = 0
cTime = 0

while True
cTime = time.time()
    fps = 1 / (cTime - pTime)
    pTime = cTime

    cv2.putText(img, str(int(fps)), (10, 70), cv2.FONT_HERSHEY_PLAIN, 3,
                (255, 0, 255), 3)       #FPS的字号,颜色等设置

身体动作捕捉:

while True:
    if bboxInfo:
        lmString = ''
        for lm in lmList:
            lmString += f'{lm[1]},{img.shape[0] - lm[2]},{lm[3]},'
        posList.append(lmString)

数据传输:

# 定义localhost和端口
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
serverAddressPort = ("127.0.0.1", 5054)

# 数据发送
date = lmString
sock.sendto(str.encode(str(date)), serverAddressPort)

在这里插入图片描述

完整代码

MotionCapPRO.py

import cv2
from cvzone.PoseModule import PoseDetector
import socket

# cap = cv2.VideoCapture('1.mp4')
cap = cv2.VideoCapture(0)

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
serverAddressPort = ("127.0.0.1", 5054)      # 定义localhost与端口,当然可以定义其他的host

detector = PoseDetector()
posList = []    # 保存到txt在unity中读取需要数组列表

while True:
    success, img = cap.read()
    img = detector.findPose(img)
    lmList, bboxInfo = detector.findPosition(img)

    if bboxInfo:
        lmString = ''
        for lm in lmList:
            lmString += f'{lm[1]},{img.shape[0] - lm[2]},{lm[3]},'
        posList.append(lmString)

    # print(len(posList))       
    print(lmString)
    date = lmString
    sock.sendto(str.encode(str(date)), serverAddressPort)

    cv2.imshow("Image", img)
    key = cv2.waitKey(1)
    # 记录数据到本地
    # if key == ord('r'):    
    with open("MotionData.txt", 'w') as f:
        f.writelines(["%s\n" % item for item in posList])

运行效果

在这里插入图片描述
在这里插入图片描述

Unity 部分

建模

在Unity中,我们需要搭建一个人物的模型,这里需要一个33个Sphere作为身体的特征点33个Cube作为中间的支架
具体文件目录如下:
在这里插入图片描述
Line的编号对应人物模型特征点
在这里插入图片描述

UPD.cs (用于接收端口数据)

using UnityEngine;
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;

public class UDPReceive : MonoBehaviour
{

    Thread receiveThread;
    UdpClient client; 
    public int port = 5052;
    public bool startRecieving = true;
    public bool printToConsole = false;
    public string data;


    public void Start()
    {

        receiveThread = new Thread(
            new ThreadStart(ReceiveData));
        receiveThread.IsBackground = true;
        receiveThread.Start();
    }
    
    private void ReceiveData()
    {

        client = new UdpClient(port);
        while (startRecieving)
        {
            try
            {
                IPEndPoint anyIP = new IPEndPoint(IPAddress.Any, 0);
                byte[] dataByte = client.Receive(ref anyIP);
                data = Encoding.UTF8.GetString(dataByte);

                if (printToConsole) { print(data); }
            }
            catch (Exception err)
            {
                print(err.ToString());
            }
        }
    }
}

image.png

image.png
(水印是我的,非盗用)

Line.cs

这里是每个Line对应cs文件,实现功能:使特征点和Line连接在一起

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class LineCode : MonoBehaviour
{

    LineRenderer lineRenderer;

    public Transform origin;
    public Transform destination;

    void Start()
    {
        lineRenderer = GetComponent<LineRenderer>();
        lineRenderer.startWidth = 0.1f;
        lineRenderer.endWidth = 0.1f;
    }
// 连接两个点
    void Update()
    {
        lineRenderer.SetPosition(0, origin.position);
        lineRenderer.SetPosition(1, destination.position);
    }
}

Action.cs

这里是读取上文识别并保存的人物动作数据并将每个子数据循环遍历到每个Sphere点,使特征点随着视频中人物动作运动

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class body : MonoBehaviour
{
    // Start is called before the first frame update
    public UDPReceive udpReceive;
    public GameObject[] bodyPoints;
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        string data = udpReceive.data;
        
        // data = data.Remove(0, 1);
        // data = data.Remove(data.Length - 1, 1);
        print(data);
        string[] points = data.Split(',');
        print(points[0]);

        //0        1*3      2*3
        //x1,y1,z1,x2,y2,z2,x3,y3,z3

        for (int i = 0; i < 32; i++)
        {

            float x = float.Parse(points[0 + (i * 3)]) / 100;
            float y = float.Parse(points[1 + (i * 3)]) / 100;
            float z = float.Parse(points[2 + (i * 3)]) / 300;

            bodyPoints[i].transform.localPosition = new Vector3(x, y, z);

        }

    }
}

最终实现效果

这里的视频与Unity运行有延时
YouCut_20220528_225044263_1.gif
Good Luck,Have Fun and Happy Coding!!!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Mediapipe+OpenCV图像识别技术与Unity引擎的结合-Part2 的相关文章

  • 查找公因数以将浮点数列表转换为整数列表

    我有一个来自其他函数的浮点数列表 我所知道的是 在理想世界中存在一个共同因素 可用于将每一项相乘以获得整数列表 可能存在一些小的数值噪声 1e 14 例如 2 3333333333333335 4 666666666666667 1 0 1
  • Python - Pandas - 将特定函数应用于给定级别 - 多索引数据帧

    我有一个多索引 DataFrame 并且我希望仅对分配给我的级别之一的向量应用一些计算 使用下面的代码 import pandas as pd import datetime ticker date US datetime date tod
  • Django - 未找到“”的反向。 '' 不是有效的视图函数或模式名称

    我正在研究我的课程项目 但现在我完全陷入困境 我正在创建一个网站通过 PayPal 销售产品 但 PayPal 退货 取消页面未正确呈现 我已经按照课程中的示例检查了代码一百次 但显然我遗漏了一些东西 当我转到产品 单击 立即购买 登录 P
  • 根据日期列过滤并创建列

    我有一个样本数据如下 date Deadline 2018 08 01 2018 08 11 2018 09 18 2018 12 08 2018 12 18 我想用代码中描述的条件填写截止日期列 如 1 DL 2 DL 3 DL 等 基于
  • 使用组合时如何解决循环依赖?

    我遇到了如下所示的情况 其中每个类都需要另一个类 并且它创建了循环依赖关系 我在使用 ctypes 包装一些 C 代码时遇到了这种情况 已经有很多关于这个主题的帖子 但我发现它们没有帮助 我需要一些例子 Module A from B im
  • 表单输入框不显示

    我正在尝试使用 Django 显示一个简单的表单输入文本框 我正在亚马逊 AWS 上部署 该网站在不同的服务器 pythonanywhere 上运行良好 但在 AWS 上存在主要问题 具体来说 输入框没有被显示 我使用的模板如下 首页 ht
  • 使用 python 将 bibtex 文件转换为 html (也许是 pybtex?)

    您好 我想解析 bibtex 出版物文件并对特定字段 例如年份 进行排序并过滤某些内容 然后将其放在网站上 我遇到了 pybtex 它可以读取和解析 bibtex 文件 但它基本上没有记录 我不知道如何对条目进行排序 pybtex 是可行的
  • python:如何检查一行是否为空行

    试图弄清楚如何编写一个 if 循环来检查一行是否为空 该文件有许多字符串 其中之一是一个空行 用于与其他语句分隔开 不是 我认为是一个回车符后面跟着另一个回车符 new statement asdasdasd asdasdasdasd ne
  • 根据另一个非索引数组中的值从 numpy 数组中选择元素

    假设我有以下两个数组 a array 1 L 74 423088306605 5 H 128 05441039929008 2 L 68 0581377353869 0 H 88 15726964130869 4 L 97 45015825
  • 是否可以使用 csv.DictReader 保持列顺序?

    例如 我的 csv 有如下列 ID ID2 Date Job No Code 我需要以相同的顺序写回各列 这dict立即打乱了顺序 所以我相信这更多是读者的问题 蟒蛇的dicts 在 3 6 之前不维持顺序 但是 无论如何 在该版本中csv
  • 使用Python处理Sqlite数据库中的换行符“\n”?

    我有一个名为 test db 的 Sqlite 数据库 其中包含两个表 其结构如下 表 1 ID 整数主键自动增量 名称 varchar 500 颜色 varchar 500 表2 ID INTEGER PRIMARY KEY AUTOIN
  • Groupby Sum 忽略几列

    在此数据框中 我想按 位置 进行分组并获得 分数 的总和 但我不希望 纬度 经度 和 年份 在此过程中受到影响 sample pd DataFrame Location A B C A B C Year 2001 2002 2003 200
  • 与 GridSearchCV 的并行错误,与其他方法一起工作正常

    我使用 GridSearchCV 时遇到以下问题 它在使用时给我一个并行错误n jobs gt 1 同时n jobs gt 1与 RadonmForestClassifier 等单一模型配合良好 下面是一个显示错误的简单工作示例 train
  • 函数内部变量的赋值会改变外部的赋值 - Python

    我从使用 Matlab 转向使用 Python 使用函数时的变量赋值让我感到困惑 我有一个代码如下 a 1 1 1 def keeps x y x y 1 2 return y def changes x y x y 1 2 return
  • 使用字典时如何避免 KeyError?

    现在我正在尝试编写汇编程序 但我不断收到此错误 Traceback most recent call last File Users Douglas Documents NeWS py line 44 in if item in regis
  • 将 tf.contrib.layers.xavier_initializer() 更改为 2.0.0

    我该如何改变 tf contrib layers xavier initializer tf 版本 gt 2 0 0 所有代码 W1 tf get variable W1 shape self input size h size initi
  • 使用 matplotlib 在 python3 中对多个形状进行动画处理

    尝试在 python3 中使用 matplotlib 动画函数同时对多个对象进行动画处理 下面写的代码是我到目前为止的位置 我能够创建多个对象并将它们显示在图中 我通过使用包含矩形补丁函数的 for 循环来完成此操作 从这里开始 我希望通过
  • 在视图之间共享并在 AppConfig 中初始化的变量

    我想要一个在应用程序启动时初始化的变量 并且可以从视图访问该变量 my app my config py class WebConfig AppConfig name verbose name def ready self print lo
  • 将 pi 打印到小数点后几位

    w3resources 面临的挑战之一是将 pi 打印到小数点后 n 位 这是我的代码 from math import pi fraser str pi length of pi number of places raw input En
  • Django中的自动递增值

    我在 django 中有一个表并尝试自动递增它的序列号 在自定义模板中 for 循环用于变量 自定义模板 for i in getodeskview tr td 1 td td i odesk id td td i hours td td

随机推荐

  • phpshe v1.7漏洞复现(Sql injection+XXE)

    前几天研究了一下xss的绕过 这两天准备深入研究下sql注入的审计 首先自动审计一波 看到疑似的一个变量覆盖点 点进去看原来是 register globals的隐患消除 简单来说如果这个配置设置为On的话 从客户端传输过来的任意参数值会被
  • jboss 热部署

    文章目录 JBoss EAP 6 4 0 GA AS 7 5 0 Final redhat 21 JBoss EAP 6 4 0 GA AS 7 5 0 Final redhat 21
  • 一文学会动态规划

    系列文章目录 注意 在学习理论之前 希望读者能看如下几个例子 有助于理解 算法导论 学习 十七 动态规划之钢条切割 C语言 算法导论 学习 十八 动态规划之矩阵链乘 C语言 算法导论 学习 十九 动态规划之最长公共子序列 C语言 文章目录
  • 浅谈数据挖掘——频繁模式、序列挖掘与搜索优化算法

    本系列将从下面几方面谈谈最近的一点点收获 令声明 本文主要是对我找到的一个莫名其妙国外英文pdf文件的学习与解读 因为我也没有找到他的出处 也没作者也没学校 所以我仅以此段文字向这个未知的作者致敬 本文主要处于科普类的理解 列出的主要算法并
  • SpringBoot学习之单点登录

    SpringBoot学习之单点登录 单点登录 登录 注销 部署 实现 主要功能 重要步骤 sso client拦截未登录请求 sso server拦截未登录请求 sso server验证用户登录信息 sso server创建授权令牌 sso
  • 直播运营岗

    一 理论知识 直播基础知识 直播团队构成 直播工作流程 中控工作流程 中控话术 二 界面操作 电商罗盘 巨量百应 直播伴侣 发单打单 产品链接 三 进阶学习 千川投放 直播复盘 四 面试规划 简历制作 职业生涯规划 1 直播基础知识 1 1
  • 银河麒麟桌面操作系统安装 postgreSQL13(源码安装)

    1 首先下载源码postgres wget http ftp postgresql org pub source v13 1 postgresql 13 1 tar bz2 2 解压 tar xjvf postgresql 13 1 tar
  • visual studio 2017 installer 安装包制作过程出现的问题---无法注册模块 HRESULT -2147024769 请与您的技术支持人员联系...

    使用visual studio 2017 installer制作打包程序时如果用到了外部控件需要按以下方式操作 1 将应用程序及应用程序所用到的所有DLL拷贝到打包目录 加入打包程序之中 2 将应用程序的XXX dll或XXX ocx的Re
  • STM32 C++编程系列一:STM32 C++编程介绍

    一 STM32及其他单片机开发现状 在目前绝大部分的单片机开发当中 C语言占据着主流的地位 但由于C语言本身是一种面向过程的语言 因此在当前利用面向对象思想构建可复用代码为主流的今天显得比较麻烦 很多人写单片机程序时都会遇到一个问题 明明写
  • 大数据采集概述

    文章目录 大数据采集概述 1 互联网大数据与采集 1 1互联网大数据来源 1 社交媒体 2 社交网络 3 百科知识库 4 新闻网站 5 评论信息 6 位置型信息 1 2 互联网大数据的特征 1 大数据类型和语义更加丰富 2 数据的规范化程度
  • 内存溢出问题解决思路

    内存溢出问题解决 一 常规解决思路 首先 在JVM参数配置时需要配置内存溢出后dump出内存的快照来 配置如下 XX HeapDumpOnOutOfMemoryError XX HeapDumpPath 内存快照 hprof输出路径 然后
  • 理解Java类加载的步骤

    前言 与在编译时需要进行 连接 工作的语言不同 在Java语言里 类的加载 连接 初始化过程都是在程序运行期间完成的 这种策略虽然牺牲了一小部分性能 但是大大增加了Java的灵活性 Java里天生可以动态拓展的语言特性就是依赖运行期动态加载
  • Linux线程同步(二)---互斥锁实现线程同步

    一 why 先给自己打个广告 本人的微信公众号 嵌入式Linux江湖 主要关注嵌入式软件开发 股票基金定投 足球等等 希望大家多多关注 有问题可以直接留言给我 一定尽心尽力回答大家的问题 在博客 Linux线程同步 一 初识篇 中 介绍了为
  • 基于STM32F407的人脸追踪

    整体概述 本项目采用两个舵机构成的二自由度的电动云台作为执行机构 控制摄像头在水平和垂直方向的运动 舵机带动摄像头进行二维平面的运动的同时 摄像头进行实时人脸检测 一旦检测到人脸 则进行人脸跟踪 摄像头采用星瞳openMV H7 主控采用的
  • (C语言)打印菱形图案 (15分)

    本题要求编写程序 打印一个高度为n的 由 组成的正菱形图案 输入格式 输入在一行中给出一个正的奇数n 输出格式 输出由n行星号 组成的菱形 如样例所示 每个星号后跟一个空格 输入样例 7 输出样例 通过点 模拟 include
  • EM算法估计beta混合模型参数

    1 用 network memerisation 造成的 clean noisy 数据 loss 差异来区分 clean noisy data 当得到一批数据的 normalised loss l i 0
  • android 填充,Android Drawable部分填充

    是的 如果您使用Layer List并定义重叠的项目 则是可能的 这是一个例子 android height 30dp gt android height 30dp gt 您可能需要尝试这些值 并根据需要进行调整 编辑 我认为您无法指定相对
  • MATLAB 添加自有的工具包

    我们经常会用到一些专业的MATLAB工具包 这些工具包下载好后应该如何添加呢 下面简单介绍 1 在命令行中敲入 pathtool 启动 设置路径 窗口 如下图所示 2 根据自己的需求 选择 添加文件夹 或者 添加并包含子文件夹 然后选择自己
  • linux 串口调试助手,COMTool: Cross platform Serial Assistant ( 跨平台 串口 调试 助手 串口助手 串口调试助手 linux windows mac R...

    COMTool A cross platform serial debug tools written by python Windows Linux Elementry OS Raspberry Pi3 screenshot shows
  • Mediapipe+OpenCV图像识别技术与Unity引擎的结合-Part2

    前言 之前写了一篇文章 Mediapipe OpenCV图像识别技术与Unity引擎的结合 其中的技术是Python利用OpenCV图像捕捉 配合强大的Mediapipe库来实现人体动作检测与识别 将识别结果实时同步至Unity中 实现人物