21 #define GRT_DLL_EXPORTS
31 classType =
"MovementTrajectoryFeatures";
32 featureExtractionType = classType;
33 debugLog.setProceedingText(
"[DEBUG MovementTrajectoryFeatures]");
34 errorLog.setProceedingText(
"[ERROR MovementTrajectoryFeatures]");
35 warningLog.setProceedingText(
"[WARNING ZeroCrossingCounter]");
37 init(trajectoryLength,numCentroids,featureMode,numHistogramBins,numDimensions,useTrajStartAndEndValues,useWeightedMagnitudeValues);
42 classType =
"MovementTrajectoryFeatures";
43 featureExtractionType = classType;
44 debugLog.setProceedingText(
"[DEBUG MovementTrajectoryFeatures]");
45 errorLog.setProceedingText(
"[ERROR MovementTrajectoryFeatures]");
46 warningLog.setProceedingText(
"[WARNING ZeroCrossingCounter]");
58 this->trajectoryLength = rhs.trajectoryLength;
59 this->numCentroids = rhs.numCentroids;
60 this->featureMode = rhs.featureMode;
61 this->numHistogramBins = rhs.numHistogramBins;
62 this->useTrajStartAndEndValues = rhs.useTrajStartAndEndValues;
63 this->useWeightedMagnitudeValues = rhs.useWeightedMagnitudeValues;
64 this->trajectoryDataBuffer = rhs.trajectoryDataBuffer;
65 this->centroids = rhs.centroids;
75 if( featureExtraction == NULL )
return false;
85 errorLog <<
"clone(FeatureExtraction *featureExtraction) - FeatureExtraction Types Do Not Match!" << std::endl;
93 errorLog <<
"computeFeatures(const VectorFloat &inputVector) - Not initialized!" << std::endl;
97 if( inputVector.
getSize() != numInputDimensions ){
98 errorLog <<
"computeFeatures(const VectorFloat &inputVector) - The size of the inputVector (" << inputVector.
getSize() <<
") does not match that of the filter (" << numInputDimensions <<
")!" << std::endl;
102 featureVector =
update( inputVector );
109 return init(trajectoryLength,numCentroids,featureMode,numHistogramBins,numInputDimensions,useTrajStartAndEndValues,useWeightedMagnitudeValues);
117 file.open(filename.c_str(), std::ios::out);
131 file.open(filename.c_str(), std::ios::in);
145 if( !file.is_open() ){
146 errorLog <<
"saveModelToFile(fstream &file) - The file is not open!" << std::endl;
151 file <<
"GRT_MOVEMENT_TRAJECTORY_FEATURES_FILE_V1.0" << std::endl;
155 errorLog <<
"saveFeatureExtractionSettingsToFile(fstream &file) - Failed to save base feature extraction settings to file!" << std::endl;
160 file <<
"TrajectoryLength: " << trajectoryLength << std::endl;
161 file <<
"NumCentroids: " << numCentroids << std::endl;
162 file <<
"FeatureMode: " << featureMode << std::endl;
163 file <<
"NumHistogramBins: " << numHistogramBins << std::endl;
164 file <<
"UseTrajStartAndEndValues: " << useTrajStartAndEndValues << std::endl;
165 file <<
"UseWeightedMagnitudeValues: " << useWeightedMagnitudeValues << std::endl;
172 if( !file.is_open() ){
173 errorLog <<
"loadModelFromFile(fstream &file) - The file is not open!" << std::endl;
182 if( word !=
"GRT_MOVEMENT_TRAJECTORY_FEATURES_FILE_V1.0" ){
183 errorLog <<
"loadModelFromFile(fstream &file) - Invalid file format!" << std::endl;
188 errorLog <<
"loadFeatureExtractionSettingsFromFile(fstream &file) - Failed to load base feature extraction settings from file!" << std::endl;
194 if( word !=
"TrajectoryLength:" ){
195 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read TrajectoryLength header!" << std::endl;
198 file >> trajectoryLength;
202 if( word !=
"NumCentroids:" ){
203 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read NumCentroids header!" << std::endl;
206 file >> numCentroids;
210 if( word !=
"FeatureMode:" ){
211 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read FeatureMode header!" << std::endl;
218 if( word !=
"NumHistogramBins:" ){
219 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read NumHistogramBins header!" << std::endl;
222 file >> numHistogramBins;
226 if( word !=
"UseTrajStartAndEndValues:" ){
227 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read UseTrajStartAndEndValues header!" << std::endl;
230 file >> useTrajStartAndEndValues;
234 if( word !=
"UseWeightedMagnitudeValues:" ){
235 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read UseWeightedMagnitudeValues header!" << std::endl;
238 file >> useWeightedMagnitudeValues;
241 return init(trajectoryLength,numCentroids,featureMode,numHistogramBins,numInputDimensions,useTrajStartAndEndValues,useWeightedMagnitudeValues);
244 bool MovementTrajectoryFeatures::init(UINT trajectoryLength,UINT numCentroids,UINT featureMode,UINT numHistogramBins,UINT numDimensions,
bool useTrajStartAndEndValues,
bool useWeightedMagnitudeValues){
248 if( numCentroids > trajectoryLength ){
249 errorLog <<
"init(...) - The number of centroids parameter can not be larger than the trajectory length parameter!" << std::endl;
252 if( trajectoryLength % numCentroids != 0 ){
253 errorLog <<
"init(...) - The trajectory length parameter must be divisible with no remainders by the number of centroids parameter!" << std::endl;
257 if( featureMode == CENTROID_ANGLE_2D && numDimensions % 2 != 0 ){
258 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;
262 if( numHistogramBins == 0 && featureMode == CENTROID_ANGLE_2D ){
263 errorLog <<
"init(...) - If the featureMode is CENTROID_ANGLE_2D then the numHistogramBins parameter must greater than 0!" << std::endl;
268 this->trajectoryLength = trajectoryLength;
269 this->numCentroids = numCentroids;
270 this->featureMode = featureMode;
271 this->numHistogramBins = numHistogramBins;
272 this->numInputDimensions = numDimensions;
273 this->useTrajStartAndEndValues = useTrajStartAndEndValues;
274 this->useWeightedMagnitudeValues = useWeightedMagnitudeValues;
275 featureDataReady =
false;
278 numOutputDimensions = 0;
279 switch( featureMode ){
282 numOutputDimensions = numInputDimensions*numCentroids;
284 case NORMALIZED_CENTROID_VALUE:
285 numOutputDimensions = numInputDimensions*numCentroids;
286 if( useTrajStartAndEndValues ){
287 numOutputDimensions += numInputDimensions*2;
290 case CENTROID_DERIVATIVE:
291 numOutputDimensions = numInputDimensions*(numCentroids-1);
292 if( useTrajStartAndEndValues ){
293 numOutputDimensions += numInputDimensions*2;
296 case CENTROID_ANGLE_2D:
297 numOutputDimensions = numHistogramBins*(numDimensions/2);
300 errorLog <<
"init(...)- Unknown featureMode!" << std::endl;
305 if( numOutputDimensions == 0 ){
306 errorLog <<
"init(...) - The numOutputDimensions is zero!" << std::endl;
311 featureVector.
resize(numOutputDimensions);
314 trajectoryDataBuffer.
resize( trajectoryLength,
VectorFloat(numInputDimensions,0) );
317 centroids.
resize(numCentroids,numInputDimensions);
332 errorLog <<
"update(const VectorFloat &x) - Not Initialized!" << std::endl;
336 if( x.
getSize() != numInputDimensions ){
337 errorLog <<
"update(const VectorFloat &x)- The Number Of Input Dimensions (" << numInputDimensions <<
") does not match the size of the input Vector (" << x.
getSize() <<
")!" << std::endl;
346 featureDataReady =
true;
347 }
else featureDataReady =
false;
352 UINT dataBufferIndex = 0;
353 UINT numValuesPerCentroid = (UINT)floor(Float(trajectoryLength/numCentroids));
354 for(UINT n=0; n<numInputDimensions; n++){
356 for(UINT i=0; i<numCentroids; i++){
357 for(UINT j=0; j<numValuesPerCentroid; j++){
358 centroids[i][n] += trajectoryDataBuffer[dataBufferIndex++][n];
360 centroids[i][n] /= Float(numValuesPerCentroid);
365 UINT featureIndex = 0;
369 switch( featureMode ){
372 for(UINT n=0; n<numInputDimensions; n++){
373 for(UINT i=0; i<numCentroids; i++){
374 featureVector[ featureIndex++ ] = centroids[i][n];
378 case NORMALIZED_CENTROID_VALUE:
379 for(UINT n=0; n<numInputDimensions; n++){
382 for(UINT i=0; i<numCentroids; i++){
383 centroidNormValues[n].updateMinMax( centroids[i][n] );
387 for(UINT i=0; i<numCentroids; i++){
388 if( centroidNormValues[n].maxValue != centroidNormValues[n].minValue ){
389 featureVector[ featureIndex++ ] =
Util::scale(centroids[i][n],centroidNormValues[n].minValue,centroidNormValues[n].maxValue,0,1);
390 }
else featureVector[ featureIndex++ ] = 0;
394 if( useTrajStartAndEndValues ){
395 featureVector[ featureIndex++ ] = centroids[0][n];
396 featureVector[ featureIndex++ ] = centroids[numCentroids-1][n];
400 case CENTROID_DERIVATIVE:
401 for(UINT n=0; n<numInputDimensions; n++){
404 for(UINT i=0; i<numCentroids-1; i++){
405 featureVector[ featureIndex++ ] = centroids[i+1][n]-centroids[i][n];
409 if( useTrajStartAndEndValues ){
410 featureVector[ featureIndex++ ] = centroids[0][n];
411 featureVector[ featureIndex++ ] = centroids[numCentroids-1][n];
415 case CENTROID_ANGLE_2D:
416 histSumValues.
resize( numInputDimensions/2, 0);
417 angleMagnitudeValues.
resize( numInputDimensions/2 );
420 fill(featureVector.begin(),featureVector.end(),0);
423 for(UINT n=0; n<numInputDimensions/2; n++){
425 angleMagnitudeValues[n].
resize(numCentroids-1);
426 for(UINT i=0; i<numCentroids-1; i++){
427 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);
431 for(UINT i=0; i<numCentroids-1; i++){
433 Float degreesPerBin = 360.0/numHistogramBins;
434 Float binStartValue = 0;
435 Float binEndValue = degreesPerBin;
437 if( angleMagnitudeValues[n][i].angle < 0 || angleMagnitudeValues[n][i].angle > 360.0 ){
438 warningLog <<
"The angle of a point is not between [0 360]. Angle: " << angleMagnitudeValues[n][i].angle << std::endl;
444 if( angleMagnitudeValues[n][i].angle >= binStartValue && angleMagnitudeValues[n][i].angle < binEndValue ){
448 binStartValue += degreesPerBin;
449 binEndValue += degreesPerBin;
452 histSumValues[ n ] += useWeightedMagnitudeValues ? angleMagnitudeValues[n][i].magnitude : 1;
453 featureVector[ n*numHistogramBins + histBin ] += useWeightedMagnitudeValues ? angleMagnitudeValues[n][i].magnitude : 1;
457 for(UINT n=0; n<numInputDimensions/2; n++){
458 if( histSumValues[ n ] > 0 ){
459 for(UINT i=0; i<numHistogramBins; i++){
460 featureVector[ n*numHistogramBins + i ] /= histSumValues[ n ];
467 errorLog <<
"update(VectorFloat x)- Unknown featureMode!" << std::endl;
468 return featureVector;
472 return featureVector;
477 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)
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)