怎样把caffe提取的特征格式mdb转换成mat和txt

我是用caffe提取每一层的特征,但是是mdb格式的,不能用matlab读取,忘答疑
已邀请:

薛云峰 - 工程问题找我

赞同来自: xinmiao

可以自己写个matlab的扩展,使用memorydatalayer进行输入,然后将得到的blob内存数据结合matlab的c接口转换成matlab的矩阵。blob的读取百度可以找到
下面是读取pool5的代码示例:
boost::shared_ptr<caffe::Blob<NetF>> pool5 = _net->blob_by_name("pool5");
    cv::Mat Pool5FeatureMat(pool5->num(), pool5->width()*pool5->height()*pool5->channels(), CV_32F);
    int channel_step = pool5->height()*pool5->width();
    for (size_t n = 0; n < pool5->num(); n++)
    {
        for (size_t c = 0; c < pool5->channels(); c++)
        {
            
            for (size_t h = 0; h < pool5->height(); h++)
            {
                for (size_t w = 0; w < pool5->width(); w++)
                {
                    float value = pool5->data_at(n, c, h, w);
                }
                
            }
        }
    }
然后我们使用matlab的接口就可以自己进行matlab的矩阵转换了,如果是单张图片num一层的循环可以去掉。
下面我给出c++将数组转成matlab的矩阵的代码:
#include <iostream.h>  
#include "xMatrix.h"  
#include "MatlabEngine.h"  
void main()  
{  
    printf("matlab&c++ /n      /  
        visualsan@yahoo.cn  NUAA/  
        2011/n------------------------/n");  
    //matlab 引擎  
    CMatlabEngine  g;  
    //打开  
    cout<<"Open Matlab Engine..../n";  
    if( g.OpenEngine() )  
    {  
        //1.从matlab中获取一个5X5的随机矩阵  
        char tmp[200];  
          
        //准备矩阵5X5  
        double  mr[]=  
        {  
            1.2,4.4,5.5,6.6,7.7,  
            1.12,1.44,15.5,1.66,1.77,  
            21.2,2.44,2.55,2.66,2.77,  
            3.12,3.44,3.55,3.66,3.77,  
            4.12,4.44,4.55,4.66,4.77  
        };  
        //转换为matlab格式,按列存储  
        xMatrixDouble::C2Mat(mr,5,5,mr);  
        xMatrixDouble  xd(5,5,mr);  
        //写入矩阵  
        g.PutVar("text_matrix",xd.GetArray());  
        //计算矩阵的逆矩阵  
        g.EvalString("text_matrix_inv=inv(text_matrix);");  
        mxWrap  text_matrix;  
        mxWrap  text_matrix_inv;  
        //获取名称为text_matrix的矩阵  
        g.GetVar("text_matrix",&text_matrix);  
        xMatrixDouble *pd=(xMatrixDouble*)text_matrix.GetArrayInterface();  
        //获取名称为text_matrix_inv的逆矩阵  
        g.GetVar("text_matrix_inv",&text_matrix_inv);  
        xMatrixDouble *pd_inv=(xMatrixDouble*)text_matrix_inv.GetArrayInterface();  
        //打印矩阵  
        cout<<"原矩阵:/n";  
        for (int i=0;i<xd.GetR();i++)  
        {  
            for (int j=0;j<xd.GetC();j++)  
            {  
                cout<<xd.GetRealAt(i,j)<<" ";  
            }  
            cout<<endl;  
        }  
        cout<<"从matlab中读取的矩阵:/n";  
        for ( i=0;i<pd->GetR();i++)  
        {  
            for (int j=0;j<pd->GetC();j++)  
            {  
                cout<<pd->GetRealAt(i,j)<<" ";  
            }  
            cout<<endl;  
        }  
        cout<<"从matlab中读取的逆矩阵:/n";  
        for ( i=0;i<pd_inv->GetR();i++)  
        {  
            for (int j=0;j<pd_inv->GetC();j++)  
            {  
                cout<<pd_inv->GetRealAt(i,j)<<" ";  
            }  
            cout<<endl;  
        }  
  
        //关闭引擎  
        g.CloseEngine();  
    }  
  
      
}  
顺便把c++读取matlab矩阵的代码也贴出来吧
#include <iostream.h>  
#include "xMatrix.h"  
#include "MatlabEngine.h"  
void main()  
{  
    printf("matlab&c++ /n      /  
        visualsan@yahoo.cn  NUAA/  
        2011/n------------------------/n");  
    //matlab 引擎  
    CMatlabEngine  g;  
    //打开  
    cout<<"Open Matlab Engine..../n";  
    if( g.OpenEngine() )  
    {  
        //1.从matlab中获取一个5X5的随机矩阵  
        char tmp[200];  
        //调用rand生成随机矩阵  
        strcpy(tmp,"rang_natrix=rand(5);");  
        g.EvalString(tmp);  
        mxWrap  rang_natrix;  
        //获取名称为rang_natrix的矩阵  
        g.GetVar("rang_natrix",&rang_natrix);  
        xMatrixDouble *pd=(xMatrixDouble*)rang_natrix.GetArrayInterface();  
        //打印矩阵  
        for (int i=0;i<pd->GetR();i++)  
        {  
            for (int j=0;j<pd->GetC();j++)  
            {  
                cout<<pd->GetRealAt(i,j)<<" ";  
            }  
            cout<<endl;  
        }  
        //关闭引擎  
        g.CloseEngine();  
    }      
}
这样基本你需要的操作就都有了。

李扬 - 密码六个一

赞同来自: caffe

用 caffe 的 python 接口提取和保存特征比较方便,例如:
features = net.blobs['conv5'].data  # 提取卷积层 5 的特征
np.savetxt('conv5_feature.txt', features) # 将特征存储到本文文件中
 
np.savetxt 的用法参看 这里

attitude

赞同来自:

python 接口 lmdb2mat.py:
 
import lmdb
import feat_helper_pb2
import numpy as np
import scipy.io as sio
import time

def main(argv):
    lmdb_name = sys.argv[1]
    print "%s" % sys.argv[1]
    batch_num = int(sys.argv[2]);
    batch_size = int(sys.argv[3]);
    window_num = batch_num*batch_size;

    start = time.time()
    if 'db' not in locals().keys():
        db = lmdb.open(lmdb_name)
        txn= db.begin()
        cursor = txn.cursor()
        cursor.iternext()
        datum = feat_helper_pb2.Datum()

        keys =
        values =
        for key, value in enumerate( cursor.iternext_nodup()):
            keys.append(key)
            values.append(cursor.value())

    ft = np.zeros((window_num, int(sys.argv[4])))
    for im_idx in range(window_num):
        datum.ParseFromString(values[im_idx])
        ft[im_idx, :] = datum.float_data

    print 'time 1: %f' %(time.time() - start)
    sio.savemat(sys.argv[5], {'feats':ft})
    print 'time 2: %f' %(time.time() - start)
    print 'done!'

if __name__ == '__main__':
    import sys
    main(sys.argv)
 
测试脚本:
 
#!/usr/bin/env sh
LMDB=./examples/_temp/features # lmdb文件路径
BATCHNUM=10
BATCHSIZE=10
# DIM=290400 # feature长度,conv1
# DIM=43264 # conv5
DIM=4096
OUT=./examples/_temp/badfea2.mat #mat文件保存路径
python ./lmdb2mat.py $LMDB $BATCHNUM $BATCHSIZE $DIM $OUT
 

要回复问题请先登录注册