【Caffe代码解析】compute_image_mean
功能:
计算训练数据库的平均图像。
由于平均归一化训练图像会对结果有提升,所以Caffe里面,提供了一个可选项。
用法:
compute_image_mean [FLAGS] INPUT_DB [OUTPUT_FILE]\n”)
參数:INPUT_DB: 数据库
參数(可选):OUTPUT_FILE: 输出文件名称,不提供的话,不保存平均图像blob
实现方法:
数据源:求平均图像的方法是直接从数据库(LevelDB或者LMDB)里面直接读取出来的,而不是直接用图像数据库里面求出,意味着,必须先进行图像到数据库的转换后,才干求平均图像这一步。
接下来就是遍历KV数据库的每个值while (cursor->valid())
将每个数据值转换为Datum,datum.ParseFromString(cursor->value());
接着将Datum阶码到sum_blob
中。sum_blob
是一个num=1,channels=图像.channel,height=图像.height ,width=图像.width 的blob
累加:
sum_blob.set_data(i, sum_blob.data(i) + (uint8_t)data[i]);
最后求平均:
sum_blob.set_data(i, sum_blob.data(i) / count);
存在的问题:上述代码仅仅是先累加在处于数目求和,显然,假设须要求平均的图像的数目相当多的话,就有可能溢出(浮点溢出)。
最后,假设要求简单一点的话,也能够直接求每个通道的平均值。
源码://2015.06.04版本号
#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; // NOLINT(build/namespaces)
using std::max;
using std::pair;
using boost::scoped_ptr;
DEFINE_string(backend, "lmdb",
"The backend {leveldb, lmdb} containing the images");
int main(int argc, char** argv) {
::google::InitGoogleLogging(argv[0]);
#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");
gflags::ParseCommandLineFlags(&argc, &argv, true);
if (argc < 2 || argc > 3) {
gflags::ShowUsageWithFlagsRestrict(argv[0], "tools/compute_image_mean");
return 1;
}
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;
}
return 0;
}
【Caffe代码解析】compute_image_mean的更多相关文章
- 【Caffe代码解析】Layer网络层
Layer 功能: 是全部的网络层的基类,当中.定义了一些通用的接口,比方前馈.反馈.reshape,setup等. #ifndef CAFFE_LAYER_H_ #define CAFFE_LAYE ...
- 【Caffe代码解析】Blob
主要功能: Blob 是Caffe作为传输数据的媒介,不管是网络权重參数,还是输入数据,都是转化为Blob数据结构来存储,网络,求解器等都是直接与此结构打交道的. 其直观的能够把它看成一个有4纬的结构 ...
- VBA常用代码解析
031 删除工作表中的空行 如果需要删除工作表中所有的空行,可以使用下面的代码. Sub DelBlankRow() DimrRow As Long DimLRow As Long Dimi As L ...
- [nRF51822] 12、基础实验代码解析大全 · 实验19 - PWM
一.PWM概述: PWM(Pulse Width Modulation):脉冲宽度调制技术,通过对一系列脉冲的宽度进行调制,来等效地获得所需要波形. PWM 的几个基本概念: 1) 占空比:占空比是指 ...
- [nRF51822] 11、基础实验代码解析大全 · 实验16 - 内部FLASH读写
一.实验内容: 通过串口发送单个字符到NRF51822,NRF51822 接收到字符后将其写入到FLASH 的最后一页,之后将其读出并通过串口打印出数据. 二.nRF51822芯片内部flash知识 ...
- [nRF51822] 10、基础实验代码解析大全 · 实验15 - RTC
一.实验内容: 配置NRF51822 的RTC0 的TICK 频率为8Hz,COMPARE0 匹配事件触发周期为3 秒,并使能了TICK 和COMPARE0 中断. TICK 中断中驱动指示灯D1 翻 ...
- [nRF51822] 9、基础实验代码解析大全 · 实验12 - ADC
一.本实验ADC 配置 分辨率:10 位. 输入通道:5,即使用输入通道AIN5 检测电位器的电压. ADC 基准电压:1.2V. 二.NRF51822 ADC 管脚分布 NRF51822 的ADC ...
- java集合框架之java HashMap代码解析
java集合框架之java HashMap代码解析 文章Java集合框架综述后,具体集合类的代码,首先以既熟悉又陌生的HashMap开始. 源自http://www.codeceo.com/arti ...
- Kakfa揭秘 Day8 DirectKafkaStream代码解析
Kakfa揭秘 Day8 DirectKafkaStream代码解析 今天让我们进入SparkStreaming,看一下其中重要的Kafka模块DirectStream的具体实现. 构造Stream ...
随机推荐
- [python学习篇][书籍学习][python standrad library][内建函数]之[list,open,len,pow,range,
Python 解释器内置了一些函数,它们总是可用的.这里将它们按字母表顺序列出. Built-in Functions abs() divmod() input() open() st ...
- Set容器——HashSet及常用API
Set容器特点: ① Set容器是一个不包含重复元素的Collection,并且最多包含一个null元素,它和List容器相反,Set容器不能保证其元素的顺序; ② 最常用的两个Set接口的实 ...
- HDU——4291A Short problem(矩阵快速幂+循环节)
A Short problem Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)T ...
- IPython:一种交互式计算和开发环境
一 键盘快捷键 - Ctrl-P 或上箭头键 后向搜索命令历史中以当前输入的文本开头的命令 - Ctrl-N 或下箭头键 前向搜索命令历史中以当前输入的文本开头的命令 - Ctrl-R ...
- javascript之进阶
一 模态框 1 什么是模态框 模态框(Modal)是覆盖在父窗体上的子窗体.指在用户想要对对话框以外的应用程序进行操作时,必须首先对该对话框进行响应.如单击[确定]或[取消]按钮等将该对话框关闭. 2 ...
- VMware 11 安装Mac 10.9
VMware Workstation 11, 10, 9 and 8 Unlocker to Run Mac OS X Guests in Windows 8.1 and 7 VM10装Mac OS ...
- 【MFC】Button控件和Picture Control的鼠标事件执行顺序
1.Button控件鼠标事件执行顺序 (1) WM_LBUTTONDOWN (2) WM_LBUTTONUP (3) OnBnClickedButton1(); 2.Picture Control的鼠 ...
- 反汇编->C++内联
C/C++提供了内联函数机制 内联函数就是向编译器建议:编译这个函数的时候.直接把函数展开,而不是进行函数调用call.当然编译器并不接受这个建议.仍然把他当做普通函数进行编译 使用内联函数的优点:减 ...
- 系统虚拟内存的理解 转载自http://blog.csdn.net/do2jiang/article/details/4690967
在进入正题前先来谈谈操作系统内存管理机制的发展历程,了解这些有利于我们更好的理解目前操作系统的内存管理机制. 一 早期的内存分配机制 在 早期的计算机中,要运行一个程序,会把这些程序全都装入内存,程序 ...
- Scrapy学习-17-暂停和重启
Scrapy爬虫暂停和重启 在当前项目下新建一个用于存储中间过程变量的目录 注意不同的spider不能共用一个目录 同一个spider每次运行时也必须使用新的目录 mkdir <spider_p ...