@ -2,22 +2,23 @@
# include <stdlib.h>
# include <math.h>
# include <float.h>
# include <string.h>
# include "serialDeclarations.h"
void meanshift ( double * * x , int h , struct parameters * opt ) {
void meanshift ( double * * originalPoints , int h , parameters * opt ) {
double * * y ;
y = alloc_2d_double ( ROWS , COLUMNS ) ;
y = duplicate ( x , y , ROWS , COLUMNS ) ;
y = duplicate ( originalPoints , y , ROWS , COLUMNS ) ;
// mean shift vectors
double * * m ;
m = alloc_2d_double ( ROWS , COLUMNS ) ;
// initialize elements of m to inf
// mean shift vector
double * * meanShiftVector ;
meanShiftVector = alloc_2d_double ( ROWS , COLUMNS ) ;
// initialize elements of meanShiftVector to inf
for ( int i = 0 ; i < ROWS ; i + + ) {
for ( int j = 0 ; j < COLUMNS ; j + + ) {
m [ i ] [ j ] = DBL_MAX ;
meanShiftVector [ i ] [ j ] = DBL_MAX ;
}
}
@ -26,117 +27,81 @@ void meanshift(double **x, int h, struct parameters *opt){
// printf("%f \n", opt->epsilon);
double * * W = alloc_2d_double ( ROWS , ROWS ) ;
double * l = malloc ( ROWS * sizeof ( double ) ) ;
double * * kernelMatrix = alloc_2d_double ( ROWS , ROWS ) ;
double * denominator = malloc ( ROWS * sizeof ( double ) ) ;
/** iterate until convergence **/
// printf("norm : %f \n", norm(m, ROWS, COLUMNS));
while ( norm ( m , ROWS , COLUMNS ) > opt - > epsilon ) {
while ( norm ( meanShiftVector , ROWS , COLUMNS ) > opt - > epsilon ) {
iter = iter + 1 ;
// find pairwise distance matrix (inside radius)
/** allocate memory for inside iteration arrays **/
// [I, D] = rangesearch(x,y,h);
for ( int i = 0 ; i < ROWS ; i + + ) {
for ( int j = 0 ; j < ROWS ; j + + ) {
double dist = calculateDistance ( y [ i ] , x [ j ] ) ;
// 2sparse matrix
if ( dist < h ) {
W [ i ] [ j ] = dist ;
//printf("%f \n", W[i][j]);
} else {
W [ i ] [ j ] = 0 ;
}
}
}
// for each element of W (x) do x^2
// size of W is [600 600]
// W is a sparse matrix -> apply to non-zero elements
for ( int i = 0 ; i < ROWS ; i + + ) {
double sum = 0 ;
for ( int j = 0 ; j < ROWS ; j + + ) {
if ( W [ i ] [ j ] ! = 0 ) {
W [ i ] [ j ] = W [ i ] [ j ] * W [ i ] [ j ] ;
// compute kernel matrix
// apply function to non zero elements of a sparse matrix
double pow = ( ( - 1 ) * ( W [ i ] [ j ] ) ) / ( 2 * ( h * h ) ) ;
W [ i ] [ j ] = exp ( pow ) ;
}
// make sure diagonal elements are 1
double dist = calculateDistance ( y [ i ] , originalPoints [ j ] ) ;
if ( i = = j ) {
W [ i ] [ j ] = W [ i ] [ j ] + 1 ;
kernelMatrix [ i ] [ j ] = 1 ;
} else if ( dist < h * h ) {
kernelMatrix [ i ] [ j ] = dist * dist ;
// compute kernel matrix
double pow = ( ( - 1 ) * ( kernelMatrix [ i ] [ j ] ) ) / ( 2 * ( h * h ) ) ;
kernelMatrix [ i ] [ j ] = exp ( pow ) ;
} else {
kernelMatrix [ i ] [ j ] = 0 ;
}
// calculate sum(W,2)
sum = sum + W [ i ] [ j ] ;
sum = sum + kernelMatrix [ i ] [ j ] ;
}
/** l array is correct**/
l [ i ] = sum ;
// printf("l[%d] : %f \n", i, l[i]);
denominator [ i ] = sum ;
}
/** W is correct**/
//print_matrix(W, ROWS, ROWS);
// create new y vector
double * * y_new = alloc_2d_double ( ROWS , COLUMNS ) ;
multiply ( W , x , y_new ) ;
/** y_new is CORRECT **/
// print_matrix(y_new, ROWS, COLUMNS);
multiply ( kernelMatrix , originalPoints , y_new ) ;
// divide element-wise
for ( int i = 0 ; i < ROWS ; i + + ) {
for ( int j = 0 ; j < COLUMNS ; j + + ) {
y_new [ i ] [ j ] = y_new [ i ] [ j ] / l [ i ] ;
y_new [ i ] [ j ] = y_new [ i ] [ j ] / denominator [ i ] ;
// calculate mean-shift vector
m [ i ] [ j ] = y_new [ i ] [ j ] - y [ i ] [ j ] ;
meanShiftVector [ i ] [ j ] = y_new [ i ] [ j ] - y [ i ] [ j ] ;
// update y
y [ i ] [ j ] = y_new [ i ] [ j ] ;
}
}
save_matrix ( y , iter ) ;
printf ( " Iteration n. %d, error %f \n " , iter , norm ( m , ROWS , COLUMNS ) ) ;
printf ( " Iteration n. %d, error %f \n " , iter , norm ( meanShiftVector , ROWS , COLUMNS ) ) ;
// TODO maybe keep y for live display later?
} ;
}
// allocates a 2d array in continuous memory positions
double * * alloc_2d_double ( int rows , int cols ) {
double * data = ( double * ) malloc ( rows * cols * sizeof ( double ) ) ;
double * * array = ( double * * ) malloc ( rows * sizeof ( double * ) ) ;
for ( int i = 0 ; i < rows ; i + + )
array [ i ] = & ( data [ cols * i ] ) ;
return array ;
}
// copy the values of a 2d double array to another
double * * duplicate ( double * * a , double * * b , int rows , int cols ) {
// TODO check why there's is a difference in the norm calculate in matlab
double norm ( double * * matrix , int rows , int cols ) {
double sum = 0 , tempMul = 0 ;
for ( int i = 0 ; i < rows ; i + + ) {
for ( int j = 0 ; j < cols ; j + + ) {
b [ i ] [ j ] = a [ i ] [ j ] ;
tempMul = matrix [ i ] [ j ] * matrix [ i ] [ j ] ;
sum = sum + tempMul ;
}
}
return b ;
double norm = sqrt ( sum ) ;
return norm ;
}
// TODO check why there's is a difference in the norm calculate in matlab
double norm ( double * * m , int rows , int cols ) {
double sum = 0 , a = 0 ;
for ( int i = 0 ; i < rows ; i + + ) {
for ( int j = 0 ; j < cols ; j + + ) {
a = m [ i ] [ j ] * m [ i ] [ j ] ;
sum = sum + a ;
void multiply ( double * * matrix1 , double * * matrix2 , double * * output ) {
// W dims are ROWS ROWS and x dims are ROWS COLUMNS
for ( int i = 0 ; i < ROWS ; i + + ) {
for ( int j = 0 ; j < COLUMNS ; j + + ) {
output [ i ] [ j ] = 0 ;
for ( int k = 0 ; k < ROWS ; k + + ) {
output [ i ] [ j ] + = matrix1 [ i ] [ k ] * matrix2 [ k ] [ j ] ;
}
}
}
double norm = sqrt ( sum ) ;
return norm ;
}
double calculateDistance ( double * y , double * x ) {
@ -149,18 +114,23 @@ double calculateDistance(double *y, double *x){
return distance ;
}
void multiply ( double * * matrix1 , double * * matrix2 , double * * output ) {
// W dims are ROWS ROWS and x dims are ROWS COLUMNS
int i , j , k ;
for ( i = 0 ; i < ROWS ; i + + ) {
for ( j = 0 ; j < COLUMNS ; j + + ) {
output [ i ] [ j ] = 0 ;
for ( k = 0 ; k < ROWS ; k + + ) {
output [ i ] [ j ] + = matrix1 [ i ] [ k ] * matrix2 [ k ] [ j ] ;
// allocates a 2d array in continuous memory positions
double * * alloc_2d_double ( int rows , int cols ) {
double * data = ( double * ) malloc ( rows * cols * sizeof ( double ) ) ;
double * * array = ( double * * ) malloc ( rows * sizeof ( double * ) ) ;
for ( int i = 0 ; i < rows ; i + + )
array [ i ] = & ( data [ cols * i ] ) ;
return array ;
}
// copy the values of a 2d double array to another
double * * duplicate ( double * * a , double * * b , int rows , int cols ) {
for ( int i = 0 ; i < rows ; i + + ) {
for ( int j = 0 ; j < cols ; j + + ) {
b [ i ] [ j ] = a [ i ] [ j ] ;
}
}
return b ;
}
void print_matrix ( double * * array , int rows , int cols ) {
@ -171,3 +141,19 @@ void print_matrix(double ** array, int rows, int cols){
printf ( " \n " ) ;
}
}
void save_matrix ( double * * matrix , int iteration ) {
char filename [ 18 ] ;
snprintf ( filename , sizeof ( filename ) , " %s%d " , " output/output_ " , iteration ) ;
FILE * iterOutput ;
iterOutput = fopen ( filename , " w " ) ;
for ( int rows = 0 ; rows < ROWS ; + + rows ) {
for ( int cols = 0 ; cols < COLUMNS ; + + cols ) {
fprintf ( iterOutput , " %f " , matrix [ rows ] [ cols ] ) ;
if ( cols ! = COLUMNS - 1 ) {
fprintf ( iterOutput , " , " ) ;
}
}
fprintf ( iterOutput , " \n " ) ;
}
}