LightCNN C++接口抽取人脸特征

来源:互联网 发布:手机mysql服务器 编辑:程序博客网 时间:2024/06/05 06:32
#include <caffe/caffe.hpp>#ifdef USE_OPENCV#include <opencv2/core/core.hpp>#include <opencv2/highgui/highgui.hpp>#include <opencv2/imgproc/imgproc.hpp>#endif  // USE_OPENCV#include <algorithm>#include <iosfwd>#include <memory>#include <string>#include <utility>#include <vector>#include<caffe\data_transformer.hpp>using namespace caffe;  // NOLINT(build/namespaces)using namespace cv;/* Pair (label, confidence) representing a prediction. */typedef std::pair<string, float> Prediction;class Classifier {public:    Classifier(const string& model_file,        const string& trained_file,        const string& label_file);    std::vector<float> Classify(const cv::Mat& img, int N = 5);    std::vector<float> Predict(cv::Mat img);    void OpenCV2Blob(const std::vector<cv::Mat>& imgs);private:    void WrapInputLayer(std::vector<cv::Mat>* input_channels);    void Preprocess(const cv::Mat& img,        std::vector<cv::Mat>* input_channels);private:    shared_ptr<Net<float> > net_;    cv::Size input_geometry_;    int num_channels_;    cv::Mat mean_;    std::vector<string> labels_;};Classifier::Classifier(const string& model_file,    const string& trained_file,    const string& label_file) {    Caffe::set_mode(Caffe::CPU);    /* Load the network. */    net_.reset(new Net<float>(model_file, TEST));    net_->CopyTrainedLayersFrom(trained_file);    CHECK_EQ(net_->num_inputs(), 1) << "Network should have exactly one input.";    CHECK_EQ(net_->num_outputs(), 1) << "Network should have exactly one output.";    Blob<float>* input_layer = net_->input_blobs()[0];    num_channels_ = input_layer->channels();    CHECK(num_channels_ == 3 || num_channels_ == 1)        << "Input layer should have 1 or 3 channels.";    input_geometry_ = cv::Size(input_layer->width(), input_layer->height());    /* Load the binaryproto mean file. */    //SetMean(mean_file);    /* Load labels. */    std::ifstream labels(label_file.c_str());    CHECK(labels) << "Unable to open labels file " << label_file;    string line;    while (std::getline(labels, line))        labels_.push_back(string(line));    Blob<float>* output_layer = net_->output_blobs()[0];    /*CHECK_EQ(labels_.size(), output_layer->channels())        << "Number of labels is different from the output layer dimension.";*/}static bool PairCompare(const std::pair<float, int>& lhs,    const std::pair<float, int>& rhs) {    return lhs.first > rhs.first;}/* Return the indices of the top N values of vector v. */static std::vector<int> Argmax(const std::vector<float>& v, int N) {    std::vector<std::pair<float, int> > pairs;    for (size_t i = 0; i < v.size(); ++i)        pairs.push_back(std::make_pair(v[i], i));    std::partial_sort(pairs.begin(), pairs.begin() + N, pairs.end(), PairCompare);    std::vector<int> result;    for (int i = 0; i < N; ++i)        result.push_back(pairs[i].second);    return result;}/* Return the top N predictions. */std::vector<float> Classifier::Classify(const cv::Mat& img, int N) {    std::vector<float> output = Predict(img);    return output;    //N = std::min<int>(labels_.size(), N);    //std::vector<int> maxN = Argmax(output, N);    //std::vector<Prediction> predictions;    /*for (int i = 0; i < N; ++i) {        int idx = maxN[i];        predictions.push_back(std::make_pair(labels_[idx], output[idx]));    }    return predictions;*/}/* Load the mean file in binaryproto format. */std::vector<float> Classifier::Predict(cv::Mat img) {    Blob<float>* input_layer = net_->input_blobs()[0];    input_layer->Reshape(1, num_channels_,        input_geometry_.height, input_geometry_.width);    /* Forward dimension change to all layers. */    net_->Reshape();    std::vector<cv::Mat> input_channels;    WrapInputLayer(&input_channels);    Preprocess(img, &input_channels);    net_->Forward();    /* Copy the output layer to a std::vector */    shared_ptr<caffe::Blob<float>> out = net_->blob_by_name("fc1");    const float* begin = out->cpu_data();    const float* end = begin + out->channels();    //  //return std::vector<float>(begin, end);    //Blob<float>* output_layer = net_->output_blobs()[0];    //const float* begin = output_layer->cpu_data();    //const float* end = begin + output_layer->channels();    //return std::vector<float>(begin, end);    return std::vector<float>(begin, end);}/* Wrap the input layer of the network in separate cv::Mat objects* (one per channel). This way we save one memcpy operation and we* don't need to rely on cudaMemcpy2D. The last preprocessing* operation will write the separate channels directly to the input* layer. */void Classifier::WrapInputLayer(std::vector<cv::Mat>* input_channels) {    Blob<float>* input_layer = net_->input_blobs()[0];    int width = input_layer->width();    int height = input_layer->height();    float* input_data = input_layer->mutable_cpu_data();    for (int i = 0; i < input_layer->channels(); ++i) {        cv::Mat channel(height, width, CV_32FC1, input_data);        input_channels->push_back(channel);        input_data += width * height;    }}void Classifier::Preprocess(const cv::Mat& img,    std::vector<cv::Mat>* input_channels) {    /* Convert the input image to the input image format of the network. */    cv::Mat sample;    if (img.channels() == 3 && num_channels_ == 1)        cv::cvtColor(img, sample, cv::COLOR_BGR2GRAY);    /*if (img.channels() == 3 && num_channels_ ==3)        cv::cvtColor(img, sample, cv::COLOR_BGR2RGB);*/    else if (img.channels() == 4 && num_channels_ == 1)        cv::cvtColor(img, sample, cv::COLOR_BGRA2GRAY);    else if (img.channels() == 4 && num_channels_ == 3)        cv::cvtColor(img, sample, cv::COLOR_BGRA2BGR);    else if (img.channels() == 1 && num_channels_ == 3)        cv::cvtColor(img, sample, cv::COLOR_GRAY2BGR);    else        sample = img;    cv::imshow("sample", sample);    cv::waitKey(0);    cv::Mat sample_resized;    if (sample.size() != input_geometry_)        cv::resize(sample, sample_resized, input_geometry_);    else        sample_resized = sample;    cv::Mat sample_float;    if (num_channels_ == 3)        sample_resized.convertTo(sample_float, CV_32FC3);    else        sample_resized.convertTo(sample_float, CV_32FC1);        //sample_float = sample_resized / 255.0;    //cv::Mat sample_normalized;    //cv::subtract(sample_float, mean_, sample_normalized);    /* This operation will write the separate BGR planes directly to the    * input layer of the network because it is wrapped by the cv::Mat    * objects in input_channels. */    sample_float = sample_float / 255.0;    cv::split(sample_float, *input_channels);    CHECK(reinterpret_cast<float*>(input_channels->at(0).data)        == net_->input_blobs()[0]->cpu_data())        << "Input channels are not wrapping the input layer of the network.";}float simd_dot(const float* x, const float* y, const long& len) {    float inner_prod = 0.0f;    __m128 X, Y; // 128-bit values    __m128 acc = _mm_setzero_ps(); // set to (0, 0, 0, 0)    float temp[4];    long i;    for (i = 0; i + 4 < len; i += 4) {        X = _mm_loadu_ps(x + i); // load chunk of 4 floats        Y = _mm_loadu_ps(y + i);        acc = _mm_add_ps(acc, _mm_mul_ps(X, Y));    }    _mm_storeu_ps(&temp[0], acc); // store acc into an array    inner_prod = temp[0] + temp[1] + temp[2] + temp[3];    // add the remaining values    for (; i < len; ++i) {        inner_prod += x[i] * y[i];    }    return inner_prod;}void matrix_procuct(const float* A, const float* B, float* C, const int n,    const int m, const int k, bool ta, bool tb) {#ifdef _BLAS    arma::fmat mA = ta ? arma::fmat(A, k, n).t() : arma::fmat(A, n, k);    arma::fmat mB = tb ? arma::fmat(B, m, k).t() : arma::fmat(B, k, m);    arma::fmat mC(C, n, m, false);    mC = mA * mB;#else    const float* x = B;    for (int i = 0, idx = 0; i < m; ++i) {        const float* y = A;        for (int j = 0; j < n; ++j, ++idx) {            C[idx] = simd_dot(x, y, k);            y += k;        }        x += k;    }#endif}float CalcSimilarity(const float* fc1,    const float* fc2,    long dim) {    return simd_dot(fc1, fc2, dim)        / (sqrt(simd_dot(fc1, fc1, dim))        * sqrt(simd_dot(fc2, fc2, dim)));}int main(){    //const string  trained_file = "F:/caffe-master/sphereface-master/test/code/sphereface_model.caffemodel";    //const string  model_file = "F:/caffe-master/sphereface-master/test/code/sphereface_deploy.prototxt";    const string label_file = "F:/caffe-master/caffe_ilsvrc12/det_synset_words.txt";    /*const string  trained_file = "F:/caffe-master/vgg_face_caffe/vgg_face_caffe/VGG_FACE.caffemodel";    const string  model_file =   "F:/caffe-master/vgg_face_caffe/vgg_face_caffe/VGG_FACE_deploy.prototxt";*/    const string  trained_file = "F:/caffe-master/LightCNN/light_cnn_small.caffemodel";    const string  model_file = "F:/caffe-master/LightCNN/light_cnn_small.prototxt";     Classifier classifier(model_file, trained_file, label_file);    //Mat face_img = cv::imread("F:/caffe-master/vgg_face_caffe/vgg_face_caffe/ak.png");    Mat face_img = cv::imread("F:/caffe-master/LightCNN/17.jpg");    std::vector<float>  output1 = classifier.Classify(face_img);    face_img = cv::imread("F:/caffe-master/LightCNN/16.jpg");    std::vector<float>  output2 = classifier.Classify(face_img);    float* out1 = new float[256];    float* out2 = new float[256];    for (int i = 0; i < output1.size();i++){        out1[i] = output1[i];        out2[i] = output2[i];    }    float sim = CalcSimilarity(out1, out2,256);    std::cout << sim << std::endl;    fstream out ("F:/caffe-master/LightCNN/light_c_1.txt", ios::out);    fstream outP("F:/caffe-master/LightCNN/light_c_2.txt", ios::out);    for (int i = 0; i < output1.size(); i++){        out << output1[i] << std::endl;        //out2 << output2[i] << std::endl;    }    for (int i = 0; i < output1.size(); i++){        outP << output2[i] << std::endl;        //out2 << output2[i] << std::endl;    }}
原创粉丝点击