return new ConvolutionLayer<Dtype>(param);
} else if (type == "data") {
return new DataLayer<Dtype>(param);
- } else if (type == "input") {
- return new InputLayer<Dtype>(param);
+ } else if (type == "images") {
+ return new ImagesLayer<Dtype>(param);
} else if (type == "dropout") {
return new DropoutLayer<Dtype>(param);
} else if (type == "euclidean_loss") {
namespace caffe {
template <typename Dtype>
-void* InputLayerPrefetch(void* layer_pointer) {
+void* ImagesLayerPrefetch(void* layer_pointer) {
CHECK(layer_pointer);
- InputLayer<Dtype>* layer = reinterpret_cast<InputLayer<Dtype>*>(layer_pointer);
+ ImagesLayer<Dtype>* layer = reinterpret_cast<ImagesLayer<Dtype>*>(layer_pointer);
CHECK(layer);
Datum datum;
CHECK(layer->prefetch_data_);
const int batchsize = layer->layer_param_.batchsize();
const int cropsize = layer->layer_param_.cropsize();
const bool mirror = layer->layer_param_.mirror();
- const int resize_image = layer->layer_param_.resize_image();
+ const int new_height = layer->layer_param_.new_height();
+ const int new_width = layer->layer_param_.new_height();
if (mirror && cropsize == 0) {
LOG(FATAL) << "Current implementation requires mirror and cropsize to be "
// get a blob
CHECK_GT(lines_size,layer->lines_id_);
if (!ReadImageToDatum(layer->lines_[layer->lines_id_].first, layer->lines_[layer->lines_id_].second,
- resize_image, resize_image, &datum)) {
+ new_height, new_width, &datum)) {
continue;
};
const string& data = datum.data();
// We have reached the end. Restart from the first.
DLOG(INFO) << "Restarting data prefetching from start.";
layer->lines_id_=0;
- if (layer->layer_param_.shuffle_data()) {
+ if (layer->layer_param_.shuffle_images()) {
std::random_shuffle(layer->lines_.begin(), layer->lines_.end());
}
}
}
template <typename Dtype>
-InputLayer<Dtype>::~InputLayer<Dtype>() {
+ImagesLayer<Dtype>::~ImagesLayer<Dtype>() {
// Finally, join the thread
CHECK(!pthread_join(thread_, NULL)) << "Pthread joining failed.";
}
template <typename Dtype>
-void InputLayer<Dtype>::SetUp(const vector<Blob<Dtype>*>& bottom,
+void ImagesLayer<Dtype>::SetUp(const vector<Blob<Dtype>*>& bottom,
vector<Blob<Dtype>*>* top) {
CHECK_EQ(bottom.size(), 0) << "Input Layer takes no input blobs.";
CHECK_EQ(top->size(), 2) << "Input Layer takes two blobs as output.";
lines_.push_back(std::make_pair(filename, label));
}
- if (this->layer_param_.shuffle_data()) {
+ if (this->layer_param_.shuffle_images()) {
// randomly shuffle data
LOG(INFO) << "Shuffling data";
std::random_shuffle(lines_.begin(), lines_.end());
}
// Read a data point, and use it to initialize the top blob.
Datum datum;
- const int resize_image = this->layer_param_.resize_image();
+ const int new_height = layer->layer_param_.new_height();
+ const int new_width = layer->layer_param_.new_height();
CHECK(ReadImageToDatum(lines_[lines_id_].first, lines_[lines_id_].second,
- resize_image,resize_image,&datum));
+ new_height,new_width,&datum));
// image
int cropsize = this->layer_param_.cropsize();
if (cropsize > 0) {
prefetch_label_->mutable_cpu_data();
data_mean_.cpu_data();
DLOG(INFO) << "Initializing prefetch";
- CHECK(!pthread_create(&thread_, NULL, InputLayerPrefetch<Dtype>,
+ CHECK(!pthread_create(&thread_, NULL, ImagesLayerPrefetch<Dtype>,
reinterpret_cast<void*>(this))) << "Pthread execution failed.";
DLOG(INFO) << "Prefetch initialized.";
}
template <typename Dtype>
-void InputLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
+void ImagesLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
vector<Blob<Dtype>*>* top) {
// First, join the thread
CHECK(!pthread_join(thread_, NULL)) << "Pthread joining failed.";
memcpy((*top)[1]->mutable_cpu_data(), prefetch_label_->cpu_data(),
sizeof(Dtype) * prefetch_label_->count());
// Start a new prefetch thread
- CHECK(!pthread_create(&thread_, NULL, InputLayerPrefetch<Dtype>,
+ CHECK(!pthread_create(&thread_, NULL, ImagesLayerPrefetch<Dtype>,
reinterpret_cast<void*>(this))) << "Pthread execution failed.";
}
template <typename Dtype>
-void InputLayer<Dtype>::Forward_gpu(const vector<Blob<Dtype>*>& bottom,
+void ImagesLayer<Dtype>::Forward_gpu(const vector<Blob<Dtype>*>& bottom,
vector<Blob<Dtype>*>* top) {
// First, join the thread
CHECK(!pthread_join(thread_, NULL)) << "Pthread joining failed.";
prefetch_label_->cpu_data(), sizeof(Dtype) * prefetch_label_->count(),
cudaMemcpyHostToDevice));
// Start a new prefetch thread
- CHECK(!pthread_create(&thread_, NULL, InputLayerPrefetch<Dtype>,
+ CHECK(!pthread_create(&thread_, NULL, ImagesLayerPrefetch<Dtype>,
reinterpret_cast<void*>(this))) << "Pthread execution failed.";
}
// The backward operations are dummy - they do not carry any computation.
template <typename Dtype>
-Dtype InputLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,
+Dtype ImagesLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,
const bool propagate_down, vector<Blob<Dtype>*>* bottom) {
return Dtype(0.);
}
template <typename Dtype>
-Dtype InputLayer<Dtype>::Backward_gpu(const vector<Blob<Dtype>*>& top,
+Dtype ImagesLayer<Dtype>::Backward_gpu(const vector<Blob<Dtype>*>& top,
const bool propagate_down, vector<Blob<Dtype>*>* bottom) {
return Dtype(0.);
}
-INSTANTIATE_CLASS(InputLayer);
+INSTANTIATE_CLASS(ImagesLayer);
} // namespace caffe
// be larger than the number of keys in the leveldb.
optional uint32 rand_skip = 53 [ default = 0 ];
- // Used by Input_layer to shuffle the list of files at every epoch
- optional bool shuffle_data = 61 [default = false];
- // If >0 then it will resize input images to size given by resize_image using cv::resize
- optional int32 resize_image = 62 [default = 0 ];
+ // Used by ImageLayer to shuffle the list of files at every epoch it will also
+ // resize images if new_height or new_width are not zero
+ optional bool shuffle_images = 64 [default = false];
+
}
message LayerConnection {
--- /dev/null
+// Copyright 2014 Sergio Guadarrama
+
+#include <cuda_runtime.h>
+#include <iostream>
+#include <fstream>
+
+#include <string>
+
+#include "gtest/gtest.h"
+#include "caffe/blob.hpp"
+#include "caffe/common.hpp"
+#include "caffe/filler.hpp"
+#include "caffe/vision_layers.hpp"
+#include "caffe/proto/caffe.pb.h"
+#include "caffe/test/test_caffe_main.hpp"
+
+using std::string;
+
+namespace caffe {
+
+extern cudaDeviceProp CAFFE_TEST_CUDA_PROP;
+
+template <typename Dtype>
+class ImagesLayerTest : public ::testing::Test {
+ protected:
+ ImagesLayerTest()
+ : blob_top_data_(new Blob<Dtype>()),
+ blob_top_label_(new Blob<Dtype>()),
+ filename(NULL) {};
+ virtual void SetUp() {
+ blob_top_vec_.push_back(blob_top_data_);
+ blob_top_vec_.push_back(blob_top_label_);
+ // Create a Vector of files with labels
+ filename = tmpnam(NULL); // get temp name
+ std::ofstream outfile(filename, std::ofstream::out);
+ LOG(INFO) << "Using temporary file " << filename;
+ for (int i = 0; i < 5; ++i) {
+ outfile << "data/cat.jpg " << i;
+ }
+ outfile.close();
+ };
+
+ virtual ~ImagesLayerTest() { delete blob_top_data_; delete blob_top_label_; }
+
+ char* filename;
+ Blob<Dtype>* const blob_top_data_;
+ Blob<Dtype>* const blob_top_label_;
+ vector<Blob<Dtype>*> blob_bottom_vec_;
+ vector<Blob<Dtype>*> blob_top_vec_;
+};
+
+typedef ::testing::Types<float, double> Dtypes;
+TYPED_TEST_CASE(ImagesLayerTest, Dtypes);
+
+TYPED_TEST(ImagesLayerTest, TestRead) {
+ LayerParameter param;
+ param.set_batchsize(5);
+ param.set_source(this->filename);
+ param.set_shuffle_images(false);
+ ImagesLayer<TypeParam> layer(param);
+ layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_);
+ EXPECT_EQ(this->blob_top_data_->num(), 5);
+ EXPECT_EQ(this->blob_top_data_->channels(), 3);
+ EXPECT_EQ(this->blob_top_data_->height(), 1200);
+ EXPECT_EQ(this->blob_top_data_->width(), 1600);
+ EXPECT_EQ(this->blob_top_label_->num(), 5);
+ EXPECT_EQ(this->blob_top_label_->channels(), 1);
+ EXPECT_EQ(this->blob_top_label_->height(), 1);
+ EXPECT_EQ(this->blob_top_label_->width(), 1);
+ // Go through the data 5 times
+ for (int iter = 0; iter < 5; ++iter) {
+ layer.Forward(this->blob_bottom_vec_, &this->blob_top_vec_);
+ for (int i = 0; i < 5; ++i) {
+ EXPECT_EQ(i, this->blob_top_label_->cpu_data()[i]);
+ }
+ }
+}
+
+TYPED_TEST(ImagesLayerTest, TestResize) {
+ LayerParameter param;
+ param.set_batchsize(5);
+ param.set_source(this->filename);
+ param.set_resize_image(256);
+ param.set_shuffle_images(false);
+ ImagesLayer<TypeParam> layer(param);
+ layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_);
+ EXPECT_EQ(this->blob_top_data_->num(), 5);
+ EXPECT_EQ(this->blob_top_data_->channels(), 3);
+ EXPECT_EQ(this->blob_top_data_->height(), 256);
+ EXPECT_EQ(this->blob_top_data_->width(), 256);
+ EXPECT_EQ(this->blob_top_label_->num(), 5);
+ EXPECT_EQ(this->blob_top_label_->channels(), 1);
+ EXPECT_EQ(this->blob_top_label_->height(), 1);
+ EXPECT_EQ(this->blob_top_label_->width(), 1);
+ // Go through the data 50 times
+ for (int iter = 0; iter < 5; ++iter) {
+ layer.Forward(this->blob_bottom_vec_, &this->blob_top_vec_);
+ for (int i = 0; i < 5; ++i) {
+ EXPECT_EQ(i, this->blob_top_label_->cpu_data()[i]);
+ }
+ }
+}
+
+TYPED_TEST(ImagesLayerTest, TestShuffle) {
+ LayerParameter param;
+ param.set_batchsize(5);
+ param.set_source(this->filename);
+ param.set_shuffle_images(true);
+ ImagesLayer<TypeParam> layer(param);
+ layer.SetUp(this->blob_bottom_vec_, &this->blob_top_vec_);
+ EXPECT_EQ(this->blob_top_data_->num(), 5);
+ EXPECT_EQ(this->blob_top_data_->channels(), 3);
+ EXPECT_EQ(this->blob_top_data_->height(), 1200);
+ EXPECT_EQ(this->blob_top_data_->width(), 1600);
+ EXPECT_EQ(this->blob_top_label_->num(), 5);
+ EXPECT_EQ(this->blob_top_label_->channels(), 1);
+ EXPECT_EQ(this->blob_top_label_->height(), 1);
+ EXPECT_EQ(this->blob_top_label_->width(), 1);
+ // Go through the data 5 times
+ for (int iter = 0; iter < 5; ++iter) {
+ layer.Forward(this->blob_bottom_vec_, &this->blob_top_vec_);
+ for (int i = 0; i < 5; ++i) {
+ EXPECT_GE(this->blob_top_label_->cpu_data()[i],0);
+ EXPECT_LE(this->blob_top_label_->cpu_data()[i],5);
+ }
+ }
+}
+}