21 #define GRT_DLL_EXPORTS 27 std::string MovementTrajectoryFeatures::id =
"MovementTrajectoryFeatures";
35 init(trajectoryLength,numCentroids,featureMode,numHistogramBins,numDimensions,useTrajStartAndEndValues,useWeightedMagnitudeValues);
50 this->trajectoryLength = rhs.trajectoryLength;
51 this->numCentroids = rhs.numCentroids;
52 this->featureMode = rhs.featureMode;
53 this->numHistogramBins = rhs.numHistogramBins;
54 this->useTrajStartAndEndValues = rhs.useTrajStartAndEndValues;
55 this->useWeightedMagnitudeValues = rhs.useWeightedMagnitudeValues;
56 this->trajectoryDataBuffer = rhs.trajectoryDataBuffer;
57 this->centroids = rhs.centroids;
67 if( featureExtraction == NULL )
return false;
69 if( this->
getId() == featureExtraction->
getId() ){
77 errorLog <<
"deepCopyFrom(FeatureExtraction *featureExtraction) - FeatureExtraction Types Do Not Match!" << std::endl;
85 errorLog <<
"computeFeatures(const VectorFloat &inputVector) - Not initialized!" << std::endl;
89 if( inputVector.
getSize() != numInputDimensions ){
90 errorLog <<
"computeFeatures(const VectorFloat &inputVector) - The size of the inputVector (" << inputVector.
getSize() <<
") does not match that of the filter (" << numInputDimensions <<
")!" << std::endl;
94 featureVector =
update( inputVector );
101 return init(trajectoryLength,numCentroids,featureMode,numHistogramBins,numInputDimensions,useTrajStartAndEndValues,useWeightedMagnitudeValues);
108 if( !file.is_open() ){
109 errorLog <<
"save(fstream &file) - The file is not open!" << std::endl;
114 file <<
"GRT_MOVEMENT_TRAJECTORY_FEATURES_FILE_V1.0" << std::endl;
118 errorLog <<
"saveFeatureExtractionSettingsToFile(fstream &file) - Failed to save base feature extraction settings to file!" << std::endl;
123 file <<
"TrajectoryLength: " << trajectoryLength << std::endl;
124 file <<
"NumCentroids: " << numCentroids << std::endl;
125 file <<
"FeatureMode: " << featureMode << std::endl;
126 file <<
"NumHistogramBins: " << numHistogramBins << std::endl;
127 file <<
"UseTrajStartAndEndValues: " << useTrajStartAndEndValues << std::endl;
128 file <<
"UseWeightedMagnitudeValues: " << useWeightedMagnitudeValues << std::endl;
135 if( !file.is_open() ){
136 errorLog <<
"load(fstream &file) - The file is not open!" << std::endl;
145 if( word !=
"GRT_MOVEMENT_TRAJECTORY_FEATURES_FILE_V1.0" ){
146 errorLog <<
"load(fstream &file) - Invalid file format!" << std::endl;
151 errorLog <<
"loadFeatureExtractionSettingsFromFile(fstream &file) - Failed to load base feature extraction settings from file!" << std::endl;
157 if( word !=
"TrajectoryLength:" ){
158 errorLog <<
"load(fstream &file) - Failed to read TrajectoryLength header!" << std::endl;
161 file >> trajectoryLength;
165 if( word !=
"NumCentroids:" ){
166 errorLog <<
"load(fstream &file) - Failed to read NumCentroids header!" << std::endl;
169 file >> numCentroids;
173 if( word !=
"FeatureMode:" ){
174 errorLog <<
"load(fstream &file) - Failed to read FeatureMode header!" << std::endl;
181 if( word !=
"NumHistogramBins:" ){
182 errorLog <<
"load(fstream &file) - Failed to read NumHistogramBins header!" << std::endl;
185 file >> numHistogramBins;
189 if( word !=
"UseTrajStartAndEndValues:" ){
190 errorLog <<
"load(fstream &file) - Failed to read UseTrajStartAndEndValues header!" << std::endl;
193 file >> useTrajStartAndEndValues;
197 if( word !=
"UseWeightedMagnitudeValues:" ){
198 errorLog <<
"load(fstream &file) - Failed to read UseWeightedMagnitudeValues header!" << std::endl;
201 file >> useWeightedMagnitudeValues;
204 return init(trajectoryLength,numCentroids,featureMode,numHistogramBins,numInputDimensions,useTrajStartAndEndValues,useWeightedMagnitudeValues);
207 bool MovementTrajectoryFeatures::init(
const UINT trajectoryLength,
const UINT numCentroids,
const UINT featureMode,
const UINT numHistogramBins,
const UINT numDimensions,
const bool useTrajStartAndEndValues,
const bool useWeightedMagnitudeValues){
211 if( numCentroids > trajectoryLength ){
212 errorLog <<
"init(...) - The number of centroids parameter can not be larger than the trajectory length parameter!" << std::endl;
215 if( trajectoryLength % numCentroids != 0 ){
216 errorLog <<
"init(...) - The trajectory length parameter must be divisible with no remainders by the number of centroids parameter!" << std::endl;
220 if( featureMode == CENTROID_ANGLE_2D && numDimensions % 2 != 0 ){
221 errorLog <<
"init(...) - If the featureMode is CENTROID_ANGLE_2D then the numberOfDimensions should be divisble by 2 (as each pair of points should represent {x,y})!" << std::endl;
225 if( numHistogramBins == 0 && featureMode == CENTROID_ANGLE_2D ){
226 errorLog <<
"init(...) - If the featureMode is CENTROID_ANGLE_2D then the numHistogramBins parameter must greater than 0!" << std::endl;
231 this->trajectoryLength = trajectoryLength;
232 this->numCentroids = numCentroids;
233 this->featureMode = featureMode;
234 this->numHistogramBins = numHistogramBins;
235 this->numInputDimensions = numDimensions;
236 this->useTrajStartAndEndValues = useTrajStartAndEndValues;
237 this->useWeightedMagnitudeValues = useWeightedMagnitudeValues;
238 featureDataReady =
false;
241 numOutputDimensions = 0;
242 switch( featureMode ){
245 numOutputDimensions = numInputDimensions*numCentroids;
247 case NORMALIZED_CENTROID_VALUE:
248 numOutputDimensions = numInputDimensions*numCentroids;
249 if( useTrajStartAndEndValues ){
250 numOutputDimensions += numInputDimensions*2;
253 case CENTROID_DERIVATIVE:
254 numOutputDimensions = numInputDimensions*(numCentroids-1);
255 if( useTrajStartAndEndValues ){
256 numOutputDimensions += numInputDimensions*2;
259 case CENTROID_ANGLE_2D:
260 numOutputDimensions = numHistogramBins*(numDimensions/2);
263 errorLog <<
"init(...)- Unknown featureMode!" << std::endl;
268 if( numOutputDimensions == 0 ){
269 errorLog <<
"init(...) - The numOutputDimensions is zero!" << std::endl;
274 featureVector.
resize(numOutputDimensions);
277 trajectoryDataBuffer.
resize( trajectoryLength,
VectorFloat(numInputDimensions,0) );
280 centroids.
resize(numCentroids,numInputDimensions);
295 errorLog <<
"update(const VectorFloat &x) - Not Initialized!" << std::endl;
299 if( x.
getSize() != numInputDimensions ){
300 errorLog <<
"update(const VectorFloat &x)- The Number Of Input Dimensions (" << numInputDimensions <<
") does not match the size of the input Vector (" << x.
getSize() <<
")!" << std::endl;
309 featureDataReady =
true;
310 }
else featureDataReady =
false;
315 UINT dataBufferIndex = 0;
316 UINT numValuesPerCentroid = (UINT)floor(Float(trajectoryLength/numCentroids));
317 for(UINT n=0; n<numInputDimensions; n++){
319 for(UINT i=0; i<numCentroids; i++){
320 for(UINT j=0; j<numValuesPerCentroid; j++){
321 centroids[i][n] += trajectoryDataBuffer[dataBufferIndex++][n];
323 centroids[i][n] /= Float(numValuesPerCentroid);
328 UINT featureIndex = 0;
332 switch( featureMode ){
335 for(UINT n=0; n<numInputDimensions; n++){
336 for(UINT i=0; i<numCentroids; i++){
337 featureVector[ featureIndex++ ] = centroids[i][n];
341 case NORMALIZED_CENTROID_VALUE:
342 for(UINT n=0; n<numInputDimensions; n++){
345 for(UINT i=0; i<numCentroids; i++){
346 centroidNormValues[n].updateMinMax( centroids[i][n] );
350 for(UINT i=0; i<numCentroids; i++){
351 if( centroidNormValues[n].maxValue != centroidNormValues[n].minValue ){
352 featureVector[ featureIndex++ ] =
Util::scale(centroids[i][n],centroidNormValues[n].minValue,centroidNormValues[n].maxValue,0,1);
353 }
else featureVector[ featureIndex++ ] = 0;
357 if( useTrajStartAndEndValues ){
358 featureVector[ featureIndex++ ] = centroids[0][n];
359 featureVector[ featureIndex++ ] = centroids[numCentroids-1][n];
363 case CENTROID_DERIVATIVE:
364 for(UINT n=0; n<numInputDimensions; n++){
367 for(UINT i=0; i<numCentroids-1; i++){
368 featureVector[ featureIndex++ ] = centroids[i+1][n]-centroids[i][n];
372 if( useTrajStartAndEndValues ){
373 featureVector[ featureIndex++ ] = centroids[0][n];
374 featureVector[ featureIndex++ ] = centroids[numCentroids-1][n];
378 case CENTROID_ANGLE_2D:
379 histSumValues.
resize( numInputDimensions/2, 0);
380 angleMagnitudeValues.
resize( numInputDimensions/2 );
383 fill(featureVector.begin(),featureVector.end(),0);
386 for(UINT n=0; n<numInputDimensions/2; n++){
388 angleMagnitudeValues[n].
resize(numCentroids-1);
389 for(UINT i=0; i<numCentroids-1; i++){
390 Util::cartToPolar(centroids[i+1][n*2]-centroids[i][n*2], centroids[i+1][n*2+1]-centroids[i][n*2+1], angleMagnitudeValues[n][i].magnitude, angleMagnitudeValues[n][i].angle);
394 for(UINT i=0; i<numCentroids-1; i++){
396 Float degreesPerBin = 360.0/numHistogramBins;
397 Float binStartValue = 0;
398 Float binEndValue = degreesPerBin;
400 if( angleMagnitudeValues[n][i].angle < 0 || angleMagnitudeValues[n][i].angle > 360.0 ){
401 warningLog <<
"The angle of a point is not between [0 360]. Angle: " << angleMagnitudeValues[n][i].angle << std::endl;
407 if( angleMagnitudeValues[n][i].angle >= binStartValue && angleMagnitudeValues[n][i].angle < binEndValue ){
411 binStartValue += degreesPerBin;
412 binEndValue += degreesPerBin;
415 histSumValues[ n ] += useWeightedMagnitudeValues ? angleMagnitudeValues[n][i].magnitude : 1;
416 featureVector[ n*numHistogramBins + histBin ] += useWeightedMagnitudeValues ? angleMagnitudeValues[n][i].magnitude : 1;
420 for(UINT n=0; n<numInputDimensions/2; n++){
421 if( histSumValues[ n ] > 0 ){
422 for(UINT i=0; i<numHistogramBins; i++){
423 featureVector[ n*numHistogramBins + i ] /= histSumValues[ n ];
430 errorLog <<
"update(VectorFloat x)- Unknown featureMode!" << std::endl;
431 return featureVector;
435 return featureVector;
440 return trajectoryDataBuffer;
virtual bool computeFeatures(const VectorFloat &inputVector)
bool push_back(const T &value)
std::string getId() const
VectorFloat update(const Float x)
virtual bool save(std::fstream &file) const
static Float scale(const Float &x, const Float &minSource, const Float &maxSource, const Float &minTarget, const Float &maxTarget, const bool constrain=false)
MatrixDouble getCentroids() const
bool getBufferFilled() const
virtual bool resize(const unsigned int size)
This class implements the MovementTrajectory feature extraction module.
bool setAllValues(const T &value)
static void cartToPolar(const Float x, const Float y, Float &r, Float &theta)
virtual bool load(std::fstream &file)
CircularBuffer< VectorFloat > getTrajectoryData() const
MovementTrajectoryFeatures & operator=(const MovementTrajectoryFeatures &rhs)
virtual bool deepCopyFrom(const FeatureExtraction *featureExtraction)
static std::string getId()
MovementTrajectoryFeatures(const UINT trajectoryLength=100, const UINT numCentroids=10, const UINT featureMode=CENTROID_VALUE, const UINT numHistogramBins=10, const UINT numDimensions=1, const bool useTrajStartAndEndValues=false, const bool useWeightedMagnitudeValues=true)
virtual ~MovementTrajectoryFeatures()
virtual bool resize(const unsigned int r, const unsigned int c)
UINT getFeatureMode() const
bool resize(const unsigned int newBufferSize)