index 5b957701ce7d9904e1ec42df0d705a19d10498d2..12fd6d94625e68e82188951e208c8af728ae85c3 100644 (file)
#include <vector>
#include "caffe/layer.hpp"
+#include "caffe/util/io.hpp"
#include "caffe/vision_layers.hpp"
using std::string;
Dtype* top_data = layer->prefetch_data_->mutable_cpu_data();
Dtype* top_label = layer->prefetch_label_->mutable_cpu_data();
const Dtype scale = layer->layer_param_.scale();
- const Dtype subtraction = layer->layer_param_.subtraction();
const int batchsize = layer->layer_param_.batchsize();
const int cropsize = layer->layer_param_.cropsize();
+ const bool mirror = layer->layer_param_.mirror();
+
+ if (mirror && cropsize == 0) {
+ LOG(FATAL) << "Current implementation requires mirror and cropsize to be "
+ << "set at the same time.";
+ }
+ // datum scales
+ const int channels = layer->datum_channels_;
+ const int height = layer->datum_height_;
+ const int width = layer->datum_width_;
+ const int size = layer->datum_size_;
+ const Dtype* mean = layer->data_mean_.cpu_data();
for (int itemid = 0; itemid < batchsize; ++itemid) {
// get a blob
datum.ParseFromString(layer->iter_->value().ToString());
const string& data = datum.data();
if (cropsize) {
CHECK(data.size()) << "Image cropping only support uint8 data";
- int h_offset = rand() % (layer->datum_height_ - cropsize);
- int w_offset = rand() % (layer->datum_width_ - cropsize);
- for (int c = 0; c < layer->datum_channels_; ++c) {
- for (int h = 0; h < cropsize; ++h) {
- for (int w = 0; w < cropsize; ++w) {
- top_data[((itemid * layer->datum_channels_ + c) * cropsize + h) * cropsize + w] =
- static_cast<Dtype>((uint8_t)data[
- (c * layer->datum_height_ + h + h_offset) * layer->datum_width_
- + w + w_offset]
- ) * scale - subtraction;
+ int h_off, w_off;
+ // We only do random crop when we do training.
+ if (Caffe::phase() == Caffe::TRAIN) {
+ h_off = rand() % (height - cropsize);
+ w_off = rand() % (width - cropsize);
+ } else {
+ h_off = (height - cropsize) / 2;
+ w_off = (width - cropsize) / 2;
+ }
+ if (mirror && rand() % 2) {
+ // Copy mirrored version
+ for (int c = 0; c < channels; ++c) {
+ for (int h = 0; h < cropsize; ++h) {
+ for (int w = 0; w < cropsize; ++w) {
+ top_data[((itemid * channels + c) * cropsize + h) * cropsize
+ + cropsize - 1 - w] =
+ (static_cast<Dtype>(
+ (uint8_t)data[(c * height + h + h_off) * width
+ + w + w_off])
+ - mean[(c * height + h + h_off) * width + w + w_off])
+ * scale;
+ }
+ }
+ }
+ } else {
+ // Normal copy
+ for (int c = 0; c < channels; ++c) {
+ for (int h = 0; h < cropsize; ++h) {
+ for (int w = 0; w < cropsize; ++w) {
+ top_data[((itemid * channels + c) * cropsize + h) * cropsize + w]
+ = (static_cast<Dtype>(
+ (uint8_t)data[(c * height + h + h_off) * width
+ + w + w_off])
+ - mean[(c * height + h + h_off) * width + w + w_off])
+ * scale;
+ }
}
}
}
} else {
// we will prefer to use data() first, and then try float_data()
if (data.size()) {
- for (int j = 0; j < layer->datum_size_; ++j) {
- top_data[itemid * layer->datum_size_ + j] =
- (static_cast<Dtype>((uint8_t)data[j]) * scale) - subtraction;
+ for (int j = 0; j < size; ++j) {
+ top_data[itemid * size + j] =
+ (static_cast<Dtype>((uint8_t)data[j]) - mean[j]) * scale;
}
} else {
- for (int j = 0; j < layer->datum_size_; ++j) {
- top_data[itemid * layer->datum_size_ + j] =
- (datum.float_data(j) * scale) - subtraction;
+ for (int j = 0; j < size; ++j) {
+ top_data[itemid * size + j] =
+ (datum.float_data(j) - mean[j]) * scale;
}
}
}
+
top_label[itemid] = datum.label();
// go to the next iter
layer->iter_->Next();
if (!layer->iter_->Valid()) {
// We have reached the end. Restart from the first.
- LOG(INFO) << "Restarting data read from start.";
+ DLOG(INFO) << "Restarting data prefetching from start.";
layer->iter_->SeekToFirst();
}
}
+
+ return (void*)NULL;
}
datum_size_ = datum.channels() * datum.height() * datum.width();
CHECK_GT(datum_height_, cropsize);
CHECK_GT(datum_width_, cropsize);
- // Now, start the prefetch thread.
- //LOG(INFO) << "Initializing prefetch";
- CHECK(!pthread_create(&thread_, NULL, DataLayerPrefetch<Dtype>, (void*)this))
- << "Pthread execution failed.";
- //LOG(INFO) << "Prefetch initialized.";
+ // check if we want to have mean
+ if (this->layer_param_.has_meanfile()) {
+ BlobProto blob_proto;
+ LOG(INFO) << "Loading mean file from" << this->layer_param_.meanfile();
+ ReadProtoFromBinaryFile(this->layer_param_.meanfile().c_str(), &blob_proto);
+ data_mean_.FromProto(blob_proto);
+ CHECK_EQ(data_mean_.num(), 1);
+ CHECK_EQ(data_mean_.channels(), datum_channels_);
+ CHECK_EQ(data_mean_.height(), datum_height_);
+ CHECK_EQ(data_mean_.width(), datum_width_);
+ } else {
+ // Simply initialize an all-empty mean.
+ data_mean_.Reshape(1, datum_channels_, datum_height_, datum_width_);
+ }
+ // Now, start the prefetch thread. Before calling prefetch, we make two
+ // cpu_data calls so that the prefetch thread does not accidentally make
+ // simultaneous cudaMalloc calls when the main thread is running. In some
+ // GPUs this seems to cause failures if we do not so.
+ prefetch_data_->mutable_cpu_data();
+ prefetch_label_->mutable_cpu_data();
+ data_mean_.cpu_data();
+ DLOG(INFO) << "Initializing prefetch";
+ CHECK(!pthread_create(&thread_, NULL, DataLayerPrefetch<Dtype>,
+ reinterpret_cast<void*>(this))) << "Pthread execution failed.";
+ DLOG(INFO) << "Prefetch initialized.";
}
template <typename Dtype>
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, DataLayerPrefetch<Dtype>, (void*)this))
- << "Pthread execution failed.";
+ CHECK(!pthread_create(&thread_, NULL, DataLayerPrefetch<Dtype>,
+ reinterpret_cast<void*>(this))) << "Pthread execution failed.";
}
template <typename Dtype>
// First, join the thread
CHECK(!pthread_join(thread_, NULL)) << "Pthread joining failed.";
// Copy the data
- CUDA_CHECK(cudaMemcpy((*top)[0]->mutable_gpu_data(), prefetch_data_->cpu_data(),
- sizeof(Dtype) * prefetch_data_->count(), cudaMemcpyHostToDevice));
- CUDA_CHECK(cudaMemcpy((*top)[1]->mutable_gpu_data(), prefetch_label_->cpu_data(),
- sizeof(Dtype) * prefetch_label_->count(), cudaMemcpyHostToDevice));
+ CUDA_CHECK(cudaMemcpy((*top)[0]->mutable_gpu_data(),
+ prefetch_data_->cpu_data(), sizeof(Dtype) * prefetch_data_->count(),
+ cudaMemcpyHostToDevice));
+ CUDA_CHECK(cudaMemcpy((*top)[1]->mutable_gpu_data(),
+ prefetch_label_->cpu_data(), sizeof(Dtype) * prefetch_label_->count(),
+ cudaMemcpyHostToDevice));
// Start a new prefetch thread
- CHECK(!pthread_create(&thread_, NULL, DataLayerPrefetch<Dtype>, (void*)this))
- << "Pthread execution failed.";
+ CHECK(!pthread_create(&thread_, NULL, DataLayerPrefetch<Dtype>,
+ reinterpret_cast<void*>(this))) << "Pthread execution failed.";
}
// The backward operations are dummy - they do not carry any computation.