00001 #include<cob_people_detection/subspace_analysis.h>
00002 #include<thirdparty/decomposition.hpp>
00003
00004
00005
00006
00007
00008
00009
00010
00011 void SubspaceAnalysis::mat2arr(cv::Mat& src_mat, cv::Mat& dst_mat)
00012 {
00013
00014 dst_mat = src_mat.clone().reshape(1, 1);
00015
00016 return;
00017 }
00018
00019 void SubspaceAnalysis::condense_labels(std::vector<int>& labels)
00020 {
00021 int min_val = std::numeric_limits<int>::max();
00022 for (int i = 0; i < labels.size(); i++)
00023 {
00024 if (labels[i] < min_val)
00025 min_val = labels[i];
00026 }
00027 if (min_val > 0)
00028 {
00029 for (int i = 0; i < labels.size(); i++)
00030 {
00031 labels[i] -= min_val;
00032 }
00033 }
00034 }
00035 void SubspaceAnalysis::unique_elements(cv::Mat & mat, int& unique_elements, std::vector<int>& distinct_vec)
00036 {
00037 bool unique = true;
00038 for (int i = 0; i < mat.total(); ++i)
00039 {
00040
00041 if (i != 0)
00042 {
00043 unique = true;
00044 for (int j = 0; j < distinct_vec.size(); j++)
00045 {
00046 if (mat.at<float>(i) == distinct_vec[j])
00047 unique = false;
00048 }
00049 }
00050 if (unique == true)
00051 distinct_vec.push_back(mat.at<float>(i));
00052 }
00053 unique_elements = distinct_vec.size();
00054 }
00055 void SubspaceAnalysis::unique_elements(std::vector<int> & vec, int& unique_elements, std::vector<int>& distinct_vec)
00056 {
00057 bool unique = true;
00058 for (int i = 0; i < vec.size(); ++i)
00059 {
00060
00061 if (i != 0)
00062 {
00063 unique = true;
00064 for (int j = 0; j < distinct_vec.size(); j++)
00065 {
00066 if (vec[i] == distinct_vec[j])
00067 unique = false;
00068 }
00069 }
00070 if (unique == true)
00071 distinct_vec.push_back(vec[i]);
00072 }
00073 unique_elements = distinct_vec.size();
00074 }
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245 void SubspaceAnalysis::SSA::calcDataMatMean(cv::Mat& data, cv::Mat& mean_row)
00246 {
00247 for (int i = 0; i < data.rows; ++i)
00248 {
00249 cv::Mat data_row = data.row(i);
00250
00251 cv::add(mean_row, data_row, mean_row);
00252 }
00253 mean_row.convertTo(mean_row, CV_64F, 1.0 / static_cast<double>(data.rows));
00254
00255 }
00256
00257 void SubspaceAnalysis::SSA::decomposeAsymmetricMatrix(cv::Mat& data_mat)
00258 {
00259 EigenvalueDecomposition es(data_mat);
00260 eigenvals = es.eigenvalues();
00261 eigenvals = eigenvals.reshape(1, 1).t();
00262 eigenvecs = es.eigenvectors();
00263 eigenvecs = eigenvecs.t();
00264
00265 }
00266 void SubspaceAnalysis::SSA::decomposeSVD(cv::Mat& data_mat)
00267 {
00268
00269 data_mat.convertTo(data_mat, CV_64F, 1 / sqrt(data_mat.rows));
00270 cv::SVD svd(data_mat.t());
00271 eigenvecs = svd.u;
00272
00273
00274 eigenvecs = eigenvecs.t();
00275
00276 eigenvals = svd.w;
00277
00278 }
00279
00280 void SubspaceAnalysis::SSA::decomposeSymmetricMatrix(cv::Mat& data_mat)
00281 {
00282
00283 cv::eigen(data_mat, eigenvals, eigenvecs);
00284
00285 }
00286
00287
00288
00289
00290 SubspaceAnalysis::PCA2D::PCA2D(std::vector<cv::Mat>& input_data, std::vector<int>& input_labels, int& num_classes, int& ss_dim)
00291 {
00292 SubspaceAnalysis::unique_elements(input_labels, num_classes_, unique_labels_);
00293
00294
00295 cv::Mat mean = cv::Mat::zeros(input_data[0].rows, input_data[0].cols, CV_64FC1);
00296
00297 for (int i = 0; i < input_data.size(); i++)
00298 {
00299
00300 mean += input_data[i];
00301 }
00302
00303 mean /= input_data.size();
00304
00305
00306 cv::Mat P = cv::Mat::zeros(input_data[0].cols, input_data[0].cols, CV_64FC1);
00307
00308 for (int i = 0; i < input_data.size(); i++)
00309 {
00310 cv::Mat temp;
00311 cv::subtract(input_data[i], mean, temp);
00312 cv::mulTransposed(temp, temp, true);
00313 cv::add(temp, P, P);
00314 }
00315
00316 P /= input_data.size();
00317 decomposeSymmetricMatrix(P);
00318 eigenvecs = eigenvecs(cv::Rect(0, 0, input_data[0].cols, ss_dim));
00319 eigenvals = eigenvals(cv::Rect(0, 0, 1, ss_dim)).t();
00320
00321 }
00322 SubspaceAnalysis::LDA2D::LDA2D(std::vector<cv::Mat>& input_data, std::vector<int>& input_labels, int& num_classes, int& ss_dim)
00323 {
00324 SubspaceAnalysis::unique_elements(input_labels, num_classes_, unique_labels_);
00325 mean = cv::Mat::zeros(input_data[0].rows, input_data[0].cols, CV_64FC1);
00326
00327
00328 cv::Mat mean_mat = cv::Mat::zeros(input_data[0].rows, input_data[0].cols, CV_64FC1);
00329 std::vector<cv::Mat> class_means;
00330 std::vector<int> class_sizes;
00331
00332
00333 class_means.resize(num_classes_);
00334 class_sizes.resize(num_classes_);
00335
00336
00337 for (int i = 0; i < num_classes_; i++)
00338 {
00339 class_means[i] = cv::Mat::zeros(input_data[0].rows, input_data[0].cols, CV_64FC1);
00340 class_sizes[i] = 0;
00341 }
00342
00343 for (int i = 0; i < input_data.size(); i++)
00344 {
00345
00346 class_means[input_labels[i]] += input_data[i];
00347 mean_mat += input_data[i];
00348 class_sizes[input_labels[i]]++;
00349 }
00350
00351 mean_mat /= input_data.size();
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368 for (int i = 0; i < num_classes_; i++)
00369 {
00370 class_means[i] /= class_sizes[i];
00371 }
00372
00373 cv::Mat S_intra = cv::Mat::zeros(input_data[0].cols, input_data[0].cols, CV_64FC1);
00374 cv::Mat S_inter = cv::Mat::zeros(input_data[0].cols, input_data[0].cols, CV_64FC1);
00375 int class_index;
00376
00377 for (int i = 0; i < input_data.size(); ++i)
00378 {
00379
00380 class_index = input_labels[i];
00381 cv::Mat tmp;
00382
00383 cv::subtract(input_data[i], class_means[class_index], tmp);
00384 cv::Mat temp;
00385 cv::mulTransposed(input_data[i], temp, true);
00386 cv::add(temp, S_intra, S_intra);
00387 }
00388 for (int c = 0; c < num_classes_; c++)
00389 {
00390 cv::Mat temp;
00391 class_index = unique_labels_[c];
00392 cv::subtract(class_means[c], mean_mat, temp);
00393 cv::mulTransposed(temp, temp, true);
00394 temp = temp * class_sizes[c];
00395 cv::add(S_inter, temp, S_inter);
00396 }
00397
00398 for (int i = 0; i < input_data.size(); i++)
00399 {
00400 }
00401
00402
00403 cv::Mat S_intra_inv = S_intra.inv();
00404
00405 cv::Mat P;
00406 gemm(S_intra_inv, S_inter, 1.0, cv::Mat(), 0.0, P);
00407
00408 decomposeSymmetricMatrix(P);
00409
00410 eigenvecs = eigenvecs(cv::Rect(0, 0, input_data[0].cols, ss_dim));
00411 eigenvals = eigenvals(cv::Rect(0, 0, 1, ss_dim)).t();
00412
00413
00414 }
00415 SubspaceAnalysis::LDA::LDA(cv::Mat& input_data, std::vector<int>& input_labels, int& num_classes, int& ss_dim)
00416 {
00417
00418 SubspaceAnalysis::unique_elements(input_labels, num_classes_, unique_labels_);
00419 cv::Mat data_work = input_data.clone();
00420 mean = cv::Mat::zeros(1, data_work.cols, CV_64FC1);
00421 calcDataMatMean(data_work, mean);
00422
00423
00424
00425
00426 class_mean_arr = cv::Mat::zeros(num_classes_, input_data.cols, CV_64FC1);
00427 calcClassMean(data_work, input_labels, class_mean_arr, num_classes_);
00428
00429 calcProjMatrix(data_work, input_labels);
00430
00431 eigenvecs = eigenvecs(cv::Rect(0, 0, input_data.cols, ss_dim));
00432 eigenvals = eigenvals(cv::Rect(0, 0, 1, ss_dim)).t();
00433
00434
00435 }
00436 void SubspaceAnalysis::LDA::calcClassMean(cv::Mat& data_mat, cv::Mat& label_mat, cv::Mat& class_mean_arr, int& num_classes)
00437 {
00438 std::vector<int> label_vec;
00439 for (int i = 0; i < label_mat.cols; i++)
00440 {
00441 label_vec.push_back((int)label_mat.at<float>(i));
00442 }
00443
00444 calcClassMean(data_mat, label_vec, class_mean_arr, num_classes);
00445
00446 }
00447 void SubspaceAnalysis::LDA::calcClassMean(cv::Mat& data_mat, std::vector<int>& label_vec, cv::Mat& class_mean_arr, int& num_classes)
00448 {
00449
00450 std::vector<int> samples_per_class(num_classes, 0);
00451
00452 int class_index;
00453 for (int i = 0; i < data_mat.rows; i++)
00454 {
00455 cv::Mat data_row = data_mat.row(i);
00456 class_index = label_vec[i];
00457 cv::Mat mean_row = class_mean_arr.row(class_index);
00458
00459 add(mean_row, data_row, mean_row);
00460 samples_per_class[class_index]++;
00461 }
00462
00463 for (int i = 0; i < num_classes; i++)
00464 {
00465 cv::Mat mean_arr_row = class_mean_arr.row(i);
00466 mean_arr_row.convertTo(mean_arr_row, CV_64FC1, 1.0 / static_cast<double>(samples_per_class[i]));
00467 }
00468
00469 }
00470
00471 void SubspaceAnalysis::LDA::calcProjMatrix(cv::Mat& data_arr, std::vector<int>& label_vec)
00472 {
00473
00474 cv::Mat S_intra = cv::Mat::zeros(data_arr.cols, data_arr.cols, CV_64FC1);
00475 cv::Mat S_inter = cv::Mat::zeros(data_arr.cols, data_arr.cols, CV_64FC1);
00476 int class_index;
00477
00478 for (int i = 0; i < data_arr.rows; ++i)
00479 {
00480
00481 class_index = label_vec[i];
00482 cv::Mat data_row = data_arr.row(i);
00483 cv::Mat class_mean_row = class_mean_arr.row(class_index);
00484 cv::subtract(data_row, class_mean_row, data_row);
00485 }
00486 for (int c = 0; c < num_classes_; c++)
00487 {
00488 cv::Mat temp;
00489 class_index = unique_labels_[c];
00490 cv::Mat class_mean_row = class_mean_arr.row(class_index);
00491 cv::subtract(class_mean_row, mean, temp);
00492 cv::mulTransposed(temp, temp, true);
00493 cv::add(S_inter, temp, S_inter);
00494
00495 }
00496
00497 cv::mulTransposed(data_arr, S_intra, true);
00498
00499 cv::Mat S_intra_inv = S_intra.inv();
00500
00501 cv::Mat P;
00502 gemm(S_intra_inv, S_inter, 1.0, cv::Mat(), 0.0, P);
00503
00504 decomposeAsymmetricMatrix(P);
00505
00506 return;
00507
00508 }
00509
00510
00511
00512
00513
00514 SubspaceAnalysis::ILDA::ILDA(cv::Mat& input_data, std::vector<int>& input_labels, int& num_classes, int& ss_dim)
00515 {
00516 SubspaceAnalysis::unique_elements(input_labels, num_classes_, unique_labels_);
00517 cv::Mat data_work = input_data.clone();
00518 mean = cv::Mat::zeros(1, data_work.cols, CV_64FC1);
00519 calcDataMatMean(data_work, mean);
00520 num_classes_ = num_classes;
00521
00522
00523
00524
00525 class_mean_arr = cv::Mat::zeros(num_classes_, input_data.cols, CV_64FC1);
00526 calcClassMean(data_work, input_labels, class_mean_arr, num_classes_);
00527
00528 calcProjMatrix(data_work, input_labels);
00529
00530 eigenvecs = eigenvecs(cv::Rect(0, 0, input_data.cols, ss_dim));
00531 eigenvals = eigenvals(cv::Rect(0, 0, 1, ss_dim)).t();
00532
00533 }
00534 void SubspaceAnalysis::ILDA::calcProjMatrix(cv::Mat& data_arr, std::vector<int>& label_vec)
00535 {
00536
00537 cv::Mat S_intra = cv::Mat::zeros(data_arr.cols, data_arr.cols, CV_64FC1);
00538 cv::Mat S_inter = cv::Mat::zeros(data_arr.cols, data_arr.cols, CV_64FC1);
00539 int class_index;
00540
00541 for (int i = 0; i < data_arr.rows; ++i)
00542 {
00543
00544 class_index = label_vec[i];
00545 cv::Mat data_row = data_arr.row(i);
00546 cv::Mat class_mean_row = class_mean_arr.row(class_index);
00547 cv::subtract(data_row, class_mean_row, data_row);
00548 }
00549 for (int c = 0; c < num_classes_; c++)
00550 {
00551 cv::Mat temp;
00552 class_index = unique_labels_[c];
00553 cv::Mat class_mean_row = class_mean_arr.row(class_index);
00554 cv::subtract(class_mean_row, mean, temp);
00555 cv::mulTransposed(temp, temp, true);
00556 cv::add(S_inter, temp, S_inter);
00557
00558 }
00559
00560 cv::mulTransposed(data_arr, S_intra, true);
00561 cv::Mat S_intra_inv = S_intra.inv();
00562 cv::Mat sigma = cv::Mat(1, num_classes_, CV_64FC1);
00563
00564 for (int i = 0; i < num_classes_; ++i)
00565 {
00566 cv::Mat mu_i = class_mean_arr.row(i);
00567 for (int j = 0; j < num_classes_; ++j)
00568 {
00569 cv::Mat mu_j = class_mean_arr.row(j);
00570
00571 cv::Mat delta_ij = ((mu_j - mu_i) * S_intra_inv * (mu_j - mu_i).t());
00572 for (int k = 0; k < data_arr.rows; k++)
00573 {
00574
00575 }
00576 sigma.at<double>(j) = 1 / (delta_ij.at<double>(0, 0));
00577 }
00578
00579 }
00580
00581 for (int j = 0; j < num_classes_; j++)
00582 {
00583 class_index = label_vec[j];
00584 cv::Mat s_intra_row = S_intra.row(j);
00585 cv::Mat s_inter_row = S_inter.row(j);
00586 double sigma_j = sigma.at<double>(class_index);
00587 s_intra_row *= sigma_j;
00588 s_inter_row *= sigma_j;
00589 }
00590
00591 S_intra_inv = S_intra.inv();
00592
00593 cv::Mat P;
00594 gemm(S_intra_inv, S_inter, 1.0, cv::Mat(), 0.0, P);
00595
00596 decomposeAsymmetricMatrix(P);
00597
00598 return;
00599
00600 }
00601
00602
00603
00604
00605 SubspaceAnalysis::PCA::PCA(cv::Mat& input_data, int& ss_dim)
00606 {
00607
00608 ss_dim_ = ss_dim;
00609 PCA_OpenCv(input_data, ss_dim);
00610 return;
00611 cv::Mat data_work = input_data.clone();
00612 mean = cv::Mat::zeros(1, data_work.cols, CV_64FC1);
00613 calcDataMatMean(data_work, mean);
00614 calcProjMatrix(data_work);
00615
00616 eigenvecs = eigenvecs(cv::Rect(0, 0, input_data.cols, ss_dim));
00617 eigenvals = eigenvals(cv::Rect(0, 0, 1, ss_dim)).t();
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628 }
00629 void SubspaceAnalysis::PCA::PCA_OpenCv(cv::Mat& input_data, int& ss_dim)
00630 {
00631 ss_dim_ = ss_dim;
00632 cv::PCA ocv_pca(input_data, cv::Mat(), CV_PCA_DATA_AS_ROW, ss_dim);
00633
00634 eigenvecs = ocv_pca.eigenvectors.clone();
00635 eigenvals = ocv_pca.eigenvalues.clone();
00636 mean = ocv_pca.mean.reshape(1, 1).clone();
00637
00638
00639 eigenvecs = eigenvecs(cv::Rect(0, 0, input_data.cols, ss_dim));
00640 eigenvals = eigenvals(cv::Rect(0, 0, 1, ss_dim)).t();
00641
00642
00643 }
00644
00645 void SubspaceAnalysis::PCA::calcProjMatrix(cv::Mat& data)
00646 {
00647 cv::Mat data_row;
00648 for (int i = 0; i < data.rows; ++i)
00649 {
00650
00651 data_row = data.row(i);
00652 cv::subtract(data_row, mean, data_row);
00653 }
00654
00655 decomposeSVD(data);
00656 }
00657