GestureRecognitionToolkit  Version: 0.1.0
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 #include "MatrixFloat.h"
22 
23 GRT_BEGIN_NAMESPACE
24 
26  warningLog.setProceedingText("[WARNING MatrixFloat]");
27  errorLog.setProceedingText("[ERROR MatrixFloat]");
28  this->dataPtr = NULL;
29  this->rows = 0;
30  this->cols = 0;
31 }
32 
33 MatrixFloat::MatrixFloat(const unsigned int rows,const unsigned int cols){
34  warningLog.setProceedingText("[WARNING MatrixFloat]");
35  errorLog.setProceedingText("[ERROR MatrixFloat]");
36  this->dataPtr = NULL;
37  if( rows > 0 && cols > 0 ){
38  resize(rows, cols);
39  }
40 }
41 
43  warningLog.setProceedingText("[WARNING MatrixFloat]");
44  errorLog.setProceedingText("[ERROR MatrixFloat]");
45  this->dataPtr = NULL;
46  this->rowPtr = NULL;
47  this->copy( rhs );
48 }
49 
51  warningLog.setProceedingText("[WARNING MatrixFloat]");
52  errorLog.setProceedingText("[ERROR MatrixFloat]");
53  this->dataPtr = NULL;
54  this->rowPtr = NULL;
55  this->copy( rhs );
56 }
57 
59  clear();
60 }
61 
63  if( this != &rhs ){
64  this->clear();
65  this->copy( rhs );
66  }
67  return *this;
68 }
69 
71  if( this != &rhs ){
72  this->clear();
73  this->copy( rhs );
74  }
75  return *this;
76 }
77 
79 
80  clear();
81 
82  if( rhs.size() == 0 ) return *this;
83 
84  unsigned int M = rhs.getSize();
85  unsigned int N = (unsigned int)rhs[0].getSize();
86  resize(M, N);
87 
88  for(unsigned int i=0; i<M; i++){
89  if( rhs[i].size() != N ){
90  clear();
91  return *this;
92  }
93  for(unsigned int j=0; j<N; j++){
94  dataPtr[i*cols+j] = rhs[i][j];
95  }
96  }
97 
98  return *this;
99 }
100 
101 bool MatrixFloat::print(const std::string title) const {
102 
103  if( dataPtr == NULL ) return false;
104 
105  if( title != "" ){
106  std::cout << title << std::endl;
107  }
108  for(unsigned int i=0; i<rows; i++){
109  for(unsigned int j=0; j<cols; j++){
110  std::cout << dataPtr[i*cols+j] << "\t";
111  }
112  std::cout << std::endl;
113  }
114 
115  return true;
116 }
117 
119 
120  if( dataPtr == NULL ) return false;
121 
122  MatrixFloat temp(cols,rows);
123  for(unsigned int i=0; i<rows; i++){
124  for(unsigned int j=0; j<cols; j++){
125  temp[j][i] = dataPtr[i*cols+j];
126  }
127  }
128 
129  *this = temp;
130 
131  return true;
132 }
133 
134 bool MatrixFloat::scale(const Float minTarget,const Float maxTarget){
135 
136  if( dataPtr == NULL ) return false;
137 
138  Vector< MinMax > ranges = getRanges();
139 
140  return scale(ranges,minTarget,maxTarget);
141 }
142 
143 bool MatrixFloat::scale(const Vector< MinMax > &ranges,const Float minTarget,const Float maxTarget){
144  if( dataPtr == NULL ) return false;
145 
146  if( ranges.size() != cols ){
147  return false;
148  }
149 
150  unsigned int i,j = 0;
151  for(i=0; i<rows; i++){
152  for(j=0; j<cols; j++){
153  dataPtr[i*cols+j] = grt_scale(dataPtr[i*cols+j],ranges[j].minValue,ranges[j].maxValue,minTarget,maxTarget);
154  }
155  }
156  return true;
157 }
158 
159 bool MatrixFloat::znorm(const Float alpha){
160  if( dataPtr == NULL ) return false;
161 
162  UINT i,j = 0;
163  Float mean, std = 0;
164  for(i=0; i<rows; i++){
165  mean = 0;
166  std = 0;
167 
168  //Compute the mean
169  for(j=0; j<cols; j++){
170  mean += dataPtr[i*cols+j];
171  }
172  mean /= cols;
173 
174  //Compute the std dev
175  for(j=0; j<cols; j++){
176  std += (dataPtr[i*cols+j]-mean)*(dataPtr[i*cols+j]-mean);
177  }
178  std /= cols;
179  std = sqrt( std + alpha );
180 
181  //Normalize the row
182  for(j=0; j<cols; j++){
183  dataPtr[i*cols+j] = (dataPtr[i*cols+j]-mean) / std;
184  }
185  }
186 
187  return true;
188 }
189 
190 MatrixFloat MatrixFloat::multiple(const Float value) const{
191 
192  if( dataPtr == NULL ) return MatrixFloat();
193 
194  MatrixFloat d(rows,cols);
195  Float *d_p = &(d[0][0]);
196 
197  unsigned int i = 0;
198  for(i=0; i<rows*cols; i++){
199  d_p[i] = dataPtr[i] * value;
200  }
201 
202  return d;
203 }
204 
206 
207  const unsigned int M = rows;
208  const unsigned int N = cols;
209  const unsigned int K = (unsigned int)b.size();
210 
211  if( N != K ){
212  warningLog << "multiple(vector b) - The size of b (" << b.size() << ") does not match the number of columns in this matrix (" << N << ")" << std::endl;
213  return VectorFloat();
214  }
215 
216  VectorFloat c(M);
217  const Float *pb = &b[0];
218  Float *pc = &c[0];
219 
220  unsigned int i,j = 0;
221  for(i=0; i<rows; i++){
222  pc[i] = 0;
223  for(j=0; j<cols; j++){
224  pc[i] += dataPtr[i*cols+j]*pb[j];
225  }
226  }
227 
228  return c;
229 }
230 
232 
233  const unsigned int M = rows;
234  const unsigned int N = cols;
235  const unsigned int K = b.getNumRows();
236  const unsigned int L = b.getNumCols();
237 
238  if( N != K ) {
239  errorLog << "multiple(MatrixFloat b) - The number of rows in b (" << K << ") does not match the number of columns in this matrix (" << N << ")" << std::endl;
240  return MatrixFloat();
241  }
242 
243  MatrixFloat c(M,L);
244  Float **pb = b.getDataPointer();
245  Float **pc = c.getDataPointer();
246 
247  unsigned int i,j,k = 0;
248  for(i=0; i<M; i++){
249  for(j=0; j<L; j++){
250  pc[i][j] = 0;
251  for(k=0; k<K; k++){
252  pc[i][j] += dataPtr[i*cols+k] * pb[k][j];
253  }
254  }
255  }
256 
257  return c;
258 }
259 
260 bool MatrixFloat::multiple(const MatrixFloat &a,const MatrixFloat &b,const bool aTranspose){
261 
262  const unsigned int M = !aTranspose ? a.getNumRows() : a.getNumCols();
263  const unsigned int N = !aTranspose ? a.getNumCols() : a.getNumRows();
264  const unsigned int K = b.getNumRows();
265  const unsigned int L = b.getNumCols();
266 
267  if( N != K ) {
268  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;
269  return false;
270  }
271 
272  if( !resize( M, L ) ){
273  errorLog << "multiple(const MatrixFloat &b,const MatrixFloat &c,const bool bTranspose) - Failed to resize matrix!" << std::endl;
274  return false;
275  }
276 
277  unsigned int i, j, k = 0;
278 
279  //Using direct pointers really helps speed up the computation time
280  Float **pa = a.getDataPointer();
281  Float **pb = b.getDataPointer();
282 
283  if( aTranspose ){
284 
285  for(j=0; j<L; j++){
286  for(i=0; i<M; i++){
287  dataPtr[i*cols+j] = 0;
288  for(k=0; k<K; k++){
289  dataPtr[i*cols+j] += pa[k][i] * pb[k][j];
290  }
291  }
292  }
293 
294  }else{
295 
296  for(j=0; j<L; j++){
297  for(i=0; i<M; i++){
298  dataPtr[i*cols+j] = 0;
299  for(k=0; k<K; k++){
300  dataPtr[i*cols+j] += pa[i][k] * pb[k][j];
301  }
302  }
303  }
304 
305  }
306 
307  return true;
308 }
309 
311 
312  if( b.getNumRows() != rows ){
313  errorLog << "add(const MatrixFloat &b) - Failed to add matrix! The rows do not match!" << std::endl;
314  return false;
315  }
316 
317  if( b.getNumCols() != cols ){
318  errorLog << "add(const MatrixFloat &b) - Failed to add matrix! The rows do not match!" << std::endl;
319  return false;
320  }
321 
322  unsigned int i = 0;
323 
324  //Using direct pointers really helps speed up the computation time
325  const Float *p_b = &(b[0][0]);
326 
327  for(i=0; i<rows*cols; i++){
328  dataPtr[i] += p_b[i];
329  }
330 
331  return true;
332 }
333 
334 bool MatrixFloat::add(const MatrixFloat &a,const MatrixFloat &b){
335 
336  const unsigned int M = a.getNumRows();
337  const unsigned int N = a.getNumCols();
338 
339  if( M != b.getNumRows() ){
340  errorLog << "add(const MatrixFloat &a,const MatrixFloat &b) - Failed to add matrix! The rows do not match!";
341  errorLog << " a rows: " << M << " b rows: " << b.getNumRows() << std::endl;
342  return false;
343  }
344 
345  if( N != b.getNumCols() ){
346  errorLog << "add(const MatrixFloat &a,const MatrixFloat &b) - Failed to add matrix! The columns do not match!";
347  errorLog << " a cols: " << N << " b cols: " << b.getNumCols() << std::endl;
348  return false;
349  }
350 
351  resize( M, N );
352 
353  UINT i,j;
354 
355  //Using direct pointers really helps speed up the computation time
356  Float *pa = a.getData();
357  Float *pb = b.getData();
358 
359  const unsigned int size = M*N;
360  for(i=0; i<size; i++){
361  dataPtr[i] = pa[i] + pb[i];
362  }
363 
364  return true;
365 }
366 
368 
369  if( b.getNumRows() != rows ){
370  errorLog << "subtract(const MatrixFloat &b) - Failed to add matrix! The rows do not match!" << std::endl;
371  errorLog << " rows: " << rows << " b rows: " << b.getNumRows() << std::endl;
372  return false;
373  }
374 
375  if( b.getNumCols() != cols ){
376  errorLog << "subtract(const MatrixFloat &b) - Failed to add matrix! The rows do not match!" << std::endl;
377  errorLog << " cols: " << cols << " b cols: " << b.getNumCols() << std::endl;
378  return false;
379  }
380 
381  unsigned int i,j;
382 
383  //Using direct pointers really helps speed up the computation time
384  Float *pb = b.getData();
385 
386  const unsigned int size = rows*cols;
387  for(i=0; i<size; i++){
388  dataPtr[i] -= pb[i];
389  }
390 
391  return true;
392 }
393 
395 
396  const unsigned int M = a.getNumRows();
397  const unsigned int N = a.getNumCols();
398 
399  if( M != b.getNumRows() ){
400  errorLog << "subtract(const MatrixFloat &a,const MatrixFloat &b) - Failed to add matrix! The rows do not match!";
401  errorLog << " a rows: " << M << " b rows: " << b.getNumRows() << std::endl;
402  return false;
403  }
404 
405  if( N != b.getNumCols() ){
406  errorLog << "subtract(const MatrixFloat &a,const MatrixFloat &b) - Failed to add matrix! The columns do not match!";
407  errorLog << " a cols: " << N << " b cols: " << b.getNumCols() << std::endl;
408  return false;
409  }
410 
411  resize( M, N );
412 
413  UINT i,j;
414 
415  //Using direct pointers really helps speed up the computation time
416  Float **pa = a.getDataPointer();
417  Float **pb = b.getDataPointer();
418 
419  for(i=0; i<M; i++){
420  for(j=0; j<N; j++){
421  dataPtr[i*cols+j] = pa[i][j] - pb[i][j];
422  }
423  }
424 
425  return true;
426 }
427 
429  Float minValue = 99e+99;
430  for(unsigned int i=0; i<rows*cols; i++){
431  if( dataPtr[i] < minValue ) minValue = dataPtr[i];
432  }
433  return minValue;
434 }
435 
437  Float maxValue = 99e-99;
438  for(unsigned int i=0; i<rows*cols; i++){
439  if( dataPtr[i] > maxValue ) maxValue = dataPtr[i];
440  }
441  return maxValue;
442 }
443 
445 
446  VectorFloat mean(cols);
447 
448  for(unsigned int c=0; c<cols; c++){
449  mean[c] = 0;
450  for(unsigned int r=0; r<rows; r++){
451  mean[c] += dataPtr[r*cols+c];
452  }
453  mean[c] /= Float( rows );
454  }
455 
456  return mean;
457 }
458 
460 
461  VectorFloat mean = getMean();
462  VectorFloat stdDev(cols,0);
463 
464  for(unsigned int j=0; j<cols; j++){
465  for(unsigned int i=0; i<rows; i++){
466  stdDev[j] += (dataPtr[i*cols+j]-mean[j])*(dataPtr[i*cols+j]-mean[j]);
467  }
468  stdDev[j] = sqrt( stdDev[j] / Float(rows-1) );
469  }
470  return stdDev;
471 }
472 
474 
475  Vector<Float> mean = getMean();
476  MatrixFloat covMatrix(cols,cols);
477 
478  for(unsigned int j=0; j<cols; j++){
479  for(unsigned int k=0; k<cols; k++){
480  covMatrix[j][k] = 0;
481  for(unsigned int i=0; i<rows; i++){
482  covMatrix[j][k] += (dataPtr[i*cols+j]-mean[j]) * (dataPtr[i*cols+k]-mean[k]);
483  }
484  covMatrix[j][k] /= Float(rows-1);
485  }
486  }
487 
488  return covMatrix;
489 }
490 
492 
493  if( rows == 0 ) return Vector< MinMax >();
494 
495  Vector< MinMax > ranges(cols);
496  for(unsigned int i=0; i<rows; i++){
497  for(unsigned int j=0; j<cols; j++){
498  ranges[j].updateMinMax( dataPtr[i*cols+j] );
499  }
500  }
501  return ranges;
502 }
503 
504 Float MatrixFloat::getTrace() const{
505  Float t = 0;
506  unsigned int K = (rows < cols ? rows : cols);
507  for(unsigned int i=0; i < K; i++) {
508  t += dataPtr[i*cols+i];
509  }
510  return t;
511 }
512 
513 bool MatrixFloat::save(const std::string &filename) const{
514 
515  std::fstream file;
516  file.open(filename.c_str(), std::ios::out);
517 
518  if( !file.is_open() ){
519  return false;
520  }
521 
522  for(UINT i=0; i<rows; i++){
523  for(UINT j=0; j<cols; j++){
524  file << dataPtr[i*cols+j] << (j<cols-1 ? "," : "\n");
525  }
526  }
527 
528  file.close();
529  return true;
530 }
531 
532 bool MatrixFloat::load(const std::string &filename,const char seperator){
533 
534  //Clear any previous data
535  clear();
536 
537  //Open the file
538  std::ifstream file( filename.c_str(), std::ifstream::in );
539  if ( !file.is_open() ){
540  warningLog << "parseFile(...) - Failed to open file: " << filename << std::endl;
541  return false;
542  }
543 
545  VectorFloat row;
546  std::string line;
547  std::string columnString = "";
548  const int sepValue = seperator;
549  unsigned int rowCounter = 0;
550  unsigned int columnCounter = 0;
551  unsigned int length = 0;
552 
553  //Count the number of columns in the first row
554  if( !getline(file,line) ){
555  warningLog << "parseFile(...) - Failed to read first row!" << std::endl;
556  return false;
557  }
558 
559  length = (unsigned int)line.length();
560  for(unsigned int i=0; i<length; i++){
561  if( int(line[i]) == sepValue ){
562  columnCounter++;
563  }
564  }
565  columnCounter++;
566 
567  std::cout << "counting rows..." << std::endl;
568 
569  //Count the number of rows in the file
570  rowCounter = 1;
571  while ( getline(file,line) ){
572  rowCounter++;
573  }
574 
575  std::cout << "matrix size: " << rowCounter << " " << columnCounter << std::endl;
576 
577  //Assign the memory
578  if( !resize(rowCounter, columnCounter) ){
579  warningLog << "parseFile(...) - Failed to resize memory!" << std::endl;
580  return false;
581  }
582 
583  //Reset the file read pointer
584  file.close();
585  file.open( filename.c_str(), std::ifstream::in );
586  rowCounter = 0;
587 
588  //Loop over each line of data and parse the contents
589  while ( getline(file,line) )
590  {
591  //Scan the line contents for the seperator token and parse the contents between each token
592  vec.clear();
593  columnString = "";
594  length = (unsigned int)line.length();
595  for(unsigned int i=0; i<length; i++){
596  if( int(line[i]) == sepValue ){
597  vec.push_back( columnString );
598  columnString = "";
599  }else columnString += line[i];
600  }
601 
602  //Add the last column
603  vec.push_back( columnString );
604 
605  //Check to make sure all the columns are consistent
606  if( columnCounter != vec.size() ){
607  clear();
608  warningLog << "parseFile(...) - Found inconsistent column size in row " << rowCounter;
609  warningLog << " ColumnSize: " << columnCounter << " LastColumnSize: " << vec.size() << std::endl;
610  return false;
611  }
612 
613  //Remove the new line character from the string in the last column
614  if( vec.size() >= 1 ){
615  size_t K = vec.size()-1;
616  size_t foundA = vec[ K ].find('\n');
617  size_t foundB = vec[K ].find('\r');
618  if( foundA != std::string::npos || foundB != std::string::npos ){
619  vec[ K ] = vec[ K ].substr(0,vec[ K ].length()-1);
620  }
621  }
622 
623  //Convert the string column values to Float values
624  for(unsigned int j=0; j<columnCounter; j++){
625  dataPtr[rowCounter*cols+j] = grt_from_str< Float >( vec[j] );
626  }
627  rowCounter++;
628  }
629 
630  //Close the file
631  file.close();
632 
633  return true;
634 }
635 
636 bool MatrixFloat::saveToCSVFile(const std::string &filename) const{
637  return save( filename );
638 }
639 
640 bool MatrixFloat::loadFromCSVFile(const std::string &filename,const char seperator){
641  return load( filename, seperator );
642 }
643 
644 GRT_END_NAMESPACE
void clear()
Definition: Matrix.h:522
bool save(const std::string &filename) const
Float getMaxValue() const
bool saveToCSVFile(const std::string &filename) const
unsigned int getSize() const
Definition: Matrix.h:564
bool load(const std::string &filename, const char seperator= ',')
bool scale(const Float minTarget, const Float maxTarget)
virtual ~MatrixFloat()
Definition: MatrixFloat.cpp:58
bool transpose()
T * getData() const
Definition: Matrix.h:583
unsigned int getSize() const
Definition: Vector.h:193
Float ** rowPtr
A pointer to each row in the data.
Definition: Matrix.h:593
bool add(const MatrixFloat &b)
bool subtract(const MatrixFloat &b)
unsigned int rows
The number of rows in the Matrix.
Definition: Matrix.h:588
bool print(const std::string title="") const
VectorFloat getMean() const
MatrixFloat & operator=(const MatrixFloat &rhs)
Definition: MatrixFloat.cpp:62
MatrixFloat getCovarianceMatrix() const
bool loadFromCSVFile(const std::string &filename, const char seperator= ',')
unsigned int getNumRows() const
Definition: Matrix.h:542
unsigned int getNumCols() const
Definition: Matrix.h:549
Float getMinValue() const
T ** getDataPointer() const
Definition: Matrix.h:571
virtual bool copy(const Matrix< Float > &rhs)
Definition: Matrix.h:306
unsigned int size
Stores rows * cols.
Definition: Matrix.h:590
Vector< MinMax > getRanges() const
Float * dataPtr
A pointer to the raw data.
Definition: Matrix.h:592
unsigned int cols
The number of columns in the Matrix.
Definition: Matrix.h:589
virtual bool resize(const unsigned int r, const unsigned int c)
Definition: Matrix.h:232
VectorFloat getStdDev() const
MatrixFloat multiple(const Float value) const
Float getTrace() const
bool znorm(const Float alpha=0.001)