这次为大家带来骨骼和彩色图像的叠加,其实很简单,就是将获取的骨骼点对应到彩色图像上,方式用到以前的基础,还是老的步骤和调调!
在实际运用中,最多的就是采用kinect v2的骨骼数据进行实际的交互了,十分有趣的东东。
先取上骨骼类型,用于画骨骼图像;骨架图像的连接顺序为 主躯干->左手->右手->左脚->右脚 从SDK提供的骨架点构成数组存储,如下:
private JointType[] _JointType = new JointType[]{
JointType.SpineBase,JointType.SpineMid,
JointType.SpineMid,JointType.SpineShoulder,
JointType.SpineShoulder,JointType.Neck,
JointType.Neck,JointType.Head,
JointType.SpineShoulder,JointType.ShoulderLeft,
JointType.ShoulderLeft,JointType.ElbowLeft,
JointType.ElbowLeft,JointType.WristLeft,
JointType.WristLeft,JointType.HandLeft,
JointType.HandLeft,JointType.HandTipLeft,
JointType.HandLeft,JointType.ThumbLeft,
JointType.SpineShoulder,JointType.ShoulderRight,
JointType.ShoulderRight,JointType.ElbowRight,
JointType.ElbowRight,JointType.WristRight,
JointType.WristRight,JointType.HandRight,
JointType.HandRight,JointType.HandTipRight,
JointType.HandRight,JointType.ThumbRight,
JointType.SpineBase,JointType.HipLeft,
JointType.HipLeft,JointType.KneeLeft,
JointType.KneeLeft,JointType.AnkleLeft,
JointType.AnkleLeft,JointType.FootLeft,
JointType.SpineBase,JointType.HipRight,
JointType.HipRight,JointType.KneeRight,
JointType.KneeRight,JointType.AnkleRight,
JointType.AnkleRight,JointType.FootRight
};
构成了骨架后,打开kinect多种数据流模式,采用彩色和骨架数据流图像的叠加;打开方式可参照之前系列文章,或者微软的PPT。
以下是处理画骨骼和显示彩色图像:
//打开多种帧
MultiSourceFrame msf = e.FrameReference.AcquireFrame();
//不为空
if (msf != null)
{
//打开骨骼帧和彩色帧
using (BodyFrame bodyFrame = msf.BodyFrameReference.AcquireFrame())
{
using (ColorFrame colorFrame = msf.ColorFrameReference.AcquireFrame())
{
//骨骼帧和彩色帧都不为空
if (bodyFrame != null && colorFrame != null)
{
//彩色帧拷贝到数组
colorFrame.CopyConvertedFrameDataToArray(this._ColorPixelData, ColorImageFormat.Bgra);
//数组写到位图
this._ColorBitmap.WritePixels(this._ColorBitmapRect, this._ColorPixelData, this._ColorBitmapStride, 0);
//骨骼数据拷贝到数组
bodyFrame.GetAndRefreshBodyData(this._Bodies);
//清空,保证每一帧都画一次
CanvasBody.Children.Clear();
//画骨架
DrawBodies();
}
}
}
}
}
//画骨架,六个人
private void DrawBodies()
{
//遍历6个玩家
for (int i = 0; i < 6; i++)
{
if (this._Bodies[i].IsTracked == true)
{
lState.Content = "状态"+this._Bodies[i].Joints[JointType.SpineBase].TrackingState.ToString();
Brush color = ColorBody[i % 6];
Body oneBody = this._Bodies[i];
//通过循环将关节点两两连接,
for (int j = 0; j < this._JointType.Length; j += 2)
{
Line line = new Line();
line.Stroke = color;
line.StrokeThickness = 5;
//起点的屏幕坐标和终点的屏幕坐标
Point StartP = GetJointPointScreen(oneBody.Joints[this._JointType[j]]);
Point EndP = GetJointPointScreen(oneBody.Joints[this._JointType[j + 1]]);
Ellipse sp = new Ellipse();
Ellipse ep = new Ellipse();
sp.Width = 15;
sp.Height = 15;
sp.HorizontalAlignment = HorizontalAlignment.Left;
sp.VerticalAlignment = VerticalAlignment.Top;
sp.Fill = Brushes.Red;
ep.Width = 15;
ep.Height = 15;
ep.HorizontalAlignment = HorizontalAlignment.Left;
ep.VerticalAlignment = VerticalAlignment.Top;
ep.Fill = Brushes.Red;
sp.Margin = new Thickness(StartP.X - sp.Width / 2, StartP.Y - sp.Height / 2, 0, 0);
ep.Margin = new Thickness(EndP.X - ep.Width / 2, EndP.Y - ep.Height / 2, 0, 0);
//设置起点、终点的坐标
line.X1 = StartP.X;
line.Y1 = StartP.Y;
line.X2 = EndP.X;
line.Y2 = EndP.Y;
//把起点、终点及连接添加到网格中。
CanvasBody.Children.Add(sp);
CanvasBody.Children.Add(ep);
CanvasBody.Children.Add(line);
}
}
}
以及坐标转换的处理:(用到SDK自带的coordinatemapping类)
最后,最最重要的是由于不同数据流之间的分辨率不同,要采取图像重合就必须进行坐标转换,以下将骨骼图像升为彩色图像的方式。
附:本应用建立在.net4.0 .net4.5,采用WPF编写; Kinect中图像在实际中相当于镜像关系,类似照镜子,骨架流中存储着很多信息,比如追踪状态等。
//骨骼坐标转化为彩色图像坐标
ColorSpacePoint colorPoint = this._KinectDevice.CoordinateMapper.MapCameraPointToColorSpace(oneJoint.Position);
//彩色图像坐标转化为屏幕坐标
colorPoint.X = (int)((colorPoint.X * CanvasBody.Width) / 1920);
colorPoint.Y = (int)((colorPoint.Y * CanvasBody.Height) / 1080);
//返回Point类型变量
return new Point(colorPoint.X, colorPoint.Y);