diff --git a/openbr/plugins/cuda/cublaspca.cpp b/openbr/plugins/cuda/cublaspca.cpp new file mode 100644 index 0000000..98121a2 --- /dev/null +++ b/openbr/plugins/cuda/cublaspca.cpp @@ -0,0 +1,344 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright 2016 Colin Heinzmann * + * * + * Licensed under the Apache License, Version 2.0 (the "License"); * + * you may not use this file except in compliance with the License. * + * You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, software * + * distributed under the License is distributed on an "AS IS" BASIS, * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * + * See the License for the specific language governing permissions and * + * limitations under the License. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include +using namespace std; +#include + +#include + +#include + +#include +using namespace cv; + +#include +#include +#include +#include + +#include +#include +#include "cudadefines.hpp" + +namespace br +{ +/*! + * \ingroup transforms + * \brief Projects input into learned Principal Component Analysis subspace using CUDA. Modified from original PCA plugin. + * \author Colin Heinzmann \cite DepthDeluxe + * + * \br_property float keep Options are: [keep < 0 - All eigenvalues are retained, keep == 0 - No PCA is performed and the eigenvectors form an identity matrix, 0 < keep < 1 - Keep is the fraction of the variance to retain, keep >= 1 - keep is the number of leading eigenvectors to retain] Default is 0.95. + * \br_property int drop The number of leading eigen-dimensions to drop. + * \br_property bool whiten Whether or not to perform PCA whitening (i.e., normalize variance of each dimension to unit norm) + */ +class CUBLASPCATransform : public Transform +{ + Q_OBJECT + +protected: + Q_PROPERTY(float keep READ get_keep WRITE set_keep RESET reset_keep STORED false) + Q_PROPERTY(int drop READ get_drop WRITE set_drop RESET reset_drop STORED false) + Q_PROPERTY(bool whiten READ get_whiten WRITE set_whiten RESET reset_whiten STORED false) + + BR_PROPERTY(float, keep, 0.95) + BR_PROPERTY(int, drop, 0) + BR_PROPERTY(bool, whiten, false) + + Eigen::VectorXf mean, eVals; + Eigen::MatrixXf eVecs; + + int originalRows; + + cublasHandle_t cublasHandle; + float* cudaMeanPtr; // holds the "keep" long vector + float* cudaEvPtr; // holds all the eigenvectors + +public: + CUBLASPCATransform() : keep(0.95), drop(0), whiten(false) { + // try to initialize CUBLAS + cublasStatus_t status; + status = cublasCreate(&cublasHandle); + CUBLAS_ERROR_CHECK(status); + } + + ~CUBLASPCATransform() { + // tear down CUBLAS + cublasDestroy(cublasHandle); + } + +private: + double residualReconstructionError(const Template &src) const + { + Template proj; + project(src, proj); + + Eigen::Map srcMap(src.m().ptr(), src.m().rows*src.m().cols); + Eigen::Map projMap(proj.m().ptr(), keep); + + return (srcMap - mean).squaredNorm() - projMap.squaredNorm(); + } + + void train(const TemplateList &cudaTrainingSet) + { + // copy the data back from the graphics card so the training can be done on the CPU + const int instances = cudaTrainingSet.size(); // get the number of training set instances + QList