1 module des.mc.multitrack.model.util;
2 import std.algorithm;
3 import std.array;
4 
5 import des.mc.core;
6 import std.math;
7 
8 T[] plainArray(T)( in T[][] arr )
9 {
10     T[] ret;
11     return array( reduce!((r,a)=>(r~=a))( ret, arr ) );
12 }
13 
14 size_t[] getHighQualityIndexes( in Joint[] a, in Joint[] b, float min_qual )
15 {
16     size_t[] res;
17     foreach( i; 0 .. a.length )
18         if( a[i].qual > min_qual && b[i].qual > min_qual )
19             res ~= i;
20     return res;
21 }
22 
23 vec3[2] calcDistibution( in vec3[] arr )
24 {
25     vec3 exp;
26     vec3 var;
27 
28     foreach( v; arr ) exp += v;
29     exp /= cast(float)arr.length;
30     foreach( v; arr ) var += (exp - v)^^2;
31     var /= cast(float)(arr.length - 1);
32     return [ exp, var ];
33 }
34 
35 vec3[] calcOffsetInIndexes( in Joint[] a, in Joint[] b, size_t[] hiq )
36 {
37     vec3[] res;
38     foreach( index; hiq )
39         res ~= b[index].pos - a[index].pos;
40     return res;
41 }
42 
43 class ClassifierClass
44 {
45     float min_quality = 0.5;
46 
47     Skeleton mean;
48     Skeleton[] array;
49 
50     this( float min_qual=0.5 )
51     {
52         min_quality = min_qual;
53     }
54 
55     float[2] diff( in Skeleton s )
56     {
57         auto mj = mean.allJoints();
58         auto sj = s.allJoints();
59 
60         auto hiq = getHighQualityIndexes( mj, sj, min_quality );
61         auto offset = calcOffsetInIndexes( mj, sj, hiq );
62         auto dp = calcDistibution( offset );
63 
64         auto exp = dp[0].len;
65         auto dev = sqrt(dp[1].len);
66         exp = (exp!=exp) ? float.max : exp;
67 
68         return [exp,dev];
69     }
70 
71     void append( in Skeleton s )
72     {
73         auto mj = mean.allJoints();
74         auto sj = s.allJoints();
75 
76         if( array.length )
77         {
78             auto hiq = getHighQualityIndexes( mj, sj, min_quality );
79             auto offset = calcOffsetInIndexes( mj, sj, hiq );
80             auto dp = calcDistibution( offset );
81 
82             auto n = array.length;
83 
84             foreach( ind; hiq )
85             {
86                 mj[ind].pos = ( ( mj[ind].pos * n ) + sj[ind].pos ) / (n + 1);
87                 mj[ind].qual = 1.0f;
88             }
89             mean.setJoints(mj);
90         }
91         else mean = s;
92 
93         array ~= s;
94     }
95 
96 }
97 
98 unittest
99 {
100     auto a = getFakeSkeletons(vec3(0,0,.1),[vec3(0,0,0)])[0];
101     auto b = getFakeSkeletons(vec3(0,0.1,0),[vec3(0,0,0)])[0];
102 
103     auto cf = new ClassifierClass;
104     assert( abs( cf.diff(a)[0] - float.max ) < 1e-12 );
105     cf.append( a );
106     import std.stdio;
107     assert( cf.diff(b)[0] > 0.0f && cf.diff(b)[0] < 0.2 );
108     assert( cf.diff(b)[1] < 0.0001f );
109 }