Commit 41995b76 authored by Vladislav Sovrasov's avatar Vladislav Sovrasov Committed by Vadim Pisarevsky

KCF speedup (#1374)

* kcf use float data type rather than double.

In our practice, float is good enough and could get better performance.
With this patch, one of my benchmark could get about 20% performance gain.
Signed-off-by: 's avatarZhigang Gong <zhigang.gong@intel.com>

* Offload transpose matrix multiplication to ocl.

The matrix multiplication in updateProjectMatrix is one of the
hotspot. And because of the matrix shape is special, say the
m is very short but the n is very large. The GEMM implementation
in neither the clBLAS nor the in trunk implementation are very
inefficient, I implement an standalone transpose matrix mulplication
kernel here. It can get about 10% performance gain on Intel
desktop platform or 20% performance gain on a braswell platform.
And in the mean time, the CPU utilization will be lower.
Signed-off-by: 's avatarZhigang Gong <zhigang.gong@intel.com>

* Add verification code for kcf ocl transpose mm kernel.
Signed-off-by: 's avatarZhigang Gong <zhigang.gong@linux.intel.com>

* tracking: show FPS in traker sample

* tracking: fix MSVC warnings in KCF

* tracking: move OCL kernel initialization to constructor in KCF
parent 0058eca1
......@@ -1236,12 +1236,12 @@ public:
*/
void write(FileStorage& /*fs*/) const;
double detect_thresh; //!< detection confidence threshold
double sigma; //!< gaussian kernel bandwidth
double lambda; //!< regularization
double interp_factor; //!< linear interpolation factor for adaptation
double output_sigma_factor; //!< spatial bandwidth (proportional to target)
double pca_learning_rate; //!< compression learning rate
float detect_thresh; //!< detection confidence threshold
float sigma; //!< gaussian kernel bandwidth
float lambda; //!< regularization
float interp_factor; //!< linear interpolation factor for adaptation
float output_sigma_factor; //!< spatial bandwidth (proportional to target)
float pca_learning_rate; //!< compression learning rate
bool resize; //!< activate the resize feature to improve the processing speed
bool split_coeff; //!< split the training coefficients into two matrices
bool wrap_kernel; //!< wrap around the kernel values
......
......@@ -117,6 +117,7 @@ int main( int argc, char** argv ){
bool initialized = false;
int frameCounter = 0;
int64 timeTotal = 0;
for ( ;; )
{
......@@ -142,11 +143,14 @@ int main( int argc, char** argv ){
}
else if( initialized )
{
int64 frameTime = getTickCount();
//updates the tracker
if( tracker->update( frame, boundingBox ) )
{
rectangle( image, boundingBox, Scalar( 255, 0, 0 ), 2, 1 );
}
frameTime = getTickCount() - frameTime;
timeTotal += frameTime;
}
imshow( "Tracking API", image );
frameCounter++;
......@@ -159,5 +163,8 @@ int main( int argc, char** argv ){
paused = !paused;
}
double s = frameCounter / (timeTotal / getTickFrequency());
printf("FPS: %f\n", s);
return 0;
}
This source diff could not be displayed because it is too large. You can view the blob instead.
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
// Copyright (C) 2016, Intel, Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
#define LOCAL_SIZE_X 64
#define BLOCK_SIZE_X 3
__kernel void tmm(__global float *A, int m, int n, float alpha, __global float *D)
{
int lidX = get_local_id(0);
uint lsizeX = get_local_size(0);
uint matI = get_group_id(1);
uint matJ = get_group_id(0);
if (matI < matJ)
return;
__local float4 a[LOCAL_SIZE_X], b[LOCAL_SIZE_X];
float4 result;
__local uint cnt;
result = 0;
cnt = 0;
barrier(CLK_LOCAL_MEM_FENCE);
do {
// load block data to SLM.
int global_block_base = (lidX + cnt * lsizeX) * BLOCK_SIZE_X;
float4 pa[BLOCK_SIZE_X], pb[BLOCK_SIZE_X];
#pragma unroll
for(uint j = 0; j < BLOCK_SIZE_X && (cnt * lsizeX + lidX) * BLOCK_SIZE_X < n / 4; j++) {
pa[j] = *(__global float4*)&A[matI * n + (global_block_base + j) * 4];
if (matI != matJ)
pb[j] = *(__global float4*)&A[matJ * n + (global_block_base + j) * 4];
else
pb[j] = pa[j];
}
// zero the data out-of-boundary.
if (global_block_base + BLOCK_SIZE_X - 1 >= n/4) {
#pragma unroll
for(int i = 0; i < BLOCK_SIZE_X; i++) {
if (global_block_base + i >= n/4)
pb[i] = 0;
}
}
pb[0] *= pa[0];
for(int j = 1; j < BLOCK_SIZE_X; j++)
pb[0] = fma(pb[j], pa[j], pb[0]);
b[lidX] = pb[0];
barrier(CLK_LOCAL_MEM_FENCE);
// perform reduce add
for(int offset = LOCAL_SIZE_X / 2; offset > 0; offset >>= 1) {
if (lidX < offset)
b[lidX] += b[(lidX + offset)];
barrier(CLK_LOCAL_MEM_FENCE);
}
if (lidX == 0) {
result += b[0];
cnt++;
}
barrier(CLK_LOCAL_MEM_FENCE);
} while(cnt * BLOCK_SIZE_X * lsizeX < n / 4);
if (lidX == 0) {
float ret = (result.s0 + result.s1 + result.s2 + result.s3) * alpha;
D[matI * m + matJ] = ret;
if (matI != matJ)
D[matJ * m + matI] = ret;
}
}
......@@ -42,6 +42,7 @@
#ifndef __OPENCV_PRECOMP_H__
#define __OPENCV_PRECOMP_H__
#include "cvconfig.h"
#include "opencv2/tracking.hpp"
#include "opencv2/core/utility.hpp"
#include "opencv2/core/ocl.hpp"
......@@ -50,7 +51,7 @@
namespace cv
{
extern const double ColorNames[][10];
extern const float ColorNames[][10];
namespace tracking {
......
......@@ -40,7 +40,9 @@
//M*/
#include "precomp.hpp"
#include "opencl_kernels_tracking.hpp"
#include <complex>
#include <cmath>
/*---------------------------
| TrackerKCFModel
......@@ -93,13 +95,13 @@ namespace cv{
void inline ifft2(const Mat src, Mat & dest) const;
void inline pixelWiseMult(const std::vector<Mat> src1, const std::vector<Mat> src2, std::vector<Mat> & dest, const int flags, const bool conjB=false) const;
void inline sumChannels(std::vector<Mat> src, Mat & dest) const;
void inline updateProjectionMatrix(const Mat src, Mat & old_cov,Mat & proj_matrix,double pca_rate, int compressed_sz,
std::vector<Mat> & layers_pca,std::vector<Scalar> & average, Mat pca_data, Mat new_cov, Mat w, Mat u, Mat v) const;
void inline updateProjectionMatrix(const Mat src, Mat & old_cov,Mat & proj_matrix,float pca_rate, int compressed_sz,
std::vector<Mat> & layers_pca,std::vector<Scalar> & average, Mat pca_data, Mat new_cov, Mat w, Mat u, Mat v);
void inline compress(const Mat proj_matrix, const Mat src, Mat & dest, Mat & data, Mat & compressed) const;
bool getSubWindow(const Mat img, const Rect roi, Mat& feat, Mat& patch, TrackerKCF::MODE desc = GRAY) const;
bool getSubWindow(const Mat img, const Rect roi, Mat& feat, void (*f)(const Mat, const Rect, Mat& )) const;
void extractCN(Mat patch_data, Mat & cnFeatures) const;
void denseGaussKernel(const double sigma, const Mat , const Mat y_data, Mat & k_data,
void denseGaussKernel(const float sigma, const Mat , const Mat y_data, Mat & k_data,
std::vector<Mat> & layers_data,std::vector<Mat> & xf_data,std::vector<Mat> & yf_data, std::vector<Mat> xyf_v, Mat xy, Mat xyf ) const;
void calcResponse(const Mat alphaf_data, const Mat kf_data, Mat & response_data, Mat & spec_data) const;
void calcResponse(const Mat alphaf_data, const Mat alphaf_den_data, const Mat kf_data, Mat & response_data, Mat & spec_data, Mat & spec2_data) const;
......@@ -107,9 +109,12 @@ namespace cv{
void shiftRows(Mat& mat) const;
void shiftRows(Mat& mat, int n) const;
void shiftCols(Mat& mat, int n) const;
#ifdef HAVE_OPENCL
bool inline oclTransposeMM(const Mat src, float alpha, UMat &dst);
#endif
private:
double output_sigma;
float output_sigma;
Rect2d roi;
Mat hann; //hann window filter
Mat hann_cn; //10 dimensional hann-window filter for CN features,
......@@ -154,6 +159,10 @@ namespace cv{
bool resizeImage; // resize the image whenever needed and the patch size is large
#ifdef HAVE_OPENCL
ocl::Kernel transpose_mm_ker; // OCL kernel to compute transpose matrix multiply matrix.
#endif
int frame;
};
......@@ -174,6 +183,16 @@ namespace cv{
use_custom_extractor_pca = false;
use_custom_extractor_npca = false;
#ifdef HAVE_OPENCL
// For update proj matrix's multiplication
if(ocl::useOpenCL())
{
cv::String err;
ocl::ProgramSource tmmSrc = ocl::tracking::tmm_oclsrc;
ocl::Program tmmProg(tmmSrc, String(), err);
transpose_mm_ker.create("tmm", tmmProg);
}
#endif
}
void TrackerKCFImpl::read( const cv::FileNode& fn ){
......@@ -196,8 +215,8 @@ namespace cv{
roi = boundingBox;
//calclulate output sigma
output_sigma=sqrt(roi.width*roi.height)*params.output_sigma_factor;
output_sigma=-0.5/(output_sigma*output_sigma);
output_sigma=std::sqrt(static_cast<float>(roi.width*roi.height))*params.output_sigma_factor;
output_sigma=-0.5f/(output_sigma*output_sigma);
//resize the ROI whenever needed
if(params.resize && roi.width*roi.height>params.max_patch_size){
......@@ -215,21 +234,22 @@ namespace cv{
roi.height*=2;
// initialize the hann window filter
createHanningWindow(hann, roi.size(), CV_64F);
createHanningWindow(hann, roi.size(), CV_32F);
// hann window filter for CN feature
Mat _layer[] = {hann, hann, hann, hann, hann, hann, hann, hann, hann, hann};
merge(_layer, 10, hann_cn);
// create gaussian response
y=Mat::zeros((int)roi.height,(int)roi.width,CV_64F);
for(unsigned i=0;i<(unsigned)roi.height;i++){
for(unsigned j=0;j<(unsigned)roi.width;j++){
y.at<double>(i,j)=(i-roi.height/2+1)*(i-roi.height/2+1)+(j-roi.width/2+1)*(j-roi.width/2+1);
y=Mat::zeros((int)roi.height,(int)roi.width,CV_32F);
for(int i=0;i<roi.height;i++){
for(int j=0;j<roi.width;j++){
y.at<float>(i,j) =
static_cast<float>((i-roi.height/2+1)*(i-roi.height/2+1)+(j-roi.width/2+1)*(j-roi.width/2+1));
}
}
y*=(double)output_sigma;
y*=(float)output_sigma;
cv::exp(y,y);
// perform fourier transfor to the gaussian response
......@@ -259,10 +279,10 @@ namespace cv{
|| use_custom_extractor_npca
);
//return true only if roi has intersection with the image
if((roi & Rect2d(0,0, resizeImage ? image.cols / 2 : image.cols,
resizeImage ? image.rows / 2 : image.rows)) == Rect2d())
return false;
//return true only if roi has intersection with the image
if((roi & Rect2d(0,0, resizeImage ? image.cols / 2 : image.cols,
resizeImage ? image.rows / 2 : image.rows)) == Rect2d())
return false;
return true;
}
......@@ -331,7 +351,7 @@ namespace cv{
// compute the fourier transform of the kernel
fft2(k,kf);
if(frame==1)spec2=Mat_<Vec2d >(kf.rows, kf.cols);
if(frame==1)spec2=Mat_<Vec2f >(kf.rows, kf.cols);
// calculate filter response
if(params.split_coeff)
......@@ -411,7 +431,7 @@ namespace cv{
vxf.resize(x.channels());
vyf.resize(x.channels());
vxyf.resize(vyf.size());
new_alphaf=Mat_<Vec2d >(yf.rows, yf.cols);
new_alphaf=Mat_<Vec2f >(yf.rows, yf.cols);
}
// Kernel Regularized Least-Squares, calculate alphas
......@@ -421,19 +441,19 @@ namespace cv{
fft2(k,kf);
kf_lambda=kf+params.lambda;
double den;
float den;
if(params.split_coeff){
mulSpectrums(yf,kf,new_alphaf,0);
mulSpectrums(kf,kf_lambda,new_alphaf_den,0);
}else{
for(int i=0;i<yf.rows;i++){
for(int j=0;j<yf.cols;j++){
den = 1.0/(kf_lambda.at<Vec2d>(i,j)[0]*kf_lambda.at<Vec2d>(i,j)[0]+kf_lambda.at<Vec2d>(i,j)[1]*kf_lambda.at<Vec2d>(i,j)[1]);
den = 1.0f/(kf_lambda.at<Vec2f>(i,j)[0]*kf_lambda.at<Vec2f>(i,j)[0]+kf_lambda.at<Vec2f>(i,j)[1]*kf_lambda.at<Vec2f>(i,j)[1]);
new_alphaf.at<Vec2d>(i,j)[0]=
(yf.at<Vec2d>(i,j)[0]*kf_lambda.at<Vec2d>(i,j)[0]+yf.at<Vec2d>(i,j)[1]*kf_lambda.at<Vec2d>(i,j)[1])*den;
new_alphaf.at<Vec2d>(i,j)[1]=
(yf.at<Vec2d>(i,j)[1]*kf_lambda.at<Vec2d>(i,j)[0]-yf.at<Vec2d>(i,j)[0]*kf_lambda.at<Vec2d>(i,j)[1])*den;
new_alphaf.at<Vec2f>(i,j)[0]=
(yf.at<Vec2f>(i,j)[0]*kf_lambda.at<Vec2f>(i,j)[0]+yf.at<Vec2f>(i,j)[1]*kf_lambda.at<Vec2f>(i,j)[1])*den;
new_alphaf.at<Vec2f>(i,j)[1]=
(yf.at<Vec2f>(i,j)[1]*kf_lambda.at<Vec2f>(i,j)[0]-yf.at<Vec2f>(i,j)[0]*kf_lambda.at<Vec2f>(i,j)[1])*den;
}
}
}
......@@ -467,24 +487,25 @@ namespace cv{
int rows = dst.rows, cols = dst.cols;
AutoBuffer<double> _wc(cols);
double * const wc = (double *)_wc;
AutoBuffer<float> _wc(cols);
float * const wc = (float *)_wc;
double coeff0 = 2.0 * CV_PI / (double)(cols - 1), coeff1 = 2.0f * CV_PI / (double)(rows - 1);
const float coeff0 = 2.0f * (float)CV_PI / (cols - 1);
const float coeff1 = 2.0f * (float)CV_PI / (rows - 1);
for(int j = 0; j < cols; j++)
wc[j] = 0.5 * (1.0 - cos(coeff0 * j));
wc[j] = 0.5f * (1.0f - cos(coeff0 * j));
if(dst.depth() == CV_32F){
for(int i = 0; i < rows; i++){
float* dstData = dst.ptr<float>(i);
double wr = 0.5 * (1.0 - cos(coeff1 * i));
float wr = 0.5f * (1.0f - cos(coeff1 * i));
for(int j = 0; j < cols; j++)
dstData[j] = (float)(wr * wc[j]);
}
}else{
for(int i = 0; i < rows; i++){
double* dstData = dst.ptr<double>(i);
double wr = 0.5 * (1.0 - cos(coeff1 * i));
double wr = 0.5f * (1.0f - cos(coeff1 * i));
for(int j = 0; j < cols; j++)
dstData[j] = wr * wc[j];
}
......@@ -535,11 +556,37 @@ namespace cv{
}
}
#ifdef HAVE_OPENCL
bool inline TrackerKCFImpl::oclTransposeMM(const Mat src, float alpha, UMat &dst){
// Current kernel only support matrix's rows is multiple of 4.
// And if one line is less than 512KB, CPU will likely be faster.
if (transpose_mm_ker.empty() ||
src.rows % 4 != 0 ||
(src.rows * 10) < (1024 * 1024 / 4))
return false;
Size s(src.rows, src.cols);
const Mat tmp = src.t();
const UMat uSrc = tmp.getUMat(ACCESS_READ);
transpose_mm_ker.args(
ocl::KernelArg::PtrReadOnly(uSrc),
(int)uSrc.rows,
(int)uSrc.cols,
alpha,
ocl::KernelArg::PtrWriteOnly(dst));
size_t globSize[2] = {static_cast<size_t>(src.cols * 64), static_cast<size_t>(src.cols)};
size_t localSize[2] = {64, 1};
if (!transpose_mm_ker.run(2, globSize, localSize, true))
return false;
return true;
}
#endif
/*
* obtains the projection matrix using PCA
*/
void inline TrackerKCFImpl::updateProjectionMatrix(const Mat src, Mat & old_cov,Mat & proj_matrix, double pca_rate, int compressed_sz,
std::vector<Mat> & layers_pca,std::vector<Scalar> & average, Mat pca_data, Mat new_cov, Mat w, Mat u, Mat vt) const {
void inline TrackerKCFImpl::updateProjectionMatrix(const Mat src, Mat & old_cov,Mat & proj_matrix, float pca_rate, int compressed_sz,
std::vector<Mat> & layers_pca,std::vector<Scalar> & average, Mat pca_data, Mat new_cov, Mat w, Mat u, Mat vt) {
CV_Assert(compressed_sz<=src.channels());
split(src,layers_pca);
......@@ -553,17 +600,40 @@ namespace cv{
merge(layers_pca,pca_data);
pca_data=pca_data.reshape(1,src.rows*src.cols);
new_cov=1.0/(double)(src.rows*src.cols-1)*(pca_data.t()*pca_data);
#ifdef HAVE_OPENCL
bool oclSucceed = false;
Size s(pca_data.cols, pca_data.cols);
UMat result(s, pca_data.type());
if (oclTransposeMM(pca_data, 1.0/(float)(src.rows*src.cols-1), result)) {
if(old_cov.rows==0) old_cov=result.getMat(ACCESS_READ).clone();
SVD::compute((1.0-pca_rate)*old_cov + pca_rate * result.getMat(ACCESS_READ), w, u, vt);
oclSucceed = true;
}
#define TMM_VERIFICATION 0
if (oclSucceed == false || TMM_VERIFICATION) {
new_cov=1.0f/(float)(src.rows*src.cols-1)*(pca_data.t()*pca_data);
#if TMM_VERIFICATION
for(int i = 0; i < new_cov.rows; i++)
for(int j = 0; j < new_cov.cols; j++)
if (abs(new_cov.at<float>(i, j) - result.getMat(ACCESS_RW).at<float>(i , j)) > abs(new_cov.at<float>(i, j)) * 1e-3)
printf("error @ i %d j %d got %G expected %G \n", i, j, result.getMat(ACCESS_RW).at<float>(i , j), new_cov.at<float>(i, j));
#endif
if(old_cov.rows==0)old_cov=new_cov.clone();
SVD::compute((1.0f - pca_rate) * old_cov + pca_rate * new_cov, w, u, vt);
}
#else
new_cov=1.0/(float)(src.rows*src.cols-1)*(pca_data.t()*pca_data);
if(old_cov.rows==0)old_cov=new_cov.clone();
// calc PCA
SVD::compute((1.0-pca_rate)*old_cov+pca_rate*new_cov, w, u, vt);
#endif
// extract the projection matrix
proj_matrix=u(Rect(0,0,compressed_sz,src.channels())).clone();
Mat proj_vars=Mat::eye(compressed_sz,compressed_sz,proj_matrix.type());
for(int i=0;i<compressed_sz;i++){
proj_vars.at<double>(i,i)=w.at<double>(i);
proj_vars.at<float>(i,i)=w.at<float>(i);
}
// update the covariance matrix
......@@ -622,8 +692,9 @@ namespace cv{
cvtColor(patch,feat, CV_BGR2GRAY);
else
feat=patch;
feat.convertTo(feat,CV_64F);
feat=feat/255.0-0.5; // normalize to range -0.5 .. 0.5
//feat.convertTo(feat,CV_32F);
feat.convertTo(feat,CV_32F, 1.0/255.0, -0.5);
//feat=feat/255.0-0.5; // normalize to range -0.5 .. 0.5
feat=feat.mul(hann); // hann window filter
break;
}
......@@ -670,8 +741,8 @@ namespace cv{
Vec3b & pixel = patch_data.at<Vec3b>(0,0);
unsigned index;
if(cnFeatures.type() != CV_64FC(10))
cnFeatures = Mat::zeros(patch_data.rows,patch_data.cols,CV_64FC(10));
if(cnFeatures.type() != CV_32FC(10))
cnFeatures = Mat::zeros(patch_data.rows,patch_data.cols,CV_32FC(10));
for(int i=0;i<patch_data.rows;i++){
for(int j=0;j<patch_data.cols;j++){
......@@ -680,7 +751,7 @@ namespace cv{
//copy the values
for(int _k=0;_k<10;_k++){
cnFeatures.at<Vec<double,10> >(i,j)[_k]=ColorNames[index][_k];
cnFeatures.at<Vec<float,10> >(i,j)[_k]=ColorNames[index][_k];
}
}
}
......@@ -690,7 +761,7 @@ namespace cv{
/*
* dense gauss kernel function
*/
void TrackerKCFImpl::denseGaussKernel(const double sigma, const Mat x_data, const Mat y_data, Mat & k_data,
void TrackerKCFImpl::denseGaussKernel(const float sigma, const Mat x_data, const Mat y_data, Mat & k_data,
std::vector<Mat> & layers_data,std::vector<Mat> & xf_data,std::vector<Mat> & yf_data, std::vector<Mat> xyf_v, Mat xy, Mat xyf ) const {
double normX, normY;
......@@ -718,11 +789,11 @@ namespace cv{
//threshold(xy,xy,0.0,0.0,THRESH_TOZERO);//max(0, (xx + yy - 2 * xy) / numel(x))
for(int i=0;i<xy.rows;i++){
for(int j=0;j<xy.cols;j++){
if(xy.at<double>(i,j)<0.0)xy.at<double>(i,j)=0.0;
if(xy.at<float>(i,j)<0.0)xy.at<float>(i,j)=0.0;
}
}
double sig=-1.0/(sigma*sigma);
float sig=-1.0f/(sigma*sigma);
xy=sig*xy;
exp(xy,k_data);
......@@ -796,14 +867,14 @@ namespace cv{
mulSpectrums(alphaf_data,kf_data,spec_data,0,false);
//z=(a+bi)/(c+di)=[(ac+bd)+i(bc-ad)]/(c^2+d^2)
double den;
float den;
for(int i=0;i<kf_data.rows;i++){
for(int j=0;j<kf_data.cols;j++){
den=1.0/(_alphaf_den.at<Vec2d>(i,j)[0]*_alphaf_den.at<Vec2d>(i,j)[0]+_alphaf_den.at<Vec2d>(i,j)[1]*_alphaf_den.at<Vec2d>(i,j)[1]);
spec2_data.at<Vec2d>(i,j)[0]=
(spec_data.at<Vec2d>(i,j)[0]*_alphaf_den.at<Vec2d>(i,j)[0]+spec_data.at<Vec2d>(i,j)[1]*_alphaf_den.at<Vec2d>(i,j)[1])*den;
spec2_data.at<Vec2d>(i,j)[1]=
(spec_data.at<Vec2d>(i,j)[1]*_alphaf_den.at<Vec2d>(i,j)[0]-spec_data.at<Vec2d>(i,j)[0]*_alphaf_den.at<Vec2d>(i,j)[1])*den;
den=1.0f/(_alphaf_den.at<Vec2f>(i,j)[0]*_alphaf_den.at<Vec2f>(i,j)[0]+_alphaf_den.at<Vec2f>(i,j)[1]*_alphaf_den.at<Vec2f>(i,j)[1]);
spec2_data.at<Vec2f>(i,j)[0]=
(spec_data.at<Vec2f>(i,j)[0]*_alphaf_den.at<Vec2f>(i,j)[0]+spec_data.at<Vec2f>(i,j)[1]*_alphaf_den.at<Vec2f>(i,j)[1])*den;
spec2_data.at<Vec2f>(i,j)[1]=
(spec_data.at<Vec2f>(i,j)[1]*_alphaf_den.at<Vec2f>(i,j)[0]-spec_data.at<Vec2f>(i,j)[0]*_alphaf_den.at<Vec2f>(i,j)[1])*den;
}
}
......@@ -825,11 +896,11 @@ namespace cv{
* Parameters
*/
TrackerKCF::Params::Params(){
detect_thresh = 0.5;
sigma=0.2;
lambda=0.0001;
interp_factor=0.075;
output_sigma_factor=1.0/16.0;
detect_thresh = 0.5f;
sigma=0.2f;
lambda=0.0001f;
interp_factor=0.075f;
output_sigma_factor=1.0f / 16.0f;
resize=true;
max_patch_size=80*80;
split_coeff=true;
......@@ -840,7 +911,7 @@ namespace cv{
//feature compression
compress_feature=true;
compressed_size=2;
pca_learning_rate=0.15;
pca_learning_rate=0.15f;
}
void TrackerKCF::Params::read( const cv::FileNode& fn ){
......
......@@ -63,10 +63,10 @@ TEST(KCF_Parameters, IO)
{
TrackerKCF::Params parameters;
parameters.sigma = 0.3;
parameters.lambda = 0.02;
parameters.interp_factor = 0.08;
parameters.output_sigma_factor = 1.0/ 32.0;
parameters.sigma = 0.3f;
parameters.lambda = 0.02f;
parameters.interp_factor = 0.08f;
parameters.output_sigma_factor = 1.0f/ 32.0f;
parameters.resize=false;
parameters.max_patch_size=90*90;
parameters.split_coeff=false;
......@@ -75,7 +75,7 @@ TEST(KCF_Parameters, IO)
parameters.desc_pca = TrackerKCF::GRAY;
parameters.compress_feature=false;
parameters.compressed_size=3;
parameters.pca_learning_rate=0.2;
parameters.pca_learning_rate=0.2f;
FileStorage fsWriter("parameters.xml", FileStorage::WRITE + FileStorage::MEMORY);
parameters.write(fsWriter);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment