From e9d6e5a0b22a9f4768b8c04c9031ee8adb822ece Mon Sep 17 00:00:00 2001 From: Sergio Date: Tue, 7 Oct 2014 11:19:16 -0700 Subject: [PATCH] Add root_folder to ImageDataLayer --- Makefile | 6 ++++++ include/caffe/net.hpp | 10 ++++++++++ src/caffe/data_transformer.cpp | 12 ++++-------- src/caffe/layers/data_layer.cpp | 25 +++++++++++++++++-------- src/caffe/layers/image_data_layer.cpp | 30 ++++++++++++++++++++++-------- src/caffe/layers/window_data_layer.cpp | 24 ++++++++++++++++++------ src/caffe/net.cpp | 10 ++++++++++ src/caffe/proto/caffe.proto | 1 + src/caffe/util/io.cpp | 5 ++--- 9 files changed, 90 insertions(+), 33 deletions(-) diff --git a/Makefile b/Makefile index 26d5964..393fe18 100644 --- a/Makefile +++ b/Makefile @@ -281,6 +281,12 @@ ifeq ($(USE_CUDNN), 1) COMMON_FLAGS += -DUSE_CUDNN endif +TIMING ?= 0 +# Timing Flag +ifneq ($(TIMING), 0) + COMMON_FLAGS += -DTIMING +endif + # CPU-only configuration ifeq ($(CPU_ONLY), 1) OBJS := $(PROTO_OBJS) $(CXX_OBJS) diff --git a/include/caffe/net.hpp b/include/caffe/net.hpp index 1d06dc4..879f474 100644 --- a/include/caffe/net.hpp +++ b/include/caffe/net.hpp @@ -11,6 +11,9 @@ #include "caffe/common.hpp" #include "caffe/layer.hpp" #include "caffe/proto/caffe.pb.h" +#ifdef TIMING +#include "caffe/util/benchmark.hpp" +#endif namespace caffe { @@ -76,9 +79,16 @@ class Net { void Reshape(); Dtype ForwardBackward(const vector* > & bottom) { + #ifdef TIMING + Timer timer; + timer.Start(); + #endif Dtype loss; Forward(bottom, &loss); Backward(); + #ifdef TIMING + LOG(INFO) << "ForwardBackward Time: " << timer.MilliSeconds() << "ms."; + #endif return loss; } diff --git a/src/caffe/data_transformer.cpp b/src/caffe/data_transformer.cpp index 8f14599..023396c 100644 --- a/src/caffe/data_transformer.cpp +++ b/src/caffe/data_transformer.cpp @@ -193,8 +193,7 @@ void DataTransformer::Transform(const cv::Mat& cv_img, CHECK_LE(width, img_width); CHECK_GE(num, 1); - CHECK(cv_img.depth() == CV_8U || cv_img.depth() == CV_8S) << - "Image data type must be unsigned or signed byte"; + CHECK(cv_img.depth() == CV_8U) << "Image data type must be unsigned byte"; const int crop_size = param_.crop_size(); const Dtype scale = param_.scale(); @@ -238,22 +237,19 @@ void DataTransformer::Transform(const cv::Mat& cv_img, h_off = (img_height - crop_size) / 2; w_off = (img_width - crop_size) / 2; } - cv::Rect roi(h_off, w_off, crop_size, crop_size); + cv::Rect roi(w_off, h_off, crop_size, crop_size); cv_cropped_img = cv_img(roi); } else { CHECK_EQ(img_height, height); CHECK_EQ(img_width, width); } - - // if (do_mirror) { - // cv::flip(cv_cropped_img, cv_cropped_img, 1); - // } + CHECK(cv_cropped_img.data); Dtype* transformed_data = transformed_blob->mutable_cpu_data(); int top_index; for (int h = 0; h < height; ++h) { - const char* ptr = cv_cropped_img.ptr(h); + const uchar* ptr = cv_cropped_img.ptr(h); int img_index = 0; for (int w = 0; w < width; ++w) { for (int c = 0; c < img_channels; ++c) { diff --git a/src/caffe/layers/data_layer.cpp b/src/caffe/layers/data_layer.cpp index 95c5427..95604e5 100644 --- a/src/caffe/layers/data_layer.cpp +++ b/src/caffe/layers/data_layer.cpp @@ -8,7 +8,9 @@ #include "caffe/dataset_factory.hpp" #include "caffe/layer.hpp" #include "caffe/proto/caffe.pb.h" +#ifdef TIMING #include "caffe/util/benchmark.hpp" +#endif #include "caffe/util/io.hpp" #include "caffe/util/math_functions.hpp" #include "caffe/util/rng.hpp" @@ -82,8 +84,13 @@ void DataLayer::DataLayerSetUp(const vector*>& bottom, // This function is used to create a thread that prefetches the data. template void DataLayer::InternalThreadEntry() { + #ifdef TIMING Timer batch_timer; batch_timer.Start(); + float read_time = 0; + float trans_time = 0; + Timer timer; + #endif CHECK(this->prefetch_data_.count()); CHECK(this->transformed_data_.count()); Dtype* top_data = this->prefetch_data_.mutable_cpu_data(); @@ -93,9 +100,6 @@ void DataLayer::InternalThreadEntry() { top_label = this->prefetch_label_.mutable_cpu_data(); } const int batch_size = this->layer_param_.data_param().batch_size(); - float read_time = 0; - float trans_time = 0; - Timer timer; for (int item_id = 0; item_id < batch_size; ++item_id) { timer.Start(); // get a blob @@ -105,31 +109,36 @@ void DataLayer::InternalThreadEntry() { if (datum.encoded()) { cv_img = DecodeDatumToCVMat(datum); } + #ifdef TIMING read_time += timer.MilliSeconds(); timer.Start(); + #endif // Apply data transformations (mirror, scale, crop...) int offset = this->prefetch_data_.offset(item_id); this->transformed_data_.set_cpu_data(top_data + offset); if (datum.encoded()) { - this->data_transformer_.Transform(cv_img, &(this->transformed_data_)); + this->data_transformer_.Transform(cv_img, &(this->transformed_data_)); } else { this->data_transformer_.Transform(datum, &(this->transformed_data_)); } - if (this->output_labels_) { top_label[item_id] = datum.label(); } + #ifdef TIMING trans_time += timer.MilliSeconds(); + #endif // go to the next iter ++iter_; if (iter_ == dataset_->end()) { iter_ = dataset_->begin(); } } - DLOG(INFO) << "Prefetch batch: " << batch_timer.MilliSeconds() << "ms."; - DLOG(INFO) << "Read time: " << read_time << "ms."; - DLOG(INFO) << "Transform time: " << trans_time << "ms."; + #ifdef TIMING + LOG(INFO) << "Prefetch batch: " << batch_timer.MilliSeconds() << "ms."; + LOG(INFO) << "Read time: " << read_time << "ms."; + LOG(INFO) << "Transform time: " << trans_time << "ms."; + #endif } INSTANTIATE_CLASS(DataLayer); diff --git a/src/caffe/layers/image_data_layer.cpp b/src/caffe/layers/image_data_layer.cpp index 6749311..0abcd88 100644 --- a/src/caffe/layers/image_data_layer.cpp +++ b/src/caffe/layers/image_data_layer.cpp @@ -6,7 +6,9 @@ #include "caffe/data_layers.hpp" #include "caffe/layer.hpp" +#ifdef TIMING #include "caffe/util/benchmark.hpp" +#endif #include "caffe/util/io.hpp" #include "caffe/util/math_functions.hpp" #include "caffe/util/rng.hpp" @@ -24,6 +26,7 @@ void ImageDataLayer::DataLayerSetUp(const vector*>& bottom, const int new_height = this->layer_param_.image_data_param().new_height(); const int new_width = this->layer_param_.image_data_param().new_width(); const bool is_color = this->layer_param_.image_data_param().is_color(); + string root_folder = this->layer_param_.image_data_param().root_folder(); CHECK((new_height == 0 && new_width == 0) || (new_height > 0 && new_width > 0)) << "Current implementation requires " @@ -57,7 +60,7 @@ void ImageDataLayer::DataLayerSetUp(const vector*>& bottom, lines_id_ = skip; } // Read an image, and use it to initialize the top blob. - cv::Mat cv_img = ReadImageToCVMat(lines_[lines_id_].first, + cv::Mat cv_img = ReadImageToCVMat(root_folder + lines_[lines_id_].first, new_height, new_width, is_color); const int channels = cv_img.channels(); const int height = cv_img.rows; @@ -92,8 +95,13 @@ void ImageDataLayer::ShuffleImages() { // This function is used to create a thread that prefetches the data. template void ImageDataLayer::InternalThreadEntry() { + #ifdef TIMING Timer batch_timer; batch_timer.Start(); + float read_time = 0; + float trans_time = 0; + Timer timer; + #endif CHECK(this->prefetch_data_.count()); CHECK(this->transformed_data_.count()); Dtype* top_data = this->prefetch_data_.mutable_cpu_data(); @@ -103,28 +111,32 @@ void ImageDataLayer::InternalThreadEntry() { const int new_height = image_data_param.new_height(); const int new_width = image_data_param.new_width(); const bool is_color = image_data_param.is_color(); + string root_folder = image_data_param.root_folder(); // datum scales const int lines_size = lines_.size(); - float read_time = 0; - float trans_time = 0; - Timer timer; for (int item_id = 0; item_id < batch_size; ++item_id) { // get a blob + #ifdef TIMING timer.Start(); + #endif CHECK_GT(lines_size, lines_id_); - cv::Mat cv_img = ReadImageToCVMat(lines_[lines_id_].first, + cv::Mat cv_img = ReadImageToCVMat(root_folder + lines_[lines_id_].first, new_height, new_width, is_color); if (!cv_img.data) { continue; } + #ifdef TIMING read_time += timer.MilliSeconds(); timer.Start(); + #endif // Apply transformations (mirror, crop...) to the image int offset = this->prefetch_data_.offset(item_id); this->transformed_data_.set_cpu_data(top_data + offset); this->data_transformer_.Transform(cv_img, &(this->transformed_data_)); + #ifdef TIMING trans_time += timer.MilliSeconds(); + #endif top_label[item_id] = lines_[lines_id_].second; // go to the next iter @@ -138,9 +150,11 @@ void ImageDataLayer::InternalThreadEntry() { } } } - DLOG(INFO) << "Prefetch batch: " << batch_timer.MilliSeconds() << "ms."; - DLOG(INFO) << "Read time: " << read_time << "ms."; - DLOG(INFO) << "Transform time: " << trans_time << "ms."; + #ifdef TIMING + LOG(INFO) << "Prefetch batch: " << batch_timer.MilliSeconds() << "ms."; + LOG(INFO) << "Read time: " << read_time << "ms."; + LOG(INFO) << "Transform time: " << trans_time << "ms."; + #endif } INSTANTIATE_CLASS(ImageDataLayer); diff --git a/src/caffe/layers/window_data_layer.cpp b/src/caffe/layers/window_data_layer.cpp index 47e0fb2..8e65615 100644 --- a/src/caffe/layers/window_data_layer.cpp +++ b/src/caffe/layers/window_data_layer.cpp @@ -13,7 +13,9 @@ #include "caffe/common.hpp" #include "caffe/data_layers.hpp" #include "caffe/layer.hpp" +#ifdef TIMING #include "caffe/util/benchmark.hpp" +#endif #include "caffe/util/io.hpp" #include "caffe/util/math_functions.hpp" #include "caffe/util/rng.hpp" @@ -193,8 +195,13 @@ template void WindowDataLayer::InternalThreadEntry() { // At each iteration, sample N windows where N*p are foreground (object) // windows and N*(1-p) are background (non-object) windows + #ifdef TIMING Timer batch_timer; batch_timer.Start(); + float read_time = 0; + float trans_time = 0; + Timer timer; + #endif Dtype* top_data = this->prefetch_data_.mutable_cpu_data(); Dtype* top_label = this->prefetch_label_.mutable_cpu_data(); const Dtype scale = this->layer_param_.window_data_param().scale(); @@ -221,14 +228,13 @@ void WindowDataLayer::InternalThreadEntry() { const int num_samples[2] = { batch_size - num_fg, num_fg }; int item_id = 0; - float read_time = 0; - float trans_time = 0; - Timer timer; // sample from bg set then fg set for (int is_fg = 0; is_fg < 2; ++is_fg) { for (int dummy = 0; dummy < num_samples[is_fg]; ++dummy) { // sample a window + #ifdef TIMING timer.Start(); + #endif const unsigned int rand_index = PrefetchRand(); vector window = (is_fg) ? fg_windows_[rand_index % fg_windows_.size()] : @@ -245,8 +251,10 @@ void WindowDataLayer::InternalThreadEntry() { LOG(ERROR) << "Could not open or find file " << image.first; return; } + #ifdef TIMING read_time += timer.MilliSeconds(); timer.Start(); + #endif const int channels = cv_img.channels(); // crop window out of image and warp it @@ -364,7 +372,9 @@ void WindowDataLayer::InternalThreadEntry() { } } } + #ifdef TIMING trans_time += timer.MilliSeconds(); + #endif // get window label top_label[item_id] = window[WindowDataLayer::LABEL]; @@ -404,9 +414,11 @@ void WindowDataLayer::InternalThreadEntry() { item_id++; } } - DLOG(INFO) << "Prefetch batch: " << batch_timer.MilliSeconds() << "ms."; - DLOG(INFO) << "Read time: " << read_time << "ms."; - DLOG(INFO) << "Transform time: " << trans_time << "ms."; + #ifdef TIMING + LOG(INFO) << "Prefetch batch: " << batch_timer.MilliSeconds() << "ms."; + LOG(INFO) << "Read time: " << read_time << "ms."; + LOG(INFO) << "Transform time: " << trans_time << "ms."; + #endif } INSTANTIATE_CLASS(WindowDataLayer); diff --git a/src/caffe/net.cpp b/src/caffe/net.cpp index 5b7152e..c0e5692 100644 --- a/src/caffe/net.cpp +++ b/src/caffe/net.cpp @@ -9,7 +9,9 @@ #include "caffe/layer.hpp" #include "caffe/net.hpp" #include "caffe/proto/caffe.pb.h" +#ifdef TIMING #include "caffe/util/benchmark.hpp" +#endif #include "caffe/util/insert_splits.hpp" #include "caffe/util/io.hpp" #include "caffe/util/math_functions.hpp" @@ -500,8 +502,10 @@ void Net::GetLearningRateAndWeightDecay() { template Dtype Net::ForwardFromTo(int start, int end) { + #ifdef TIMING Timer timer; timer.Start(); + #endif CHECK_GE(start, 0); CHECK_LT(end, layers_.size()); Dtype loss = 0; @@ -512,7 +516,9 @@ Dtype Net::ForwardFromTo(int start, int end) { loss += layer_loss; if (debug_info_) { ForwardDebugInfo(i); } } + #ifdef TIMING LOG(INFO) << "Forward time: " << timer.MilliSeconds() << "ms."; + #endif return loss; } @@ -569,8 +575,10 @@ string Net::Forward(const string& input_blob_protos, Dtype* loss) { template void Net::BackwardFromTo(int start, int end) { + #ifdef TIMING Timer timer; timer.Start(); + #endif CHECK_GE(end, 0); CHECK_LT(start, layers_.size()); for (int i = start; i >= end; --i) { @@ -580,7 +588,9 @@ void Net::BackwardFromTo(int start, int end) { if (debug_info_) { BackwardDebugInfo(i); } } } + #ifdef TIMING LOG(INFO) << "Backward time: " << timer.MilliSeconds() << "ms."; + #endif } template diff --git a/src/caffe/proto/caffe.proto b/src/caffe/proto/caffe.proto index 53db6f7..b602d0e 100644 --- a/src/caffe/proto/caffe.proto +++ b/src/caffe/proto/caffe.proto @@ -540,6 +540,7 @@ message ImageDataParameter { // DEPRECATED. See TransformationParameter. Specify if we want to randomly mirror // data. optional bool mirror = 6 [default = false]; + optional string root_folder = 12 [default = ""]; } // Message that stores parameters InfogainLossLayer diff --git a/src/caffe/util/io.cpp b/src/caffe/util/io.cpp index 06b9deb..b136bc8 100644 --- a/src/caffe/util/io.cpp +++ b/src/caffe/util/io.cpp @@ -150,8 +150,7 @@ bool DecodeDatum(const int height, const int width, const bool is_color, } void CVMatToDatum(const cv::Mat& cv_img, Datum* datum) { - CHECK(cv_img.depth() == CV_8U || cv_img.depth() == CV_8S) << - "Image data type must be unsigned or signed byte"; + CHECK(cv_img.depth() == CV_8U) << "Image data type must be unsigned byte"; datum->set_channels(cv_img.channels()); datum->set_height(cv_img.rows); datum->set_width(cv_img.cols); @@ -164,7 +163,7 @@ void CVMatToDatum(const cv::Mat& cv_img, Datum* datum) { int datum_size = datum_channels * datum_height * datum_width; std::string buffer(datum_size, ' '); for (int h = 0; h < datum_height; ++h) { - const char* ptr = cv_img.ptr(h); + const uchar* ptr = cv_img.ptr(h); int img_index = 0; for (int w = 0; w < datum_width; ++w) { for (int c = 0; c < datum_channels; ++c) { -- 2.7.4