Removed FexTracker for good.

Originally committed to SVN as r1214.
This commit is contained in:
Niels Martin Hansen 2007-06-08 00:30:37 +00:00
parent 94385aca8f
commit 1a5906f97c
37 changed files with 3 additions and 2583 deletions

View File

@ -1,87 +0,0 @@
// This file is part of FexGenericFilter and (C) 2006 by Hajo Krabbenhöft (tentacle)
// All rights reserved but the aegisub project is allowed to use it.
#include <math.h>
#include "StdAfx.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)
x = - 1.517427129·sqrt t ? x = 1.517427129·sqrt t
x = - sqrt(2*s*s* LN(10)) ? x = sqrt(2*s*s* LN(10))
x = - 2.145966026·s ? x = 2.145966026·s
sum:
Integral from -sqrt(t LN(10) to sqrt(t LN(10) of f(x) dx
1.715955662·sqrt(t)
2.426727768·s
*/
FexFilter_Gauss::FexFilter_Gauss( double sigma )
{
Sigma = sigma;
TwoSigmaSq = 2*sigma*sigma;
Width = 2.145966026 * sigma;
Normalize = 1.0 / (2.426727768 * sigma);
Normalize *= 1.0 + 0.1 / Width; //its the 0.1 we left out
}
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 = 2.145966026 * sigma;
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

@ -1,93 +0,0 @@
// This file is part of FexGenericFilter and (C) 2006 by Hajo Krabbenhöft (tentacle)
// All rights reserved but the aegisub project is allowed to use it.
#include "StdAfx.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

@ -1,50 +0,0 @@
// This file is part of FexGenericFilter and (C) 2006 by Hajo Krabbenhöft (tentacle)
// All rights reserved but the aegisub project is allowed to use it.
{
#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

@ -1,42 +0,0 @@
// This file is part of FexGenericFilter and (C) 2006 by Hajo Krabbenhöft (tentacle)
// All rights reserved but the aegisub project is allowed to use it.
{
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

@ -1,57 +0,0 @@
// This file is part of FexGenericFilter and (C) 2006 by Hajo Krabbenhöft (tentacle)
// All rights reserved but the aegisub project is allowed to use it.
{
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

@ -1,42 +0,0 @@
// This file is part of FexGenericFilter and (C) 2006 by Hajo Krabbenh<6E>t (tentacle)
// All rights reserved but the aegisub project is allowed to use it.
class FexFilter {
public:
FexFilter();
virtual ~FexFilter();
virtual double Filter( double t );
double Width;
};
class FexFilter_Gauss : public FexFilter {
public:
FexFilter_Gauss( double sigma );
virtual ~FexFilter_Gauss();
double Filter( double t );
double Sigma;
double TwoSigmaSq;
double Normalize;
};
class FexFilter_GaussDerivation : public FexFilter {
public:
FexFilter_GaussDerivation( double sigma );
virtual ~FexFilter_GaussDerivation();
double Filter( double t );
double Sigma;
double TwoSigmaSq;
double Normalize;
};
struct FexFilterContribution {
int xMin, xMax;
double* Weight;
};

View File

@ -1,13 +0,0 @@
// This file is part of FexGenericFilter and (C) 2006 by Hajo Krabbenhöft (tentacle)
// All rights reserved but the aegisub project is allowed to use it.
#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

@ -1,115 +0,0 @@
// This file is part of FexTracker and (C) 2006 by Hajo Krabbenhöft (tentacle)
// All rights reserved but the aegisub project is allowed to use it.
// FexImgPyramid.cpp: implementation of the FexImgPyramid class.
//
//////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include "FexImgPyramid.h"
#include "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 );
#ifndef MIN
#define MIN(a,b) ((a)<(b))?(a):(b)
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
//turn off image debugging
#ifndef imdebug
#define imdebug(a,b,c,d) //
#endif
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 )
{
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

@ -1,45 +0,0 @@
// This file is part of FexTracker and (C) 2006 by Hajo Krabbenhöft (tentacle)
// All rights reserved but the aegisub project is allowed to use it.
// 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; // dimensions of this level
float CoordMul;
float* Img; // actual image data
float* GradX; // X gradients
float* GradY; // Y gradients
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

@ -1,97 +0,0 @@
// This file is part of FexTracker and (C) 2006 by Hajo Krabbenhöft (tentacle)
// All rights reserved but the aegisub project is allowed to use it.
// FexMovement.cpp: implementation of the FexMovement class.
//
//////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include "stdio.h"
#ifdef WIN32
#include <conio.h>
#endif
#include <ctype.h>
#include <string.h>
#include <time.h>
#include <wchar.h>
//#include <mmsystem.h>
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
FexMovement::FexMovement()
{
FileName = 0;
}
FexMovement::~FexMovement()
{
if( FileName ) delete []FileName;
}
FEXTRACKER_API FexMovement* CreateMovement()
{
return new FexMovement();
}
#ifndef WIN32
FILE *_wfopen(const wchar_t *wname, const wchar_t *wmode)
{
size_t namelen = wcstombs(NULL, wname, 0) + 1;
char name[namelen];
wcstombs(name, wname, namelen);
size_t modelen = wcstombs(NULL, wmode, 0) + 1;
char mode[modelen];
wcstombs(mode, wmode, modelen);
return fopen(name, mode);
}
#endif
FEXTRACKER_API void LoadMovement( FexMovement* me, const wchar_t* Filename )
{
me->Frames.nVal = 0;
me->FileName = new wchar_t[ 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 wchar_t* 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 );
}
FEXTRACKER_API void DeleteMovement( FexMovement* delme )
{
delete delme;
}

View File

@ -1,39 +0,0 @@
// This file is part of FexTracker and (C) 2006 by Hajo Krabbenhöft (tentacle)
// All rights reserved but the aegisub project is allowed to use it.
// 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_t* FileName;
tenlist<FexMovementFrame> Frames;
};
FEXTRACKER_API FexMovement* CreateMovement();
FEXTRACKER_API void LoadMovement( FexMovement* me, const wchar_t* Filename );
FEXTRACKER_API void SaveMovement( FexMovement* me, const wchar_t* Filename );
FEXTRACKER_API void DeleteMovement( FexMovement* delme );
#endif // !defined(AFX_FEXMOVEMENT_H__63D8ADD8_4EA1_4C56_8D6F_7B587A1A61A4__INCLUDED_)

View File

@ -1,558 +0,0 @@
// This file is part of FexTracker and (C) 2006 by Hajo Krabbenhöft (tentacle)
// All rights reserved but the aegisub project is allowed to use it.
// FexTracker.cpp : Defines the entry point for the DLL application.
//
#include "StdAfx.h"
#include "stdio.h"
#ifndef MIN
#define MIN(a,b) ((a)<(b))?(a):(b)
#endif
#ifndef MAX
#define MAX(a,b) ((a)>(b))?(a):(b)
#endif
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) / float(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;
}
}
FexTracker::~FexTracker()
{
delete [] lFeatures;
if( CurImg ) delete CurImg;
}
void FexTracker::ProcessImage( float *Img, bool bFirst )
{
// Receive new image to track
// This assumes it chronologically directly follows the previously processed image
if( bFirst || !CurImg )
{
// First image in series
// Initialise a few things
CurFrame = 0;
CurImg = new FexImgPyramid( Img, SizX, SizY, Cfg.EdgeDetectSigma, Cfg.DetectSmoothSigma, PyramidSubsampling, PyramidMaxLevels );
nActiveFeatures = 0;
int tmp = nFeatures;
nFeatures = 0;
// Find initial features
FindFeatures( tmp );
}
else
{
// Check if we've lost too many features, and find some more if that's the case
CountActiveFeatures();
if( nActiveFeatures<minFeatures )
FindFeatures( minFeatures );
// Build image pyramid
NextImg = new FexImgPyramid( Img, SizX, SizY, Cfg.EdgeDetectSigma, Cfg.DetectSmoothSigma, PyramidSubsampling, PyramidMaxLevels );
// Now correlate the features to the new image
TrackFeatures();
delete CurImg;
CurImg = NextImg;
NextImg = 0;
}
CurFrame++;
}
void FexTracker::ProcessingDone()
{
if( CurImg ) delete CurImg;
CurImg = 0;
}
void FexTracker::CountActiveFeatures()
{
nActiveFeatures = 0;
for( int i=0;i<nFeatures;i++ )
{
// If the feature has a known position for the active frame, it's active
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 )
{
// Determine window in the image to process
int sx = px - Cfg.WindowX;
int ex = px + Cfg.WindowX;
int sy = py - Cfg.WindowY;
int ey = py + Cfg.WindowY;
// Clip against the edges of the image
if( sx<0 )sx=0;
if( sy<0 )sy=0;
if( ex>SizX-1 )ex=SizX-1;
if( ey>SizY-1 )ey=SizY-1;
// Stride for the image
int imgSX = CurImg->lLevels[0]->sx;
// Pointers to X and Y gradient vectors
float* gradx = CurImg->lLevels[0]->GradX;
float* grady = CurImg->lLevels[0]->GradY;
// Accumulated entries into the correlation matrix [gxx gxy; gxy gyy]
register float gxx = 0, gyy = 0, gxy = 0;
// Loop over points inside the window
for( int y=sy;y<ey;y++ )
{
for( int x=sx;x<ex;x++ )
{
// Get X and Y gradient values of this point
float gx = gradx[ imgSX*y + x ];
float gy = grady[ imgSX*y + x ];
// Add to the matrix entries
gxx += gx*gx;
gyy += gy*gy;
gxy += gx*gy;
}
}
// Calculate the eigenvalue L for the correlation matrix
// 0 = det([gxx-L gxy; gxy gyy-L]) = (gxx-L)(gyy-L) - gxy*gxy = L*L + L*(-gxx-gyy) + gxx*gyy - gxy*gxy
// Only the smaller of the two eigenvalues has interest, and a factor 1/4 isn't relevant for comparison,
// so this is the smallest solution to the second-order polynomial.
float val = gxx + gyy - sqrtf((gxx - gyy)*(gxx - gyy) + 4*gxy*gxy);
// Limit the value
if( val>(1<<30) ) val=(1<<30);
return (int) val;
}
// An int triple (?!) denoting a coordinate pair and an eigenvalue for that position
typedef struct{
int val, x, y;
}littleFeature;
// Swap two triples of ints (in reality two 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; \
}
// Sort a list of int-triples (littleFeature structs)
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 )
{
// Detect new features, so there's at least minFeatures available
// First calculate eigenvalues for each pixel in the image...
int nli=0; // Number of LIttle features
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 the eigenvalue for a pixel is larger than zero, include it in the list...
if( v>0 )
{
list[nli].val = v;
list[nli].x = x;
list[nli].y = y;
nli++;
}
}
}
// ... and sort the list
_quicksort( (int*)list, nli );
// I'll call these "interest points", since they're just candidates for features...
int oldN = nFeatures;
// Look through all newly found interest-points and add the most interesting to our
// list of features, until we have at least minFeatures
for( int i=0;i<nli && nActiveFeatures<minFeatures;i++ )
{
// Check if this interest point is too close to an existing feature, to avoid excessive clustering
int j;
for( j=0;j<nFeatures;j++ )
{
// Check that we didn't lose this feature
if( lFeatures[j].StartTime + lFeatures[j].Pos.size() < CurFrame ) continue;
// Calculate distance between the interest point of the outer loop and this feature
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;
// And see if it's close enough
if( sqr < Cfg.MinDistanceSquare ) break;
}
if( j!=nFeatures ) continue; // Found an existing feature too close, so skip this interest point
// Check if we need to allocate more space for features
if( nFeatures >= mFeatures )
{
// Allocate new, larger feature list and copy old features into new list
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] );
}
// ... finally replacing the old list
delete [] lFeatures;
lFeatures = nlFeatures;
}
// Add this interest point to the end of the feature list
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++;
}
// Subtract 1 from the start time of all newly found features
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++ )
{
// Check if this feature was already lost in an earlier frame
if( lFeatures[i].StartTime + lFeatures[i].Pos.size() < CurFrame ) continue;
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; // Original point
// Calculate position of original point on top level of the pyramid
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; // New point
np = op; // Assume no motion initially
int l;
for( l=CurImg->nLevels-1;l>=0;l-- )
{
// Move coordinates one level down in the pyramid
op.x *= CurImg->Subsampling;
op.y *= CurImg->Subsampling;
np.x *= CurImg->Subsampling;
np.y *= CurImg->Subsampling;
// And try to track the feature
if( !TrackOneFeature( l, op, np ) ) break;
}
// Did the loop finish? If not, tracking failed and the feature was lost
if( l!=-1 ) continue;
// Tracked outside the frame? Feature lost.
if( np.x<0 || np.y<0 || np.x>SizX || np.y>SizY ) continue;
// Otherwise add the new position to the feature's point list
lFeatures[i].Pos.Add( np );
}
}
bool FexTracker::TrackOneFeature( int lvl, vec2 op, vec2& np )
{
// Motion estimate one feature on one level in the image pyramid
// @op (in) is the coordinate for the point on the previous frame
// @np (out) is the coordinate for the new location of the point, based on the information in this level of the pyramid
// Border epsilon, defines what is "too close" to the edge of the image
static float bordereps = 1.1f;
// Check that the point isn't already "almost outside" the image, and let tracking fail if it is
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;
// Temporary images for holding data in the window around the feature
// Desired width of the window
int isx = (Cfg.WindowX*2+1);
// Desired number of pixels in the window
int imsiz = isx*(Cfg.WindowY*2+1);
// Simple difference between image data in window around current frame/position and next frame/position
float *diff = new float[imsiz];
// Something with gradients around old/new position
float *gradx = new float[imsiz];
float *grady = new float[imsiz];
bool bOk = 1;
// Iteratively obtain better precision motion estimation (FIXME)
for( int iteration=0;iteration<Cfg.MaxIterations;iteration++ )
{
// Calculate diffs and gradients ((FIXME)
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);
*/
// Calculate gradient correlation matrix and some other matrix related to gradients and differences
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;
}
// Too small determinant in the gradient corr. matrix? (what does that mean?)
float det = gxx*gyy - gxy*gxy;
if( det < Cfg.MinDeterminant )
{
bOk = 0;
break;
}
// So apparently those two matrices together tell something about the movement
float dx = (gyy*ex - gxy*ey)/det;
float dy = (gxx*ey - gxy*ex)/det;
np.x += dx;
np.y += dy;
// Check if the feature moved too close to a border, in which case it's lost
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 the feature didn't move enough in this iteration, assume its motion is properly estimated
if( fabs(dx) < Cfg.MinDisplacement && fabs(dy) < Cfg.MinDisplacement )break;
}
delete [] gradx;
delete [] grady;
// I think this checks if there's too large a difference between the image at the current and the next frame
// around the motion estimated feature
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 )
{
// Bilinear interpolation between (x,y) and ((int)x,(int)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 )
{
// Calculate the difference between the current frame and the next frame
// locally around the feature point
// (using the currently motion estimated coordinates for the new position)
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 )
{
// Dark magic
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

@ -1,138 +0,0 @@
// This file is part of FexTracker and (C) 2006 by Hajo Krabbenh<6E>t (tentacle)
// All rights reserved but the aegisub project is allowed to use it.
// 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.
#ifndef AEGISUB
#ifdef FEXTRACKER_EXPORTS
#define FEXTRACKER_API __declspec(dllexport)
#else
#define FEXTRACKER_API __declspec(dllimport)
#endif
#else
#define FEXTRACKER_API
#endif
class FEXTRACKER_API FexTrackerConfig
{
public:
inline FexTrackerConfig() :
FeatureNumber(0),
WindowX(3), WindowY(3),
SearchRange(15),
DetectSmoothSigma(0.9f),
EdgeDetectSigma(1.f),
MaxIterations(10),
MinDeterminant(0.01f),
MinDisplacement(0.1f),
MaxResidue(10.f),
IgnoreLightning(0),
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; // list of allocated features
int nFeatures; // current number of used feature slots
int nActiveFeatures; // number of features with motion data on current image
int mFeatures; // number of features allocated space for
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

@ -1,160 +0,0 @@
// This file is part of FexTracker and (C) 2006 by Hajo Krabbenhöft (tentacle)
// All rights reserved but the aegisub project is allowed to use it.
// FexTrackerMovement.cpp
//
#include "StdAfx.h"
#include "stdio.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;
}
}
#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

@ -1,23 +0,0 @@
// This file is part of FexTracker and (C) 2006 by Hajo Krabbenh<6E>t (tentacle)
// All rights reserved but the aegisub project is allowed to use it.
// FexTrackingFeature.cpp: implementation of the FexTrackingFeature class.
//
//////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
FexTrackingFeature::FexTrackingFeature()
{
}
FexTrackingFeature::~FexTrackingFeature()
{
}

View File

@ -1,30 +0,0 @@
// This file is part of FexTracker and (C) 2006 by Hajo Krabbenhöft (tentacle)
// All rights reserved but the aegisub project is allowed to use it.
// 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

@ -1,25 +0,0 @@
SUFFIXES = .c .cpp
noinst_LIBRARIES = libfex.a
AM_CPPFLAGS = -DAEGISUB
libfex_a_SOURCES = \
FexGenericFilter.cpp \
FexGenericFilter_BaseFloatImage.cpp \
FexImgPyramid.cpp \
FexMovement.cpp \
FexTracker.cpp \
FexTrackerMovement.cpp \
FexTrackingFeature.cpp
noinst_HEADERS = \
FexGenericFilter_BaseFloatImageApply.h \
FexGenericFilter_Contribution.h \
FexGenericFilter_FilteringCore.h \
FexGenericFilter_Include.h \
FexGenericFilter_StaticFor.h \
FexImgPyramid.h \
FexMovement.h \
FexTracker.h \
FexTrackingFeature.h \
StdAfx.h \
tenlist.h

View File

@ -1,11 +0,0 @@
// This file is part of FexTracker and (C) 2006 by Hajo Krabbenhöft (tentacle)
// All rights reserved but the aegisub project is allowed to use it.
// 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

View File

@ -1,44 +0,0 @@
// This file is part of FexTracker and (C) 2006 by Hajo Krabbenhöft (tentacle)
// All rights reserved but the aegisub project is allowed to use it.
// 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
#ifdef WIN32
#include <windows.h>
#endif
#include <stdlib.h>
#include <math.h>
#include <memory.h>
#include <assert.h>
#include "FexTracker.h"
#include "FexImgPyramid.h"
#include "FexTrackingFeature.h"
#include "FexMovement.h"
#ifdef IMAGE_DEBUGGER
#include "ext/imdebug.h"
#else
#define imdebug(a,b,c,d) //
#endif
// 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

@ -1,68 +0,0 @@
// This file is part of FexTracker and (C) 2006 by Hajo Krabbenhöft (tentacle)
// All rights reserved but the aegisub project is allowed to use it.
#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

@ -1,5 +1,5 @@
AUTOMAKE_OPTIONS = foreign
SUBDIRS = ac auto3 automation FexTrackerSource csri aegisub locale
SUBDIRS = ac auto3 automation csri aegisub locale
lua51/src/liblua.a:
make -C lua51/src CC=$(CXX) a

View File

@ -14,7 +14,7 @@ REVISION := $(if $(SVNREV),-DBUILD_SVN_REVISION=$(SVNREV)) $(if $(DARCSREV),-DBU
BUILDINFO := -DBUILD_CREDIT="\"$(shell whoami)\"" $(REVISION)
AM_CPPFLAGS = -DAEGISUB -Iposix -include posix/defines.h $(BUILDINFO)
aegisub_LDADD = posix/libposix.a ../FexTrackerSource/libfex.a ../csri/lib/.libs/libcsri.a
aegisub_LDADD = posix/libposix.a ../csri/lib/.libs/libcsri.a
aegisub_LDFLAGS =
if USE_LIBASS
@ -85,7 +85,6 @@ EXTRA_aegisub_SOURCES = \
avisynth_wrap.cpp \
dialog_associations.cpp \
factory.h \
fextracker_main_events.cpp \
lavc_file.cpp \
setup0.h \
setup.cpp \
@ -94,7 +93,6 @@ EXTRA_aegisub_SOURCES = \
stdwx.h \
subtitle_format_prs.cpp \
subtitles_provider_libass.cpp \
video_display_fextracker.cpp \
video_provider_avs.cpp \
video_provider_dshow.cpp \
video_provider_lavc.cpp \
@ -140,7 +138,6 @@ aegisub_SOURCES = \
dialog_detached_video.cpp \
dialog_dummy_video.cpp \
dialog_export.cpp \
dialog_fextracker.cpp \
dialog_fonts_collector.cpp \
dialog_jumpto.cpp \
dialog_kanji_timer.cpp \
@ -208,7 +205,6 @@ aegisub_SOURCES = \
video_box.cpp \
video_context.cpp \
video_display.cpp \
video_display_fextracker.cpp \
video_display_visual.cpp \
video_frame.cpp \
video_provider.cpp \

View File

@ -38,10 +38,6 @@
// Includes
#include <fstream>
#include <wx/tokenzr.h>
#if USE_FEXTRACKER == 1
#include "../FexTrackerSource/FexTracker.h"
#include "../FexTrackerSource/FexMovement.h"
#endif
#include "setup.h"
#include "ass_dialogue.h"
#include "ass_override.h"
@ -52,11 +48,6 @@
////////////////////// AssDialogue //////////////////////
// Constructs AssDialogue
AssDialogue::AssDialogue() {
#if USE_FEXTRACKER == 1
Tracker = 0;
Movement = 0;
#endif
group = _T("[Events]");
Valid = true;
@ -76,11 +67,6 @@ AssDialogue::AssDialogue() {
AssDialogue::AssDialogue(wxString _data,int version) {
#if USE_FEXTRACKER == 1
Tracker = 0;
Movement = 0;
#endif
// Set group
group = _T("[Events]");
@ -115,18 +101,6 @@ AssDialogue::~AssDialogue () {
// Clear
void AssDialogue::Clear () {
ClearBlocks();
#if USE_FEXTRACKER == 1
if( Tracker )
{
delete Tracker;
Tracker = 0;
}
if( Movement )
{
DeleteMovement( Movement );
Movement = 0;
}
#endif
}
@ -230,20 +204,9 @@ bool AssDialogue::Parse(wxString rawData, int version) {
Effect.Trim(true);
Effect.Trim(false);
#if USE_FEXTRACKER == 1
if( Effect.BeforeFirst(':')==_T("FexMovement") )
{
if( Movement ) DeleteMovement( Movement );
Movement = CreateMovement();
LoadMovement( Movement, Effect.AfterFirst(':').c_str() );
}
#endif
// Get text
Text = rawData.Mid(pos+tkn.GetPosition());
return true;
}

View File

@ -43,10 +43,6 @@
#include <vector>
#include "ass_entry.h"
#include "ass_time.h"
#if USE_FEXTRACKER == 1
class FexTracker;
class FexMovement;
#endif
//////////////
@ -171,10 +167,6 @@ public:
wxString Actor; // Actor name
wxString Effect; // Effect name
wxString Text; // Raw text data
#if USE_FEXTRACKER == 1
FexTracker *Tracker; // Point tracker
FexMovement *Movement; // Point tracker generated movement
#endif
ASS_EntryType GetType() { return ENTRY_DIALOGUE; }

View File

@ -129,6 +129,7 @@ Please visit http://aegisub.net to download latest version
- Commiting text now commits times as well. (AMZ)
- Fixed display of end frames on the subtitles grid, when set to frame mode. (demi)
- Treat comments inside {}'s as plain text, not as overrides; Also, don't assume override blocks start with a backslash, even if they probably should (Dansolo)
- Removed FexTracker due to licensing problems; there are plans to implement a new motion tracker in its place
= 1.10 beta - 2006.08.07 ===========================

View File

@ -1,113 +0,0 @@
// AEGISUB
//
// Website: http://aegisub.cellosoft.com
// Contact: mailto:zeratul@cellosoft.com
//
///////////
// Headers
#include <wx/notebook.h>
#include <wx/statbox.h>
#include <wx/sizer.h>
#include "dialog_fextracker.h"
#include "../FexTrackerSource/FexTracker.h"
///////////////
// Constructor
DialogFexTracker::DialogFexTracker(wxWindow *parent, FexTrackerConfig *_cfg)
: wxDialog (parent,-1,_("Tracker configuration"),wxDefaultPosition)
{
cfg = _cfg;
cfg->FeatureNumber = 0;
FeatureNumber = new wxTextCtrl(this,-1,_T("250"));
MinDistanceSquare = new wxTextCtrl(this,-1,_T("100"));
SearchRange = new wxTextCtrl(this,-1,_T("15"));
MaxResidue = new wxTextCtrl(this,-1,_T("10"));
MaxIterations = new wxTextCtrl(this,-1,_T("10"));
EdgeDetectSigma = new wxTextCtrl(this,-1,_T("1.0"));
WindowX = new wxTextCtrl(this,-1,_T("3"));
WindowY = new wxTextCtrl(this,-1,_T("3"));
MinDeterminant = new wxTextCtrl(this,-1,_T("0.01"));
MinDisplacement = new wxTextCtrl(this,-1,_T("0.1"));
wxFlexGridSizer *std_grid = new wxFlexGridSizer(2, 5, 10);
std_grid->AddGrowableCol(0, 1);
wxFlexGridSizer *adv_grid = new wxFlexGridSizer(2, 5, 10);
adv_grid->AddGrowableCol(0, 1);
std_grid->Add(new wxStaticText(this, -1, _("Number of points to track:")), 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL);
std_grid->Add(FeatureNumber, 1, wxALIGN_LEFT);
std_grid->Add(new wxStaticText(this, -1, _("Minimal (squared) distance between two points:")), 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL);
std_grid->Add(MinDistanceSquare, 1, wxALIGN_LEFT);
std_grid->Add(new wxStaticText(this,-1,_("Maximum feature movement:")), 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL);
std_grid->Add(SearchRange, 1, wxALIGN_LEFT);
std_grid->Add(new wxStaticText(this,-1,_("Maximum feature appearance change:")), 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL);
std_grid->Add(MaxResidue, 1, wxALIGN_LEFT);
std_grid->Add(new wxStaticText(this,-1,_("How much CPU per feature?")), 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL);
std_grid->Add(MaxIterations, 1, wxALIGN_LEFT);
adv_grid->Add(new wxStaticText(this,-1,_("Edge detect filter size:")), 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL);
adv_grid->Add(EdgeDetectSigma, 1, wxALIGN_LEFT);
adv_grid->Add(new wxStaticText(this,-1,_("Feature comparison width:")), 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL);
adv_grid->Add(WindowX, 1, wxALIGN_LEFT);
adv_grid->Add(new wxStaticText(this,-1,_("Feature comparison height:")), 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL);
adv_grid->Add(WindowY, 1, wxALIGN_LEFT);
adv_grid->Add(new wxStaticText(this,-1,_("Minimal determinant:")), 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL);
adv_grid->Add(MinDeterminant, 1, wxALIGN_LEFT);
adv_grid->Add(new wxStaticText(this,-1,_("Minimal displacement per iteration:")), 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL);
adv_grid->Add(MinDisplacement, 1, wxALIGN_LEFT);
wxSizer *std_box = new wxStaticBoxSizer(new wxStaticBox(this, -1, _("Basic settings")), wxVERTICAL);
std_box->Add(std_grid, 0, wxALL|wxEXPAND, 5);
wxSizer *adv_box = new wxStaticBoxSizer(new wxStaticBox(this, -1, _("Additional settings")), wxVERTICAL);
adv_box->Add(adv_grid, 0, wxALL|wxEXPAND, 5);
wxStdDialogButtonSizer *buttons = new wxStdDialogButtonSizer();
buttons->AddButton(new wxButton(this,wxID_OK,_("Start")));
buttons->AddButton(new wxButton(this, wxID_CANCEL));
buttons->Realize();
wxSizer *MainSizer = new wxBoxSizer(wxVERTICAL);
MainSizer->Add(std_box, 0, wxALL|wxEXPAND, 5);
MainSizer->Add(adv_box, 0, wxALL&~wxTOP|wxEXPAND, 5);
MainSizer->Add(buttons, 0, wxALL&~wxTOP|wxEXPAND, 5);
MainSizer->SetSizeHints( this );
SetSizer(MainSizer);
SetAutoLayout(true);
CenterOnParent();
}
///////////////
// Event table
BEGIN_EVENT_TABLE(DialogFexTracker,wxDialog)
EVT_BUTTON(wxID_OK,DialogFexTracker::OnStart)
END_EVENT_TABLE()
////////////
// OnStart
void DialogFexTracker::OnStart (wxCommandEvent &event) {
cfg->FeatureNumber = 0;
swscanf( FeatureNumber->GetValue(), _T("%d"), &cfg->FeatureNumber );
swscanf( WindowX->GetValue(), _T("%d"), &cfg->WindowX );
swscanf( WindowY->GetValue(), _T("%d"), &cfg->WindowY );
swscanf( SearchRange->GetValue(), _T("%d"), &cfg->SearchRange );
swscanf( MaxIterations->GetValue(), _T("%d"), &cfg->MaxIterations );
swscanf( EdgeDetectSigma->GetValue(), _T("%f"), &cfg->EdgeDetectSigma );
swscanf( MinDeterminant->GetValue(), _T("%f"), &cfg->MinDeterminant );
swscanf( MinDisplacement->GetValue(), _T("%f"), &cfg->MinDisplacement );
swscanf( MaxResidue->GetValue(), _T("%f"), &cfg->MaxResidue );
swscanf( MinDistanceSquare->GetValue(), _T("%f"), &cfg->MinDistanceSquare );
EndModal(0);
}

View File

@ -1,54 +0,0 @@
// AEGISUB
//
// Website: http://aegisub.cellosoft.com
// Contact: mailto:zeratul@cellosoft.com
//
#ifndef DIALOG_FEXTRACKER_H
#define DIALOG_FEXTRACKER_H
///////////
// Headers
#include <wx/wxprec.h>
//////////////
// Prototypes
class FexTrackerConfig;
/////////
// Class
class DialogFexTracker : public wxDialog {
private:
FexTrackerConfig * cfg;
wxTextCtrl *FeatureNumber;
wxTextCtrl *EdgeDetectSigma;
wxTextCtrl *WindowX, *WindowY;
wxTextCtrl *SearchRange;
wxTextCtrl *MaxIterations;
wxTextCtrl *MinDeterminant;
wxTextCtrl *MinDisplacement;
wxTextCtrl *MaxResidue;
wxTextCtrl *MinDistanceSquare;
void OnStart (wxCommandEvent &event);
public:
DialogFexTracker(wxWindow *parent, FexTrackerConfig * cfg);
DECLARE_EVENT_TABLE()
};
///////
// IDs
enum {
BUTTON_START = 1520,
};
#endif

View File

@ -71,12 +71,6 @@
#include "audio_display.h"
#include "toggle_bitmap.h"
#include "dialog_timing_processor.h"
#if USE_FEXTRACKER == 1
#include "../FexTrackerSource/FexTracker.h"
#include "../FexTrackerSource/FexTrackingFeature.h"
#include "../FexTrackerSource/FexMovement.h"
#include "dialog_fextracker.h"
#endif
#include "dialog_progress.h"
#include "dialog_options.h"
#include "utils.h"

View File

@ -22,23 +22,6 @@ typedef int64_t __int64;
typedef uint64_t __uint64;
#define abs64 llabs
/*
#if defined(HAVE_ASA) && defined(HAVE_ASA_H)
#define USE_ASA 1
#endif
#if defined(HAVE_LIBSSA) && defined(HAVE_LIBSSA_LIBSSA_H)
#define USE_LIBSSA 1
#endif
#define USE_PRS 0
#ifndef USE_FEXTRACKER
#define USE_FEXTRACKER 0
#endif
#ifndef USE_ASA
#define USE_ASA 0
#endif
*/
#include "res.h"
#endif /* _DEFINES_H */

View File

@ -44,7 +44,6 @@
#include "video_box.h"
#include "video_display.h"
#include "video_display_visual.h"
#include "video_display_fextracker.h"
#include "video_slider.h"
#include "frame_main.h"
#include "toggle_bitmap.h"
@ -81,14 +80,6 @@ VideoBox::VideoBox(wxWindow *parent)
AutoScroll->SetToolTip(_("Toggle autoscroll of video"));
AutoScroll->SetValue(Options.AsBool(_T("Sync video with subs")));
// Fextracker
#if USE_FEXTRACKER == 1
wxBitmapButton *VideoTrackerMenuButton = new wxBitmapButton(videoPage,Video_Tracker_Menu,wxBITMAP(button_track_points));
VideoTrackerMenuButton->SetToolTip(_("FexTracker"));
wxBitmapButton *VideoTrackerMenu2Button = new wxBitmapButton(videoPage,Video_Tracker_Menu2,wxBITMAP(button_track_trail));
VideoTrackerMenu2Button->SetToolTip(_("FexMovement"));
#endif
// Seek
videoSlider = new VideoSlider(videoPage,-1);
videoSlider->SetToolTip(_("Seek video."));
@ -138,11 +129,6 @@ VideoBox::VideoBox(wxWindow *parent)
typeSizer->Add(scale,0,wxEXPAND,0);
typeSizer->Add(clip,0,wxEXPAND | wxBOTTOM,5);
typeSizer->Add(realtime,0,wxEXPAND,0);
#if USE_FEXTRACKER == 1
typeSizer->Add(new wxStaticLine(videoPage),0,wxEXPAND|wxBOTTOM|wxTOP,5);
typeSizer->Add(VideoTrackerMenuButton,0,wxEXPAND,0);
typeSizer->Add(VideoTrackerMenu2Button,0,wxEXPAND,0);
#endif
typeSizer->AddStretchSpacer(1);
// Top sizer
@ -184,12 +170,6 @@ BEGIN_EVENT_TABLE(VideoBox, wxPanel)
EVT_BUTTON(Video_Mode_Scale, VideoBox::OnModeScale)
EVT_BUTTON(Video_Mode_Clip, VideoBox::OnModeClip)
EVT_TOGGLEBUTTON(Video_Mode_Realtime, VideoBox::OnToggleRealtime)
#if USE_FEXTRACKER == 1
EVT_BUTTON(Video_Tracker_Menu, VideoBox::OnVideoTrackerMenu)
EVT_BUTTON(Video_Tracker_Menu2, VideoBox::OnVideoTrackerMenu2)
EVT_MENU_RANGE(Video_Tracker_START,Video_Tracker_END, VideoBox::OnTrackerOption)
#endif
END_EVENT_TABLE()
@ -275,46 +255,3 @@ void VideoBox::OnToggleRealtime(wxCommandEvent &event) {
Options.Save();
}
#if USE_FEXTRACKER == 1
///////////////////
// Tracker Menu
void VideoBox::OnVideoTrackerMenu(wxCommandEvent &event) {
wxMenu menu( _("FexTracker") );
AppendBitmapMenuItem(&menu, Video_Track_Points, _("Track points"), _T(""), wxBITMAP(button_track_points));
menu.AppendSeparator();
AppendBitmapMenuItem(&menu, Video_Track_Point_Add, _("Add points to movement"), _T(""), wxBITMAP(button_track_point_add));
AppendBitmapMenuItem(&menu, Video_Track_Point_Del, _("Remove points from movement"), _T(""), wxBITMAP(button_track_point_del));
menu.AppendSeparator();
AppendBitmapMenuItem(&menu, Video_Track_Movement, _("Generate movement from points"), _T(""), wxBITMAP(button_track_movement));
PopupMenu(&menu);
}
///////////////////
// Movement Menu
void VideoBox::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));
AppendBitmapMenuItem(&menu, Video_Track_Movement_MoveOne, _("Move subtitle (this frame)"), _T(""), wxBITMAP(button_track_move));
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);
}
////////////////////
// Forward options
void VideoBox::OnTrackerOption(wxCommandEvent &event) {
videoDisplay->tracker->AddPendingEvent(event);
}
#endif

View File

@ -67,7 +67,6 @@
#include "main.h"
#include "video_slider.h"
#include "video_box.h"
#include "video_display_fextracker.h"
///////
@ -117,10 +116,6 @@ VideoDisplay::VideoDisplay(wxWindow* parent, wxWindowID id, const wxPoint& pos,
zoomValue = 1.0;
freeSize = false;
visual = new VideoDisplayVisual(this);
tracker = NULL;
#if USE_FEXTRACKER == 1
tracker = new VideoDisplayFexTracker(this);
#endif
SetCursor(wxNullCursor);
}
@ -129,9 +124,6 @@ VideoDisplay::VideoDisplay(wxWindow* parent, wxWindowID id, const wxPoint& pos,
// Destructor
VideoDisplay::~VideoDisplay () {
delete visual;
#if USE_FEXTRACKER == 1
delete tracker;
#endif
VideoContext::Get()->RemoveDisplay(this);
}
@ -369,12 +361,6 @@ void VideoDisplay::OnMouseEvent(wxMouseEvent& event) {
// Disable when playing
if (VideoContext::Get()->IsPlaying()) return;
// OnMouseLeave isn't called as long as we have an OnMouseEvent
// Just check for it and call it manually instead
if (event.Leaving()) {
if (tracker) tracker->bTrackerEditing = 0;
}
// Right click
if (event.ButtonUp(wxMOUSE_BTN_RIGHT)) {
// Create menu

View File

@ -56,7 +56,6 @@ class AudioDisplay;
class AssDialogue;
class VideoProvider;
class VideoDisplayVisual;
class VideoDisplayFexTracker;
class VideoBox;
@ -86,7 +85,6 @@ private:
public:
VideoDisplayVisual *visual;
VideoDisplayFexTracker *tracker;
VideoBox *box;
double zoomValue;

View File

@ -1,434 +0,0 @@
// Copyright (c) 2005-2007, Rodrigo Braz Monteiro, Hajo Krabbenhöft
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Aegisub Group nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// -----------------------------------------------------------------------------
//
// AEGISUB
//
// Website: http://aegisub.cellosoft.com
// Contact: mailto:zeratul@cellosoft.com
//
////////////////////////////// HERE BE DRAGONS //////////////////////////////
///////////
// Headers
#include "setup.h"
#if USE_FEXTRACKER == 1
#include "video_display_fextracker.h"
#include "../FexTrackerSource/FexTracker.h"
#include "../FexTrackerSource/FexTrackingFeature.h"
#include "../FexTrackerSource/FexMovement.h"
#include "dialog_progress.h"
#include "dialog_fextracker.h"
#include "ass_dialogue.h"
#include "video_box.h"
#include "video_context.h"
#include "video_display.h"
#include "subs_grid.h"
#include "subs_edit_box.h"
#include "vfr.h"
#include "main.h"
#include "frame_main.h"
#include "video_provider.h"
#include "ass_file.h"
///////////////
// Event table
BEGIN_EVENT_TABLE(VideoDisplayFexTracker,wxEvtHandler)
EVT_MENU(Video_Track_Points, VideoDisplayFexTracker::OnVideoTrackPoints)
EVT_MENU(Video_Track_Point_Add, VideoDisplayFexTracker::OnVideoTrackPointAdd)
EVT_MENU(Video_Track_Point_Del, VideoDisplayFexTracker::OnVideoTrackPointDel)
EVT_MENU(Video_Track_Movement, VideoDisplayFexTracker::OnVideoTrackMovement)
EVT_MENU(Video_Track_Movement_MoveAll, VideoDisplayFexTracker::OnVideoTrackMovementMoveAll)
EVT_MENU(Video_Track_Movement_MoveOne, VideoDisplayFexTracker::OnVideoTrackMovementMoveOne)
EVT_MENU(Video_Track_Movement_MoveBefore, VideoDisplayFexTracker::OnVideoTrackMovementMoveBefore)
EVT_MENU(Video_Track_Movement_MoveAfter, VideoDisplayFexTracker::OnVideoTrackMovementMoveAfter)
EVT_MENU(Video_Track_Split_Line, VideoDisplayFexTracker::OnVideoTrackSplitLine)
EVT_MENU(Video_Track_Link_File, VideoDisplayFexTracker::OnVideoTrackLinkFile)
EVT_MENU(Video_Track_Movement_Empty, VideoDisplayFexTracker::OnVideoTrackMovementEmpty)
END_EVENT_TABLE()
///////////////
// Constructor
VideoDisplayFexTracker::VideoDisplayFexTracker(VideoDisplay *par) {
parent = par;
}
///////////////
// Mouse event
void VideoDisplayFexTracker::OnMouseEvent(wxMouseEvent &event) {
// Variables
int frame_n = VideoContext::Get()->GetFrameN();
int dw,dh;
parent->GetClientSize(&dw,&dh);
int x = event.GetX();
int y = event.GetY();
int mx = x * VideoContext::Get()->GetWidth() / dw;
int my = y * VideoContext::Get()->GetHeight() / dh;
// Click
if (event.ButtonDown(wxMOUSE_BTN_LEFT)) {
MouseDownX = mx;
MouseDownY = my;
bTrackerEditing = 1;
}
if (event.ButtonUp(wxMOUSE_BTN_LEFT)) bTrackerEditing = 0;
// Do tracker influence if needed
if( bTrackerEditing ) {
AssDialogue *curline = VideoContext::Get()->grid->GetDialogue(VideoContext::Get()->grid->editBox->linen);
int StartFrame, EndFrame, localframe;
// Visible?
if (curline && (StartFrame = VFR_Output.GetFrameAtTime(curline->Start.GetMS(),true)) <= frame_n && (EndFrame = VFR_Output.GetFrameAtTime(curline->End.GetMS(),false)) >= frame_n ) {
localframe = frame_n - StartFrame;
if (TrackerEdit!=0 && curline->Tracker && localframe < curline->Tracker->GetFrame())
curline->Tracker->InfluenceFeatures (localframe, float(mx), float(my), TrackerEdit);
if (MovementEdit!=0 && curline->Movement && localframe < curline->Movement->Frames.size()) {
// Set start/end
int movMode = MovementEdit;
int start = 0;
int end = localframe+1;
if (movMode == 2 || movMode == 4) start = localframe;
if (movMode == 1 || movMode == 4) end = curline->Movement->Frames.size();
// Apply
for (int i=0;i<curline->Movement->Frames.size();i++) {
curline->Movement->Frames[i].Pos.x += float(mx-MouseDownX);
curline->Movement->Frames[i].Pos.y += float(my-MouseDownY);
}
}
MouseDownX = mx;
MouseDownY = my;
}
}
}
/////////////////////////
// Draw tracking overlay
void VideoDisplayFexTracker::Render() {
int frame_n = VideoContext::Get()->GetFrameN();
// Get line
AssDialogue *curline = VideoContext::Get()->grid->GetDialogue(VideoContext::Get()->grid->editBox->linen);
if (!curline) return;
int StartFrame = VFR_Output.GetFrameAtTime(curline->Start.GetMS(),true);
int EndFrame = VFR_Output.GetFrameAtTime(curline->End.GetMS(),false);
if (frame_n<StartFrame || frame_n>EndFrame) return;
int localframe = frame_n - StartFrame;
if (curline->Tracker) {
if (curline->Tracker->GetFrame() <= localframe) return;
// Draw ticks
for (int i=0;i<curline->Tracker->GetCount();i++) {
FexTrackingFeature* f = (*curline->Tracker)[i];
if (f->StartTime > localframe) continue;
int llf = localframe - f->StartTime;
if (f->Pos.size() <= llf) continue;
vec2 pt = f->Pos[llf];
SetLineColour(wxColour(255*(1-f->Influence),255*f->Influence,0),1);
DrawLine (pt.x-2, pt.y, pt.x, pt.y);
DrawLine (pt.x, pt.y-2, pt.x, pt.y);
DrawLine (pt.x+1, pt.y, pt.x+3, pt.y);
DrawLine (pt.x, pt.y+1, pt.x, pt.y+3);
}
}
if (curline->Movement) {
if (curline->Movement->Frames.size() <= localframe) return;
FexMovementFrame f = curline->Movement->Frames.lVal[localframe];
f.Scale.x *= 30;
f.Scale.y *= 30;
FexMovementFrame f3 = f;
SetLineColour(wxColour(0,0,255),1);
int nBack = 8;
while (--localframe>0 && nBack-- >0) {
FexMovementFrame f2 = curline->Movement->Frames.lVal[localframe];
DrawLine (f2.Pos.x, f2.Pos.y, f3.Pos.x, f3.Pos.y);
f3 = f2;
}
SetLineColour(wxColour(200,0,0),2);
DrawLine (f.Pos.x-f.Scale.x, f.Pos.y, f.Pos.x+f.Scale.x+1, f.Pos.y);
DrawLine (f.Pos.x, f.Pos.y-f.Scale.y, f.Pos.x, f.Pos.y+f.Scale.y+1);
f3 = f;
SetLineColour(wxColour(0,255,0),1);
int nFront = 8;
localframe = frame_n - StartFrame;
while( ++localframe<curline->Movement->Frames.size() && nFront-- >0 ) {
FexMovementFrame f2 = curline->Movement->Frames.lVal[localframe];
DrawLine (f2.Pos.x, f2.Pos.y, f3.Pos.x, f3.Pos.y);
f3 = f2;
}
}
}
///////////////////
// Track current line
void VideoDisplayFexTracker::OnVideoTrackPoints(wxCommandEvent &event) {
VideoContext::Get()->Stop();
// Get line
FrameMain *frame = AegisubApp::Get()->frame;
AssDialogue *curline = frame->SubsBox->GetDialogue(frame->EditBox->linen);
if (!curline) return;
FexTrackerConfig config;
DialogFexTracker configDlg (frame, &config);
configDlg.ShowModal();
if (!config.FeatureNumber) return;
// Get Video
VideoProvider *movie = VideoProviderFactory::GetProvider(VideoContext::Get()->videoName);
// Create Tracker
if( curline->Tracker ) delete curline->Tracker;
curline->Tracker = new FexTracker( movie->GetWidth(), movie->GetHeight(), config.FeatureNumber );
curline->Tracker->minFeatures = config.FeatureNumber;
curline->Tracker->Cfg = config;
// Start progress
volatile bool canceled = false;
DialogProgress *progress = new DialogProgress(frame,_("FexTracker"),&canceled,_("Tracking points"),0,1);
progress->Show();
// Allocate temp image
float* FloatImg = new float[ movie->GetWidth()*movie->GetHeight() ];
int StartFrame = VFR_Output.GetFrameAtTime(curline->Start.GetMS(),true);
int EndFrame = VFR_Output.GetFrameAtTime(curline->End.GetMS(),false);
for( int Frame = StartFrame; Frame <= EndFrame; Frame ++ )
{
progress->SetProgress( Frame-StartFrame, EndFrame-StartFrame );
if( canceled ) break;
movie->GetFloatFrame( FloatImg, Frame );
curline->Tracker->ProcessImage( FloatImg );
}
delete FloatImg;
delete movie;
// Clean up progress
if (!canceled)
progress->Destroy();
else
{
delete curline->Tracker;
curline->Tracker = 0;
}
VideoContext::Get()->Refresh(true,false);
}
///////////////////
// Track current line
void VideoDisplayFexTracker::OnVideoTrackMovement(wxCommandEvent &event) {
VideoContext::Get()->Stop();
// Get line
FrameMain *frame = AegisubApp::Get()->frame;
AssDialogue *curline = frame->SubsBox->GetDialogue(frame->EditBox->linen);
if (!curline) return;
if( !curline->Tracker ) return;
// Create Movement
if( curline->Movement ) DeleteMovement( curline->Movement );
curline->Movement = curline->Tracker->GetMovement();
VideoContext::Get()->Refresh(true,false);
}
///////////////////
// split current line
void VideoDisplayFexTracker::OnVideoTrackSplitLine(wxCommandEvent &event) {
VideoContext::Get()->Stop();
// Get line
FrameMain *frame = AegisubApp::Get()->frame;
AssDialogue *curline = frame->SubsBox->GetDialogue(frame->EditBox->linen);
if (!curline) return;
if( !curline->Movement ) return;
// Create split lines
int StartFrame = VFR_Output.GetFrameAtTime(curline->Start.GetMS(),true);
int EndFrame = VFR_Output.GetFrameAtTime(curline->End.GetMS(),false);
AssFile *subs = AssFile::top;
int ResXValue,ResYValue;
swscanf( subs->GetScriptInfo(_T("PlayResX")), _T("%d"), &ResXValue );
swscanf( subs->GetScriptInfo(_T("PlayResY")), _T("%d"), &ResYValue );
int SrcXValue = VideoContext::Get()->GetWidth();
int SrcYValue = VideoContext::Get()->GetHeight();
float sx = float(ResXValue)/float(SrcXValue);
float sy = float(ResYValue)/float(SrcYValue);
for( int Frame = StartFrame; Frame < EndFrame; Frame ++ )
{
int localframe = Frame - StartFrame;
while( curline->Movement->Frames.size() <= localframe ) localframe--;
FexMovementFrame f = curline->Movement->Frames[localframe];
// f.Pos.x /= videoDisplay->GetW
AssDialogue *cur = new AssDialogue( curline->GetEntryData() );
cur->Start.SetMS(VFR_Output.GetTimeAtFrame(Frame,true));
cur->End.SetMS(VFR_Output.GetTimeAtFrame(Frame,false));
cur->Text = wxString::Format( _T("{\\pos(%.0f,%.0f)\\fscx%.2f\\fscy%.2f}"), f.Pos.x*sx, f.Pos.y*sy, f.Scale.x*100, f.Scale.y*100 ) + cur->Text;
cur->UpdateData();
frame->SubsBox->InsertLine(cur,frame->EditBox->linen + Frame - StartFrame,true,false);
}
// Remove Movement
DeleteMovement( curline->Movement );
curline->Movement = 0;
// Remove Tracker
delete curline->Tracker;
curline->Tracker = 0;
// Remove this line
frame->SubsBox->DeleteLines(frame->SubsBox->GetRangeArray(frame->EditBox->linen, frame->EditBox->linen));
VideoContext::Get()->Refresh(true,false);
}
///////////////////
// generate empty movement
void VideoDisplayFexTracker::OnVideoTrackMovementEmpty(wxCommandEvent &event) {
// Get line
FrameMain *frame = AegisubApp::Get()->frame;
AssDialogue *curline = frame->SubsBox->GetDialogue(frame->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 VideoDisplayFexTracker::OnVideoTrackLinkFile(wxCommandEvent &event) {
VideoContext::Get()->Stop();
// Get line
FrameMain *frame = AegisubApp::Get()->frame;
AssDialogue *curline = frame->SubsBox->GetDialogue(frame->EditBox->linen);
if (!curline) return;
wxString link = wxGetTextFromUser(_("Link name:"), _("Link line to movement file"), curline->Movement?curline->Movement->FileName:_T(""), frame);
if( link.empty() ) curline->Effect = _T("");
else curline->Effect = _T("FexMovement:")+link;
curline->UpdateData();
if( !curline->Effect.empty() && curline->Movement )
SaveMovement( curline->Movement, curline->Effect.AfterFirst(':').c_str() );
}
//////////////////////
// Increase Influence
void VideoDisplayFexTracker::OnVideoTrackPointAdd(wxCommandEvent &event) {
TrackerEdit = 1;
bTrackerEditing = 0;
}
//////////////////////
// Decrease Influence
void VideoDisplayFexTracker::OnVideoTrackPointDel(wxCommandEvent &event) {
TrackerEdit = -1;
bTrackerEditing = 0;
}
////////////
// Move All
void VideoDisplayFexTracker::OnVideoTrackMovementMoveAll(wxCommandEvent &event) {
MovementEdit = 1;
bTrackerEditing = 0;
}
////////////
// Move One
void VideoDisplayFexTracker::OnVideoTrackMovementMoveOne(wxCommandEvent &event) {
MovementEdit = 2;
bTrackerEditing = 0;
}
///////////////
// Move Before
void VideoDisplayFexTracker::OnVideoTrackMovementMoveBefore(wxCommandEvent &event) {
MovementEdit = 3;
bTrackerEditing = 0;
}
//////////////
// Move After
void VideoDisplayFexTracker::OnVideoTrackMovementMoveAfter(wxCommandEvent &event) {
MovementEdit = 4;
bTrackerEditing = 0;
}
#endif

View File

@ -1,79 +0,0 @@
// Copyright (c) 2005-2007, Rodrigo Braz Monteiro, Hajo Krabbenhöft
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Aegisub Group nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// -----------------------------------------------------------------------------
//
// AEGISUB
//
// Website: http://aegisub.cellosoft.com
// Contact: mailto:zeratul@cellosoft.com
//
#pragma once
///////////
// Headers
#include "gl_wrap.h"
//////////////
// Prototypes
class VideoDisplay;
///////////////////////////////
// Fex tracker video interface
class VideoDisplayFexTracker : public wxEvtHandler, public OpenGLWrapper {
public:
bool bTrackerEditing;
int MovementEdit;
double TrackerEdit;
int MouseDownX, MouseDownY;
VideoDisplay *parent;
VideoDisplayFexTracker(VideoDisplay *parent);
void OnMouseEvent(wxMouseEvent &event);
void Render();
void OnVideoTrackPoints(wxCommandEvent &event);
void OnVideoTrackPointAdd(wxCommandEvent &event);
void OnVideoTrackPointDel(wxCommandEvent &event);
void OnVideoTrackMovement(wxCommandEvent &event);
void OnVideoTrackMovementMoveAll(wxCommandEvent &event);
void OnVideoTrackMovementMoveOne(wxCommandEvent &event);
void OnVideoTrackMovementMoveBefore(wxCommandEvent &event);
void OnVideoTrackMovementMoveAfter(wxCommandEvent &event);
void OnVideoTrackSplitLine(wxCommandEvent &event);
void OnVideoTrackLinkFile(wxCommandEvent &event);
void OnVideoTrackMovementEmpty(wxCommandEvent &event);
DECLARE_EVENT_TABLE()
};

View File

@ -40,7 +40,6 @@
#include <GL/glu.h>
#include <wx/wxprec.h>
#include "video_display_visual.h"
#include "video_display_fextracker.h"
#include "video_display.h"
#include "video_provider.h"
#include "vfr.h"
@ -103,12 +102,6 @@ void VideoDisplayVisual::DrawOverlay() {
int mx = mouseX * sw / w;
int my = mouseY * sh / h;
// Draw the control points for FexTracker
glDisable(GL_TEXTURE_2D);
#if USE_FEXTRACKER == 1
parent->tracker->Render();
#endif
// Draw lines
if (mode != 0) {
int numRows = VideoContext::Get()->grid->GetRows();
@ -769,11 +762,6 @@ void VideoDisplayVisual::OnMouseEvent (wxMouseEvent &event) {
bool hasOverlay = false;
bool realTime = Options.AsBool(_T("Video Visual Realtime"));
// Fextracker
#if USE_FEXTRACKER == 1
if (parent->tracker) parent->tracker->OnMouseEvent(event);
#endif
// Text of current coords
int vx = (sw * x + w/2) / w;
int vy = (sh * y + h/2) / h;

View File

@ -231,7 +231,6 @@ AC_OUTPUT([
ac/Makefile
auto3/Makefile
automation/Makefile
FexTrackerSource/Makefile
locale/Makefile
aegisub/Makefile
aegisub/bitmaps/Makefile