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; }}
阅读全文
0 0
- LightCNN C++接口抽取人脸特征
- 基于PCA的人脸特征抽取
- SphereFace python抽取人脸特征
- VGGFace python 抽取人脸特征
- 特征选择与特征抽取
- 特征抽取与特征选择
- 特征抽取与特征选择
- 特征提升之特征抽取
- 特征抽取概述
- 模式特征抽取研究进展
- pca 特征抽取
- 从文本抽取特征
- pca 特征抽取
- 图像局部特征抽取
- Caffe抽取图像特征
- caffe -- Python特征抽取
- 特征抽取-信息增益
- 用C3D抽取特征
- POJ 3258.River Hopscotch
- Go日记——手写一个资源池
- 51nod 1195 斐波那契数列的循环节【斐波那契数列&&二次剩余&&欧拉判定准则】
- java中使用Jedis操作Redis实例
- HDU P1004 Let the Balloon Rise
- LightCNN C++接口抽取人脸特征
- Spark Metrics配置详解
- 【拜小白opencv】44-灰度直方图(一维直方图)calcHist()函数、minMaxLoc()函数、normalize()函数
- faster-rcnn tensorflow windows demo运行
- Insertion_sort
- 复习三:java基础知识点
- 《看透springMVC源码》之Container分析
- 查看APK的签名的方法,和应用商店更改签名导致第三方无法登录问题
- 这5步让我们职场的2018顺风顺水