Added two kernels to existing SVM framework
Histogram intersection kernel (accessible by using SVM::INTER in CV namespace as kernel_type) Exponetial chi2 kernel (accessible by using SVM::CHI2 in CV namespace as kernel_type) Formulars: Exp-CHI2 k(x,y) = exp(-gamma * CHI2(x,y)) CHI2(x,y) = 1- 2* SUM_i[(xi-yi)²/(xi+yi)] Intersec k(x,y) = SUM_i[min(xi,yi)]
This commit is contained in:
@@ -220,6 +220,8 @@ bool CvSVMKernel::create( const CvSVMParams* _params, Calc _calc_func )
|
||||
calc_func = params->kernel_type == CvSVM::RBF ? &CvSVMKernel::calc_rbf :
|
||||
params->kernel_type == CvSVM::POLY ? &CvSVMKernel::calc_poly :
|
||||
params->kernel_type == CvSVM::SIGMOID ? &CvSVMKernel::calc_sigmoid :
|
||||
params->kernel_type == CvSVM::CHI2 ? &CvSVMKernel::calc_chi2 :
|
||||
params->kernel_type == CvSVM::INTER ? &CvSVMKernel::calc_intersec :
|
||||
&CvSVMKernel::calc_linear;
|
||||
|
||||
return true;
|
||||
@@ -318,6 +320,52 @@ void CvSVMKernel::calc_rbf( int vcount, int var_count, const float** vecs,
|
||||
cvExp( &R, &R );
|
||||
}
|
||||
|
||||
/// Histogram intersection kernel
|
||||
void CvSVMKernel::calc_intersec( int vcount, int var_count, const float** vecs,
|
||||
const float* another, Qfloat* results )
|
||||
{
|
||||
int j, k;
|
||||
for( j = 0; j < vcount; j++ )
|
||||
{
|
||||
const float* sample = vecs[j];
|
||||
double s = 0;
|
||||
for( k = 0; k <= var_count - 4; k += 4 )
|
||||
s += min(sample[k],another[k]) + min(sample[k+1],another[k+1]) +
|
||||
min(sample[k+2],another[k+2]) + min(sample[k+3],another[k+3]);
|
||||
for( ; k < var_count; k++ )
|
||||
s += min(sample[k],another[k]);
|
||||
results[j] = (Qfloat)(s);
|
||||
}
|
||||
}
|
||||
|
||||
/// Exponential chi2 kernel
|
||||
void CvSVMKernel::calc_chi2( int vcount, int var_count, const float** vecs,
|
||||
const float* another, Qfloat* results )
|
||||
{
|
||||
CvMat R = cvMat( 1, vcount, QFLOAT_TYPE, results );
|
||||
double gamma = -params->gamma;
|
||||
int j, k;
|
||||
for( j = 0; j < vcount; j++ )
|
||||
{
|
||||
const float* sample = vecs[j];
|
||||
double chi2 = 0;
|
||||
for(k = 0 ; k < var_count; k++ )
|
||||
{
|
||||
double d = sample[k]*another[k];
|
||||
double devisor = sample[k]+another[k];
|
||||
/// if devisor == 0, the Chi2 distance would be zero, but calculation would rise an error because of deviding by zero
|
||||
if (devisor != 0)
|
||||
{
|
||||
chi2 += d*d/devisor;
|
||||
}
|
||||
}
|
||||
results[j] = (Qfloat) (gamma*(1.0-2*chi2));
|
||||
}
|
||||
if( vcount > 0 )
|
||||
cvExp( &R, &R );
|
||||
|
||||
|
||||
}
|
||||
|
||||
void CvSVMKernel::calc( int vcount, int var_count, const float** vecs,
|
||||
const float* another, Qfloat* results )
|
||||
|
Reference in New Issue
Block a user