Kinect测量人体身高的程序
对着书上敲得,从中体会kinect骨骼识别与深度识别的原理。大体原理是懂了,但有些细节还没有完全弄明白。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Kinect; namespace KinectMeasure
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
private KinectSensor kinect;
public MainWindow()
{
InitializeComponent();
}
private void startKinect()
{
if (KinectSensor.KinectSensors.Count > 0)
{
kinect = KinectSensor.KinectSensors[0];
kinect.DepthStream.Enable();
kinect.SkeletonStream.Enable();
kinect.DepthFrameReady += new EventHandler<DepthImageFrameReadyEventArgs>(kinect_DepthFrameReady);
kinect.SkeletonFrameReady += new EventHandler<SkeletonFrameReadyEventArgs>(kinect_SkeletonFrameReady);
kinect.Start();
}
}
private void stopKinect()
{
if (kinect != null)
{
if (kinect.Status == KinectStatus.Connected)
{
kinect.Stop();
}
}
}
Skeleton GetClosetSkeleton(SkeletonFrame frame)
{
frame.CopySkeletonDataTo(allSkeletons);
Skeleton closestSkeleton = (from s in allSkeletons
where s.TrackingState == SkeletonTrackingState.Tracked && s.Joints[JointType.Head].TrackingState == JointTrackingState.Tracked
select s).OrderBy(s => s.Joints[JointType.Head].Position.Z).FirstOrDefault();//这……这是what?
return closestSkeleton;
}
void kinect_SkeletonFrameReady(object sensor, SkeletonFrameReadyEventArgs e)
{
using (SkeletonFrame SFrame = e.OpenSkeletonFrame())
{
if (SFrame == null)
return;
Skeleton s = GetClosetSkeleton(SFrame);
if (s == null)
return;
if (s.ClippedEdges == FrameEdges.None)
return;
SkeletonPoint head = s.Joints[JointType.Head].Position;//头
SkeletonPoint centerShoulder = s.Joints[JointType.ShoulderCenter].Position;//肩
SkeletonPoint leftFoot = s.Joints[JointType.FootLeft].Position;//左脚
float height = Math.Abs(head.Y - leftFoot.Y);//身高
float heightEx = Math.Abs(head.Y - centerShoulder.Y) + 0.1f;//头高?
float realHeightViaskeleton = height + heightEx;//计算出的真实高度
labelHeightViaSkeleton.Content = realHeightViaskeleton.ToString();
}
}
const int MaxSkeletonTrackingCount=6;//最多可以同时跟踪的用户数
private Skeleton[]allSkeletons=new Skeleton[MaxSkeletonTrackingCount];//用户骨骼的集合
void kinect_DepthFrameReady(object sender, DepthImageFrameReadyEventArgs e)
{
using (DepthImageFrame DFrame = e.OpenDepthImageFrame())
{
if (DFrame != null)
{
short[] pixelData = new short[kinect.DepthStream.FramePixelDataLength];
DFrame.CopyPixelDataTo(pixelData);
MessureSpecifiedPlayerSize(DFrame,pixelData);
BitmapSource source = BitmapSource.Create(640, 480, 969, 96, PixelFormats.Gray16, null, pixelData, 640 * 2);
imageDepth.Source = source;
}
}
}
private static readonly double HorizontalPoVTanA = Math.Tan(57.0 / 2.0 * Math.PI / 180);
private void MessureSpecifiedPlayerSize(DepthImageFrame depthFrame,short[] pixelData)
{
int depth;
int playerIndex;
int pixelIndex;
int bytesPerPixel = depthFrame.BytesPerPixel;//这是what?
int depthSum = 0;
int depthCount = 0;
//身体各个部位的深度
int depthPixelBodyLeft = int.MaxValue;
int depthPixelBodyRight = int.MinValue;
int depthPixelBodyBottom = int.MaxValue;
int depthPixelBodyTop = int.MinValue;
for(int row = 0; row < depthFrame.Height; row++)
{
for (int col = 0; col < depthFrame.Width; col++)
{
pixelIndex=col+(row*depthFrame.Width);
depth = pixelData[pixelIndex] >> DepthImageFrame.PlayerIndexBitmaskWidth;//获得此处的深度数据
playerIndex=(pixelData[pixelIndex]&DepthImageFrame.PlayerIndexBitmask);//判断此处是否为用户
//注:该代码仅支持一个用户测量
if (depth != 0 && playerIndex != 0)
{
depthCount++;//非0的深度
depthSum += depth;//总深度
depthPixelBodyLeft = Math.Min(depthPixelBodyLeft, col);
depthPixelBodyRight = Math.Max(depthPixelBodyRight, col);
depthPixelBodyBottom = Math.Min(depthPixelBodyBottom, row);
depthPixelBodyTop = Math.Max(depthPixelBodyTop, row);
}
}
}
if (depthCount != 0)
{
double avgDepth = depthSum / depthCount;
int pixelWidth = Math.Abs(depthPixelBodyRight - depthPixelBodyLeft);
int pixelHeight = Math.Abs(depthPixelBodyTop - depthPixelBodyBottom);
double realHeightViaDepth = (2 * avgDepth * HorizontalPoVTanA * pixelHeight) / depthFrame.Width;//depthFrame.Wdith是计算机中框架的宽度
labelHeightViaSkeleton.Content = realHeightViaDepth.ToString();
}
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
startKinect();
} private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
stopKinect();
}
}
}
Kinect测量人体身高的程序的更多相关文章
- 基于三个kinect的人体建模
单个kinect的人体重建,在Kinect SDK 1.8中,Kinect Fusion的效果已经很不错了.其缺点显而易见,一是扫描时间长,重建对象也需要长时间保持静态:二是需要人体或者kine ...
- C#测量程序运行时间及cpu使用时间
转载:http://www.cnblogs.com/yanpeng/archive/2008/10/15/1943369.html 对一个服务器程序想统计每秒可以处理多少数据包,要如何做?答案是用处理 ...
- C#测量程序运行时间及cpu使用时间实例方法
private void ShowRunTime() { TimeSpan ts1 = Process.GetCurrentProcess().TotalProcessorTime; Stopwatc ...
- Kinect开发文章目录
整理了一下去年为止到现在写的和翻译的Kinect的相关文章,方便大家查看.另外,最近京东上微软在搞活动, 微软 Kinect for Windows 京东十周年专供礼包 ,如果您想从事Kinect开发 ...
- 【翻译】Kinect v2程序设计(C++) Body 篇
Kinect SDK v2预览版的主要功能的使用介绍,基本上完成了.这次,是关于取得Body(人体姿势)方法的说明. 上一节,是使用Kinect SDK v2预览版从Kinect v2预览版取得B ...
- Kinect开发学习笔记之(一)Kinect介绍和应用
Kinect开发学习笔记之(一)Kinect介绍和应用 zouxy09@qq.com http://blog.csdn.net/zouxy09 一.Kinect简单介绍 Kinectfor Xbox ...
- Kinect的学习笔记发展(一)Kinect引进和应用
Kinect的学习笔记发展(一)Kinect引进和应用 zouxy09@qq.com http://blog.csdn.net/zouxy09 一.Kinect简单介绍 Kinectfor Xbox ...
- Kinect的学习笔记发展一Kinect引进和应用
Kinect开发学习笔记之(一)Kinect介绍和应用 zouxy09@qq.com http://blog.csdn.net/zouxy09 一.Kinect简单介绍 Kinectfor Xbox ...
- Kinect 开发 —— 控制PPT播放
实现Kinect控制幻灯片播放很简单,主要思路是:使用Kinect捕捉人体动作,然后根据识别出来的动作向系统发出点击向前,向后按键的事件,从而使得幻灯片能够切换. 这里的核心功能在于手势的识别,我们在 ...
随机推荐
- 一个LINUX狂人的语录(个人认为很精辟)
http://blog.chinaunix.net/uid-57160-id-2734431.html?page=2 我已经半年没有使用 Windows 的方式工作了.Linux 高效的完成了我所有的 ...
- sql语言参考
set operators UNION, UNION ALL, INTERSECT, and MINUS这三个操作符优先级相同,从左至右,除非有括号 单库单表操作,单库多表操作,多库多表操作(用到db ...
- libc-glibc
glibc 和 libc 都是 Linux 下的 C 函数库. libc 是 Linux 下的 ANSI C 函数库:glibc 是 Linux 下的 GUN C 函数库. ANSI C 和 GNU ...
- C++流格式控制符的使用【来自网络】
注意添加<iomanip>头文件. 使用控制符控制输出格式 控制符 作用 dec 设置整数的基数为10 hex 设置整数的基数为16 oct 设置整数的基数为8 setbase(n) 设置 ...
- wamp下Apache2.4.x局域网访问403的解决办法
1.我们打开Apache目录\wamp\bin\apache\apache2.4.9下的“conf”文件夹,找到httpd.conf. 2.找到# onlineoffline tag - don' ...
- newman 3.0改变
https://github.com/postmanlabs/newman/blob/develop/MIGRATION.md
- 如何处理JSON数据中含有双引号
{"quality": "B"A"D"} 实际上要 value.replace("\"","\\\& ...
- SQL SERVER 生成ORACLE建表脚本
/****** Object: StoredProcedure [dbo].[GET_TableScript_ORACLE] Script Date: 06/15/2012 13:07:16 **** ...
- SPOJ #2 Prime Generator
My first idea was Sieve of Eratosthenes, too. But obviously my coding was not optimal and it exceede ...
- bzoj 3920: Yuuna的礼物
Description 转眼就要到Karin的生日了!Yuuna她们想为她准备生日礼物!现在有许多礼物被排列成了一个一维序列,每个礼物都有一个价值.Yuuna对这个序列十分感兴趣.因此,你需要多次回答 ...