OpenCV dnn模块支持Caffe

    xiaoxiao2022-06-23  33

    #include <opencv2/dnn.hpp> #include <opencv2/imgproc.hpp> #include <opencv2/highgui.hpp> using namespace cv; using namespace cv::dnn; #include <fstream> #include <iostream> #include <cstdlib> using namespace std;

    /* Find best class for the blob (i. e. class with maximal probability) */

    void getMaxClass(dnn::Blob &probBlob, int *classId, double *classProb) { Mat probMat = probBlob.matRefConst().reshape(1, 1); //reshape the blob to 1x1000 matrix Point classNumber; minMaxLoc(probMat, NULL, classProb, NULL, &classNumber); *classId = classNumber.x; } std::vector<String> readClassNames(const char *filename = "synset_words.txt") { std::vector<String> classNames; std::ifstream fp(filename); if (!fp.is_open()) { std::cerr << "File with classes labels not found: " << filename << std::endl; exit(-1); } std::string name; while (!fp.eof()) { std::getline(fp, name); if (name.length()) classNames.push_back(name.substr(name.find(' ') + 1)); } fp.close(); return classNames; } int main(int argc, char **argv) { String modelTxt = "bvlc_googlenet.prototxt"; String modelBin = "bvlc_googlenet.caffemodel"; String imageFile = (argc > 1) ? argv[1] : "space_shuttle.jpg"; Ptr<dnn::Importer> importer; try                                     //Try to import Caffe GoogleNet model { importer = dnn::createCaffeImporter(modelTxt, modelBin); } catch (const cv::Exception &err)        //Importer can throw errors, we will catch them { std::cerr << err.msg << std::endl; } if (!importer) { std::cerr << "Can't load network by using the following files: " << std::endl; std::cerr << "prototxt:   " << modelTxt << std::endl; std::cerr << "caffemodel: " << modelBin << std::endl; std::cerr << "bvlc_googlenet.caffemodel can be downloaded here:" << std::endl; std::cerr << "http://dl.caffe.berkeleyvision.org/bvlc_googlenet.caffemodel" << std::endl; exit(-1); } dnn::Net net; importer->populateNet(net); importer.release();                     //We don't need importer anymore Mat img = imread(imageFile); if (img.empty()) { std::cerr << "Can't read image from the file: " << imageFile << std::endl; exit(-1); } resize(img, img, Size(224, 224));       //GoogLeNet accepts only 224x224 RGB-images dnn::Blob inputBlob = dnn::Blob(img);   //Convert Mat to dnn::Blob image batch net.setBlob(".data", inputBlob);        //set the network input net.forward();                          //compute output dnn::Blob prob = net.getBlob("prob");   //gather output of "prob" layer int classId; double classProb; getMaxClass(prob, &classId, &classProb);//find the best class std::vector<String> classNames = readClassNames(); std::cout << "Best class: #" << classId << " '" << classNames.at(classId) << "'" << std::endl; std::cout << "Probability: " << classProb * 100 << "%" << std::endl; return 0;

    } //main

    这里给出了一个样例,如何使用Opencv的dnn模块进行人脸识别,因为在编译Opencv时似乎没有加上WITH_CUDA,所以导致forward()的传播速度巨慢,但是不影响我们进行实验。

    准备工作

    1、编译好Opencv的contrib库,并没有错误。  2、有用于提取特征的caffemodel文件,网络的prototxt文件。

    思路

    注册人脸->将人脸批量提取特征->多个同一维度的向量->保存在vector

    代码

    网络向前传播的速度非常“感人”,我自己写的caffe深度学习人脸识别就没这个情况。  以下的例子比较简单,可以适当修改,保留核心部分。  头文件:

    #include <opencv2/dnn.hpp> #include <opencv.hpp> #include <string> #include <fstream> #include <iostream> #include <cstdlib> #include <iostream> #include <vector> #include <cassert> #include <cmath> using namespace std; using namespace cv; Mat Facedetect(Mat frame);//一个人脸检测的函数,可以把其封装成这个样子,用Opencv的adaboost分类器也可以 float coefficient(const std::vector<float>& v1, const std::vector<float>& v2);//用于计算两个向量的相似度,下面有说明。

    计算相似度

    float mean(const std::vector<float>& v) {     assert(v.size() != 0);     float ret = 0.0;     for (std::vector<float>::size_type i = 0; i != v.size(); ++i)     {         ret += v[i];     }     return ret / v.size(); } float cov(const std::vector<float>& v1, const std::vector<float>& v2) {     assert(v1.size() == v2.size() && v1.size() > 1);     float ret = 0.0;     float v1a = mean(v1), v2a = mean(v2);     for (std::vector<float>::size_type i = 0; i != v1.size(); ++i)     {         ret += (v1[i] - v1a) * (v2[i] - v2a);     }     return ret / (v1.size() - 1); } // 相关系数 float coefficient(const std::vector<float>& v1, const std::vector<float>& v2) {     assert(v1.size() == v2.size());     return cov(v1, v2) / sqrt(cov(v1, v1) * cov(v2, v2)); }

    提取训练样本特征

    string modelTxt = "VGG_FACE_deploy.prototxt";//prototxt     string modelBin = "VGG_FACE.caffemodel";//model     Ptr<dnn::Importer> importer;     try     {         importer = dnn::createCaffeImporter(modelTxt, modelBin);     }     catch (const cv::Exception &err)     {         cerr << err.msg << endl;     }     if (!importer)     {         cout << "Please Check your caffemodel and prototxt";         exit(0);     }     dnn::Net net;     importer->populateNet(net);     importer.release(); //===============进行训练样本提取=======================可修改==================== //========================五个人,每人一张照片====================================     std::vector<Mat> train;     std::vector<int> train_label;     int train_man = 1, train_num = 1;//训练的人的种类、人的个数     for (train_man = 1; train_man <= 5; train_man++) {         for (train_num = 1; train_num <= 1; train_num++)         {             string train_road = "VGG_train/" + Int_String(train_man) + " (" + Int_String(train_num) + ").jpg";             cv::Mat train_Sample = imread(train_road);             if (!train_Sample.empty())             {                 train.push_back(train_Sample);                 train_label.push_back(train_man);                 cout << "There is train pic!!" << train_man << "" << train_num << endl;             }             else             {                 cout << "There is no pic!!" << train_man << "" << train_num;                 getchar();                 exit(-1);             }         }     }         dnn::Blob train_blob = dnn::Blob(train);         net.setBlob(".data", train_blob);         cout << "Please wait..." << endl;  net.forward();         dnn::Blob prob = net.getBlob("fc8");//提取哪一层         vector <   vector <float>   >   feature_vector;         int train_man_num=0;//第几个人         for (train_man_num = 0; train_man_num <= 4; train_man_num++)         {             vector<float> feature_one;//单个人的feature             int channel = 0;             while (channel < 2622)//看网络相应层的output             {                 feature_one.push_back(*prob.ptrf(train_man_num, channel, 1, 1));                 channel++;                 string train_txt = Int_String(train_man_num) + ".txt";                 ofstream myfile(train_txt, ios::app);  //example.txt是你要输出的文件的名字,这里把向量都分开保存为txt,以便于后面可以直接读取                 myfile << *prob.ptrf(train_man_num, channel, 1, 1) << endl;             }             feature_vector.push_back(feature_one);//把它赋给二维数组             feature_one.clear();         }         cout << "Successful extract!!!" << endl;         train_blob.offset();

    测试样本特征提取  string test_fileroad = "C://wamp//www//pic//" + Int_String(x) + ".jpg";//图片的地方,改成摄像头也可以。             Mat testSample = imread(test_fileroad);             if (testSample.empty())                 cout << "There is no testSample ..." << endl;             else             {                 testSample = Facedetect(testSample);                     vector<Mat> test;                     vector<int> test_label;                     test.push_back(testSample);                     test_label.push_back(0);                     //then                     dnn::Blob test_blob = dnn::Blob(test);//如果用原来的似乎会报错。。。                     net.setBlob(".data", test_blob);                     cout << "extracting features..." << endl;                     net.forward();                     dnn::Blob prob_test = net.getBlob("fc8");                     vector<float> test_feature;//第8层的特征                     int channel = 0;                     while (channel < 2622)                     {                         test_feature.push_back(*prob.ptrf(0, channel, 1, 1));                         channel++;                     }                     cout << "we got it.." << endl; float higher_score = 0;//相似度                     int T_number = 0;                     for (int test_num_vector = 0; test_num_vector <= 4; test_num_vector++)                     {                         float score = coefficient(feature_vector[test_num_vector], test_feature);                         cout << "The coefficient" << test_num_vector << "------------to----------" << score << endl;                         if (score > higher_score)                         {                             higher_score = score;                             T_number = test_num_vector;                         }                     }                     x++;                     imshow("testSample", testSample);                     imshow("trainSample", train[T_number]);//可以直接把和测试样本最相近的一张图亮出来                     waitKey(1);                 }             }

    转载请注明原文地址: https://ju.6miu.com/read-1123506.html

    最新回复(0)