little tenfex interface change

+ moved FexTracker to OPEN SOURCE :)

Originally committed to SVN as r194.
This commit is contained in:
tentacle 2006-03-03 19:00:47 +00:00
parent 12363b6dc5
commit cd6beca548
25 changed files with 1802 additions and 0 deletions

View File

@ -0,0 +1,78 @@
#include <math.h>
#include "FexGenericFilter_Include.h"
FexFilter::FexFilter()
{
Width = 3;
}
FexFilter::~FexFilter()
{
}
double FexFilter::Filter( double t )
{
return t/Width;
}
/*
f(x) = e^(-x^2 / (2 s^2) )
f(x) = e^(-x^2 / t)
width:
SOLVE(0.1 = f(x), x, Real)
x = - sqrt(t LN(10) ? x = sqrt(t LN(10)
sum:
Integral from -sqrt(t LN(10) to sqrt(t LN(10) of f(x) dx
1.715955662·sqrt(t)
*/
FexFilter_Gauss::FexFilter_Gauss( double sigma )
{
Sigma = sigma;
TwoSigmaSq = 2*sigma*sigma;
Width = sqrt( TwoSigmaSq*log(10) );
Normalize = 1.0 / (1.715955662 * sqrt( TwoSigmaSq ));
}
FexFilter_Gauss::~FexFilter_Gauss()
{
}
double FexFilter_Gauss::Filter( double t )
{
return exp( -t*t / TwoSigmaSq ) * Normalize;
}
/*
f(x) = -x * e^(-x^2 / (2 s^2) )
f(x) = -x * e^(-x^2 / t)
width:
use the width of gauss since i'm clueless here
sum:
Integral from -sqrt(t LN(10) to sqrt(t LN(10) of -x*f(x) dx
0.7062351183·t^1.5
*/
FexFilter_GaussDerivation::FexFilter_GaussDerivation( double sigma )
{
Sigma = sigma;
TwoSigmaSq = 2*sigma*sigma;
Width = sqrt( TwoSigmaSq*log(10) );
Normalize = 1.0 / (0.7062351183 * pow( TwoSigmaSq, 1.5 ));
}
FexFilter_GaussDerivation::~FexFilter_GaussDerivation()
{
}
double FexFilter_GaussDerivation::Filter( double t )
{
return -t * exp( -t*t / TwoSigmaSq ) * Normalize;
}

View File

@ -0,0 +1,91 @@
#include "stdio.h"
#include "math.h"
#include "memory.h"
#include "FexGenericFilter_Include.h"
void BaseFloatImage_Filter( float* in, int inSx, int inSy, FexFilter* filter, float* out, int outSx, int outSy )
{
#define FilterWidth (filter->Width)
#define FilterWeight(t) (filter->Filter(t))
float* tmp = new float[outSx*inSy];
#include "FexGenericFilter_BaseFloatImageApply.h"
delete []tmp;
#undef FilterWidth
#undef FilterWeight
}
void BaseFloatImage_FilterSeperate( float* in, int inSx, int inSy, FexFilter* filterX, FexFilter* filterY, float* out, int outSx, int outSy )
{
float* tmp = new float[outSx*inSy];
#define FilterWidth (filterX->Width)
#define FilterWeight(t) (filterX->Filter(t))
#define FILTER_NO_Y
#include "FexGenericFilter_BaseFloatImageApply.h"
#undef FilterWidth
#undef FilterWeight
#undef FILTER_NO_Y
#define FilterWidth (filterY->Width)
#define FilterWeight(t) (filterY->Filter(t))
#define FILTER_NO_X
#include "FexGenericFilter_BaseFloatImageApply.h"
#undef FilterWidth
#undef FilterWeight
#undef FILTER_NO_X
delete []tmp;
}
void BaseFloatImage_GaussEdgeDetect( float* Img, int sizx, int sizy, float sigma, float* GradX, float* GradY )
{
FexFilter_Gauss gauss (sigma);
FexFilter_GaussDerivation gaussDeriv (sigma);
BaseFloatImage_FilterSeperate( Img, sizx, sizy, &gaussDeriv, &gauss, GradX, sizx, sizy );
BaseFloatImage_FilterSeperate( Img, sizx, sizy, &gauss, &gaussDeriv, GradY, sizx, sizy );
}
void BaseFloatImage_GaussSmooth( float* Img, int sizx, int sizy, float sigma, float* Out )
{
FexFilter_Gauss gauss (sigma);
BaseFloatImage_Filter( Img, sizx,sizy, &gauss, Out, sizx, sizy );
}
#include <math.h>
inline double sinc( double x )
{
x *= 3.1415;
if( x != 0 )
return( sin(x) / x );
return( 1.0 );
}
inline double RescaleFilter( double t )
{
if( t < 0 )
t = -t;
if( t < 3.0 )
return( sinc(t) * sinc(t/3.0) );
return( 0.0 );
}
void BaseFloatImage_LanczosRescale( float* in, int inSx, int inSy, float* out, int outSx, int outSy )
{
#define FilterWidth (3)
#define FilterWeight(t) (RescaleFilter(t))
float* tmp = new float[outSx*inSy];
#include "FexGenericFilter_BaseFloatImageApply.h"
delete []tmp;
#undef FilterWidth
#undef FilterWeight
}

View File

@ -0,0 +1,46 @@
{
#define PixelType float
#define PixelMin 0
#define PixelMax 255
#define ImagePlanes 1
//do filtering + scaling in x-dir
#define ImageInSX (inSx)
#define ImageInSY (inSy)
#define ImageIn(x,y,p) (in[ (y*inSx+x) ])
#define ImageOutSX (outSx)
#define ImageOut(x,y,p) (tmp[ (y*outSx+x) ])
#ifndef FILTER_NO_X
#include "FexGenericFilter_FilteringCore.h"
#endif
#undef ImageInSX
#undef ImageInSY
#undef ImageIn
#undef ImageOutSX
#undef ImageOut
//do filtering + scaling in y-dir by using transposed image
#define ImageInSX (inSy)
#define ImageInSY (outSx)
#define ImageIn(y,x,p) (tmp[ (y*outSx+x) ])
#define ImageOutSX (outSy)
#define ImageOut(y,x,p) (out[ (y*outSx+x) ])
#ifndef FILTER_NO_Y
#include "FexGenericFilter_FilteringCore.h"
#endif
#undef ImageInSX
#undef ImageInSY
#undef ImageIn
#undef ImageOutSX
#undef ImageOut
#undef PixelType
#undef PixelMin
#undef PixelMax
#undef ImagePlanes
}

View File

@ -0,0 +1,38 @@
{
double width = FilterWidth;
#ifdef CONTRIB_XSCALE
width /= XScale;
double fscale = 1.0 / XScale;
#endif
for(int i=0;i<ImageOutSX;++i)
{
double center = (double) i / XScale;
FexFilterContribution* cc = &Contrib[i];
int left = (int) ceil(center - width);
int right = (int) (floor(center + width) + 0.1);
cc->xMin = left;
cc->xMax = right;
if( cc->xMin < 0 ) cc->xMin = 0;
if( cc->xMax > ImageInSX-1 ) cc->xMax = ImageInSX - 1;
int len = cc->xMax-cc->xMin+1;
cc->Weight = new double[ len ];
memset( cc->Weight, 0x00, sizeof(double)*len );
for(int j=left;j<=right;++j) {
double weight = center - (double) j;
#ifdef CONTRIB_XSCALE
weight = FilterWeight(weight / fscale) / fscale;
#else
weight = FilterWeight(weight);
#endif
int n;
if(j < 0) n=0;
else if(j >= ImageInSX) n = ImageInSX - 1;
else n = j;
cc->Weight[n-cc->xMin] += weight;
}
}
}

View File

@ -0,0 +1,47 @@
#include "stdafx.h"
#include "FexSystem.h"
#include "ext\imdebug.h"
void FexImage_Filter( FexImage* in, FexFilter* filter, FexImage* out )
{
#define FilterWidth (filter->Width)
#define FilterWeight(t) (filter->Filter(t))
#include "FexGenericFilter_FexImageApply.h"
#undef FilterWidth
#undef FilterWeight
}
#include <math.h>
inline double sinc( double x )
{
x *= 3.1415;
if( x != 0 )
return( sin(x) / x );
return( 1.0 );
}
inline double RescaleFilter( double t )
{
if( t < 0 )
t = -t;
if( t < 3.0 )
return( sinc(t) * sinc(t/3.0) );
return( 0.0 );
}
void FexImage_Rescale( FexImage* in, FexImage* out )
{
#define FilterWidth (3)
#define FilterWeight(t) (RescaleFilter(t))
#include "FexGenericFilter_FexImageApply.h"
#undef FilterWidth
#undef FilterWeight
}

View File

@ -0,0 +1,46 @@
{
#define PixelType BYTE
#define PixelMin 0
#define PixelMax 255.9
#define ImagePlanes 4
FexImage* tmp = new FexImage(out->sx,in->sy);
//do filtering + scaling in x-dir
#define ImageInSX (in->sx)
#define ImageInSY (in->sy)
#define ImageIn(x,y,p) (in->data[ (y*in->sx+x)*4 + p ])
#define ImageOutSX (tmp->sx)
#define ImageOut(x,y,p) (tmp->data[ (y*tmp->sx+x)*4 + p ])
#include "FexGenericFilter_FilteringCore.h"
#undef ImageInSX
#undef ImageInSY
#undef ImageIn
#undef ImageOutSX
#undef ImageOut
//do filtering + scaling in y-dir by using transposed image
#define ImageInSX (tmp->sy)
#define ImageInSY (tmp->sx)
#define ImageIn(y,x,p) (tmp->data[ (y*tmp->sx+x)*4 + p ])
#define ImageOutSX (out->sy)
#define ImageOut(y,x,p) (out->data[ (y*out->sx+x)*4 + p ])
#include "FexGenericFilter_FilteringCore.h"
#undef ImageInSX
#undef ImageInSY
#undef ImageIn
#undef ImageOutSX
#undef ImageOut
delete tmp;
#undef PixelType
#undef PixelMin
#undef PixelMax
#undef ImagePlanes
}

View File

@ -0,0 +1,53 @@
{
FexFilterContribution* Contrib = new FexFilterContribution[ ImageOutSX ];
double XScale = (double)ImageOutSX / (double) ImageInSX;
//calculate contributions
if( XScale < 1.0 )
{
#define CONTRIB_XSCALE
#include "FexGenericFilter_Contribution.h"
#undef CONTRIB_XSCALE
}
else
{
#include "FexGenericFilter_Contribution.h"
}
#include "FexGenericFilter_StaticFor.h"
//apply filter
for( int y=0;y<ImageInSY;++y)
{
for( int x=0;x<ImageOutSX;++x )
{
FexFilterContribution* cc = &Contrib[x];
double Sum[ImagePlanes];
#define DOFOR(i) Sum[i] = 0.0;
STATIC_FOR
#undef DOFOR
for( int lx=cc->xMin;lx<=cc->xMax;++lx )
{
#define DOFOR(i) Sum[i] += ((double)ImageIn(lx,y,i))*cc->Weight[lx-cc->xMin];
STATIC_FOR
#undef DOFOR
}
#define DOFOR(i) {if(Sum[i]<PixelMin)Sum[i]=PixelMin;if(Sum[i]>PixelMax)Sum[i]=PixelMax;}
STATIC_FOR
#undef DOFOR
#define DOFOR(i) ImageOut(x,y,i) = (PixelType) Sum[i];
STATIC_FOR
#undef DOFOR
}
}
for( int x=0;x<ImageOutSX;++x )
delete []Contrib[x].Weight;
delete []Contrib;
}

View File

@ -0,0 +1,38 @@
class FexFilter {
public:
FexFilter();
~FexFilter();
virtual double Filter( double t );
double Width;
};
class FexFilter_Gauss : public FexFilter {
public:
FexFilter_Gauss( double sigma );
~FexFilter_Gauss();
double Filter( double t );
double Sigma;
double TwoSigmaSq;
double Normalize;
};
class FexFilter_GaussDerivation : public FexFilter {
public:
FexFilter_GaussDerivation( double sigma );
~FexFilter_GaussDerivation();
double Filter( double t );
double Sigma;
double TwoSigmaSq;
double Normalize;
};
struct FexFilterContribution {
int xMin, xMax;
double* Weight;
};

View File

@ -0,0 +1,10 @@
#if ImagePlanes==1
#define STATIC_FOR {DOFOR(0)}
#elif ImagePlanes==3
#define STATIC_FOR {DOFOR(0) DOFOR(1) DOFOR(2)}
#elif ImagePlanes==4
#define STATIC_FOR {DOFOR(0) DOFOR(1) DOFOR(2) DOFOR(3)}
#else
#define STATIC_FOR {for( int dofori=0;dofori<ImagePlanes;++doforti ){DOFOR(i)}}
#endif

View File

@ -0,0 +1,109 @@
// FexImgPyramid.cpp: implementation of the FexImgPyramid class.
//
//////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include "FexImgPyramid.h"
#include "../FexGenericFilter/FexGenericFilter_Include.h"
void BaseFloatImage_GaussEdgeDetect( float* Img, int sizx, int sizy, float sigma, float* GradX, float* GradY );
void BaseFloatImage_GaussSmooth( float* Img, int sizx, int sizy, float sigma, float* Out );
void BaseFloatImage_LanczosRescale( float* in, int inSx, int inSy, float* out, int outSx, int outSy );
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
FexImgPyramidLevel::FexImgPyramidLevel( int isx, int isy )
{
sx = isx;
sy = isy;
Img = new float[ sx*sy ];
GradX = new float[ sx*sy ];
GradY = new float[ sx*sy ];
}
FexImgPyramidLevel::~FexImgPyramidLevel()
{
delete [] Img;
delete [] GradX;
delete [] GradY;
}
void FexImgPyramidLevel::Fill( float* iImg, float DetectSmoothSigma )
{
/*
for( int y=0;y<sy;y++ )
for( int x=0;x<sx;x++ )
Img[ sx*y + x ] = iImg[ sx*y + x ];
*/
imdebug("lum b=32f w=%d h=%d %p /255", sx, sy, iImg);
BaseFloatImage_GaussSmooth( iImg, sx, sy, DetectSmoothSigma, Img );
imdebug("lum b=32f w=%d h=%d %p /255", sx, sy, Img);
}
void FexImgPyramidLevel::Scale( FexImgPyramidLevel* old )
{
imdebug("lum b=32f w=%d h=%d %p /255", old->sx, old->sy, old->Img);
BaseFloatImage_LanczosRescale( old->Img, old->sx, old->sy, Img, sx, sy );
imdebug("lum b=32f w=%d h=%d %p /255", sx, sy, Img);
}
void FexImgPyramidLevel::Calc( float EdgeDetectSigma )
{
imdebug("lum b=32f w=%d h=%d %p /255", sx, sy, Img);
BaseFloatImage_GaussEdgeDetect( Img, sx, sy, EdgeDetectSigma, GradX, GradY );
imdebug("lum b=32f w=%d h=%d %p /2", sx, sy, GradX);
imdebug("lum b=32f w=%d h=%d %p /2", sx, sy, GradY);
}
FexImgPyramid::FexImgPyramid( float* Img, int SizX, int SizY, float EdgeDetectSigma, float DetectSmoothSigma, int iSubsampling, int Levels )
{
int i;
Subsampling = iSubsampling;
if( Levels == -1 ) Levels = 999;
int mLvl = 0;
int tsm = min(SizX,SizY);
while( tsm>1 && tsm%2==0 )
{
tsm/=Subsampling;
++mLvl;
}
if( Levels > mLvl ) Levels = mLvl;
if( Levels < 1 ) Levels = 1;
nLevels = Levels;
lLevels = new FexImgPyramidLevel*[ nLevels ];
lLevels[0] = new FexImgPyramidLevel( SizX, SizY );
lLevels[0]->Fill( Img, DetectSmoothSigma );
for( i=1;i<nLevels;i++ )
{
SizX /= Subsampling;
SizY /= Subsampling;
lLevels[i] = new FexImgPyramidLevel( SizX, SizY );
lLevels[i]->Scale( lLevels[i-1] );
}
float cmul = 1.f;
for( i=0;i<nLevels;i++ )
{
lLevels[i]->CoordMul = cmul;
lLevels[i]->Calc( EdgeDetectSigma );
cmul /= Subsampling;
}
}
FexImgPyramid::~FexImgPyramid()
{
for( int i=0;i<nLevels;i++ )
delete lLevels[i];
delete [] lLevels;
}

View File

@ -0,0 +1,42 @@
// FexImgPyramid.h: interface for the FexImgPyramid class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_FEXIMGPYRAMID_H__B289955E_6660_483D_AF51_CE78F2D03944__INCLUDED_)
#define AFX_FEXIMGPYRAMID_H__B289955E_6660_483D_AF51_CE78F2D03944__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class FexImgPyramidLevel
{
public:
FexImgPyramidLevel( int sx, int sy );
~FexImgPyramidLevel();
int sx, sy;
float CoordMul;
float* Img;
float* GradX;
float* GradY;
void Fill( float* Img, float DetectSmoothSigma );
void Scale( FexImgPyramidLevel* old );
void Calc( float EdgeDetectSigma );
};
class FexImgPyramid
{
public:
FexImgPyramid( float* Img, int SizX, int SizY, float EdgeDetectSigma, float DetectSmoothSigma, int Subsampling, int Levels );
~FexImgPyramid();
int Subsampling;
FexImgPyramidLevel** lLevels;
int nLevels;
};
#endif // !defined(AFX_FEXIMGPYRAMID_H__B289955E_6660_483D_AF51_CE78F2D03944__INCLUDED_)

View File

@ -0,0 +1,94 @@
// FexMovement.cpp: implementation of the FexMovement class.
//
//////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include "stdio.h"
#include <conio.h>
#include <ctype.h>
#include <string.h>
#include <time.h>
//#include <mmsystem.h>
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
FexMovement::FexMovement()
{
FileName = 0;
}
FexMovement::~FexMovement()
{
if( FileName ) delete []FileName;
}
FEXTRACKER_API FexMovement* CreateMovement()
{
return new FexMovement();
}
FEXTRACKER_API void LoadMovement( FexMovement* me, const unsigned short* Filename )
{
me->Frames.nVal = 0;
me->FileName = new WCHAR[ wcslen(Filename)+1 ];
wcscpy( me->FileName, Filename );
FILE *fi = _wfopen( Filename, L"rt" );
if( !fi ) return;
int CurFeat = -1;
char Line[512];
while( !feof(fi) )
{
Line[0]=0;
fgets( Line, 510, fi );
if( !Line[0] ) break;
FexMovementFrame f;
int r = sscanf( Line, "(%f %f)(%f %f %f)(%f %f)",
&f.Pos.x, &f.Pos.y,
&f.Rot.x, &f.Rot.y, &f.Rot.z,
&f.Scale.x, &f.Scale.y );
if( r != 7 ) continue;
me->Frames.Add( f );
}
fclose( fi );
}
FEXTRACKER_API void SaveMovement( FexMovement* me, const unsigned short* Filename )
{
FILE *fi = _wfopen( Filename, L"wt" );
if( !fi ) return;
for( int i=0;i<me->Frames.size();i++ )
{
const FexMovementFrame f = me->Frames[i];
fprintf( fi, "(%f %f)(%f %f %f)(%f %f)\n",
f.Pos.x, f.Pos.y,
f.Rot.x, f.Rot.y, f.Rot.z,
f.Scale.x, f.Scale.y );
}
fclose( fi );
}
/*
const WCHAR* FEXTRACKER_API GetUniqueName()
{
static WCHAR Name[512];
time_t long_time;
time( &long_time );
swprintf( Name, L"%x%x\n", timeGetTime(), long_time );
for( DWORD i=0;i<wcslen(Name);i++ )
{
Name[i] = towlower( Name[i] );
if( Name[i]<'a' || Name[i]>'z' )
Name[i] = '_';
}
wcscat( Name, L".fexmove" );
return Name;
}
*/
FEXTRACKER_API void DeleteMovement( FexMovement* delme )
{
delete delme;
}

View File

@ -0,0 +1,37 @@
// FexMovement.h: interface for the FexMovement class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_FEXMOVEMENT_H__63D8ADD8_4EA1_4C56_8D6F_7B587A1A61A4__INCLUDED_)
#define AFX_FEXMOVEMENT_H__63D8ADD8_4EA1_4C56_8D6F_7B587A1A61A4__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
typedef struct
{
vec2 Pos;
vec3 Rot;
vec2 Scale;
}FexMovementFrame;
#include "tenlist.h"
class FexMovement
{
public:
FexMovement();
~FexMovement();
WCHAR* FileName;
tenlist<FexMovementFrame> Frames;
};
FEXTRACKER_API FexMovement* CreateMovement();
FEXTRACKER_API void LoadMovement( FexMovement* me, const unsigned short* Filename );
FEXTRACKER_API void SaveMovement( FexMovement* me, const unsigned short* Filename );
FEXTRACKER_API void DeleteMovement( FexMovement* delme );
//WCHAR* FEXTRACKER_API GetUniqueName();
#endif // !defined(AFX_FEXMOVEMENT_H__63D8ADD8_4EA1_4C56_8D6F_7B587A1A61A4__INCLUDED_)

View File

@ -0,0 +1,479 @@
// FexTracker.cpp : Defines the entry point for the DLL application.
//
#include "StdAfx.h"
#include "stdio.h"
//#include "mmsystem.h"
FexTracker::FexTracker( int sx, int sy, int inFeatures )
{
printf( "[ using FexTracker (c)2006 Hajo Krabbenhoft ]\n" );
nFeatures = inFeatures;
minFeatures = 0;
mFeatures = 8;
lFeatures = (FexTrackingFeature*) new FexTrackingFeature[mFeatures];
SizX = sx;
SizY = sy;
CurImg = 0;
CurFrame = 0;
bDebug = 0;
float subsampling = float(Cfg.SearchRange) / min(Cfg.WindowX,Cfg.WindowY);
if (subsampling < 1.0) { /* 1.0 = 0+1 */
PyramidMaxLevels = 1;
} else if (subsampling <= 3.0) { /* 3.0 = 2+1 */
PyramidMaxLevels = 2;
PyramidSubsampling = 2;
} else if (subsampling <= 5.0) { /* 5.0 = 4+1 */
PyramidMaxLevels = 2;
PyramidSubsampling = 4;
} else if (subsampling <= 9.0) { /* 9.0 = 8+1 */
PyramidMaxLevels = 2;
PyramidSubsampling = 8;
} else {
/* The following lines are derived from the formula:
search_range =
window_halfwidth * \sum_{i=0}^{nPyramidLevels-1} 8^i,
which is the same as:
search_range =
window_halfwidth * (8^nPyramidLevels - 1)/(8 - 1).
Then, the value is rounded up to the nearest integer. */
float val = (float) (log(7.0*subsampling+1.0)/log(8.0));
PyramidMaxLevels = (int) (val + 0.99);
PyramidSubsampling = 8;
}
/*
PyramidMaxLevels = 2;
PyramidSubsampling = 2;
*/
}
FexTracker::~FexTracker()
{
delete [] lFeatures;
if( CurImg ) delete CurImg;
}
void FexTracker::ProcessImage( float *Img, bool bFirst )
{
//DWORD t = timeGetTime();
if( bFirst || !CurImg )
{
CurFrame = 0;
CurImg = new FexImgPyramid( Img, SizX, SizY, Cfg.EdgeDetectSigma, Cfg.DetectSmoothSigma, PyramidSubsampling, PyramidMaxLevels );
nActiveFeatures = 0;
int tmp = nFeatures;
nFeatures = 0;
FindFeatures( tmp );
}
else
{
CountActiveFeatures();
if( nActiveFeatures<minFeatures )
FindFeatures( minFeatures );
NextImg = new FexImgPyramid( Img, SizX, SizY, Cfg.EdgeDetectSigma, Cfg.DetectSmoothSigma, PyramidSubsampling, PyramidMaxLevels );
TrackFeatures();
delete CurImg;
CurImg = NextImg;
NextImg = 0;
}
CurFrame++;
//DWORD t2 = timeGetTime();
//printf( "ProcessImage: %d ms\n", (t2-t) );
}
void FexTracker::ProcessingDone()
{
if( CurImg ) delete CurImg;
CurImg = 0;
}
void FexTracker::CountActiveFeatures()
{
nActiveFeatures = 0;
for( int i=0;i<nFeatures;i++ )
{
if( lFeatures[i].StartTime + lFeatures[i].Pos.size() >= CurFrame )
nActiveFeatures++;
}
}
FexTrackingFeature* FexTracker::operator [] ( int i )
{
if( i<0 || i>=nFeatures ) return 0;
return & lFeatures[i];
}
int FexTracker::GetEigenvalueForPoint( int px, int py )
{
int sx = px - Cfg.WindowX;
int ex = px + Cfg.WindowX;
int sy = py - Cfg.WindowY;
int ey = py + Cfg.WindowY;
if( sx<0 )sx=0;
if( sy<0 )sy=0;
if( ex>SizX-1 )ex=SizX-1;
if( ey>SizY-1 )ey=SizY-1;
int imgSX = CurImg->lLevels[0]->sx;
float* gradx = CurImg->lLevels[0]->GradX;
float* grady = CurImg->lLevels[0]->GradY;
register float gxx = 0, gyy = 0, gxy = 0;
for( int y=sy;y<ey;y++ )
{
for( int x=sx;x<ex;x++ )
{
float gx = gradx[ imgSX*y + x ];
float gy = grady[ imgSX*y + x ];
gxx += gx*gx;
gyy += gy*gy;
gxy += gx*gy;
}
}
float val = gxx + gyy - sqrtf((gxx - gyy)*(gxx - gyy) + 4*gxy*gxy);
if( val>(1<<30) ) val=(1<<30);
return (int) val;
}
typedef struct{
int val, x, y;
}littleFeature;
#define SWAP3(list, i, j) \
{register int *pi, *pj, tmp; \
pi=list+3*(i); pj=list+3*(j); \
\
tmp=*pi; \
*pi++=*pj; \
*pj++=tmp; \
\
tmp=*pi; \
*pi++=*pj; \
*pj++=tmp; \
\
tmp=*pi; \
*pi=*pj; \
*pj=tmp; \
}
void _quicksort(int *pointlist, int n)
{
unsigned int i, j, ln, rn;
while (n > 1)
{
SWAP3(pointlist, 0, n/2);
for (i = 0, j = n; ; )
{
do
--j;
while (pointlist[3*j] < pointlist[0]);
do
++i;
while (i < j && pointlist[3*i] > pointlist[0]);
if (i >= j)
break;
SWAP3(pointlist, i, j);
}
SWAP3(pointlist, j, 0);
ln = j;
rn = n - ++j;
if (ln < rn)
{
_quicksort(pointlist, ln);
pointlist += 3*j;
n = rn;
}
else
{
_quicksort(pointlist + 3*j, rn);
n = ln;
}
}
}
#undef SWAP3
void FexTracker::FindFeatures( int minFeatures )
{
int nli=0;
littleFeature *list = new littleFeature[SizX*SizY];
for( int y=0;y<SizY;y++ )
{
for( int x=0;x<SizX;x++ )
{
int v = GetEigenvalueForPoint( x, y );
if( v>0 )
{
list[nli].val = v;
list[nli].x = x;
list[nli].y = y;
nli++;
}
}
}
_quicksort( (int*)list, nli );
int oldN = nFeatures;
for( int i=0;i<nli && nActiveFeatures<minFeatures;i++ )
{
for( int j=0;j<nFeatures;j++ )
{
if( lFeatures[j].StartTime + lFeatures[j].Pos.size() < CurFrame ) continue; //feature was lost
float dx = list[i].x - lFeatures[j].Pos[ CurFrame - lFeatures[j].StartTime ].x;
float dy = list[i].y - lFeatures[j].Pos[ CurFrame - lFeatures[j].StartTime ].y;
float sqr = dx*dx+dy*dy;
if( sqr < Cfg.MinDistanceSquare ) break;
}
if( j!=nFeatures ) continue;
if( nFeatures >= mFeatures )
{
mFeatures = nFeatures+9;
mFeatures -= mFeatures%8;
FexTrackingFeature * nlFeatures = (FexTrackingFeature*) new FexTrackingFeature[mFeatures];
for( int cpy=0;cpy<nFeatures;cpy++ )
{
nlFeatures[ cpy ].Eigenvalue = lFeatures[ cpy ].Eigenvalue;
nlFeatures[ cpy ].StartTime = lFeatures[ cpy ].StartTime;
nlFeatures[ cpy ].Influence = lFeatures[ cpy ].Influence;
for( int cpy2=0;cpy2<lFeatures[ cpy ].Pos.size();cpy2++ )
nlFeatures[ cpy ].Pos.Add( lFeatures[ cpy ].Pos[cpy2] );
}
delete [] lFeatures;
lFeatures = nlFeatures;
}
lFeatures[nFeatures].Eigenvalue = list[i].val;
vec2 pt;
pt.x = (float)list[i].x;
pt.y = (float)list[i].y;
lFeatures[nFeatures].Pos.Add( pt );
lFeatures[nFeatures].StartTime = CurFrame;
lFeatures[nFeatures].Influence = 0;
nFeatures++;
nActiveFeatures++;
}
for( int j=oldN;j<nFeatures;j++ )
lFeatures[j].StartTime = max(0,lFeatures[j].StartTime-1);
delete []list;
}
void FexTracker::TrackFeatures()
{
for( int i=0;i<nFeatures;i++ )
{
if( lFeatures[i].StartTime + lFeatures[i].Pos.size() < CurFrame ) continue; //feature was lost
int FeatureFrame = CurFrame - lFeatures[i].StartTime;
float orig_px = lFeatures[i].Pos[FeatureFrame-1].x;
float orig_py = lFeatures[i].Pos[FeatureFrame-1].y;
vec2 op;
op.x = orig_px * CurImg->lLevels[ CurImg->nLevels-1 ]->CoordMul / CurImg->Subsampling;
op.y = orig_py * CurImg->lLevels[ CurImg->nLevels-1 ]->CoordMul / CurImg->Subsampling;
vec2 np;
np = op;
for( int l=CurImg->nLevels-1;l>=0;l-- )
{
op.x *= CurImg->Subsampling;
op.y *= CurImg->Subsampling;
np.x *= CurImg->Subsampling;
np.y *= CurImg->Subsampling;
if( !TrackOneFeature( l, op, np ) ) break;
}
if( l!=-1 ) continue; //we aborted
if( np.x<0 || np.y<0 || np.x>SizX || np.y>SizY ) continue;
lFeatures[i].Pos.Add( np );
}
}
bool FexTracker::TrackOneFeature( int lvl, vec2 op, vec2& np )
{
static float bordereps = 1.1f;
if( op.x - Cfg.WindowX < bordereps || op.x + Cfg.WindowX > CurImg->lLevels[lvl]->sx - bordereps ) return 0;
if( op.y - Cfg.WindowY < bordereps || op.y + Cfg.WindowY > CurImg->lLevels[lvl]->sy - bordereps ) return 0;
if( np.x - Cfg.WindowX < bordereps || np.x + Cfg.WindowX > CurImg->lLevels[lvl]->sx - bordereps ) return 0;
if( np.y - Cfg.WindowY < bordereps || np.y + Cfg.WindowY > CurImg->lLevels[lvl]->sy - bordereps ) return 0;
int isx = (Cfg.WindowX*2+1);
int imsiz = isx*(Cfg.WindowY*2+1);
float *diff = new float[imsiz];
float *gradx = new float[imsiz];
float *grady = new float[imsiz];
bool bOk = 1;
for( int iteration=0;iteration<Cfg.MaxIterations;iteration++ )
{
GetDiffForPointset( lvl, op, np, diff );
GetGradForPointset( lvl, op, np, gradx, grady );
/*
imdebug("lum b=32f w=%d h=%d %p /255", isx, imsiz/isx, diff);
imdebug("lum b=32f w=%d h=%d %p /255", isx, imsiz/isx, gradx);
imdebug("lum b=32f w=%d h=%d %p /255", isx, imsiz/isx, grady);
*/
register float gx, gy, di;
float gxx = 0, gyy = 0, gxy = 0, ex = 0, ey = 0;
for( int i=0;i<imsiz;i++ )
{
di = diff[i];
gx = gradx[i];
gy = grady[i];
gxx += gx*gx;
gyy += gy*gy;
gxy += gx*gy;
ex += di*gx;
ey += di*gy;
}
float det = gxx*gyy - gxy*gxy;
if( det < Cfg.MinDeterminant )
{
bOk = 0;
break;
}
float dx = (gyy*ex - gxy*ey)/det;
float dy = (gxx*ey - gxy*ex)/det;
np.x += dx;
np.y += dy;
if( ( np.x - Cfg.WindowX < bordereps || np.x + Cfg.WindowX > CurImg->lLevels[lvl]->sx - bordereps )
|| ( np.y - Cfg.WindowY < bordereps || np.y + Cfg.WindowY > CurImg->lLevels[lvl]->sy - bordereps ) )
{
bOk = 0;
break;
}
if( fabs(dx) < Cfg.MinDisplacement && fabs(dy) < Cfg.MinDisplacement )break;
}
delete [] gradx;
delete [] grady;
if( bOk )
{
GetDiffForPointset( lvl, op, np, diff );
float sum = 0;
for( int i=0;i<imsiz;i++ )
sum += fabsf( diff[i] );
if( sum / float(imsiz) > Cfg.MaxResidue ) bOk = 0;
}
delete [] diff;
return bOk;
}
inline float Interpolate( float *img, int ImgSX, float x, float y )
{
int xt = (int) x; /* coordinates of top-left corner */
int yt = (int) y;
float ax = x - xt;
float ay = y - yt;
float *ptr = img + (ImgSX*yt) + xt;
return ( (1-ax) * (1-ay) * *ptr +
ax * (1-ay) * *(ptr+1) +
(1-ax) * ay * *(ptr+(ImgSX)) +
ax * ay * *(ptr+(ImgSX)+1) );
}
void FexTracker::GetDiffForPointset( int lvl, vec2 op, vec2 np, float* diff )
{
float* img1 = CurImg->lLevels[lvl]->Img;
int isx1 = CurImg->lLevels[lvl]->sx;
float* img2 = NextImg->lLevels[lvl]->Img;
int isx2 = NextImg->lLevels[lvl]->sx;
for( int y = -Cfg.WindowY; y <= Cfg.WindowY; y++ )
{
for( int x = -Cfg.WindowX; x <= Cfg.WindowX; x++ )
{
*diff++ = Interpolate(img1,isx1,op.x+x,op.y+y) - Interpolate(img2,isx2,np.x+x,np.y+y);
}
}
}
void FexTracker::GetGradForPointset( int lvl, vec2 op, vec2 np, float* gradx, float* grady )
{
int isx = CurImg->lLevels[lvl]->sx;
float* gx1 = CurImg->lLevels[lvl]->GradX;
float* gx2 = NextImg->lLevels[lvl]->GradX;
float* gy1 = CurImg->lLevels[lvl]->GradY;
float* gy2 = NextImg->lLevels[lvl]->GradY;
for( int y = -Cfg.WindowY; y <= Cfg.WindowY; y++ )
{
for( int x = -Cfg.WindowX; x <= Cfg.WindowX; x++ )
{
*gradx++ = Interpolate(gx1,isx,op.x+x,op.y+y) + Interpolate(gx2,isx,np.x+x,np.y+y);
*grady++ = Interpolate(gy1,isx,op.x+x,op.y+y) + Interpolate(gy2,isx,np.x+x,np.y+y);
}
}
}
/*
static float _minEigenvalue(float gxx, float gxy, float gyy)
{
return (float) ((gxx + gyy - sqrt((gxx - gyy)*(gxx - gyy) + 4*gxy*gxy))/2.0f);
}
//gen eigenvalue matrix:
gxx = 0; gxy = 0; gyy = 0;
for (yy = y-window_hh ; yy <= y+window_hh ; yy++)
{
for (xx = x-window_hw ; xx <= x+window_hw ; xx++)
{
gx = *(gradx->data + ncols*yy+xx);
gy = *(grady->data + ncols*yy+xx);
gxx += gx * gx;
gxy += gx * gy;
gyy += gy * gy;
}
}
//get eigenvalue number
val = _minEigenvalue(gxx, gxy, gyy);
for every frame:
for every feature:
through all pyramid levels from lowres to highres:
calculate diff, gradx, grady
gen eigenvalue matrix
error vector = [gradx, grady]*imdiff
float det = gxx*gyy - gxy*gxy;
if (det < small) return KLT_SMALL_DET;
*dx = (gyy*ex - gxy*ey)/det;
*dy = (gxx*ey - gxy*ex)/det;
add [dx,dy] to search position
*/

View File

@ -0,0 +1,131 @@
// The following ifdef block is the standard way of creating macros which make exporting
// from a DLL simpler. All files within this DLL are compiled with the FEXTRACKER_EXPORTS
// symbol defined on the command line. this symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see
// FEXTRACKER_API functions as being imported from a DLL, wheras this DLL sees symbols
// defined with this macro as being exported.
#ifdef FEXTRACKER_EXPORTS
#define FEXTRACKER_API __declspec(dllexport)
#else
#define FEXTRACKER_API __declspec(dllimport)
#endif
class FEXTRACKER_API FexTrackerConfig
{
public:
inline FexTrackerConfig() :
FeatureNumber(0),
EdgeDetectSigma(1.f),
WindowX(3), WindowY(3),
SearchRange(15),
MaxIterations(10),
MinDeterminant(0.01f),
MinDisplacement(0.1f),
MaxResidue(10.f),
IgnoreLightning(0),
DetectSmoothSigma(0.9f),
MinDistanceSquare(100.f)
{};
int FeatureNumber;
int WindowX, WindowY; //static const int window_size = 7;
int SearchRange;
float DetectSmoothSigma; //static const float pyramid_sigma_fact = 0.9f;
float EdgeDetectSigma; //static const float grad_sigma = 1.0f;
int MaxIterations; //static const int max_iterations = 10;
float MinDeterminant; //static const float min_determinant = 0.01f;
float MinDisplacement; //static const float min_displacement = 0.1f;
float MaxResidue; //static const float max_residue = 10.0f;
bool IgnoreLightning; //static const KLT_BOOL lighting_insensitive = FALSE;
float MinDistanceSquare; //static const int mindist = 10;
//static const int min_eigenvalue = 1;
//static const float smooth_sigma_fact = 0.1f;
//static const KLT_BOOL sequentialMode = FALSE;
///* for affine mapping*/
//static const int affineConsistencyCheck = -1;
//static const int affine_window_size = 15;
//static const int affine_max_iterations = 10;
//static const float affine_max_residue = 10.0;
//static const float affine_min_displacement = 0.02f;
//static const float affine_max_displacement_differ = 1.5f;
};
typedef struct{
float x, y;
}vec2;
typedef struct{
float x, y, z;
}vec3;
class FexImgPyramid;
class FexTrackingFeature;
class FexMovement;
class FEXTRACKER_API FexTracker
{
public:
FexTracker( int sx, int sy, int nFeatures );
~FexTracker();
//config
FexTrackerConfig Cfg;
//work
void ProcessImage( float *Img, bool bFirst=0 ); //we assume grayscale image here
void ProcessingDone(); // call after last call to ProcessImage to clear temporary storage
//point -> movement
void InfluenceFeatures( int Frame, float x, float y, float off );
FexMovement* GetMovement();
//feature access
FexTrackingFeature* operator [] ( int i );
inline int GetCount(){ return nFeatures; };
inline int GetFrame(){ return CurFrame; };
inline int GetSizeX(){ return SizX; };
inline int GetSizeY(){ return SizY; };
bool bDebug;
int minFeatures;
private:
int SizX, SizY;
int PyramidSubsampling;
int PyramidMaxLevels;
FexImgPyramid* CurImg;
FexImgPyramid* NextImg;
void FindFeatures( int minFeatures );
void TrackFeatures();
bool TrackOneFeature( int lvl, vec2 op, vec2& np );
int GetEigenvalueForPoint( int px, int py );
void GetDiffForPointset( int lvl, vec2 op, vec2 np, float* diff );
void GetGradForPointset( int lvl, vec2 op, vec2 np, float* gradx, float* grady );
void CountActiveFeatures();
//result
FexTrackingFeature* lFeatures;
int nFeatures;
int nActiveFeatures;
int mFeatures;
int CurFrame;
};
FEXTRACKER_API void FexBaseResize( float* out, int newx, int newy, float* in, int sizx, int sizy );
FEXTRACKER_API void GaussKernelWidths( float sigma, int *gauss_width, int *gaussderiv_width );
FEXTRACKER_API void GaussEdgeDetect( float* Img, int sizx, int sizy, float sigma, float* GradX, float* GradY );
FEXTRACKER_API void GaussSmooth( float* Img, int sizx, int sizy, float sigma, float* Out );

View File

@ -0,0 +1,248 @@
// FexTrackerMovement.cpp
//
#include "StdAfx.h"
#include "stdio.h"
//#include "mmsystem.h"
void FexTracker::InfluenceFeatures( int Frame, float x, float y, float off )
{
for( int i=0;i<nFeatures;i++ )
{
if( Frame < lFeatures[i].StartTime ) continue;
int FeatureFrame = Frame - lFeatures[i].StartTime;
if( lFeatures[i].Pos.size() < FeatureFrame ) continue; //feature was lost
vec2 p = lFeatures[i].Pos[ FeatureFrame ];
float dist = sqrtf( (p.x-x)*(p.x-x)+(p.y-y)*(p.y-y) );
float infl = 1/(dist+1);
if( infl < 0.1 ) continue;
lFeatures[i].Influence += infl * off;
if( lFeatures[i].Influence<0 ) lFeatures[i].Influence = 0;
if( lFeatures[i].Influence>1 ) lFeatures[i].Influence = 1;
}
}
/*
void LineTracing( haAssLine *c, vec2& TracePos, vec2& TraceScale, int Frame, vec2 InScreenPlace )
{
TracePos = vec2(0,0);
TraceScale = vec2(0,0);
vec2 Sum1Pos = vec2(0,0);
vec2 Sum2Pos = vec2(0,0);
float TraceScaleV=0;
float wsum = 0;
for( int i=0;i<c->FeatureIdList.GetSize();i++ )
{
tenFeatureLink l = c->FeatureIdList[i];
tenFeature f = Trace_GetFeatureByID( l.id, Frame );
if( f.id < 0 || l.weight<0.01 )
continue;
Sum1Pos += vec2(
(f.x)/float(ncols)*float(AssRes[0]),
(f.y)/float(nrows)*float(AssRes[1])
)*l.weight;
Sum2Pos += vec2(
(l.sub.x)/float(ncols)*float(AssRes[0]),
(l.sub.y)/float(nrows)*float(AssRes[1])
)*l.weight;
wsum += l.weight;
}
if( wsum>0.01 )
{
Sum1Pos /= wsum;
Sum2Pos /= wsum;
TracePos = Sum1Pos - Sum2Pos;
wsum = 0;
CArray<float, float&> DistList;
CArray<float, float&> WeightList;
//now we know weighted mid point, gen vectors from points to mid
for( int i=0;i<c->FeatureIdList.GetSize();i++ )
{
tenFeatureLink l = c->FeatureIdList[i];
tenFeature f = Trace_GetFeatureByID( l.id, Frame );
if( f.id < 0 || l.weight<0.01 )
continue;
vec2 mid = vec2(
(f.x)/float(ncols)*float(AssRes[0]),
(f.y)/float(nrows)*float(AssRes[1])
);
vec2 midToMe = mid - Sum1Pos;
vec2 stdMidToMe = vec2(
(l.sub.x)/float(ncols)*float(AssRes[0]),
(l.sub.y)/float(nrows)*float(AssRes[1])
) - Sum2Pos;
float stdlen = sqrtf( stdMidToMe.x*stdMidToMe.x + stdMidToMe.y*stdMidToMe.y );
if( stdlen < 3 )
{//too much error amplification.skip
continue;
}
float len = sqrtf( midToMe.x*midToMe.x + midToMe.y*midToMe.y );
float scale = len/stdlen;
// TRACE( "%f\n", scale );
float addme = scale*l.weight;
TraceScaleV += addme;
DistList.Add( scale );
WeightList.Add( l.weight );
wsum += l.weight;
}
TraceScaleV /= wsum;
float TraceScaleV2=0;
for( i=0;i<DistList.GetSize();i++ )
{
TraceScaleV2 += ((DistList[i]-TraceScaleV)*0.5f+TraceScaleV)*WeightList[i];
}
TraceScaleV2 /= wsum;
TraceScale = vec2(1,1)*TraceScaleV2;
vec2 MidToItemStd = InScreenPlace - Sum2Pos;
TracePos += MidToItemStd*(TraceScaleV2-1);
}
else
{
TracePos = vec2(0,0);
TraceScale = vec2(1,1);
}
}
*/
#define VEC2LEN(a) sqrtf( (a).x*(a).x+(a).y*(a).y )
FexMovement* FexTracker::GetMovement()
{
FILE *log = fopen( "movementlog.txt", "wt" );
int i;
for( i=0;i<nFeatures;i++ )
{
if( lFeatures[i].Influence>0.01 )
fprintf( log, "Feature(%.2f): %d - %d\n", lFeatures[i].Influence, lFeatures[i].StartTime, lFeatures[i].StartTime+lFeatures[i].Pos.size() );
}
FexMovement *m = new FexMovement();
FexMovementFrame f;
float FirstInfluenceSum = 0;
vec2 FirstPos;
FirstPos.x = FirstPos.y = 0;
for( i=0;i<nFeatures;i++ )
{
if( 0 < lFeatures[i].StartTime ) continue;
if( lFeatures[i].Pos.size() <= 0 ) continue;
vec2 p = lFeatures[i].Pos[ 0 ];
FirstPos.x += p.x * lFeatures[i].Influence;
FirstPos.y += p.y * lFeatures[i].Influence;
FirstInfluenceSum += lFeatures[i].Influence;
}
FirstPos.x /= FirstInfluenceSum;
FirstPos.y /= FirstInfluenceSum;
float FirstLen = 1;
vec2* MidOffset = (vec2*) new vec2[nFeatures];
float* MidOffsetLen = (float*) new float[nFeatures];
for( int Frame = 0; Frame < CurFrame; Frame ++ )
{
//set feature offset
for( i=0;i<nFeatures;i++ )
{
if( Frame == lFeatures[i].StartTime )
{
MidOffset[i].x = FirstPos.x - lFeatures[i].Pos[0].x;
MidOffset[i].y = FirstPos.y - lFeatures[i].Pos[0].y;
//realOffLen / MidOffLen = FirstLen
// => MidOffLen /= FirstLen;
MidOffset[i].x /= FirstLen;
MidOffset[i].y /= FirstLen;
MidOffsetLen[i] = VEC2LEN( MidOffset[i] );
}
}
//accumulate position
float NextLen = 0;
float NextInfluenceSum = 0;
vec2 NextPos;
NextPos.x = NextPos.y = 0;
for( i=0;i<nFeatures;i++ )
{
if( Frame < lFeatures[i].StartTime ) continue;
int FeatureFrame = Frame - lFeatures[i].StartTime;
if( lFeatures[i].Pos.size() <= FeatureFrame ) continue; //feature was lost
vec2 p = lFeatures[i].Pos[ FeatureFrame ];
NextPos.x += (p.x+MidOffset[i].x*FirstLen) * lFeatures[i].Influence;
NextPos.y += (p.y+MidOffset[i].y*FirstLen) * lFeatures[i].Influence;
NextInfluenceSum += lFeatures[i].Influence;
}
if( NextInfluenceSum > 0.01 )
{
NextPos.x /= NextInfluenceSum;
NextPos.y /= NextInfluenceSum;
}
else
NextPos = FirstPos; //take over last one
for( i=0;i<nFeatures;i++ )
{
if( Frame < lFeatures[i].StartTime ) continue;
int FeatureFrame = Frame - lFeatures[i].StartTime;
if( lFeatures[i].Pos.size() <= FeatureFrame ) continue; //feature was lost
vec2 p = lFeatures[i].Pos[ FeatureFrame ];
vec2 realMidOff;
realMidOff.x = NextPos.x-p.x;
realMidOff.y = NextPos.y-p.y;
float realMidOffLen = VEC2LEN( realMidOff );
NextLen += realMidOffLen/MidOffsetLen[i] *lFeatures[i].Influence;
}
if( NextInfluenceSum > 0.01 )
{
NextLen /= NextInfluenceSum;
}
else
NextLen = FirstLen; //take over last one
f.Pos = NextPos;
f.Rot.x = 0;
f.Rot.y = 0;
f.Rot.z = 0;
f.Scale.x = NextLen;
f.Scale.y = NextLen;
m->Frames.Add( f );
FirstPos = NextPos;
FirstLen = NextLen;
}
delete []MidOffset;
delete []MidOffsetLen;
fclose( log );
return m;
}

View File

@ -0,0 +1,19 @@
// FexTrackingFeature.cpp: implementation of the FexTrackingFeature class.
//
//////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
FexTrackingFeature::FexTrackingFeature()
{
}
FexTrackingFeature::~FexTrackingFeature()
{
}

View File

@ -0,0 +1,27 @@
// FexTrackingFeature.h: interface for the FexTrackingFeature class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_FEXTRACKINGFEATURE_H__23B42013_9F11_467C_A0F6_F9E647D45CEB__INCLUDED_)
#define AFX_FEXTRACKINGFEATURE_H__23B42013_9F11_467C_A0F6_F9E647D45CEB__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "tenlist.h"
class FexTrackingFeature
{
public:
FexTrackingFeature();
~FexTrackingFeature();
int Eigenvalue;
tenlist<vec2> Pos;
int StartTime;
float Influence;
};
#endif // !defined(AFX_FEXTRACKINGFEATURE_H__23B42013_9F11_467C_A0F6_F9E647D45CEB__INCLUDED_)

View File

@ -0,0 +1,8 @@
// stdafx.cpp : source file that includes just the standard includes
// FexTracker.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include "StdAfx.h"
// TODO: reference any additional headers you need in STDAFX.H
// and not in this file

34
FexTrackerSource/StdAfx.h Normal file
View File

@ -0,0 +1,34 @@
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#if !defined(AFX_STDAFX_H__7E36ECD6_3192_4C7E_88C9_742CCCFA5057__INCLUDED_)
#define AFX_STDAFX_H__7E36ECD6_3192_4C7E_88C9_742CCCFA5057__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// Insert your headers here
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#include <windows.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include "FexTracker.h"
#include "FexImgPyramid.h"
#include "FexTrackingFeature.h"
#include "FexMovement.h"
#include "ext/imdebug.h"
// TODO: reference additional headers your program requires here
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_STDAFX_H__7E36ECD6_3192_4C7E_88C9_742CCCFA5057__INCLUDED_)

View File

@ -0,0 +1,65 @@
#pragma once
template< class type >
class tenlist {
public:
int nVal;
int mVal;
type* lVal;
inline tenlist()
{
mVal = 0;
nVal = 0;
lVal = 0;
//zero everything since we well over-zero it anyway
}
inline ~tenlist()
{
free( lVal );
}
inline int size()
{
return nVal;
}
inline void Add( type t )
{
if( nVal+1 >= mVal )
{
mVal += 8;
lVal = (type*)realloc( lVal, sizeof(type)*mVal );
memset( lVal+nVal, 0x00, sizeof(type)*(mVal-nVal) ); //lVal+nVal, since it'll be multiplied by sizeof(type) due to lVal being a type*
}
lVal[nVal++] = t;
}
inline void AddStr( type t )
{
if( nVal+1 >= mVal )
{
mVal += 8;
lVal = (type*)realloc( lVal, sizeof(type)*mVal );
memset( lVal+nVal, 0x00, sizeof(type)*(mVal-nVal) ); //lVal+nVal, since it'll be multiplied by sizeof(type) due to lVal being a type*
}
strcpy( lVal[nVal++], t );
}
inline void Rem( int n )
{
if( n>=nVal )
{
nVal = 0;
return;
}
for( int i=0;i<nVal;i++ )
{
lVal[i] = lVal[i+n];
}
}
type& operator[]( int i ) const
{ return lVal[i]; }
};

View File

@ -193,6 +193,15 @@ bool AssDialogue::Parse(wxString rawData, bool IsSSA) {
Effect.Trim(true);
Effect.Trim(false);
#ifndef NO_FEX
if( Effect.BeforeFirst(':')==_T("FexMovement") )
{
if( Movement ) DeleteMovement( Movement );
Movement = CreateMovement();
LoadMovement( Movement, (unsigned short*) Effect.AfterFirst(':').c_str() );
}
#endif
// Get text
Text = tkn.GetNextToken();
while (tkn.HasMoreTokens()) {

View File

@ -48,6 +48,8 @@ void FrameMain::OnVideoTrackerMenu(wxCommandEvent &event) {
// Movement Menu
void FrameMain::OnVideoTrackerMenu2(wxCommandEvent &event) {
wxMenu menu( _("FexMovement") );
AppendBitmapMenuItem(&menu, Video_Track_Movement_Empty, _("Generate empty movement"), _T(""), wxBITMAP(button_track_move));
menu.AppendSeparator();
AppendBitmapMenuItem(&menu, Video_Track_Movement_MoveAll, _("Move subtitle"), _T(""), wxBITMAP(button_track_move));
menu.AppendSeparator();
AppendBitmapMenuItem(&menu, Video_Track_Movement_MoveBefore, _("Move subtitle (this frame and preceeding frames)"), _T(""), wxBITMAP(button_track_move));
@ -55,6 +57,8 @@ void FrameMain::OnVideoTrackerMenu2(wxCommandEvent &event) {
AppendBitmapMenuItem(&menu, Video_Track_Movement_MoveAfter, _("Move subtitle (this frame and following frames)"), _T(""), wxBITMAP(button_track_move));
menu.AppendSeparator();
AppendBitmapMenuItem(&menu, Video_Track_Split_Line, _("Split line for movement"), _T(""), wxBITMAP(button_track_split_line));
menu.AppendSeparator();
AppendBitmapMenuItem(&menu, Video_Track_Link_File, _("Link movement file"), _T(""), wxBITMAP(button_track_move));
PopupMenu(&menu);
}
@ -193,6 +197,49 @@ void FrameMain::OnVideoTrackSplitLine(wxCommandEvent &event) {
}
///////////////////
// generate empty movement
void FrameMain::OnVideoTrackMovementEmpty(wxCommandEvent &event) {
// Get line
AssDialogue *curline = SubsBox->GetDialogue(EditBox->linen);
if (!curline) return;
if( curline->Movement ) DeleteMovement( curline->Movement );
curline->Movement = CreateMovement();
// Create split lines
int StartFrame = VFR_Output.GetFrameAtTime(curline->Start.GetMS(),true);
int EndFrame = VFR_Output.GetFrameAtTime(curline->End.GetMS(),false);
FexMovementFrame f;
memset( &f, 0x00, sizeof(f) );
f.Scale.x = f.Scale.y = 1;
for( int i=StartFrame;i<EndFrame;i++ )
curline->Movement->Frames.Add( f );
}
///////////////////
// link line to move file
void FrameMain::OnVideoTrackLinkFile(wxCommandEvent &event) {
videoBox->videoDisplay->Stop();
// Get line
AssDialogue *curline = SubsBox->GetDialogue(EditBox->linen);
if (!curline) return;
wxString link = wxGetTextFromUser(_("Link name:"), _("Link line to movement file"), curline->Movement?curline->Movement->FileName:_T(""), this);
if( link.empty() ) curline->Effect = _T("");
else curline->Effect = _T("FexMovement:")+link;
curline->UpdateData();
if( !curline->Effect.empty() && curline->Movement )
SaveMovement( curline->Movement, (unsigned short*) curline->Effect.AfterFirst(':').c_str() );
}
///////////////////
// Increase Influence
void FrameMain::OnVideoTrackPointAdd(wxCommandEvent &event) {

View File

@ -118,6 +118,8 @@ private:
void OnVideoTrackMovementMoveBefore(wxCommandEvent &event);
void OnVideoTrackMovementMoveAfter(wxCommandEvent &event);
void OnVideoTrackSplitLine(wxCommandEvent &event);
void OnVideoTrackLinkFile(wxCommandEvent &event);
void OnVideoTrackMovementEmpty(wxCommandEvent &event);
void OnKeyDown(wxKeyEvent &event);
@ -352,6 +354,8 @@ enum {
Video_Track_Movement_MoveBefore,
Video_Track_Movement_MoveAfter,
Video_Track_Split_Line,
Video_Track_Link_File,
Video_Track_Movement_Empty,
Menu_File_Recent = 2000,
Menu_Video_Recent = 2200,

View File

@ -104,6 +104,8 @@ BEGIN_EVENT_TABLE(FrameMain, wxFrame)
EVT_MENU(Video_Track_Movement_MoveBefore, FrameMain::OnVideoTrackMovementMoveBefore)
EVT_MENU(Video_Track_Movement_MoveAfter, FrameMain::OnVideoTrackMovementMoveAfter)
EVT_MENU(Video_Track_Split_Line, FrameMain::OnVideoTrackSplitLine)
EVT_MENU(Video_Track_Link_File, FrameMain::OnVideoTrackLinkFile)
EVT_MENU(Video_Track_Movement_Empty, FrameMain::OnVideoTrackMovementEmpty)
#endif
EVT_CLOSE(FrameMain::OnCloseWindow)