背景信息:我需要加载一些16位灰度PNG。
Caffe是否支持通过ImageDataLayer
?
经过一些谷歌搜索,答案似乎并没有。
ImageDataLayer
依赖于this io routine
cv::Mat ReadImageToCVMat(const string& filename,
const int height, const int width, const bool is_color) {
cv::Mat cv_img;
int cv_read_flag = (is_color ? CV_LOAD_IMAGE_COLOR :
CV_LOAD_IMAGE_GRAYSCALE);
cv::Mat cv_img_origin = cv::imread(filename, cv_read_flag);
if (!cv_img_origin.data) {
LOG(ERROR) << "Could not open or find file " << filename;
return cv_img_origin;
}
if (height > 0 && width > 0) {
cv::resize(cv_img_origin, cv_img, cv::Size(width, height));
} else {
cv_img = cv_img_origin;
}
return cv_img;
}
使用opencv的cv::imread
功能。除非设置了适当的标志,否则此函数将读取输入为8位
CV_LOAD_IMAGE_ANYDEPTH - 如果设置,则返回16位/ 32位图像 输入具有相应的深度,否则将其转换为8位。
简单地添加适当的标志将不起作用,因为稍后在代码[io.cpp]中他们检查8位深度:
void CVMatToDatum(const cv::Mat& cv_img, Datum* datum) {
CHECK(cv_img.depth() == CV_8U) << "Image data type must be unsigned byte";
... }
我可以删除支票,但我担心它有一个原因,可能会发生不可预测的结果。 任何人都可以对这个问题有所了解吗?
答案 0 :(得分:2)
您可以修补ImageDataLayer以读取16位图像:
后
int cv_read_flag = (is_color ? CV_LOAD_IMAGE_COLOR :
CV_LOAD_IMAGE_GRAYSCALE);
添加
cv_read_flag |= CV_LOAD_IMAGE_ANYDEPTH;
此
CHECK(cv_img.depth() == CV_8U) << "Image data type must be unsigned byte";
变为
CHECK(cv_img.depth() == CV_8U || cv_img.depth() == CV_16U) << "Image data type must be uint8 or uint16";
bool is16bit = cv_img.depth() == CV_16U;
将uint16_t类型的指针添加到:
const uchar* ptr = cv_cropped_img.ptr<uchar>(h);
像这样
const uint16_t* ptr_16 = cv_cropped_img.ptr<uint16_t>(h);
然后使用适当的指针读取:
Dtype pixel = static_cast<Dtype>(ptr[img_index++]);
变为
Dtype pixel;
if(is16bit)
pixel = static_cast<Dtype>(ptr_16[img_index++]);
else
pixel = static_cast<Dtype>(ptr[img_index++]);
答案 1 :(得分:1)
默认情况下,Caffe使用float32
个变量。图像通常表示为C
- by - H
- by - W
blob,其中C=3
表示三个颜色通道。因此,如果您正确转换为float32
,则使用uint16
类型的三个频道可以处理float32
中的图片。
我没有使用"ImageData"
图层的个人经验,因此我无法评论您如何使用此图层加载uint16
图像数据。
但,您可能会发现"HDF5Data"
图层非常有用:您可以从外部读取图像并将其转换为hdf5
数据格式(支持float32
),然后通过"HDF5Data"
图层将转换后的数据提供给caffe。