30 classType =
"MovementTrajectoryFeatures";
31 featureExtractionType = classType;
32 debugLog.setProceedingText(
"[DEBUG MovementTrajectoryFeatures]");
33 errorLog.setProceedingText(
"[ERROR MovementTrajectoryFeatures]");
34 warningLog.setProceedingText(
"[WARNING ZeroCrossingCounter]");
36 init(trajectoryLength,numCentroids,featureMode,numHistogramBins,numDimensions,useTrajStartAndEndValues,useWeightedMagnitudeValues);
41 classType =
"MovementTrajectoryFeatures";
42 featureExtractionType = classType;
43 debugLog.setProceedingText(
"[DEBUG MovementTrajectoryFeatures]");
44 errorLog.setProceedingText(
"[ERROR MovementTrajectoryFeatures]");
45 warningLog.setProceedingText(
"[WARNING ZeroCrossingCounter]");
57 this->trajectoryLength = rhs.trajectoryLength;
58 this->numCentroids = rhs.numCentroids;
59 this->featureMode = rhs.featureMode;
60 this->numHistogramBins = rhs.numHistogramBins;
61 this->useTrajStartAndEndValues = rhs.useTrajStartAndEndValues;
62 this->useWeightedMagnitudeValues = rhs.useWeightedMagnitudeValues;
63 this->trajectoryDataBuffer = rhs.trajectoryDataBuffer;
64 this->centroids = rhs.centroids;
74 if( featureExtraction == NULL )
return false;
84 errorLog <<
"clone(FeatureExtraction *featureExtraction) - FeatureExtraction Types Do Not Match!" << std::endl;
92 errorLog <<
"computeFeatures(const VectorFloat &inputVector) - Not initialized!" << std::endl;
96 if( inputVector.
getSize() != numInputDimensions ){
97 errorLog <<
"computeFeatures(const VectorFloat &inputVector) - The size of the inputVector (" << inputVector.
getSize() <<
") does not match that of the filter (" << numInputDimensions <<
")!" << std::endl;
101 featureVector =
update( inputVector );
108 return init(trajectoryLength,numCentroids,featureMode,numHistogramBins,numInputDimensions,useTrajStartAndEndValues,useWeightedMagnitudeValues);
116 file.open(filename.c_str(), std::ios::out);
130 file.open(filename.c_str(), std::ios::in);
144 if( !file.is_open() ){
145 errorLog <<
"saveModelToFile(fstream &file) - The file is not open!" << std::endl;
150 file <<
"GRT_MOVEMENT_TRAJECTORY_FEATURES_FILE_V1.0" << std::endl;
154 errorLog <<
"saveFeatureExtractionSettingsToFile(fstream &file) - Failed to save base feature extraction settings to file!" << std::endl;
159 file <<
"TrajectoryLength: " << trajectoryLength << std::endl;
160 file <<
"NumCentroids: " << numCentroids << std::endl;
161 file <<
"FeatureMode: " << featureMode << std::endl;
162 file <<
"NumHistogramBins: " << numHistogramBins << std::endl;
163 file <<
"UseTrajStartAndEndValues: " << useTrajStartAndEndValues << std::endl;
164 file <<
"UseWeightedMagnitudeValues: " << useWeightedMagnitudeValues << std::endl;
171 if( !file.is_open() ){
172 errorLog <<
"loadModelFromFile(fstream &file) - The file is not open!" << std::endl;
181 if( word !=
"GRT_MOVEMENT_TRAJECTORY_FEATURES_FILE_V1.0" ){
182 errorLog <<
"loadModelFromFile(fstream &file) - Invalid file format!" << std::endl;
187 errorLog <<
"loadFeatureExtractionSettingsFromFile(fstream &file) - Failed to load base feature extraction settings from file!" << std::endl;
193 if( word !=
"TrajectoryLength:" ){
194 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read TrajectoryLength header!" << std::endl;
197 file >> trajectoryLength;
201 if( word !=
"NumCentroids:" ){
202 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read NumCentroids header!" << std::endl;
205 file >> numCentroids;
209 if( word !=
"FeatureMode:" ){
210 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read FeatureMode header!" << std::endl;
217 if( word !=
"NumHistogramBins:" ){
218 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read NumHistogramBins header!" << std::endl;
221 file >> numHistogramBins;
225 if( word !=
"UseTrajStartAndEndValues:" ){
226 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read UseTrajStartAndEndValues header!" << std::endl;
229 file >> useTrajStartAndEndValues;
233 if( word !=
"UseWeightedMagnitudeValues:" ){
234 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read UseWeightedMagnitudeValues header!" << std::endl;
237 file >> useWeightedMagnitudeValues;
240 return init(trajectoryLength,numCentroids,featureMode,numHistogramBins,numInputDimensions,useTrajStartAndEndValues,useWeightedMagnitudeValues);
243 bool MovementTrajectoryFeatures::init(UINT trajectoryLength,UINT numCentroids,UINT featureMode,UINT numHistogramBins,UINT numDimensions,
bool useTrajStartAndEndValues,
bool useWeightedMagnitudeValues){
247 if( numCentroids > trajectoryLength ){
248 errorLog <<
"init(...) - The number of centroids parameter can not be larger than the trajectory length parameter!" << std::endl;
251 if( trajectoryLength % numCentroids != 0 ){
252 errorLog <<
"init(...) - The trajectory length parameter must be divisible with no remainders by the number of centroids parameter!" << std::endl;
256 if( featureMode == CENTROID_ANGLE_2D && numDimensions % 2 != 0 ){
257 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;
261 if( numHistogramBins == 0 && featureMode == CENTROID_ANGLE_2D ){
262 errorLog <<
"init(...) - If the featureMode is CENTROID_ANGLE_2D then the numHistogramBins parameter must greater than 0!" << std::endl;
267 this->trajectoryLength = trajectoryLength;
268 this->numCentroids = numCentroids;
269 this->featureMode = featureMode;
270 this->numHistogramBins = numHistogramBins;
271 this->numInputDimensions = numDimensions;
272 this->useTrajStartAndEndValues = useTrajStartAndEndValues;
273 this->useWeightedMagnitudeValues = useWeightedMagnitudeValues;
274 featureDataReady =
false;
277 numOutputDimensions = 0;
278 switch( featureMode ){
281 numOutputDimensions = numInputDimensions*numCentroids;
283 case NORMALIZED_CENTROID_VALUE:
284 numOutputDimensions = numInputDimensions*numCentroids;
285 if( useTrajStartAndEndValues ){
286 numOutputDimensions += numInputDimensions*2;
289 case CENTROID_DERIVATIVE:
290 numOutputDimensions = numInputDimensions*(numCentroids-1);
291 if( useTrajStartAndEndValues ){
292 numOutputDimensions += numInputDimensions*2;
295 case CENTROID_ANGLE_2D:
296 numOutputDimensions = numHistogramBins*(numDimensions/2);
299 errorLog <<
"init(...)- Unknown featureMode!" << std::endl;
304 if( numOutputDimensions == 0 ){
305 errorLog <<
"init(...) - The numOutputDimensions is zero!" << std::endl;
310 featureVector.
resize(numOutputDimensions);
313 trajectoryDataBuffer.
resize( trajectoryLength,
VectorFloat(numInputDimensions,0) );
316 centroids.
resize(numCentroids,numInputDimensions);
331 errorLog <<
"update(const VectorFloat &x) - Not Initialized!" << std::endl;
335 if( x.
getSize() != numInputDimensions ){
336 errorLog <<
"update(const VectorFloat &x)- The Number Of Input Dimensions (" << numInputDimensions <<
") does not match the size of the input Vector (" << x.
getSize() <<
")!" << std::endl;
345 featureDataReady =
true;
346 }
else featureDataReady =
false;
351 UINT dataBufferIndex = 0;
352 UINT numValuesPerCentroid = (UINT)floor(Float(trajectoryLength/numCentroids));
353 for(UINT n=0; n<numInputDimensions; n++){
355 for(UINT i=0; i<numCentroids; i++){
356 for(UINT j=0; j<numValuesPerCentroid; j++){
357 centroids[i][n] += trajectoryDataBuffer[dataBufferIndex++][n];
359 centroids[i][n] /= Float(numValuesPerCentroid);
364 UINT featureIndex = 0;
368 switch( featureMode ){
371 for(UINT n=0; n<numInputDimensions; n++){
372 for(UINT i=0; i<numCentroids; i++){
373 featureVector[ featureIndex++ ] = centroids[i][n];
377 case NORMALIZED_CENTROID_VALUE:
378 for(UINT n=0; n<numInputDimensions; n++){
381 for(UINT i=0; i<numCentroids; i++){
382 centroidNormValues[n].updateMinMax( centroids[i][n] );
386 for(UINT i=0; i<numCentroids; i++){
387 if( centroidNormValues[n].maxValue != centroidNormValues[n].minValue ){
388 featureVector[ featureIndex++ ] =
Util::scale(centroids[i][n],centroidNormValues[n].minValue,centroidNormValues[n].maxValue,0,1);
389 }
else featureVector[ featureIndex++ ] = 0;
393 if( useTrajStartAndEndValues ){
394 featureVector[ featureIndex++ ] = centroids[0][n];
395 featureVector[ featureIndex++ ] = centroids[numCentroids-1][n];
399 case CENTROID_DERIVATIVE:
400 for(UINT n=0; n<numInputDimensions; n++){
403 for(UINT i=0; i<numCentroids-1; i++){
404 featureVector[ featureIndex++ ] = centroids[i+1][n]-centroids[i][n];
408 if( useTrajStartAndEndValues ){
409 featureVector[ featureIndex++ ] = centroids[0][n];
410 featureVector[ featureIndex++ ] = centroids[numCentroids-1][n];
414 case CENTROID_ANGLE_2D:
415 histSumValues.
resize( numInputDimensions/2, 0);
416 angleMagnitudeValues.
resize( numInputDimensions/2 );
419 fill(featureVector.begin(),featureVector.end(),0);
422 for(UINT n=0; n<numInputDimensions/2; n++){
424 angleMagnitudeValues[n].
resize(numCentroids-1);
425 for(UINT i=0; i<numCentroids-1; i++){
426 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);
430 for(UINT i=0; i<numCentroids-1; i++){
432 Float degreesPerBin = 360.0/numHistogramBins;
433 Float binStartValue = 0;
434 Float binEndValue = degreesPerBin;
436 if( angleMagnitudeValues[n][i].angle < 0 || angleMagnitudeValues[n][i].angle > 360.0 ){
437 warningLog <<
"The angle of a point is not between [0 360]. Angle: " << angleMagnitudeValues[n][i].angle << std::endl;
443 if( angleMagnitudeValues[n][i].angle >= binStartValue && angleMagnitudeValues[n][i].angle < binEndValue ){
447 binStartValue += degreesPerBin;
448 binEndValue += degreesPerBin;
451 histSumValues[ n ] += useWeightedMagnitudeValues ? angleMagnitudeValues[n][i].magnitude : 1;
452 featureVector[ n*numHistogramBins + histBin ] += useWeightedMagnitudeValues ? angleMagnitudeValues[n][i].magnitude : 1;
456 for(UINT n=0; n<numInputDimensions/2; n++){
457 if( histSumValues[ n ] > 0 ){
458 for(UINT i=0; i<numHistogramBins; i++){
459 featureVector[ n*numHistogramBins + i ] /= histSumValues[ n ];
466 errorLog <<
"update(VectorFloat x)- Unknown featureMode!" << std::endl;
467 return featureVector;
471 return featureVector;
476 return trajectoryDataBuffer;
virtual bool computeFeatures(const VectorFloat &inputVector)
bool push_back(const T &value)
static Float scale(const Float &x, const Float &minSource, const Float &maxSource, const Float &minTarget, const Float &maxTarget, const bool constrain=false)
virtual bool saveModelToFile(std::string filename) const
bool getBufferFilled() const
virtual bool resize(const unsigned int size)
unsigned int getSize() const
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)
MovementTrajectoryFeatures & operator=(const MovementTrajectoryFeatures &rhs)
virtual bool deepCopyFrom(const FeatureExtraction *featureExtraction)
virtual bool loadModelFromFile(std::string filename)
MatrixDouble getCentroids()
VectorFloat update(Float x)
virtual ~MovementTrajectoryFeatures()
MovementTrajectoryFeatures(UINT trajectoryLength=100, UINT numCentroids=10, UINT featureMode=CENTROID_VALUE, UINT numHistogramBins=10, UINT numDimensions=1, bool useTrajStartAndEndValues=false, bool useWeightedMagnitudeValues=true)
virtual bool resize(const unsigned int r, const unsigned int c)
CircularBuffer< VectorFloat > getTrajectoryData()
bool resize(const unsigned int newBufferSize)