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