zoukankan      html  css  js  c++  java
  • Caffe C++API 提取任意一张图片的特征系列二----MemoryData

    介绍一种更加灵活的方法,用MemoryData层输入数据,可以直接用opencv接口读入我们的图片再添加的网络中。 
    第一个问题:仍然是工程建立问题,提示卷积层或其他层没有注册,解决方法与上一篇博客一样。可查看:http://blog.csdn.net/sunshine_in_moon/article/details/50125255 
    第二个问题:网络配置文件的改写,因为使用MemoryData层。

    layers{
      name: "data"
      type: MEMORY_DATA //MemoryData层类型,还有需要注意,MEMORY_DATA别画蛇添足加上引号,否则会报错!
      top: "data"
      top: "label" //最好写上,虽然后面没有用到
      transform_param{
        mirror: false
        crop_size:224
        mean_value:129.1863//三个通道的均值
        mean_value:104.7624
        mean_value:93.5940
      }
      memory_data_param{//以下四个参数与ImageData稍有不同,请注意
        batch_size:1
        channels:3
        height:224
        224
      }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    第三个问题:代码,这段代码写的有点乱,请见谅!

    template <typename Dtype>
    caffe::Net<Dtype>* Net_Init_Load(
        std::string param_file, std::string pretrained_param_file, caffe::Phase phase)
    {
        CheckFile(param_file);//CheckFile 是一个子函数我没有贴上,可以直接删掉这两行
        CheckFile(pretrained_param_file);
    
    
        caffe::Net<Dtype>* net(new caffe::Net<Dtype>(param_file, phase));
    
    
    
        net->CopyTrainedLayersFrom(pretrained_param_file);
        return net;
    }
    
    #define NetF float  //宏定义 很多人包括我自己刚开始看到NetF也很困惑,原来就是float
    
    int main()
    {
        /*
        boost::shared_ptr< Net<float> > feature_net;
        feature_net = Init_net();
    
        cv::Mat src1;
        src1 = cv::imread("test.jpg");
        //cv::imshow("img", src1);
        //cv::waitKey(0);
        //cv::destroyAllWindows();
        //cv::Mat rszimage;
    
        //// The mean file image size is 256x256, need to resize the input image to 256x256
        //cv::resize(src1, rszimage, cv::Size(244, 244));
        std::vector<cv::Mat> patches;
        patches.push_back(src1); // image is a cv::Mat, as I'm using #1416
        std::vector<int> labels; 
        labels.push_back(0);
    
        boost::shared_ptr<  MemoryDataLayer<float> >memory_data_layer;
        memory_data_layer = boost::static_pointer_cast<MemoryDataLayer<float>>(feature_net->layer_by_name("data"));
        /*
        caffe::Datum data;
        caffe::ReadFileToDatum("test.jpg", &data);
        caffe::MemoryDataLayer<float> *m_layer_ = (caffe::MemoryDataLayer<float> *)feature_net->layers()[0].get();
        */
        /*
        memory_data_layer->AddMatVector(patches,labels);
    
    
        feature_net->ForwardPrefilled();
    
        float data1;
        data1 = Read_Feature_data(feature_net, "fc8");
        cout << data1 << endl;
        */
    
    
    
    
        /*从这里开始*/
        cv::Mat src1;
        src1 = cv::imread("test.jpg");
        //cv::Mat rszimages;
    
        //cv::resize(src1, rszimages, cv::Size(224, 224));
        std::vector<cv::Mat> dv = { src1 };//****输入的图片,注意格式,即使只有一张图片也要使用向量格式
        std::vector<int> label = { 0 };//**输入图片的标签(可随便写),也要注意是向量,这是由AddMatVector函数决定的
    
        //caffe::Datum data;
        //caffe::ReadFileToDatum("test.jpg", &data);
    
        caffe::Net<NetF>* _net = Net_Init_Load<NetF>("FACE_deploy.prototxt", 
                                                    "FACE.caffemodel", caffe::TEST);
        caffe::MemoryDataLayer<NetF> *m_layer_ = (caffe::MemoryDataLayer<NetF> *)_net->layers()[0].get();//**定义个内存数据层指针
        m_layer_->AddMatVector(dv, label);//***这两行很重要,是使用MemoryData层必须的,这是把图片和标签,添加到
        //**MemoryData层
    
        /*float loss = 0.0;
        std::vector<caffe::Blob<float>*> results = _net->ForwardPrefilled(&loss);*/
    
        int end_ind = _net->layers().size();
        std::vector<caffe::Blob<NetF>*> input_vec;
    
        clock_t start = clock();
        _net->Forward(input_vec);
        clock_t end = clock();
        double totaltime;
        totaltime = (double)(end - start) / CLOCKS_PER_SEC;
        cout << "
    此程序的运行时间为" << totaltime << "秒!" << endl;
    
    
        boost::shared_ptr<caffe::Blob<NetF>> fc8 = _net->blob_by_name("fc8");
        const NetF* pstart = fc8->cpu_data();// ***这里是重点!重点!重点!,在这里耽误了很长时间。注意这里是个指针
        //**也就是fc8->cpu_data()返回的一般是多维数据(可以看成是个数组),cout<<* pstart<<endl;这样只是打印出一个
        //***数?当然是一个数了,*pstart只代表数组的第一个数,因此想获得所有的数据必须用循环!
        std::cout << "It is right !!
    ";
        //std::cout << m_layer_->width() << std::endl;
        //std::cout << pstart << endl;
        //std::cout << fc8->cpu_data() << endl;
        std::vector<double> V1;
        for (int i = 0; i < 2622; i++)//**必须用循环打印
        {
            std::cout << *pstart << endl;
            V1.push_back(*pstart);
            pstart++;
        }
        //std::cout << *pstart << endl;
        //std::cout << *(pstart++) << endl;
        cout << "
    此程序的运行时间为" << totaltime << "秒!" << endl;
        return 0;
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111

    重点内容已经在注释上标明(前面加了**),希望这些对你有帮助! 
    写的比较匆忙,以后如有新的体会,会及时更新!

  • 相关阅读:
    Git 总结
    .net报错大全
    对于堆和栈的理解
    html 局部打印
    c#面试问题总结
    算法题总结
    h5-plus.webview
    堆和栈,引用类型,值类型,指令,指针
    .NET framework具体解释
    前端之间的url 传值
  • 原文地址:https://www.cnblogs.com/mtcnn/p/9410030.html
Copyright © 2011-2022 走看看