2 * principal component analysis (PCA)
3 * Copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at>
5 * This file is part of FFmpeg.
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 * principal component analysis (PCA)
38 PCA
*ff_pca_init(int n
){
43 pca
= av_mallocz(sizeof(*pca
));
48 pca
->z
= av_malloc_array(n
, sizeof(*pca
->z
));
50 pca
->covariance
= av_calloc(n
*n
, sizeof(double));
51 pca
->mean
= av_calloc(n
, sizeof(double));
53 if (!pca
->z
|| !pca
->covariance
|| !pca
->mean
) {
61 void ff_pca_free(PCA
*pca
){
62 av_freep(&pca
->covariance
);
68 void ff_pca_add(PCA
*pca
, const double *v
){
75 pca
->covariance
[j
+ i
*n
] += v
[i
]*v
[j
];
80 int ff_pca(PCA
*pca
, double *eigenvector
, double *eigenvalue
){
86 memset(eigenvector
, 0, sizeof(double)*n
*n
);
89 pca
->mean
[j
] /= pca
->count
;
90 eigenvector
[j
+ j
*n
] = 1.0;
92 pca
->covariance
[j
+ i
*n
] /= pca
->count
;
93 pca
->covariance
[j
+ i
*n
] -= pca
->mean
[i
] * pca
->mean
[j
];
94 pca
->covariance
[i
+ j
*n
] = pca
->covariance
[j
+ i
*n
];
96 eigenvalue
[j
]= pca
->covariance
[j
+ j
*n
];
100 for(pass
=0; pass
< 50; pass
++){
105 sum
+= fabs(pca
->covariance
[j
+ i
*n
]);
111 if(eigenvalue
[j
] > maxvalue
){
112 maxvalue
= eigenvalue
[j
];
116 eigenvalue
[k
]= eigenvalue
[i
];
117 eigenvalue
[i
]= maxvalue
;
119 double tmp
= eigenvector
[k
+ j
*n
];
120 eigenvector
[k
+ j
*n
]= eigenvector
[i
+ j
*n
];
121 eigenvector
[i
+ j
*n
]= tmp
;
128 for(j
=i
+1; j
<n
; j
++){
129 double covar
= pca
->covariance
[j
+ i
*n
];
130 double t
,c
,s
,tau
,theta
, h
;
132 if(pass
< 3 && fabs(covar
) < sum
/ (5*n
*n
)) //FIXME why pass < 3
134 if(fabs(covar
) == 0.0) //FIXME should not be needed
136 if(pass
>=3 && fabs((eigenvalue
[j
]+z
[j
])/covar
) > (1LL<<32) && fabs((eigenvalue
[i
]+z
[i
])/covar
) > (1LL<<32)){
137 pca
->covariance
[j
+ i
*n
]=0.0;
141 h
= (eigenvalue
[j
]+z
[j
]) - (eigenvalue
[i
]+z
[i
]);
143 t
=1.0/(fabs(theta
)+sqrt(1.0+theta
*theta
));
144 if(theta
< 0.0) t
= -t
;
152 #define ROTATE(a,i,j,k,l) {\
153 double g=a[j + i*n];\
154 double h=a[l + k*n];\
155 a[j + i*n]=g-s*(h+g*tau);\
156 a[l + k*n]=h+s*(g-h*tau); }
159 ROTATE(pca
->covariance
,FFMIN(k
,i
),FFMAX(k
,i
),FFMIN(k
,j
),FFMAX(k
,j
))
161 ROTATE(eigenvector
,k
,i
,k
,j
)
163 pca
->covariance
[j
+ i
*n
]=0.0;
166 for (i
=0; i
<n
; i
++) {
167 eigenvalue
[i
] += z
[i
];