vector<int> DataTransformer<Dtype>::InferBlobShape(const Datum& datum) { if (datum.encoded()) { #ifdef USE_OPENCV CHECK(!(param_.force_color() && param_.force_gray())) << "cannot set both force_color and force_gray"; cv::Mat cv_img; if (param_.force_color() || param_.force_gray()) { // If force_color then decode in color otherwise decode in gray. cv_img = DecodeDatumToCVMat(datum, param_.force_color()); } else { cv_img = DecodeDatumToCVMatNative(datum); } // InferBlobShape using the cv::image. return InferBlobShape(cv_img); #else LOG(FATAL) << "Encoded datum requires OpenCV; compile with USE_OPENCV."; #endif // USE_OPENCV } const int crop_size = param_.crop_size(); const int datum_channels = datum.channels(); const int datum_height = datum.height(); const int datum_width = datum.width(); // Check dimensions. CHECK_GT(datum_channels, 0); CHECK_GE(datum_height, crop_size); CHECK_GE(datum_width, crop_size); // Build BlobShape. vector<int> shape(4); shape[0] = 1; shape[1] = datum_channels; shape[2] = (crop_size)? crop_size: datum_height; shape[3] = (crop_size)? crop_size: datum_width; return shape; }
TEST_F(IOTest, TestDecodeDatumToCVMatNativeGray) { string filename = EXAMPLES_SOURCE_DIR "images/cat_gray.jpg"; Datum datum; EXPECT_TRUE(ReadFileToDatum(filename, &datum)); cv::Mat cv_img = DecodeDatumToCVMatNative(datum); EXPECT_EQ(cv_img.channels(), 1); EXPECT_EQ(cv_img.rows, 360); EXPECT_EQ(cv_img.cols, 480); }
// If Datum is encoded will decoded using DecodeDatumToCVMat and CVMatToDatum // If Datum is not encoded will do nothing bool DecodeDatumNative(Datum* datum) { if (datum->encoded()) { cv::Mat cv_img = DecodeDatumToCVMatNative((*datum)); CVMatToDatum(cv_img, datum); return true; } else { return false; } }
void DataTransformer<Dtype>::Transform(const Datum& datum, Blob<Dtype>* transformed_blob) { #ifndef CAFFE_HEADLESS // If datum is encoded, decoded and transform the cv::image. if (datum.encoded()) { CHECK(!(param_.force_color() && param_.force_gray())) << "cannot set both force_color and force_gray"; cv::Mat cv_img; if (param_.force_color() || param_.force_gray()) { // If force_color then decode in color otherwise decode in gray. cv_img = DecodeDatumToCVMat(datum, param_.force_color()); } else { cv_img = DecodeDatumToCVMatNative(datum); } // Transform the cv::image into blob. return Transform(cv_img, transformed_blob); } else { if (param_.force_color() || param_.force_gray()) { LOG(ERROR) << "force_color and force_gray only for encoded datum"; } } #endif const int crop_size = param_.crop_size(); const int datum_channels = datum.channels(); const int datum_height = datum.height(); const int datum_width = datum.width(); // Check dimensions. const int channels = transformed_blob->channels(); const int height = transformed_blob->height(); const int width = transformed_blob->width(); const int num = transformed_blob->num(); CHECK_EQ(channels, datum_channels); CHECK_LE(height, datum_height); CHECK_LE(width, datum_width); CHECK_GE(num, 1); if (crop_size) { CHECK_EQ(crop_size, height); CHECK_EQ(crop_size, width); } else { CHECK_EQ(datum_height, height); CHECK_EQ(datum_width, width); } Dtype* transformed_data = transformed_blob->mutable_cpu_data(); Transform(datum, transformed_data); }
TEST_F(IOTest, TestDecodeDatumToCVMatContentNative) { string filename = EXAMPLES_SOURCE_DIR "images/cat.jpg"; Datum datum; EXPECT_TRUE(ReadImageToDatum(filename, 0, std::string("jpg"), &datum)); cv::Mat cv_img = DecodeDatumToCVMatNative(datum); cv::Mat cv_img_ref = ReadImageToCVMat(filename); EXPECT_EQ(cv_img_ref.channels(), cv_img.channels()); EXPECT_EQ(cv_img_ref.rows, cv_img.rows); EXPECT_EQ(cv_img_ref.cols, cv_img.cols); for (int c = 0; c < datum.channels(); ++c) { for (int h = 0; h < datum.height(); ++h) { for (int w = 0; w < datum.width(); ++w) { EXPECT_TRUE(cv_img.at<cv::Vec3b>(h, w)[c]== cv_img_ref.at<cv::Vec3b>(h, w)[c]); } } } }
void CPMDataLayer<Dtype>::load_batch(Batch<Dtype>* batch) { CPUTimer batch_timer; batch_timer.Start(); double deque_time = 0; double decod_time = 0; double trans_time = 0; static int cnt = 0; CPUTimer timer; CHECK(batch->data_.count()); CHECK(this->transformed_data_.count()); // Reshape on single input batches for inputs of varying dimension. const int batch_size = this->layer_param_.cpmdata_param().batch_size(); const int crop_size = this->layer_param_.transform_param().crop_size(); bool force_color = this->layer_param_.cpmdata_param().force_encoded_color(); if (batch_size == 1 && crop_size == 0) { Datum& datum = *(reader_.full().peek()); if (datum.encoded()) { if (force_color) { DecodeDatum(&datum, true); } else { DecodeDatumNative(&datum); } } batch->data_.Reshape(1, datum.channels(), datum.height(), datum.width()); this->transformed_data_.Reshape(1, datum.channels(), datum.height(), datum.width()); } Dtype* top_data = batch->data_.mutable_cpu_data(); Dtype* top_label = NULL; // suppress warnings about uninitialized variables if (this->output_labels_) { top_label = batch->label_.mutable_cpu_data(); } for (int item_id = 0; item_id < batch_size; ++item_id) { // get a blob timer.Start(); Datum& datum = *(reader_.full().pop("Waiting for data")); deque_time += timer.MicroSeconds(); timer.Start(); cv::Mat cv_img; if (datum.encoded()) { if (force_color) { cv_img = DecodeDatumToCVMat(datum, true); } else { cv_img = DecodeDatumToCVMatNative(datum); } if (cv_img.channels() != this->transformed_data_.channels()) { LOG(WARNING) << "Your dataset contains encoded images with mixed " << "channel sizes. Consider adding a 'force_color' flag to the " << "model definition, or rebuild your dataset using " << "convert_imageset."; } } decod_time += timer.MicroSeconds(); // Apply data transformations (mirror, scale, crop...) timer.Start(); const int offset_data = batch->data_.offset(item_id); const int offset_label = batch->label_.offset(item_id); this->transformed_data_.set_cpu_data(top_data + offset_data); this->transformed_label_.set_cpu_data(top_label + offset_label); if (datum.encoded()) { this->data_transformer_->Transform(cv_img, &(this->transformed_data_)); } else { this->data_transformer_->Transform_nv(datum, &(this->transformed_data_), &(this->transformed_label_), cnt); ++cnt; } // if (this->output_labels_) { // top_label[item_id] = datum.label(); // } trans_time += timer.MicroSeconds(); reader_.free().push(const_cast<Datum*>(&datum)); } batch_timer.Stop(); #ifdef BENCHMARK_DATA LOG(INFO) << "Prefetch batch: " << batch_timer.MilliSeconds() << " ms."; LOG(INFO) << " Dequeue time: " << deque_time / 1000 << " ms."; LOG(INFO) << " Decode time: " << decod_time / 1000 << " ms."; LOG(INFO) << "Transform time: " << trans_time / 1000 << " ms."; #endif }
void DataLayer<Dtype>::InternalThreadEntry() { CPUTimer batch_timer; batch_timer.Start(); double read_time = 0; double trans_time = 0; CPUTimer timer; CHECK(this->prefetch_data_.count()); CHECK(this->transformed_data_.count()); // Reshape on single input batches for inputs of varying dimension. const int batch_size = this->layer_param_.data_param().batch_size(); const int crop_size = this->layer_param_.transform_param().crop_size(); if (batch_size == 1 && crop_size == 0) { Datum datum; datum.ParseFromString(cursor_->value()); this->prefetch_data_.Reshape(1, datum.channels(), datum.height(), datum.width()); this->transformed_data_.Reshape(1, datum.channels(), datum.height(), datum.width()); } Dtype* top_data = this->prefetch_data_.mutable_cpu_data(); Dtype* top_label = NULL; // suppress warnings about uninitialized variables if (this->output_labels_) { top_label = this->prefetch_label_.mutable_cpu_data(); } bool force_color = this->layer_param_.data_param().force_encoded_color(); for (int item_id = 0; item_id < batch_size; ++item_id) { timer.Start(); // get a blob Datum datum; datum.ParseFromString(cursor_->value()); cv::Mat cv_img; if (datum.encoded()) { if (force_color) { cv_img = DecodeDatumToCVMat(datum, true); } else { cv_img = DecodeDatumToCVMatNative(datum); } if (cv_img.channels() != this->transformed_data_.channels()) { LOG(WARNING) << "Your dataset contains encoded images with mixed " << "channel sizes. Consider adding a 'force_color' flag to the " << "model definition, or rebuild your dataset using " << "convert_imageset."; } } read_time += timer.MicroSeconds(); timer.Start(); // 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_)); } else { this->data_transformer_->Transform(datum, &(this->transformed_data_)); } if (this->output_labels_) { for (int label_i = 0; label_i < datum.label_size(); ++label_i){ top_label[item_id * datum.label_size() + label_i] = datum.label(label_i); } //top_label[item_id] = datum.label(); } trans_time += timer.MicroSeconds(); // go to the next iter cursor_->Next(); if (!cursor_->valid()) { DLOG(INFO) << "Restarting data prefetching from start."; cursor_->SeekToFirst(); } } batch_timer.Stop(); DLOG(INFO) << "Prefetch batch: " << batch_timer.MilliSeconds() << " ms."; DLOG(INFO) << " Read time: " << read_time / 1000 << " ms."; DLOG(INFO) << "Transform time: " << trans_time / 1000 << " ms."; }