std::vector<std::vector<cv::Point2f> > OutlierDetector::fitSubspace(const std::vector<std::vector<cv::Point2f> > &trajectories, std::vector<cv::Point2f> &outlier_points, int num_motions, double sigma) { bool print = false; int subspace_dimensions = trajectories[0].size() * 2; // n int num_trajectories = trajectories.size(); // each column in data represents one trajectory // even rows are x coordinates, odd rows are y coordinates Eigen::MatrixXf data(subspace_dimensions, num_trajectories); if (print) std::cout << "fill matrix " << std::endl; fillMatrix(trajectories, data); if (print) std::cout << "mean subtract " << std::endl; meanSubtract(data); int num_sample_points = 4 * num_motions; // d int num_iterations = 50; Eigen::VectorXf final_residual; std::vector<int> final_columns; int max_points = 0; if (print) std::cout << " start iterations " << std::endl; for (int i = 0; i < num_iterations; i++) { Eigen::MatrixXf subset(subspace_dimensions, num_sample_points); if (print) std::cout << "file subset " << std::endl; std::vector<int> column_indices; column_indices = fillSubset(data, subset, num_sample_points); if (print) std::cout << "svd calculation " << std::endl; // Eigen::JacobiSVD<Eigen::MatrixXf> svd(subset, Eigen::ComputeFullU | Eigen::ComputeFullV); Eigen::JacobiSVD<Eigen::MatrixXf, Eigen::FullPivHouseholderQRPreconditioner> svd(subset, Eigen::ComputeFullU | Eigen::ComputeFullV); if (print) std::cout << "init Pnd " << std::endl; Eigen::MatrixXf Pnd = Eigen::MatrixXf::Zero(subspace_dimensions, subspace_dimensions); //std::cout << "U" << std::endl; //std::cout << svd.matrixU() << std::endl; //std::cout << svd.singularValues() << std::endl; if (print) std::cout << "calc M " << std::endl; for (int idx = 0; idx < num_sample_points; idx++) { Eigen::VectorXf u = svd.matrixU().col(idx); Eigen::MatrixXf M = u*u.transpose(); Pnd = Pnd + M; } if (print) std::cout << "calc Pnd " << std::endl; Pnd = Eigen::MatrixXf::Identity(subspace_dimensions, subspace_dimensions) - Pnd; Eigen::MatrixXf data_T = data.transpose(); if (print) std::cout << "calc residual " << std::endl; Eigen::VectorXf residual = (data_T * (Pnd * data)).diagonal(); if (print) std::cout << "residual : " << std::endl; if (print) std::cout << residual << std::endl; residual = residual.cwiseAbs(); int num_points = 0; for (int idx = 0; idx < residual.size(); idx++) { if (print) std::cout << "threshold " << (subspace_dimensions - num_sample_points) * sigma * sigma << std::endl; if (residual(idx) < (subspace_dimensions - num_sample_points) * sigma * sigma) { if (print) std::cout << "adding " << std::endl; num_points++; } } if (num_points > max_points) { if (print) std::cout << num_points << " to " << max_points << std::endl; if (print) std::cout << "copy residual" << residual << std::endl; max_points = num_points; final_residual = residual; final_columns = column_indices; if (print) std::cout << "copy final residual " << final_residual << std::endl; } } if (print) std::cout << "final residual " << std::endl; if (print) std::cout << final_residual << std::endl; double residual_threshold = 0.2; if (subspace_dimensions - num_sample_points < 11 && subspace_dimensions - num_sample_points > 0) { residual_threshold = sigma * sigma * chi_square_table.at(0).at(subspace_dimensions - num_sample_points); std::cout << "residual threshold: " << residual_threshold << std::endl; } for (int idx = 0; idx < final_residual.size(); idx++) { if (final_residual(idx) > residual_threshold) { outlier_points.push_back(trajectories.at(idx).at(trajectories.at(idx).size() - 2)); } } std::vector<std::vector<cv::Point2f> > trajectory_subspace_vectors; for (int i = 0; i < final_columns.size(); i++) { trajectory_subspace_vectors.push_back(trajectories.at(final_columns.at(i))); } return trajectory_subspace_vectors; }