1 // Copyright 2013 Yangqing Jia
2 #include <glog/logging.h>
3 #include <leveldb/db.h>
4 #include <stdint.h>
6 #include <string>
8 #include "caffe/proto/caffe.pb.h"
9 #include "caffe/util/io.hpp"
11 using caffe::Datum;
12 using caffe::BlobProto;
14 int main(int argc, char** argv) {
15 ::google::InitGoogleLogging(argv[0]);
16 if (argc != 3) {
17 LOG(ERROR) << "Usage: demo_compute_image_mean input_leveldb output_file";
18 return(0);
19 }
21 leveldb::DB* db;
22 leveldb::Options options;
23 options.create_if_missing = false;
25 LOG(INFO) << "Opening leveldb " << argv[1];
26 leveldb::Status status = leveldb::DB::Open(
27 options, argv[1], &db);
28 CHECK(status.ok()) << "Failed to open leveldb " << argv[1];
30 leveldb::ReadOptions read_options;
31 read_options.fill_cache = false;
32 leveldb::Iterator* it = db->NewIterator(read_options);
33 it->SeekToFirst();
34 Datum datum;
35 BlobProto sum_blob;
36 int count = 0;
37 datum.ParseFromString(it->value().ToString());
38 sum_blob.set_num(1);
39 sum_blob.set_channels(datum.channels());
40 sum_blob.set_height(datum.height());
41 sum_blob.set_width(datum.width());
42 const int data_size = datum.channels() * datum.height() * datum.width();
43 for (int i = 0; i < datum.data().size(); ++i) {
44 sum_blob.add_data(0.);
45 }
46 LOG(INFO) << "Starting Iteration";
47 for (it->SeekToFirst(); it->Valid(); it->Next()) {
48 // just a dummy operation
49 datum.ParseFromString(it->value().ToString());
50 const string& data = datum.data();
51 CHECK_EQ(data.size(), data_size) << "Incorrect data field size " << data.size();
52 for (int i = 0; i < data.size(); ++i) {
53 sum_blob.set_data(i, sum_blob.data(i) + (uint8_t)data[i]);
54 }
55 ++count;
56 if (count % 10000 == 0) {
57 LOG(ERROR) << "Processed " << count << " files.";
58 }
59 }
60 for (int i = 0; i < sum_blob.data_size(); ++i) {
61 sum_blob.set_data(i, sum_blob.data(i) / count);
62 }
63 // Write to disk
64 LOG(INFO) << "Write to " << argv[2];
65 WriteProtoToBinaryFile(sum_blob, argv[2]);
67 delete db;
68 return 0;
69 }