C# 取多个向量的平均值3';s

C# 取多个向量的平均值3';s,c#,unity3d,C#,Unity3d,所以我正在使用一个像kinect一样工作的深度相机。(这不是kinect)。后面有Nuitrack用于骨骼跟踪。然而,它为球员返回的位置是不稳定的。当完全静止时,它返回的数字可以上升或下降到10左右 示例:用户尽可能地站着,数据返回位置100第一帧,下一帧是102,然后是97,然后是100,然后是106等等。它在更新中返回这些位置,我们使用它移动图像。(因此用户控制图像)但正如您所料,由于数据不一致,该图像移动非常不稳定。根据Nuitrack的说法,这是正确的,用户本身需要找到解决方案。 我尝

所以我正在使用一个像kinect一样工作的深度相机。(这不是kinect)。后面有Nuitrack用于骨骼跟踪。然而,它为球员返回的位置是不稳定的。当完全静止时,它返回的数字可以上升或下降到10左右

示例:用户尽可能地站着,数据返回位置100第一帧,下一帧是102,然后是97,然后是100,然后是106等等。它在更新中返回这些位置,我们使用它移动图像。(因此用户控制图像)但正如您所料,由于数据不一致,该图像移动非常不稳定。根据Nuitrack的说法,这是正确的,用户本身需要找到解决方案。

我尝试了从一个位置到另一个位置的lerp,但这让它感觉不那么互动,因为一旦我到达lerp实际上是平滑的点,它就会有巨大的延迟。我还尝试只使用新的位置数据,如果它与nuitrack给我的前一个位置不同,比如说4个像素,这会更好一些,但会导致图像跳跃,即使我也会删除它。使用此功能:

foreach (User user in frame.Users)
        {
            if (Vector3.Distance(_lastPos, user.Proj.ToVector3()) >4f)
            {
                Vector3 final = ((_lastPos + user.Proj.ToVector3()) /2);
                userData.Add(new UserData(user.ID, user.Real.ToVector3(), final));
                _lastPos = user.Proj.ToVector3();
            }
            else
            {
                userData.Add(new UserData(user.ID, user.Real.ToVector3(), _lastPos));
            }
float _userX = user.ProjPosition.x * (_cameraPos.x *2)- _cameraPos.x;
            Vector3 _newPos = new Vector3(_userX, _basketPos.y, _basketPos.z);
            _basketPrefab.transform.position = Vector3.Lerp(_basketPrefab.transform.position, _newPos, Time.deltaTime * 30f);
以及lerp功能:

foreach (User user in frame.Users)
        {
            if (Vector3.Distance(_lastPos, user.Proj.ToVector3()) >4f)
            {
                Vector3 final = ((_lastPos + user.Proj.ToVector3()) /2);
                userData.Add(new UserData(user.ID, user.Real.ToVector3(), final));
                _lastPos = user.Proj.ToVector3();
            }
            else
            {
                userData.Add(new UserData(user.ID, user.Real.ToVector3(), _lastPos));
            }
float _userX = user.ProjPosition.x * (_cameraPos.x *2)- _cameraPos.x;
            Vector3 _newPos = new Vector3(_userX, _basketPos.y, _basketPos.z);
            _basketPrefab.transform.position = Vector3.Lerp(_basketPrefab.transform.position, _newPos, Time.deltaTime * 30f);

编辑:还有其他人吗?

您可以尝试保留最后n个位置的列表,然后使用
0.5f
(中间值)作为
t
将它们放在一起,计算这些位置的平均值。然后,您可以通过再次相互调整先前调整过的位置来提高“平滑度”,使其在每次迭代中更加平滑。然而,每一次迭代都会让它感觉有点迟钝,需要在平滑和反应之间找到平衡

(示例未经测试)

List lastPosition=新列表()//保留最后职位的列表
整型平滑=16//最大平滑量越高,表示平滑度将使用越多的位置
枚举平滑级别{无、轻度、中度、重度、极端}//要使用的平滑级别
平滑级别平滑级别;
向量3位;
//从列表中删除最旧的条目
如果(lastPosition.Count>0)
{
lastPosition.RemoveAt(0);
}
//将最新数据添加到列表中
while(lastPosition.Count<平滑)
{
lastPosition.Add(transform.position);
}
Vector3 vecA=lastPosition[0];
Vector3 vecB=最后位置[1];
Vector3 vecC=最后位置[2];
Vector3 vecD=最后位置[3];
Vector3 vecE=最后位置[4];
Vector3 vecF=最后位置[5];
Vector3 vecG=最后位置[6];
Vector3 vecH=最后位置[7];
Vector3 vecI=最后位置[8];
Vector3 vecJ=最后位置[9];
Vector3 vecK=最后位置[10];
Vector3 vecL=最后位置[11];
Vector3 vecM=最后位置[12];
Vector3 vecN=最后位置[13];
Vector3 vecO=最后位置[14];
Vector3 vecP=最后位置[15];
//通过t 0.5对每个后续位置进行Lerp,以获得两个位置的平均值。
//这是基本平滑,平滑度低,响应度高
Vector3-vecAB=Vector3.Lerp(vecA,vecB,0.5f);
vector3veccd=Vector3.Lerp(vecC,vecD,0.5f);
Vector3-vecEF=Vector3.Lerp(vecE,vecF,0.5f);
Vector3 vecGH=Vector3.Lerp(vecG,vecH,0.5f);
Vector3-vecIJ=Vector3.Lerp(vecI,vecJ,0.5f);
vector3veckl=Vector3.Lerp(vecK,vecL,0.5f);
vector3vecmn=Vector3.Lerp(vecM,vecN,0.5f);
Vector3-vecOP=Vector3.Lerp(vecO,vecP,0.5f);
//中度平滑,再次将先前的Lerp位置彼此对齐,以增加平滑度
向量3向量ABCD=向量3.Lerp(向量AB,向量CD,0.5f);
Vector3-vecEFGH=Vector3.Lerp(vecEF,vecGH,0.5f);
Vector3-vecIJKL=Vector3.Lerp(vecIJ,vecKL,0.5f);
Vector3-Vector3.Lerp(vecMN,vecOP,0.5f);
//严重平滑、高平滑度、低响应性
Vector3 vecABCDEFGH=Vector3.Lerp(VECABBCD,vecEFGH,0.5f);
Vector3-vecIJKLMNOP=Vector3.Lerp(vecIJKL,vecMNOP,0.5f);
//极端平滑,这将取所有16个位置的平均值。很滑,感觉很懒
Vector3 vecABCDEFGHIJKLMNOP=Vector3.Lerp(vecABCDEFGH,vecIJKLMNOP,0.5f);
开关(平滑级别)
{
大小写平滑级别。无:
pos=变换位置;
打破
案例平滑级别。轻度:
pos=vecOP;
打破
案例平滑级别。中等:
pos=vecMNOP;
打破
案例平滑级别。严重:
pos=vecIJKLMNOP;
打破
案例平滑级别。极端:
pos=vecABCDEFGHIJKLMNOP;
打破
}
//将pos应用于目标对象

在保持良好响应的同时过滤数据是一门艺术,请尝试研究PID控制器和卡尔曼滤波器。我会研究一下的。谢谢。首先感谢您的帮助!我试过你的代码,它确实起了一些作用。它仍然有点摇晃,但可以修复。问题是,我认为这是一个非常沉重的功能,为2-6个用户做每一帧。而不是最漂亮的食客。不知道现在该怎么办。我们将摄像机的位置数据放入我们自己的数据类中,然后传递给最终的游戏。你的例子很有帮助,但仍然不是我们想要的最终行为。感觉就像你说的有点慢,代码确实可以变得更漂亮,但是选择了最好的可读性。它的性能实际上取决于你用它传球的次数。根据我的经验,即使在较旧的android设备上使用,最多16次通过(如上例所示)也不会对性能产生明显影响。出于好奇,为什么每帧需要运行2-6次呢?我会假设每个用户都会在自己的设备上运行它,或者只是在每个帧的对象上运行一次,然后显示结果。是的,我可能会研究如何改进它,尽管你的解决方案与我们所寻找的不完全一样,但它是迄今为止最接近的。我经常运行它,因为相机前面可能有多个人。每个帧Nuitrack传递每个用户的所有数据。最多可以是6个。