C++ 读取 .mat 文件


#define CPU_ONLY
#include<vector>
#include<iostream>
#include<caffe/caffe.hpp>
#include<opencv2/opencv.hpp>
#include "caffe_reg.h"
#include<mat.h>

using namespace caffe;
using namespace std;
using namespace cv;

Mat read_mat_file(string file_path, int cross_id,bool isShow)
{
    MATFile *mean_pmat = NULL; // .mat file for mean_file
    mxArray *mean_var_cell = NULL; // mean variable in .mat file

    MATFile *std_pmat = NULL;
    mxArray *std_var_cell = NULL;

    const char ** var_names;// variable names in .mat file
    int nvars;// the number of variables in .mat file
              // read .mat file 
    mean_pmat = matOpen(file_path.c_str(), "r");
    if (mean_pmat == NULL)
    {
        cout << "cannot open *.mat file!" << endl;
        exit(-1);
    }
    // read the varaibles in .mat file 
    var_names = (const char **)matGetDir(mean_pmat, &nvars);
    if (var_names == NULL)
    {
        cout << "The .mat file contarin 0 variable, please perform checking!" << endl;
        exit(-1);
    }
    // output the number of variable in .mat file
    cout << "The numboer of variable in.mat file is : " << nvars << endl;
    cout << " The name for all variables:";
    for (int i = 0; i < nvars; i++) cout << string(var_names[i]) << endl;

    // get the "mean_file_cross" ( a cell) variable from .mat file
    // because we only have one variable in .mat file , so the index of var_names is set as 0
    mean_var_cell = matGetVariable(mean_pmat, var_names[0]);
    // get the size of mean_var_cell: M: rows, N :cols
    int mean_cell_M = (int)mxGetM(mean_var_cell);
    int mean_cell_N = (int)mxGetN(mean_var_cell);

    //int cross_id = 1; // the cross_id for cross validation experiments
                      // mxGetCell(cell_name,count) , "count" is a accumuative number , column as main direction
                      // The above statement should be further checked.

    mxArray * mean_file = mxGetCell(mean_var_cell, cross_id - 1); // start from 0

    cout << " The dimension of mean_file: " << (int)mxGetNumberOfDimensions(mean_file) << endl;
    double *data = (double*)mxGetData(mean_file);// get data from mxArray file
                                                 // mean_file is color image ,so mxGetM, mxGetN  is instead by mxGetDimensios,
    const size_t * dims = mxGetDimensions(mean_file);
    int M = dims[0];
    int N = dims[1];
    int C = dims[2];
    double *ptr_data = (double*)mxGetPr(mean_file);

    cout << "The shape of mean_file: " << "(" << M << "," << N << "," << C << ")" << endl;

    Mat mean_file_mat;
    if (mxGetNumberOfDimensions(mean_file) == 3)
    {
        mean_file_mat.create(M, N, CV_8UC3);
    }
    else
    {
        mean_file_mat.create(M, N, CV_8UC1);
    }

    size_t subs[3];

    // note that:  row,cols,c
    for (int i = 0; i < M; i++)
    {
        subs[0] = i;
        for (int j = 0; j < N; j++)
        {
            subs[1] = j;
            for (int k = 0; k < C; k++)
            {
                subs[2] = k;
                int index = mxCalcSingleSubscript(mean_file, 3, subs);
                mean_file_mat.at<Vec3b>(subs[0], subs[1])[k] = ptr_data[index];

            }

        }
    }
    // matlab: RGB  opencv: BGR 
    Mat mean_file_img;
    cvtColor(mean_file_mat, mean_file_img, CV_RGB2BGR);
    // show for debug
    if (isShow)
    {
        imshow(file_path, mean_file_img);
        waitKey(0);
    }

    return mean_file_img;
}
// 共享内存,仅用来演示
void check_warp_op()
{   // change the values in p-pointer, the values in mat will also changes
    // They share the same memory.
    float * p = new float[10];
    cout << "before warp: " << endl;
    for (int i = 0; i < 10; i++)
    {
        p[i] = i;
        cout << p[i] << " ";
    }
    cout << endl;
    Mat wap_mat(1, 10, CV_32FC1, p);

    wap_mat.at<float>(0, 1) = 10;
    wap_mat.at<float>(0, 2) = 10;
    wap_mat.at<float>(0, 3) = 10;

    cout << "mat: " << endl;
    cout << wap_mat << endl;

    cout << "after warp: " << endl;
    for (int i = 0; i < 10; i++)
    {
        cout << p[i] << " ";
    }
    cout << endl;


}
/* Return the indices of the top N values of vector v. */
// Argmax function and Paricompare(weici) are copied from caffe example
static bool PairCompare(const std::pair<float, int>& lhs,
    const std::pair<float, int>& rhs) {
    return lhs.first > rhs.first;
}
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], static_cast<int>(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;
}


int main(void)
{
    // for test
    string deploy_proto = "ZOO_VGG16/deploy.prototxt";
    string pre_trained_weight = "ZOO_VGG16/vgg__iter_10000.caffemodel";
    Net<float> * net = new Net<float>(deploy_proto, caffe::Phase::TEST, 0);

    net->CopyTrainedLayersFrom(pre_trained_weight);


    cout << "number of input and output:";
    cout << net->num_inputs() << " " << net->num_outputs() << endl;

    // mean_file 
    // std_file 

    string lfw_data_path = "E:/xlh/eclipse_workplace/hello_world/data/lfw/";
    string mean_file_path = lfw_data_path + "mean_file_cross224_10fold.mat";
    string std_file_path = lfw_data_path + "std_file_cross224_10fold.mat";
    string one_img = lfw_data_path + "/imgs224/Aaron_Eckhart_0001.jpg";
    int cross_id = 1;
    Mat mean_file = read_mat_file(mean_file_path, cross_id, false);
    Mat std_file = read_mat_file(std_file_path, cross_id, false);
    Mat input_img = imread(one_img);

    // only for CPU
    Caffe::set_mode(Caffe::CPU);
    Mat norm_img; //H W C(brg)
    cv::subtract(input_img, mean_file, norm_img);
    cv::divide(norm_img, std_file, norm_img);
    //
    bool isShow = false;
    // all the values are very small, so is black
    if (isShow)
    {
        Mat show_img;
        norm_img.convertTo(show_img, CV_8UC3);
        imshow("normalize", show_img);
        waitKey(0);
    }
    //
    Blob<float> * input_layer = net->input_blobs()[0];
    // or Blob<float> * input_layer = net->blobs["data"];
    int num_channels = input_layer->channels();
    cout << "channels: " << num_channels << endl;
    int npose = 5; // for lfw dataset
    Blob<float> *output_layer = net->output_blobs()[0];
    cout << "label size: " << npose << "; num_channels of output: " << output_layer->channels() << endl;

    //check_warp_op(); a faster method ,dont need copy
    // for details, please refer to classification.cpp in caffe

    cout << "input_layer.shape: ";
    for (int i = 0; i < input_layer->shape().size(); i++)
    {
        cout << input_layer->shape()[i] << " ";
    }
    cout << endl;

    // an idiot method
    // input_blob.shape: [1,3,224,224]; nsample *  channels * height * width
    // input_blob.shape: [3,224,224];
    float * data = input_layer->mutable_cpu_data();
    int nrows = input_layer->shape()[2];
    int ncols = input_layer->shape()[3];
    int nchannels = input_layer->shape()[1];
    int num = 0;
    float *p = data;
    for (int i = 0; i < nchannels; i++)
    {
        for (int j = 0; j < nrows; j++)
        {
            for (int k = 0; k < ncols; k++)
            {

                p[num] = norm_img.at<Vec3b>(j, k)[i];
                num += 1;
            }
        }

    }

    net->Forward();
    //
    const float* begin = output_layer->cpu_data();
    const float* end = begin + output_layer->channels();

    vector<float> output(begin, end);

    cout << "the probabilites for each class: ";
    for (int i = 0; i < output.size(); i++)
    {
        cout << output[i] << " ";
    }
    cout << endl;

    vector<int> class_id = Argmax(output, npose);

    // left profile, left ,front ,right ,right profile
    cout << "predict label is : " << class_id[0] -2 << endl; // change from[0,4] to [-2,2]

    // free memory
    delete(net);
}

参考文献:
1. http://blog.csdn.net/jnulzl/article/details/49623121
2. http://blog.csdn.net/shaoxiaohu1/article/details/8269690

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值