7 #include "boost/scoped_ptr.hpp"
8 #include "gflags/gflags.h"
9 #include "glog/logging.h"
11 #include "caffe/proto/caffe.pb.h"
12 #include "caffe/util/db.hpp"
13 #include "caffe/util/io.hpp"
15 using namespace caffe; // NOLINT(build/namespaces)
19 using boost::scoped_ptr;
21 DEFINE_string(backend, "lmdb",
22 "The backend {leveldb, lmdb} containing the images");
24 int main(int argc, char** argv) {
26 ::google::InitGoogleLogging(argv[0]);
27 // Print output to stderr (while still logging)
28 FLAGS_alsologtostderr = 1;
30 #ifndef GFLAGS_GFLAGS_H_
31 namespace gflags = google;
34 gflags::SetUsageMessage("Compute the mean_image of a set of images given by"
37 " compute_image_mean [FLAGS] INPUT_DB [OUTPUT_FILE]\n");
39 gflags::ParseCommandLineFlags(&argc, &argv, true);
41 if (argc < 2 || argc > 3) {
42 gflags::ShowUsageWithFlagsRestrict(argv[0], "tools/compute_image_mean");
46 scoped_ptr<db::DB> db(db::GetDB(FLAGS_backend));
47 db->Open(argv[1], db::READ);
48 scoped_ptr<db::Cursor> cursor(db->NewCursor());
54 datum.ParseFromString(cursor->value());
56 if (DecodeDatumNative(&datum)) {
57 LOG(INFO) << "Decoding Datum";
61 sum_blob.set_channels(datum.channels());
62 sum_blob.set_height(datum.height());
63 sum_blob.set_width(datum.width());
64 const int data_size = datum.channels() * datum.height() * datum.width();
65 int size_in_datum = std::max<int>(datum.data().size(),
66 datum.float_data_size());
67 for (int i = 0; i < size_in_datum; ++i) {
68 sum_blob.add_data(0.);
70 LOG(INFO) << "Starting iteration";
71 while (cursor->valid()) {
73 datum.ParseFromString(cursor->value());
74 DecodeDatumNative(&datum);
76 const std::string& data = datum.data();
77 size_in_datum = std::max<int>(datum.data().size(),
78 datum.float_data_size());
79 CHECK_EQ(size_in_datum, data_size) << "Incorrect data field size " <<
81 if (data.size() != 0) {
82 CHECK_EQ(data.size(), size_in_datum);
83 for (int i = 0; i < size_in_datum; ++i) {
84 sum_blob.set_data(i, sum_blob.data(i) + (uint8_t)data[i]);
87 CHECK_EQ(datum.float_data_size(), size_in_datum);
88 for (int i = 0; i < size_in_datum; ++i) {
89 sum_blob.set_data(i, sum_blob.data(i) +
90 static_cast<float>(datum.float_data(i)));
94 if (count % 10000 == 0) {
95 LOG(INFO) << "Processed " << count << " files.";
100 if (count % 10000 != 0) {
101 LOG(INFO) << "Processed " << count << " files.";
103 for (int i = 0; i < sum_blob.data_size(); ++i) {
104 sum_blob.set_data(i, sum_blob.data(i) / count);
108 LOG(INFO) << "Write to " << argv[2];
109 WriteProtoToBinaryFile(sum_blob, argv[2]);
111 const int channels = sum_blob.channels();
112 const int dim = sum_blob.height() * sum_blob.width();
113 std::vector<float> mean_values(channels, 0.0);
114 LOG(INFO) << "Number of channels: " << channels;
115 for (int c = 0; c < channels; ++c) {
116 for (int i = 0; i < dim; ++i) {
117 mean_values[c] += sum_blob.data(dim * c + i);
119 LOG(INFO) << "mean_value channel [" << c << "]: " << mean_values[c] / dim;
122 LOG(FATAL) << "This tool requires OpenCV; compile with USE_OPENCV.";