/*********************************************************************************************************************************
文件说明:
【1】Windows下【Caffe使用工具】之【计算图像的均值】compute_image_mean的用法
【2】在【数据读取层】的Transform阶段,需要进行减均值操作
【3】均值文件一般需要用原始数据计算得到,在此块,将介绍caffe实用工具中的这一源代码的使用
使用说明:
【用法1】从LEVELDB类型的数据库中求解均值文件:
【1】修改代码:
DEFINE_string(backend, "lmdb","The backend {leveldb, lmdb} containing the images");
将代码:
DEFINE_string(backend, "lmdb","The backend {leveldb, lmdb} containing the images");
改为:
DEFINE_string(backend, "leveldb","The backend {leveldb, lmdb} containing the images");
【2】添加代码:
argc = 3;
argv[1] = "E://caffeInstall2013CUDAVersion//caffe-master//examples//cifar10//cifar10_train_leveldb";
argv[2] = "E://caffeInstall2013CUDAVersion//caffe-master//examples//cifar10//cifar10_mean.binaryproto";
【用法2】从LMDB类型的数据库中求解均值文件:
【1】确保代码:
DEFINE_string(backend, "lmdb","The backend {leveldb, lmdb} containing the images");是这样的
【2】添加代码:
argc = 3;
argv[1] = "E://caffeInstall2013CUDAVersion//caffe-master//examples//cifar10//cifar10_train_lmdb";
argv[2] = "E://caffeInstall2013CUDAVersion//caffe-master//examples//cifar10//cifar10_mean.binaryproto";
【用法3】*bat文件的使用,请参考下面的博客:
http://www.cnblogs.com/LiuSY/p/5765810.html
开发环境:
windows+cuda7.5+cuDnnV5+opencv+caffe1+vs2013
时间地点:
陕西师范大学 文津楼 2017.8.9
作 者:
九 月
**********************************************************************************************************************************/
#include <stdint.h>
#include <algorithm>
#include <string>
#include <utility>
#include <vector>
#include "boost/scoped_ptr.hpp"
#include "gflags/gflags.h"
#include "glog/logging.h"
#include "caffe/proto/caffe.pb.h"
#include "caffe/util/db.hpp"
#include "caffe/util/io.hpp"
using namespace caffe;
using std::max;
using std::pair;
using boost::scoped_ptr;
DEFINE_string(backend, "leveldb","The backend {leveldb, lmdb} containing the images");
int main(int argc, char** argv)
{
::google::InitGoogleLogging(argv[0]);
#ifdef USE_OPENCV
#ifndef GFLAGS_GFLAGS_H_
namespace gflags = google;
#endif
gflags::SetUsageMessage("Compute the mean_image of a set of images given by"
" a leveldb/lmdb\n"
" Usage:\n"
" compute_image_mean [FLAGS] INPUT_DB [OUTPUT_FILE]\n");
argc = 3;
argv[1] = "E://caffeInstall2013CUDAVersion//caffe-master//examples//cifar10//cifar10_train_leveldb";
argv[2] = "E://caffeInstall2013CUDAVersion//caffe-master//examples//cifar10//cifar10_mean.binaryproto";
scoped_ptr<db::DB> db(db::GetDB(FLAGS_backend));
db->Open(argv[1], db::READ);
scoped_ptr<db::Cursor> cursor(db->NewCursor());
BlobProto sum_blob;
int count = 0;
// load first datum
Datum datum;
datum.ParseFromString(cursor->value());
if (DecodeDatumNative(&datum))
{
LOG(INFO) << "Decoding Datum";
}
sum_blob.set_num(1);
sum_blob.set_channels(datum.channels());
sum_blob.set_height(datum.height());
sum_blob.set_width(datum.width());
const int data_size = datum.channels() * datum.height() * datum.width();
int size_in_datum = std::max<int>(datum.data().size(),datum.float_data_size());
for (int i = 0; i < size_in_datum; ++i)
{
sum_blob.add_data(0.);
}
LOG(INFO) << "Starting Iteration";
while (cursor->valid())
{
Datum datum;
datum.ParseFromString(cursor->value());
DecodeDatumNative(&datum);
const std::string& data = datum.data();
size_in_datum = std::max<int>(datum.data().size(),datum.float_data_size());
CHECK_EQ(size_in_datum, data_size) << "Incorrect data field size " <<size_in_datum;
if (data.size() != 0)
{
CHECK_EQ(data.size(), size_in_datum);
for (int i = 0; i < size_in_datum; ++i)
{
sum_blob.set_data(i, sum_blob.data(i) + (uint8_t)data[i]);
}
}
else
{
CHECK_EQ(datum.float_data_size(), size_in_datum);
for (int i = 0; i < size_in_datum; ++i)
{
sum_blob.set_data(i, sum_blob.data(i) + static_cast<float>(datum.float_data(i)));
}
}
++count;
if (count % 10000 == 0)
{
LOG(INFO) << "Processed " << count << " files.";
}
cursor->Next();
}
if (count % 10000 != 0)
{
LOG(INFO) << "Processed " << count << " files.";
}
for (int i = 0; i < sum_blob.data_size(); ++i)
{
sum_blob.set_data(i, sum_blob.data(i) / count);
}
// Write to disk
if (argc == 3)
{
LOG(INFO) << "Write to " << argv[2];
WriteProtoToBinaryFile(sum_blob, argv[2]);
}
const int channels = sum_blob.channels();
const int dim = sum_blob.height() * sum_blob.width();
std::vector<float> mean_values(channels, 0.0);
LOG(INFO) << "Number of channels: " << channels;
for (int c = 0; c < channels; ++c)
{
for (int i = 0; i < dim; ++i)
{
mean_values[c] += sum_blob.data(dim * c + i);
}
LOG(INFO) << "mean_value channel [" << c << "]:" << mean_values[c] / dim;
}
std::system("pause");
#else
LOG(FATAL) << "This tool requires OpenCV; compile with USE_OPENCV.";
#endif // USE_OPENCV
return 0;
}
生成的均值文件如下所示:
1.首先我们使用lmdb数据格式(怎样得到lmdb数据格式,看我的另一篇)求得均值:
新建ComputeImageMean.bat,里面输入:
D:/deeptools/caffe-windows-master/bin/compute_image_mean.exe D:/deeptools/caffe-windows-master/examples/mymnist/train_lmdb D:/deeptools/caffe-windows-master/examples/mymnist/mean.binaryproto
pause
结果:
2.现在我们使用leveldb格式(怎么得到leveldb格式,看我的另一篇)来求得均值
新建ComputeImageMean-leveldb.bat,里面输入:
D:/deeptools/caffe-windows-master/bin/compute_image_mean.exe D:/deeptools/caffe-windows-master/examples/mymnist/trainbackend_leveldb D:/deeptools/caffe-windows-master/examples/mymnist/mean-leveldb.binaryproto --backend=leveldb
pause
我们可以看到 只是最后加了一个 --backend=leveldb!!!!!!!!
结果: