GestureRecognitionToolkit  Version: 0.2.5
The Gesture Recognition Toolkit (GRT) is a cross-platform, open-source, c++ machine learning library for real-time gesture recognition.
MatrixFloat.cpp
1 /*
2 GRT MIT License
3 Copyright (c) <2012> <Nicholas Gillian, Media Lab, MIT>
4 
5 Permission is hereby granted, free of charge, to any person obtaining a copy of this software
6 and associated documentation files (the "Software"), to deal in the Software without restriction,
7 including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
9 subject to the following conditions:
10 
11 The above copyright notice and this permission notice shall be included in all copies or substantial
12 portions of the Software.
13 
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
15 LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
16 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
17 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
18 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19 */
20 
21 #define GRT_DLL_EXPORTS
22 #include "MatrixFloat.h"
23 
24 GRT_BEGIN_NAMESPACE
25 
27  warningLog.setKey("[WARNING MatrixFloat]");
28  errorLog.setKey("[ERROR MatrixFloat]");
29  this->dataPtr = NULL;
30  this->rowPtr = NULL;
31  this->rows = 0;
32  this->cols = 0;
33 }
34 
35 MatrixFloat::MatrixFloat(const unsigned int rows,const unsigned int cols){
36  warningLog.setKey("[WARNING MatrixFloat]");
37  errorLog.setKey("[ERROR MatrixFloat]");
38  this->dataPtr = NULL;
39  this->rowPtr = NULL;
40  this->rows = 0;
41  this->cols = 0;
42  if( rows > 0 && cols > 0 ){
43  resize(rows, cols);
44  }
45 }
46 
48  warningLog.setKey("[WARNING MatrixFloat]");
49  errorLog.setKey("[ERROR MatrixFloat]");
50  this->dataPtr = NULL;
51  this->rowPtr = NULL;
52  this->rows = 0;
53  this->cols = 0;
54  this->copy( rhs );
55 }
56 
58  warningLog.setKey("[WARNING MatrixFloat]");
59  errorLog.setKey("[ERROR MatrixFloat]");
60  this->dataPtr = NULL;
61  this->rowPtr = NULL;
62  this->rows = 0;
63  this->cols = 0;
64  this->copy( rhs );
65 }
66 
68  warningLog.setKey("[WARNING MatrixFloat]");
69  errorLog.setKey("[ERROR MatrixFloat]");
70  this->dataPtr = NULL;
71  this->rowPtr = NULL;
72  this->rows = 0;
73  this->cols = 0;
74 
75  if( rhs.size() == 0 ) return;
76 
77  unsigned int M = rhs.getSize();
78  unsigned int N = (unsigned int)rhs[0].getSize();
79  resize(M, N);
80 
81  for(unsigned int i=0; i<M; i++){
82  if( rhs[i].size() != N ){
83  clear();
84  return;
85  }
86  for(unsigned int j=0; j<N; j++){
87  dataPtr[i*cols+j] = rhs[i][j];
88  }
89  }
90 }
91 
93  clear();
94 }
95 
97  if( this != &rhs ){
98  this->clear();
99  this->copy( rhs );
100  }
101  return *this;
102 }
103 
105  if( this != &rhs ){
106  this->clear();
107  this->copy( rhs );
108  }
109  return *this;
110 }
111 
113 
114  clear();
115 
116  if( rhs.size() == 0 ) return *this;
117 
118  unsigned int M = rhs.getSize();
119  unsigned int N = (unsigned int)rhs[0].getSize();
120  resize(M, N);
121 
122  for(unsigned int i=0; i<M; i++){
123  if( rhs[i].size() != N ){
124  clear();
125  return *this;
126  }
127  for(unsigned int j=0; j<N; j++){
128  dataPtr[i*cols+j] = rhs[i][j];
129  }
130  }
131 
132  return *this;
133 }
134 
135 bool MatrixFloat::print(const std::string title) const {
136 
137  if( dataPtr == NULL ) return false;
138 
139  if( title != "" ){
140  std::cout << title << std::endl;
141  }
142  for(unsigned int i=0; i<rows; i++){
143  for(unsigned int j=0; j<cols; j++){
144  std::cout << dataPtr[i*cols+j] << "\t";
145  }
146  std::cout << std::endl;
147  }
148 
149  return true;
150 }
151 
153 
154  if( dataPtr == NULL ) return false;
155 
156  MatrixFloat temp(cols,rows);
157  for(unsigned int i=0; i<rows; i++){
158  for(unsigned int j=0; j<cols; j++){
159  temp[j][i] = dataPtr[i*cols+j];
160  }
161  }
162 
163  *this = temp;
164 
165  return true;
166 }
167 
168 bool MatrixFloat::scale(const Float minTarget,const Float maxTarget){
169 
170  if( dataPtr == NULL ) return false;
171 
172  Vector< MinMax > ranges = getRanges();
173 
174  return scale(ranges,minTarget,maxTarget);
175 }
176 
177 bool MatrixFloat::scale(const Vector< MinMax > &ranges,const Float minTarget,const Float maxTarget){
178  if( dataPtr == NULL ) return false;
179 
180  if( ranges.size() != cols ){
181  return false;
182  }
183 
184  unsigned int i,j = 0;
185  for(i=0; i<rows; i++){
186  for(j=0; j<cols; j++){
187  dataPtr[i*cols+j] = grt_scale(dataPtr[i*cols+j],ranges[j].minValue,ranges[j].maxValue,minTarget,maxTarget);
188  }
189  }
190  return true;
191 }
192 
193 bool MatrixFloat::znorm(const Float alpha){
194  if( dataPtr == NULL ) return false;
195 
196  UINT i,j = 0;
197  Float mean, std = 0;
198  for(i=0; i<rows; i++){
199  mean = 0;
200  std = 0;
201 
202  //Compute the mean
203  for(j=0; j<cols; j++){
204  mean += dataPtr[i*cols+j];
205  }
206  mean /= cols;
207 
208  //Compute the std dev
209  for(j=0; j<cols; j++){
210  std += (dataPtr[i*cols+j]-mean)*(dataPtr[i*cols+j]-mean);
211  }
212  std /= cols;
213  std = sqrt( std + alpha );
214 
215  //Normalize the row
216  for(j=0; j<cols; j++){
217  dataPtr[i*cols+j] = (dataPtr[i*cols+j]-mean) / std;
218  }
219  }
220 
221  return true;
222 }
223 
224 MatrixFloat MatrixFloat::multiple(const Float value) const{
225 
226  if( dataPtr == NULL ) return MatrixFloat();
227 
228  MatrixFloat d(rows,cols);
229  Float *d_p = &(d[0][0]);
230 
231  unsigned int i = 0;
232  for(i=0; i<rows*cols; i++){
233  d_p[i] = dataPtr[i] * value;
234  }
235 
236  return d;
237 }
238 
240 
241  const unsigned int M = rows;
242  const unsigned int N = cols;
243  const unsigned int K = (unsigned int)b.size();
244 
245  if( N != K ){
246  warningLog << "multiple(vector b) - The size of b (" << b.size() << ") does not match the number of columns in this matrix (" << N << ")" << std::endl;
247  return VectorFloat();
248  }
249 
250  VectorFloat c(M);
251  const Float *pb = &b[0];
252  Float *pc = &c[0];
253 
254  unsigned int i,j = 0;
255  for(i=0; i<rows; i++){
256  pc[i] = 0;
257  for(j=0; j<cols; j++){
258  pc[i] += dataPtr[i*cols+j]*pb[j];
259  }
260  }
261 
262  return c;
263 }
264 
266 
267  const unsigned int M = rows;
268  const unsigned int N = cols;
269  const unsigned int K = b.getNumRows();
270  const unsigned int L = b.getNumCols();
271 
272  if( N != K ) {
273  errorLog << "multiple(MatrixFloat b) - The number of rows in b (" << K << ") does not match the number of columns in this matrix (" << N << ")" << std::endl;
274  return MatrixFloat();
275  }
276 
277  MatrixFloat c(M,L);
278  Float **pb = b.getDataPointer();
279  Float **pc = c.getDataPointer();
280 
281  unsigned int i,j,k = 0;
282  for(i=0; i<M; i++){
283  for(j=0; j<L; j++){
284  pc[i][j] = 0;
285  for(k=0; k<K; k++){
286  pc[i][j] += dataPtr[i*cols+k] * pb[k][j];
287  }
288  }
289  }
290 
291  return c;
292 }
293 
294 bool MatrixFloat::multiple(const MatrixFloat &a,const MatrixFloat &b,const bool aTranspose){
295 
296  const unsigned int M = !aTranspose ? a.getNumRows() : a.getNumCols();
297  const unsigned int N = !aTranspose ? a.getNumCols() : a.getNumRows();
298  const unsigned int K = b.getNumRows();
299  const unsigned int L = b.getNumCols();
300 
301  if( N != K ) {
302  errorLog << "multiple(const MatrixFloat &a,const MatrixFloat &b,const bool aTranspose) - The number of rows in a (" << K << ") does not match the number of columns in matrix b (" << N << ")" << std::endl;
303  return false;
304  }
305 
306  if( !resize( M, L ) ){
307  errorLog << "multiple(const MatrixFloat &b,const MatrixFloat &c,const bool bTranspose) - Failed to resize matrix!" << std::endl;
308  return false;
309  }
310 
311  unsigned int i, j, k = 0;
312 
313  //Using direct pointers really helps speed up the computation time
314  Float **pa = a.getDataPointer();
315  Float **pb = b.getDataPointer();
316 
317  if( aTranspose ){
318 
319  for(j=0; j<L; j++){
320  for(i=0; i<M; i++){
321  dataPtr[i*cols+j] = 0;
322  for(k=0; k<K; k++){
323  dataPtr[i*cols+j] += pa[k][i] * pb[k][j];
324  }
325  }
326  }
327 
328  }else{
329 
330  for(j=0; j<L; j++){
331  for(i=0; i<M; i++){
332  dataPtr[i*cols+j] = 0;
333  for(k=0; k<K; k++){
334  dataPtr[i*cols+j] += pa[i][k] * pb[k][j];
335  }
336  }
337  }
338 
339  }
340 
341  return true;
342 }
343 
345 
346  if( b.getNumRows() != rows ){
347  errorLog << "add(const MatrixFloat &b) - Failed to add matrix! The rows do not match!" << std::endl;
348  return false;
349  }
350 
351  if( b.getNumCols() != cols ){
352  errorLog << "add(const MatrixFloat &b) - Failed to add matrix! The rows do not match!" << std::endl;
353  return false;
354  }
355 
356  unsigned int i = 0;
357 
358  //Using direct pointers really helps speed up the computation time
359  const Float *p_b = &(b[0][0]);
360 
361  for(i=0; i<rows*cols; i++){
362  dataPtr[i] += p_b[i];
363  }
364 
365  return true;
366 }
367 
368 bool MatrixFloat::add(const MatrixFloat &a,const MatrixFloat &b){
369 
370  const unsigned int M = a.getNumRows();
371  const unsigned int N = a.getNumCols();
372 
373  if( M != b.getNumRows() ){
374  errorLog << "add(const MatrixFloat &a,const MatrixFloat &b) - Failed to add matrix! The rows do not match!";
375  errorLog << " a rows: " << M << " b rows: " << b.getNumRows() << std::endl;
376  return false;
377  }
378 
379  if( N != b.getNumCols() ){
380  errorLog << "add(const MatrixFloat &a,const MatrixFloat &b) - Failed to add matrix! The columns do not match!";
381  errorLog << " a cols: " << N << " b cols: " << b.getNumCols() << std::endl;
382  return false;
383  }
384 
385  resize( M, N );
386 
387  UINT i;
388 
389  //Using direct pointers really helps speed up the computation time
390  Float *pa = a.getData();
391  Float *pb = b.getData();
392 
393  const unsigned int size = M*N;
394  for(i=0; i<size; i++){
395  dataPtr[i] = pa[i] + pb[i];
396  }
397 
398  return true;
399 }
400 
402 
403  if( b.getNumRows() != rows ){
404  errorLog << "subtract(const MatrixFloat &b) - Failed to add matrix! The rows do not match!" << std::endl;
405  errorLog << " rows: " << rows << " b rows: " << b.getNumRows() << std::endl;
406  return false;
407  }
408 
409  if( b.getNumCols() != cols ){
410  errorLog << "subtract(const MatrixFloat &b) - Failed to add matrix! The rows do not match!" << std::endl;
411  errorLog << " cols: " << cols << " b cols: " << b.getNumCols() << std::endl;
412  return false;
413  }
414 
415  unsigned int i;
416 
417  //Using direct pointers really helps speed up the computation time
418  Float *pb = b.getData();
419 
420  const unsigned int size = rows*cols;
421  for(i=0; i<size; i++){
422  dataPtr[i] -= pb[i];
423  }
424 
425  return true;
426 }
427 
429 
430  const unsigned int M = a.getNumRows();
431  const unsigned int N = a.getNumCols();
432 
433  if( M != b.getNumRows() ){
434  errorLog << "subtract(const MatrixFloat &a,const MatrixFloat &b) - Failed to add matrix! The rows do not match!";
435  errorLog << " a rows: " << M << " b rows: " << b.getNumRows() << std::endl;
436  return false;
437  }
438 
439  if( N != b.getNumCols() ){
440  errorLog << "subtract(const MatrixFloat &a,const MatrixFloat &b) - Failed to add matrix! The columns do not match!";
441  errorLog << " a cols: " << N << " b cols: " << b.getNumCols() << std::endl;
442  return false;
443  }
444 
445  resize( M, N );
446 
447  UINT i,j;
448 
449  //Using direct pointers really helps speed up the computation time
450  Float **pa = a.getDataPointer();
451  Float **pb = b.getDataPointer();
452 
453  for(i=0; i<M; i++){
454  for(j=0; j<N; j++){
455  dataPtr[i*cols+j] = pa[i][j] - pb[i][j];
456  }
457  }
458 
459  return true;
460 }
461 
463  Float minValue = 99e+99;
464  for(unsigned int i=0; i<rows*cols; i++){
465  if( dataPtr[i] < minValue ) minValue = dataPtr[i];
466  }
467  return minValue;
468 }
469 
471  Float maxValue = 99e-99;
472  for(unsigned int i=0; i<rows*cols; i++){
473  if( dataPtr[i] > maxValue ) maxValue = dataPtr[i];
474  }
475  return maxValue;
476 }
477 
479 
480  VectorFloat mean(cols);
481 
482  for(unsigned int c=0; c<cols; c++){
483  mean[c] = 0;
484  for(unsigned int r=0; r<rows; r++){
485  mean[c] += dataPtr[r*cols+c];
486  }
487  mean[c] /= Float( rows );
488  }
489 
490  return mean;
491 }
492 
494 
495  VectorFloat mean = getMean();
496  VectorFloat stdDev(cols,0);
497 
498  for(unsigned int j=0; j<cols; j++){
499  for(unsigned int i=0; i<rows; i++){
500  stdDev[j] += (dataPtr[i*cols+j]-mean[j])*(dataPtr[i*cols+j]-mean[j]);
501  }
502  stdDev[j] = sqrt( stdDev[j] / Float(rows-1) );
503  }
504  return stdDev;
505 }
506 
508 
509  Vector<Float> mean = getMean();
510  MatrixFloat covMatrix(cols,cols);
511 
512  for(unsigned int j=0; j<cols; j++){
513  for(unsigned int k=0; k<cols; k++){
514  covMatrix[j][k] = 0;
515  for(unsigned int i=0; i<rows; i++){
516  covMatrix[j][k] += (dataPtr[i*cols+j]-mean[j]) * (dataPtr[i*cols+k]-mean[k]);
517  }
518  covMatrix[j][k] /= Float(rows-1);
519  }
520  }
521 
522  return covMatrix;
523 }
524 
526 
527  if( rows == 0 ) return Vector< MinMax >();
528 
529  Vector< MinMax > ranges(cols);
530  for(unsigned int i=0; i<rows; i++){
531  for(unsigned int j=0; j<cols; j++){
532  ranges[j].updateMinMax( dataPtr[i*cols+j] );
533  }
534  }
535  return ranges;
536 }
537 
538 Float MatrixFloat::getTrace() const{
539  Float t = 0;
540  unsigned int K = (rows < cols ? rows : cols);
541  for(unsigned int i=0; i < K; i++) {
542  t += dataPtr[i*cols+i];
543  }
544  return t;
545 }
546 
547 bool MatrixFloat::save(const std::string &filename) const{
548 
549  std::fstream file;
550  file.open(filename.c_str(), std::ios::out);
551 
552  if( !file.is_open() ){
553  return false;
554  }
555 
556  for(UINT i=0; i<rows; i++){
557  for(UINT j=0; j<cols; j++){
558  file << dataPtr[i*cols+j] << (j<cols-1 ? "," : "\n");
559  }
560  }
561 
562  file.close();
563  return true;
564 }
565 
566 bool MatrixFloat::load(const std::string &filename,const char seperator){
567 
568  //Clear any previous data
569  clear();
570 
571  //Open the file
572  std::ifstream file( filename.c_str(), std::ifstream::in );
573  if ( !file.is_open() ){
574  warningLog << "parseFile(...) - Failed to open file: " << filename << std::endl;
575  return false;
576  }
577 
579  VectorFloat row;
580  std::string line;
581  std::string columnString = "";
582  const int sepValue = seperator;
583  unsigned int rowCounter = 0;
584  unsigned int columnCounter = 0;
585  unsigned int length = 0;
586 
587  //Count the number of columns in the first row
588  if( !getline(file,line) ){
589  warningLog << "parseFile(...) - Failed to read first row!" << std::endl;
590  return false;
591  }
592 
593  length = (unsigned int)line.length();
594  for(unsigned int i=0; i<length; i++){
595  if( int(line[i]) == sepValue ){
596  columnCounter++;
597  }
598  }
599  columnCounter++;
600 
601  std::cout << "counting rows..." << std::endl;
602 
603  //Count the number of rows in the file
604  rowCounter = 1;
605  while ( getline(file,line) ){
606  rowCounter++;
607  }
608 
609  std::cout << "matrix size: " << rowCounter << " " << columnCounter << std::endl;
610 
611  //Assign the memory
612  if( !resize(rowCounter, columnCounter) ){
613  warningLog << "parseFile(...) - Failed to resize memory!" << std::endl;
614  return false;
615  }
616 
617  //Reset the file read pointer
618  file.close();
619  file.open( filename.c_str(), std::ifstream::in );
620  rowCounter = 0;
621 
622  //Loop over each line of data and parse the contents
623  while ( getline(file,line) )
624  {
625  //Scan the line contents for the seperator token and parse the contents between each token
626  vec.clear();
627  columnString = "";
628  length = (unsigned int)line.length();
629  for(unsigned int i=0; i<length; i++){
630  if( int(line[i]) == sepValue ){
631  vec.push_back( columnString );
632  columnString = "";
633  }else columnString += line[i];
634  }
635 
636  //Add the last column
637  vec.push_back( columnString );
638 
639  //Check to make sure all the columns are consistent
640  if( columnCounter != vec.size() ){
641  clear();
642  warningLog << "parseFile(...) - Found inconsistent column size in row " << rowCounter;
643  warningLog << " ColumnSize: " << columnCounter << " LastColumnSize: " << vec.size() << std::endl;
644  return false;
645  }
646 
647  //Remove the new line character from the string in the last column
648  if( vec.size() >= 1 ){
649  size_t K = vec.size()-1;
650  size_t foundA = vec[ K ].find('\n');
651  size_t foundB = vec[K ].find('\r');
652  if( foundA != std::string::npos || foundB != std::string::npos ){
653  vec[ K ] = vec[ K ].substr(0,vec[ K ].length()-1);
654  }
655  }
656 
657  //Convert the string column values to Float values
658  for(unsigned int j=0; j<columnCounter; j++){
659  dataPtr[rowCounter*cols+j] = grt_from_str< Float >( vec[j] );
660  }
661  rowCounter++;
662  }
663 
664  //Close the file
665  file.close();
666 
667  return true;
668 }
669 
670 bool MatrixFloat::saveToCSVFile(const std::string &filename) const{
671  return save( filename );
672 }
673 
674 bool MatrixFloat::loadFromCSVFile(const std::string &filename,const char seperator){
675  return load( filename, seperator );
676 }
677 
678 GRT_END_NAMESPACE
bool save(const std::string &filename) const
Float getMaxValue() const
bool saveToCSVFile(const std::string &filename) const
unsigned int getSize() const
Definition: Matrix.h:596
bool load(const std::string &filename, const char seperator= ',')
bool scale(const Float minTarget, const Float maxTarget)
virtual ~MatrixFloat()
Definition: MatrixFloat.cpp:92
bool transpose()
virtual bool setKey(const std::string &key)
sets the key that gets written at the start of each message, this will be written in the format &#39;key ...
Definition: Log.h:166
T * getData() const
Definition: Matrix.h:615
UINT getSize() const
Definition: Vector.h:201
bool clear()
Definition: Matrix.h:553
Float ** rowPtr
A pointer to each row in the data.
Definition: Matrix.h:625
bool add(const MatrixFloat &b)
bool subtract(const MatrixFloat &b)
unsigned int rows
The number of rows in the Matrix.
Definition: Matrix.h:620
bool print(const std::string title="") const
VectorFloat getMean() const
MatrixFloat & operator=(const MatrixFloat &rhs)
Definition: MatrixFloat.cpp:96
MatrixFloat getCovarianceMatrix() const
bool loadFromCSVFile(const std::string &filename, const char seperator= ',')
unsigned int getNumRows() const
Definition: Matrix.h:574
unsigned int getNumCols() const
Definition: Matrix.h:581
Float getMinValue() const
T ** getDataPointer() const
Definition: Matrix.h:603
virtual bool copy(const Matrix< Float > &rhs)
Definition: Matrix.h:336
unsigned int size
Stores rows * cols.
Definition: Matrix.h:622
Vector< MinMax > getRanges() const
Float * dataPtr
A pointer to the raw data.
Definition: Matrix.h:624
unsigned int cols
The number of columns in the Matrix.
Definition: Matrix.h:621
virtual bool resize(const unsigned int r, const unsigned int c)
Definition: Matrix.h:245
VectorFloat getStdDev() const
MatrixFloat multiple(const Float value) const
Float getTrace() const
bool znorm(const Float alpha=0.001)