m
在本教程中,我们将学习如何使用python中的mediapipe库进行实时3D骨架检测。
首先,我们得用pip下载下来我们需要用到的模组:
pip install mediapipe
这个工具不仅得到了谷歌的支持,而且Mediapipe中的模型也被积极地用于谷歌产品中。因此,这个模组,超级牛皮。
现在,MediaPipe的姿势检测是高保真(高质量)和低延迟(超快)的最先进的解决方案,用于在低端设备(即手机,笔记本电脑等)的实时视频源中检测一个人的33个3D地标。
pip install opencv-python
Opencv-python简称cv2, 是一个超级牛皮的模组(比mediapipe还牛皮),他可以打开你的摄像头,并且还能回去每一帧的图像并显示出来(详情请见opencv的教程),关键是,cv2还有C++和Java版的。
pip install numpy
Numpy, 为矩阵计算而生,是一个专门计算矩阵的模组,cv2会用到它。
pip install vpython
大家应该不是那么的熟悉这个模组,用来在3D中布点的。但是因为简洁且迅速的更新速度,让我选择了这个模组(主要是因为害怕会掉帧)
P.S python需要定在python 3.0 以上
接下来,就是骨架预测的操作。
首先,导入所有我们需要的模组:
import cv2
import mediapipe as mp
from vpython import *
然后来了解一下mediapipe里骨架预测模块的初始化:
import cv2
import mediapipe as mp
from vpython import *
mp_pose = mp.solutions.pose #从mediapipe里面获取pose
pose = mp_pose.Pose(static_image_mode=False, min_detection_confidence=0.5, model_complexity=1) #初始化
Static_image_mode -这是一个布尔值,如果设置为False,检测器只在需要时调用,在第一帧或当跟踪器丢失跟踪时。如果设置为True,则对每个输入图像调用人员检测器。当你处理一堆不相关的图像而不是视频时,你应该把这个设为True。默认值为False。
Min_detection_confidence—考虑骨架检测模型的预测正确性所需的最小检测置信范围(0.0,1.0)。默认值为0.5。这意味着如果一个检测器的预测置信度大于或等于50%,则被认为是阳性的。
Min_tracking_confidence -这是骨架关节点跟踪模型为了有效跟踪地标的姿态,需要考虑的最小跟踪置信度([0.0,1.0])。如果置信度小于设定值,则在下一帧/图像中再次调用检测器,因此增加其值会增加稳定性,但也会造成延迟。默认值为0.5。
Model_complexity—骨架检测模型的复杂性。由于有三种不同的模型可供选择,可能的值为0、1或2。值越高,结果越准确,但代价是延迟越长。缺省值为1。
Smooth_landmarks -这是一个布尔值,如果设置为True,将过滤不同帧的骨架关节点以减少噪音。只有当static_image_mode也设置为False时,这才有效。默认值为True。
mp_drawing = mp.solutions.drawing_utils
mp_drawing 是为了可视化关节点于它们之间的关系初始化的
然后,咱们来搞一下摄像头的初始化:
cam = cv2.VideoCapture(0) #开启摄像头
while True:
_, frame = cam.read() #获取每一帧
cv2.imshow('real time', frame) #显示每一帧
if cv2.waitKey(1) == ord(q): #检查是否按下q键
break
cam.release() #关掉摄像头
cv2.destroyAllWindows() #关掉窗口
到现在为止,你的代码应该是这样的:
import cv2
import mediapipe as mp
from vpython import *
mp_pose = mp.solutions.pose #从mediapipe里面获取pose
pose = mp_pose.Pose(static_image_mode=False, min_detection_confidence=0.5, model_complexity=1) #初始化
mp_drawing = mp.solutions.drawing_utils
cam = cv2.VideoCapture(0) #开启摄像头
while True:
_, frame = cam.read() #获取每一帧
cv2.imshow('real time', frame) #显示每一帧
if cv2.waitKey(1) == ord(q): #检查是否按下q键
break
cam.release() #关掉摄像头
cv2.destroyAllWindows() #关掉窗口
现在,我们将使用函数 mp.solutions.pose.Pose().process() 将图像传递到姿势检测机器学习管道。但是管道需要RGB颜色格式的输入图像,因此首先我们必须使用函数cv2.cvtColor()将示例图像从BGR转换为RGB格式,因为OpenCV以BGR格式(而不是RGB)读取图像:
results = pose.process(cv2.cvtColor(f, cv2.COLOR_BGR2RGB))
执行姿势检测后,我们将获得三十三个地标的列表,这些地标代表图像中突出人物的身体关节位置。每个地标都有:
x – 它是按图像宽度归一化为 [0.0, 1.0] 的地标 x 坐标。y:它是按图像高度归一化为 [0.0, 1.0] 的地标 y 坐标。z:它是归一化为与 x 大致相同的比例的地标 z 坐标。它表示以臀部中点为原点的地标深度,因此 z 的值越小,地标离相机越近。可见性:它是一个范围为 [0.0, 1.0] 的值,表示地标在图像中可见(未遮挡)的可能性。在决定是否要显示特定关节时,这是一个有用的变量,因为它可能在图像中被遮挡或部分可见。但是,我们现在只需要x,y和z。
接下来,我们需要显示它们的位置,并画上线:
mp_drawing.draw_landmarks(image=f, landmark_list=results.pose_landmarks, connections=mp_pose.POSE_CONNECTIONS)
运行一下,你的代码应该是这样的:
import cv2
import mediapipe as mp
from vpython import *
mp_pose = mp.solutions.pose #从mediapipe里面获取pose
pose = mp_pose.Pose(static_image_mode=False, min_detection_confidence=0.5, model_complexity=1) #初始化
mp_drawing = mp.solutions.drawing_utils
cam = cv2.VideoCapture(0) #开启摄像头
while True:
_, frame = cam.read() #获取每一帧
results = pose.process(cv2.cvtColor(f, cv2.COLOR_BGR2RGB)) #检查每一帧中的骨架关节点
mp_drawing.draw_landmarks(image=f, landmark_list=results.pose_landmarks, connections=mp_pose.POSE_CONNECTIONS) #画上关节点
cv2.imshow('real time', frame) #显示每一帧
if cv2.waitKey(1) == ord(q): #检查是否按下q键
break
cam.release() #关掉摄像头
cv2.destroyAllWindows() #关掉窗口
现在,一大半已经搞完了,现在只需要搞定在3D中的显示。
points = []
c = []
for x in range(33):
points.append(sphere(radius=5, pos=vector(0, -50, 0)))
c.append(curve(retain=2, radius=4))
sphere 是用来布点的。
curve 是用来连接各个点的。
import cv2
import mediapipe as mp
from vpython import *
mp_pose = mp.solutions.pose #从mediapipe里面获取pose
pose = mp_pose.Pose(static_image_mode=False, min_detection_confidence=0.5, model_complexity=1) #初始化
points = []
c = []
for x in range(33):
points.append(sphere(radius=5, pos=vector(0, -50, 0)))
c.append(curve(retain=2, radius=4))
mp_drawing = mp.solutions.drawing_utils
cam = cv2.VideoCapture(0) #开启摄像头
while True:
_, frame = cam.read() #获取每一帧
results = pose.process(cv2.cvtColor(f, cv2.COLOR_BGR2RGB)) #检查每一帧中的骨架关节点
mp_drawing.draw_landmarks(image=f, landmark_list=results.pose_landmarks, connections=mp_pose.POSE_CONNECTIONS) #画上关节点
cv2.imshow('real time', frame) #显示每一帧
if cv2.waitKey(1) == ord(q): #检查是否按下q键
break
cam.release() #关掉摄像头
cv2.destroyAllWindows() #关掉窗口
P.S 后面的操作开始变得骚了,因此我每次操作都会放上一个完整的代码。
我们现在需要让我们的点根据骨骼关节点的x,y,z数值改变:
import cv2
import mediapipe as mp
from vpython import *
mp_pose = mp.solutions.pose #从mediapipe里面获取pose
pose = mp_pose.Pose(static_image_mode=False, min_detection_confidence=0.5, model_complexity=1) #初始化
points = []
c = []
for x in range(33):
points.append(sphere(radius=5, pos=vector(0, -50, 0)))
c.append(curve(retain=2, radius=4))
mp_drawing = mp.solutions.drawing_utils
cam = cv2.VideoCapture(0) #开启摄像头
while True:
_, frame = cam.read() #获取每一帧
results = pose.process(cv2.cvtColor(f, cv2.COLOR_BGR2RGB)) #检查每一帧中的骨架关节点
if results.pose_world_landmarks:
for i in range(11, 33):
if i != 18 and i!=20 and i!= 22 and i != 17 and i!=19 and i!=21:
points[i].pos.x = results.pose_world_landmarks.landmark[mp_pose.PoseLandmark(i).value].x * -cap.get(3)
points[i].pos.y = results.pose_world_landmarks.landmark[mp_pose.PoseLandmark(i).value].y * -cap.get(4)
points[i].pos.z = results.pose_world_landmarks.landmark[mp_pose.PoseLandmark(i).value].z * -cap.get(3)
mp_drawing.draw_landmarks(image=f, landmark_list=results.pose_landmarks, connections=mp_pose.POSE_CONNECTIONS) #画上关节点
cv2.imshow('real time', frame) #显示每一帧
if cv2.waitKey(1) == ord(q): #检查是否按下q键
break
cam.release() #关掉摄像头
cv2.destroyAllWindows() #关掉窗口
再画上连接线:
import cv2
import mediapipe as mp
from vpython import *
mp_pose = mp.solutions.pose #从mediapipe里面获取pose
pose = mp_pose.Pose(static_image_mode=False, min_detection_confidence=0.5, model_complexity=1) #初始化
points = []
ids = [[12, 14, 16], [11, 13, 15], [12, 24, 26, 28, 30, 32, 28],
[11, 23, 25, 27, 29, 31, 27], [12, 11], [24, 23]]
c = []
for x in range(33):
points.append(sphere(radius=5, pos=vector(0, -50, 0)))
c.append(curve(retain=2, radius=4))
mp_drawing = mp.solutions.drawing_utils
cam = cv2.VideoCapture(0) #开启摄像头
while True:
_, frame = cam.read() #获取每一帧
results = pose.process(cv2.cvtColor(f, cv2.COLOR_BGR2RGB)) #检查每一帧中的骨架关节点
if results.pose_world_landmarks:
for i in range(11, 33):
if i != 18 and i!=20 and i!= 22 and i != 17 and i!=19 and i!=21:
points[i].pos.x = results.pose_world_landmarks.landmark[mp_pose.PoseLandmark(i).value].x * -cap.get(3)
points[i].pos.y = results.pose_world_landmarks.landmark[mp_pose.PoseLandmark(i).value].y * -cap.get(4)
points[i].pos.z = results.pose_world_landmarks.landmark[mp_pose.PoseLandmark(i).value].z * -cap.get(3)
for n in range(2):
for i in range(2):
c[i + 2 * n].append(vector(points[ids[n][i]].pos.x, points[ids[n][i]].pos.y, points[ids[n][i]].pos.z),
vector(points[ids[n][i + 1]].pos.x, points[ids[n][i + 1]].pos.y,
points[ids[n][i + 1]].pos.z), retaine=2)
for n in range(2, 4):
for i in range(6):
c[i+6*n].append(vector(points[ids[n][i]].pos.x, points[ids[n][i]].pos.y, points[ids[n][i]].pos.z),
vector(points[ids[n][i +1]].pos.x, points[ids[n][i + 1]].pos.y, points[ids[n][i+1]].pos.z), retaine = 2)
for n in range(4, 6):
for i in range(1):
c[i+2*n].append(vector(points[ids[n][i]].pos.x, points[ids[n][i]].pos.y, points[ids[n][i]].pos.z),
vector(points[ids[n][i +1]].pos.x, points[ids[n][i + 1]].pos.y, points[ids[n][i+1]].pos.z), retaine = 2)
mp_drawing.draw_landmarks(image=f, landmark_list=results.pose_landmarks, connections=mp_pose.POSE_CONNECTIONS) #画上关节点
cv2.imshow('real time', frame) #显示每一帧
if cv2.waitKey(1) == ord(q): #检查是否按下q键
break
cam.release() #关掉摄像头
cv2.destroyAllWindows() #关掉窗口
好啦!作品已完成,经过整理后就变成这样了:
import cv2
import mediapipe as mp
from vpython import *
#mediapipe 模型变量初始化
def mediapipe_varibles_init():
mp_pose = mp.solutions.pose
pose = mp_pose.Pose(static_image_mode=False, min_detection_confidence=0.5, model_complexity=1)
mp_drawing = mp.solutions.drawing_utils
return pose,mp_pose, mp_drawing
#vpython(三维画图)模型变量初始化
def vpython_variables_init():
points = []
boxs = []
ids = [[12, 14, 16], [11, 13, 15], [12, 24, 26, 28, 30, 32, 28],
[11, 23, 25, 27, 29, 31, 27], [12, 11], [24, 23]]
c = []
for x in range(33):
points.append(sphere(radius=5, pos=vector(0, -50, 0)))
c.append(curve(retain=2, radius=4))
return points, boxs, ids, c
#在3D里画出骨架的函数
def draw_3d_pose():
results = pose.process(cv2.cvtColor(f, cv2.COLOR_BGR2RGB))
if results.pose_world_landmarks:
for i in range(11, 33):
if i != 18 and i!=20 and i!= 22 and i != 17 and i!=19 and i!=21:
points[i].pos.x = results.pose_world_landmarks.landmark[mp_pose.PoseLandmark(i).value].x * -cap.get(3)
points[i].pos.y = results.pose_world_landmarks.landmark[mp_pose.PoseLandmark(i).value].y * -cap.get(4)
points[i].pos.z = results.pose_world_landmarks.landmark[mp_pose.PoseLandmark(i).value].z * -cap.get(3)
for n in range(2):
for i in range(2):
c[i + 2 * n].append(vector(points[ids[n][i]].pos.x, points[ids[n][i]].pos.y, points[ids[n][i]].pos.z),
vector(points[ids[n][i + 1]].pos.x, points[ids[n][i + 1]].pos.y,
points[ids[n][i + 1]].pos.z), retaine=2)
for n in range(2, 4):
for i in range(6):
c[i+6*n].append(vector(points[ids[n][i]].pos.x, points[ids[n][i]].pos.y, points[ids[n][i]].pos.z),
vector(points[ids[n][i +1]].pos.x, points[ids[n][i + 1]].pos.y, points[ids[n][i+1]].pos.z), retaine = 2)
for n in range(4, 6):
for i in range(1):
c[i+2*n].append(vector(points[ids[n][i]].pos.x, points[ids[n][i]].pos.y, points[ids[n][i]].pos.z),
vector(points[ids[n][i +1]].pos.x, points[ids[n][i + 1]].pos.y, points[ids[n][i+1]].pos.z), retaine = 2)
mp_drawing.draw_landmarks(image=f, landmark_list=results.pose_landmarks, connections=mp_pose.POSE_CONNECTIONS)
#窗口关闭函数
def clos_def():
cap.release()
cv2.destroyAllWindows()
#获取变量
points, boxs, ids, c = vpython_variables_init()
pose, mp_pose, mp_drawing = mediapipe_varibles_init()
#打开摄像头,0是第一个摄像头,如果想换一个摄像头请改变这个数字
cap = cv2.VideoCapture(0)
while True:
#获取每一帧的图像
_, f = cap.read()
#vpython里的一个函数,用来调整3D中的FPS
rate(150)
#调用在3D里画出骨架的函数
draw_3d_pose()
#在每一帧里画骨架
#显示每一帧
cv2.imshow('real_time', f)
#检测是否要关闭窗口
if cv2.waitKey(1) & 0xFF == ord('q'):
break
#调用窗口关闭函数
clos_def()
我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("
无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD
本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01 客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02 数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit
Unity自动旋转动画1.开门需要门把手先动,门再动2.关门需要门先动,门把手再动3.中途播放过程中不可以再次进行操作觉得太复杂?查看我的文章开关门简易进阶版效果:如果这个门可以直接打开的话,就不需要放置"门把手"如果门把手还有钥匙需要旋转,那就可以把钥匙放在门把手的"门把手",理论上是可以无限套娃的可调整参数有:角度,反向,轴向,速度运行时点击Test进行测试自己写的代码比较垃圾,命名与结构比较拉,高手轻点喷,新手有类似的需求可以拿去做参考上代码usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;u
之前说过10之后的版本没有3dScan了,所以还是9.8的版本或者之前更早的版本。 3d物体扫描需要先下载扫描的APK进行扫面。首先要在手机上装一个扫描程序,扫描现实中的三维物体,然后上传高通官网,在下载成UnityPackage类型让Unity能够使用这个扫描程序可以从高通官网上进行下载,是一个安卓程序。点到Tools往下滑,找到VuforiaObjectScanner下载后解压数据线连接手机,将apk文件拷入手机安装然后刚才解压文件中的Media文件夹打开,两个PDF图打印第一张A4-ObjectScanningTarget.pdf,主要是用来辅助扫描的。好了,接下来就是扫描三维物体。将瓶
我想知道我的代码是否在rspec下运行。这可能吗?原因是我正在加载一些错误记录器,这些记录器在测试期间会被故意错误(expect{x}.toraise_error)弄得乱七八糟。我查看了我的ENV变量,没有(明显的)测试环境变量的迹象。 最佳答案 在spec_helper.rb的开头添加:ENV['RACK_ENV']='test'现在您可以在代码中检查RACK_ENV是否经过测试。 关于ruby-检测由RSpec、Ruby运行的代码,我们在StackOverflow上找到一个类似的问题
我正在使用rubydaemongem。想知道如何向停止操作添加一些额外的步骤?希望我能检测到停止被调用,并向其添加一些额外的代码。任何人都知道我如何才能做到这一点? 最佳答案 查看守护程序gem代码,它似乎没有用于此目的的明显扩展点。但是,我想知道(在守护进程中)您是否可以捕获守护进程在发生“停止”时发送的KILL/TERM信号...?trap("TERM")do#executeyourextracodehereend或者你可以安装一个at_exit钩子(Hook):-at_exitdo#executeyourextracodehe
关闭。这个问题不符合StackOverflowguidelines.它目前不接受答案。要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于StackOverflow来说是偏离主题的,因为它们往往会吸引自以为是的答案和垃圾邮件。相反,describetheproblem以及迄今为止为解决该问题所做的工作。关闭9年前。Improvethisquestion是否有适用于这些的3d游戏引擎?
我有一个定义类的Ruby脚本。我希望脚本执行语句BoolParser.generate:file_base=>'bool_parser'仅当脚本作为可执行文件被调用时,而不是当它被irbrequire(或通过-r在命令行上传递)时。我可以用什么来包装上面的语句,以防止它在我的Ruby文件加载时执行? 最佳答案 条件$0==__FILE__...!/usr/bin/ruby1.8classBoolParserdefself.generate(args)p['BoolParser.generate',args]endendif$0==_
我有以下字符串,我想检测那里的换行符。但是Ruby的字符串方法include?检测不到它。我正在运行Ruby1.9.2p290。我哪里出错了?"/'ædres/\nYour".include?('\n')=>false 最佳答案 \n需要在双引号内,否则无法转义。>>"\n".include?'\n'=>false>>"\n".include?"\n"=>true 关于Ruby无法检测字符串中的换行符,我们在StackOverflow上找到一个类似的问题: h