C# Kinect关节-对象引用未设置为对象的实例
我已经成功地创建了一个kinect应用程序,它读取特定骨骼关节的X、Y、Z位置,然后对姿势进行分类(站立、坐等)。应用程序还将分类结果输出到txt文件C# Kinect关节-对象引用未设置为对象的实例,c#,object,kinect,instance-variables,kinect-sdk,C#,Object,Kinect,Instance Variables,Kinect Sdk,我已经成功地创建了一个kinect应用程序,它读取特定骨骼关节的X、Y、Z位置,然后对姿势进行分类(站立、坐等)。应用程序还将分类结果输出到txt文件 private void classify_Click(object sender, RoutedEventArgs e) { if (File.Exists(@"E:\KINECT\test.txt")) { File.Delete(@"E:\KINECT\test.txt");
private void classify_Click(object sender, RoutedEventArgs e)
{
if (File.Exists(@"E:\KINECT\test.txt"))
{
File.Delete(@"E:\KINECT\test.txt");
}
File.AppendAllText(@"E:\KINECT\test.txt", shoulderRightY + " " + shoulderLeftY + " " + headY + " " + hipY + Environment.NewLine);
double detect = Program.siet();
vysledok.Text = detect.ToString();
}
在我的主窗口中,我有骨架显示、将当前位置保存到训练数据集的按钮、对当前姿势进行分类的按钮和一个文本框,分类结果应该显示在哪里
应用程序运行时没有错误。它还可以在单击按钮时将当前位置保存到训练集。但是,当我单击“分类”按钮时,应用程序冻结,并且在Visual Studio中出现错误:
对象引用未设置为对象的实例
下面是一段代码,其中包括我得到错误的行(它在foreach
循环中-我在那里添加了注释行):
这是我的分类按钮。程序类位于单独的.cs文件中,并且有一个执行多类分类的SVM。它正确地对案例进行分类,因为它在我的txt文件中写入了正确的结果
private void classify_Click(object sender, RoutedEventArgs e)
{
if (File.Exists(@"E:\KINECT\test.txt"))
{
File.Delete(@"E:\KINECT\test.txt");
}
File.AppendAllText(@"E:\KINECT\test.txt", shoulderRightY + " " + shoulderLeftY + " " + headY + " " + hipY + Environment.NewLine);
double detect = Program.siet();
vysledok.Text = detect.ToString();
}
编辑:
下面是我的“Program.cs”的功能。正如O.R.Mapper所说:“我怀疑sensor_SkeletonFrameReady是在Program.siet()的某个地方调用的。”。我在这里什么地方都看不到
using System ;
using System . Collections.Generic ;
using System . Linq ;
using System . Text ;
using Encog . Neural.Networks ;
using Encog . Neural.Networks.Layers ;
using Encog . Engine.Network.Activation ;
using Encog .ML.Data;
using Encog . Neural.Networks.Training.Propagation.Resilient ;
using Encog .ML.Train;
using Encog .ML.Data.Basic ;
using System.IO;
using System.Collections;
using Encog.ML.SVM;
using Encog.ML.SVM.Training;
public class Program
{
public static double siet()
{
string cestain = @"E:\KINECT\inputs.txt";
double[][] innput = Load.FromFile(cestain);
string cestaout = @"E:\KINECT\outputs.txt";
double[][] ooutput = Load.FromFile(cestaout);
double[] skuska1 = File.ReadAllText(@"E:\KINECT\test.txt").Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).Select(double.Parse).ToArray();
// c r e a t e a neural network , wi thout us ing a f a c t o r y
var svm = new SupportVectorMachine(2, false);
// c r e a t e t r a i n i n g data
IMLDataSet trainingSet = new BasicMLDataSet(innput, ooutput);
// t r a i n the neural network
/*IMLTrain train = new ResilientPropagation(network, trainingSet);*/
IMLTrain train = new SVMSearchTrain(svm, trainingSet);
int epoch = 1;
do
{
train.Iteration();
Console.WriteLine(@"Epoch #" + epoch + @" Error:" + train.Error);
epoch++;
} while (train.Error > 0.01);
// t e s t the neural network
Console.WriteLine(@"SVM Results:");
IMLData output = svm.Compute(new BasicMLData(skuska1));
Console.WriteLine(skuska1
+ @", actual=" + output[0]);
File.AppendAllText(@"E:\KINECT\testout.txt", output[0].ToString());
return output[0];
}
}
下面是Load.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Collections;
public class Load
{
public Load()
{
}
public static double[][] FromFile(string path)
{
var rows = new List<double[]>();
foreach (var line in File.ReadAllLines(path))
{
rows.Add(line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).Select(double.Parse).ToArray());
}
return rows.ToArray();
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.IO;
使用系统集合;
公共类负载
{
公共负载()
{
}
公共静态双[][]FromFile(字符串路径)
{
var rows=新列表();
foreach(文件中的var行.ReadAllLines(路径))
{
添加(line.Split(new[]{''},StringSplitOptions.removeMptyEntries).Select(double.Parse.ToArray());
}
返回rows.ToArray();
}
}
这就是解决方案:
foreach (Skeleton skeleton in skeletons)
{
if (skeleton != null)
{
hip = skeleton.Joints[JointType.HipCenter];
rightShoulder = skeleton.Joints[JointType.ShoulderRight];
leftShoulder = skeleton.Joints[JointType.ShoulderLeft];
head = skeleton.Joints[JointType.Head];
shoulderRightY += rightShoulder.Position.Y;
shoulderLeftY += leftShoulder.Position.Y;
headY += head.Position.Y;
hipY += hip.Position.Y;
}
}
有人能证实吗?我有这个话题,但没有什么帮助。因为正如我所说,应用程序正在数据集按钮中收集这些位置,wich还使用foreach循环来更新关节位置。执行数据集按钮时,行不为空,执行分类时,行为空。Program类不处理关节,而仅处理txt数据集文件。即使您声称是这样,我也没有在数据集按钮的单击事件处理程序中看到任何
foreach
循环。在生成异常的行上设置断点后,是否可以使用调试器运行程序,然后检查skeleton
或skeleton.Joints
是否为null
?这可能是一种误解。我在SkeletonFrameReady方法中有一个foreach循环,其中位置会更新。有趣的是,只有在单击分类按钮时才会抛出异常。“数据集”按钮正常,也适用于关节。您能看看stacktrace吗?我不知道Program.siet()
做了什么,但我怀疑sensor\u SkeletonFrameReady
是在Program.siet()的某个地方调用的。因此,分类按钮出现问题并不奇怪,但数据集按钮却没有出现问题,因为数据集按钮不会执行任何可能导致调用sensor_SkeletonFrameReady
的操作。还请注意,“数据集”按钮不使用“关节”;在文件.AppendAllText
调用中,您只需写出一些double
值,这些值与您的问题无关。与此无关,请注意在“分类”按钮中写入文件的方式是有风险的。理论上,另一个进程可以在调用file.Delete
之后和调用file.AppendAllText
之前使用相同的路径编写文件,因此,如果文件随后被锁定,因此无法进行追加,则后者将失败。看一看这张照片。
foreach (Skeleton skeleton in skeletons)
{
if (skeleton != null)
{
hip = skeleton.Joints[JointType.HipCenter];
rightShoulder = skeleton.Joints[JointType.ShoulderRight];
leftShoulder = skeleton.Joints[JointType.ShoulderLeft];
head = skeleton.Joints[JointType.Head];
shoulderRightY += rightShoulder.Position.Y;
shoulderLeftY += leftShoulder.Position.Y;
headY += head.Position.Y;
hipY += hip.Position.Y;
}
}