Skip to content

Commit a2f7f47

Browse files
committedFeb 20, 2015
added a force_encoded_color flag to the data layer. Printing a warning if images of different channel dimensions are encoded together
1 parent 5246587 commit a2f7f47

File tree

7 files changed

+126
-6
lines changed

7 files changed

+126
-6
lines changed
 

‎examples/images/cat_gray.jpg

90.6 KB
Loading

‎include/caffe/util/io.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ inline bool ReadImageToDatum(const string& filename, const int label,
122122
}
123123

124124
bool DecodeDatumNative(Datum* datum);
125+
bool DecodeDatum(Datum* datum, bool is_color);
125126

126127
cv::Mat ReadImageToCVMat(const string& filename,
127128
const int height, const int width, const bool is_color);
@@ -135,6 +136,7 @@ cv::Mat ReadImageToCVMat(const string& filename,
135136
cv::Mat ReadImageToCVMat(const string& filename);
136137

137138
cv::Mat DecodeDatumToCVMatNative(const Datum& datum);
139+
cv::Mat DecodeDatumToCVMat(const Datum& datum, bool is_color);
138140

139141
void CVMatToDatum(const cv::Mat& cv_img, Datum* datum);
140142

‎src/caffe/layers/data_layer.cpp

+13-2
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ void DataLayer<Dtype>::DataLayerSetUp(const vector<Blob<Dtype>*>& bottom,
4242
Datum datum;
4343
datum.ParseFromString(cursor_->value());
4444

45-
if (DecodeDatumNative(&datum)) {
45+
bool force_color = this->layer_param_.data_param().force_encoded_color();
46+
if ((force_color && DecodeDatum(&datum, true)) ||
47+
DecodeDatumNative(&datum)) {
4648
LOG(INFO) << "Decoding Datum";
4749
}
4850
// image
@@ -90,6 +92,7 @@ void DataLayer<Dtype>::InternalThreadEntry() {
9092
top_label = this->prefetch_label_.mutable_cpu_data();
9193
}
9294
const int batch_size = this->layer_param_.data_param().batch_size();
95+
bool force_color = this->layer_param_.data_param().force_encoded_color();
9396
for (int item_id = 0; item_id < batch_size; ++item_id) {
9497
timer.Start();
9598
// get a blob
@@ -98,7 +101,15 @@ void DataLayer<Dtype>::InternalThreadEntry() {
98101

99102
cv::Mat cv_img;
100103
if (datum.encoded()) {
101-
cv_img = DecodeDatumToCVMatNative(datum);
104+
if (force_color)
105+
cv_img = DecodeDatumToCVMat(datum, true);
106+
else
107+
cv_img = DecodeDatumToCVMatNative(datum);
108+
if (cv_img.channels() != this->transformed_data_.channels())
109+
LOG(WARNING) << "Your dataset contains encoded images with mixed "
110+
<< "channel sizes. Consider adding a 'force_color' flag to the "
111+
<< "model definition, or rebuild your dataset using "
112+
<< "convert_imageset.";
102113
}
103114
read_time += timer.MicroSeconds();
104115
timer.Start();

‎src/caffe/layers/window_data_layer.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ void WindowDataLayer<Dtype>::InternalThreadEntry() {
281281
if (this->cache_images_) {
282282
pair<std::string, Datum> image_cached =
283283
image_database_cache_[window[WindowDataLayer<Dtype>::IMAGE_INDEX]];
284-
cv_img = DecodeDatumToCVMatNative(image_cached.second);
284+
cv_img = DecodeDatumToCVMat(image_cached.second, true);
285285
} else {
286286
cv_img = cv::imread(image.first, CV_LOAD_IMAGE_COLOR);
287287
if (!cv_img.data) {

‎src/caffe/proto/caffe.proto

+2
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,8 @@ message DataParameter {
426426
// DEPRECATED. See TransformationParameter. Specify if we want to randomly mirror
427427
// data.
428428
optional bool mirror = 6 [default = false];
429+
// Force the encoded image to have 3 color channels
430+
optional bool force_encoded_color = 9 [default = false];
429431
}
430432

431433
// Message that stores parameters used by DropoutLayer

‎src/caffe/test/test_io.cpp

+86-2
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,60 @@ TEST_F(IOTest, TestReadFileToDatum) {
286286
}
287287

288288
TEST_F(IOTest, TestDecodeDatum) {
289+
string filename = EXAMPLES_SOURCE_DIR "images/cat.jpg";
290+
Datum datum;
291+
EXPECT_TRUE(ReadFileToDatum(filename, &datum));
292+
EXPECT_TRUE(DecodeDatum(&datum, true));
293+
EXPECT_FALSE(DecodeDatum(&datum, true));
294+
Datum datum_ref;
295+
ReadImageToDatumReference(filename, 0, 0, 0, true, &datum_ref);
296+
EXPECT_EQ(datum.channels(), datum_ref.channels());
297+
EXPECT_EQ(datum.height(), datum_ref.height());
298+
EXPECT_EQ(datum.width(), datum_ref.width());
299+
EXPECT_EQ(datum.data().size(), datum_ref.data().size());
300+
301+
const string& data = datum.data();
302+
const string& data_ref = datum_ref.data();
303+
for (int i = 0; i < datum.data().size(); ++i) {
304+
EXPECT_TRUE(data[i] == data_ref[i]);
305+
}
306+
}
307+
308+
TEST_F(IOTest, TestDecodeDatumToCVMat) {
309+
string filename = EXAMPLES_SOURCE_DIR "images/cat.jpg";
310+
Datum datum;
311+
EXPECT_TRUE(ReadFileToDatum(filename, &datum));
312+
cv::Mat cv_img = DecodeDatumToCVMat(datum, true);
313+
EXPECT_EQ(cv_img.channels(), 3);
314+
EXPECT_EQ(cv_img.rows, 360);
315+
EXPECT_EQ(cv_img.cols, 480);
316+
cv_img = DecodeDatumToCVMat(datum, false);
317+
EXPECT_EQ(cv_img.channels(), 1);
318+
EXPECT_EQ(cv_img.rows, 360);
319+
EXPECT_EQ(cv_img.cols, 480);
320+
}
321+
322+
TEST_F(IOTest, TestDecodeDatumToCVMatContent) {
323+
string filename = EXAMPLES_SOURCE_DIR "images/cat.jpg";
324+
Datum datum;
325+
EXPECT_TRUE(ReadImageToDatum(filename, 0, std::string("jpg"), &datum));
326+
cv::Mat cv_img = DecodeDatumToCVMat(datum, true);
327+
cv::Mat cv_img_ref = ReadImageToCVMat(filename);
328+
EXPECT_EQ(cv_img_ref.channels(), cv_img.channels());
329+
EXPECT_EQ(cv_img_ref.rows, cv_img.rows);
330+
EXPECT_EQ(cv_img_ref.cols, cv_img.cols);
331+
332+
for (int c = 0; c < datum.channels(); ++c) {
333+
for (int h = 0; h < datum.height(); ++h) {
334+
for (int w = 0; w < datum.width(); ++w) {
335+
EXPECT_TRUE(cv_img.at<cv::Vec3b>(h, w)[c]==
336+
cv_img_ref.at<cv::Vec3b>(h, w)[c]);
337+
}
338+
}
339+
}
340+
}
341+
342+
TEST_F(IOTest, TestDecodeDatumNative) {
289343
string filename = EXAMPLES_SOURCE_DIR "images/cat.jpg";
290344
Datum datum;
291345
EXPECT_TRUE(ReadFileToDatum(filename, &datum));
@@ -305,7 +359,7 @@ TEST_F(IOTest, TestDecodeDatum) {
305359
}
306360
}
307361

308-
TEST_F(IOTest, TestDecodeDatumToCVMat) {
362+
TEST_F(IOTest, TestDecodeDatumToCVMatNative) {
309363
string filename = EXAMPLES_SOURCE_DIR "images/cat.jpg";
310364
Datum datum;
311365
EXPECT_TRUE(ReadFileToDatum(filename, &datum));
@@ -315,7 +369,37 @@ TEST_F(IOTest, TestDecodeDatumToCVMat) {
315369
EXPECT_EQ(cv_img.cols, 480);
316370
}
317371

318-
TEST_F(IOTest, TestDecodeDatumToCVMatContent) {
372+
TEST_F(IOTest, TestDecodeDatumNativeGray) {
373+
string filename = EXAMPLES_SOURCE_DIR "images/cat_gray.jpg";
374+
Datum datum;
375+
EXPECT_TRUE(ReadFileToDatum(filename, &datum));
376+
EXPECT_TRUE(DecodeDatumNative(&datum));
377+
EXPECT_FALSE(DecodeDatumNative(&datum));
378+
Datum datum_ref;
379+
ReadImageToDatumReference(filename, 0, 0, 0, false, &datum_ref);
380+
EXPECT_EQ(datum.channels(), datum_ref.channels());
381+
EXPECT_EQ(datum.height(), datum_ref.height());
382+
EXPECT_EQ(datum.width(), datum_ref.width());
383+
EXPECT_EQ(datum.data().size(), datum_ref.data().size());
384+
385+
const string& data = datum.data();
386+
const string& data_ref = datum_ref.data();
387+
for (int i = 0; i < datum.data().size(); ++i) {
388+
EXPECT_TRUE(data[i] == data_ref[i]);
389+
}
390+
}
391+
392+
TEST_F(IOTest, TestDecodeDatumToCVMatNativeGray) {
393+
string filename = EXAMPLES_SOURCE_DIR "images/cat_gray.jpg";
394+
Datum datum;
395+
EXPECT_TRUE(ReadFileToDatum(filename, &datum));
396+
cv::Mat cv_img = DecodeDatumToCVMatNative(datum);
397+
EXPECT_EQ(cv_img.channels(), 1);
398+
EXPECT_EQ(cv_img.rows, 360);
399+
EXPECT_EQ(cv_img.cols, 480);
400+
}
401+
402+
TEST_F(IOTest, TestDecodeDatumToCVMatContentNative) {
319403
string filename = EXAMPLES_SOURCE_DIR "images/cat.jpg";
320404
Datum datum;
321405
EXPECT_TRUE(ReadImageToDatum(filename, 0, std::string("jpg"), &datum));

‎src/caffe/util/io.cpp

+22-1
Original file line numberDiff line numberDiff line change
@@ -167,9 +167,21 @@ cv::Mat DecodeDatumToCVMatNative(const Datum& datum) {
167167
}
168168
return cv_img;
169169
}
170+
cv::Mat DecodeDatumToCVMat(const Datum& datum, bool is_color) {
171+
cv::Mat cv_img;
172+
CHECK(datum.encoded()) << "Datum not encoded";
173+
const string& data = datum.data();
174+
std::vector<char> vec_data(data.c_str(), data.c_str() + data.size());
175+
int cv_read_flag = (is_color ? CV_LOAD_IMAGE_COLOR :
176+
CV_LOAD_IMAGE_GRAYSCALE);
177+
cv_img = cv::imdecode(vec_data, cv_read_flag);
178+
if (!cv_img.data) {
179+
LOG(ERROR) << "Could not decode datum ";
180+
}
181+
return cv_img;
182+
}
170183

171184
// If Datum is encoded will decoded using DecodeDatumToCVMat and CVMatToDatum
172-
// if height and width are set it will resize it
173185
// If Datum is not encoded will do nothing
174186
bool DecodeDatumNative(Datum* datum) {
175187
if (datum->encoded()) {
@@ -180,6 +192,15 @@ bool DecodeDatumNative(Datum* datum) {
180192
return false;
181193
}
182194
}
195+
bool DecodeDatum(Datum* datum, bool is_color) {
196+
if (datum->encoded()) {
197+
cv::Mat cv_img = DecodeDatumToCVMat((*datum), is_color);
198+
CVMatToDatum(cv_img, datum);
199+
return true;
200+
} else {
201+
return false;
202+
}
203+
}
183204

184205
void CVMatToDatum(const cv::Mat& cv_img, Datum* datum) {
185206
CHECK(cv_img.depth() == CV_8U) << "Image data type must be unsigned byte";

0 commit comments

Comments
 (0)
Please sign in to comment.