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 }