梳理caffe代码io(十三)
2016-04-03 16:25
302 查看
io包含了创建临时文件临时目录操作,以及从txt文件以及bin文件读取proto数据或者写入proto的数据到txt或者bin文件。io其实就是提供如何读取如何写入的一些读取图像或者文件,以及它们之间的一些转化的函数。
hpp文件:
#ifndef CAFFE_UTIL_IO_H_
#define CAFFE_UTIL_IO_H_
#include <unistd.h>
#include <string>
#include "google/protobuf/message.h"
#include "caffe/blob.hpp"
#include "caffe/common.hpp"
#include "caffe/proto/caffe.pb.h"
namespace caffe {
using ::google::protobuf::Message;
// 内联函数,创建临时文件
inline void MakeTempFilename(string* temp_filename) {
temp_filename->clear();
*temp_filename = "/tmp/caffe_test.XXXXXX";
char* temp_filename_cstr = new char[temp_filename->size() + 1];
// NOLINT_NEXT_LINE(runtime/printf)
strcpy(temp_filename_cstr, temp_filename->c_str());
int fd = mkstemp(temp_filename_cstr);
CHECK_GE(fd, 0) << "Failed to open a temporary file at: " << *temp_filename;
close(fd);
*temp_filename = temp_filename_cstr;
delete[] temp_filename_cstr;
}
// 内联函数,创建临时目录
inline void MakeTempDir(string* temp_dirname) {
temp_dirname->clear();
*temp_dirname = "/tmp/caffe_test.XXXXXX";
char* temp_dirname_cstr = new char[temp_dirname->size() + 1];
// NOLINT_NEXT_LINE(runtime/printf)
strcpy(temp_dirname_cstr, temp_dirname->c_str());
char* mkdtemp_result = mkdtemp(temp_dirname_cstr);
CHECK(mkdtemp_result != NULL)
<< "Failed to create a temporary directory at: " << *temp_dirname;
*temp_dirname = temp_dirname_cstr;
delete[] temp_dirname_cstr;
}
// 从txt读取proto的定义
bool ReadProtoFromTextFile(const char* filename, Message* proto);
// 从text读取proto的定义
inline bool ReadProtoFromTextFile(const string& filename, Message* proto) {
return ReadProtoFromTextFile(filename.c_str(), proto);
}
// 从text读取proto的定义,只是增加了检查而已
inline void ReadProtoFromTextFileOrDie(const char* filename, Message* proto) {
CHECK(ReadProtoFromTextFile(filename, proto));
}
// 从text读取proto的定义,只是增加了检查而已
inline void ReadProtoFromTextFileOrDie(const string& filename, Message* proto) {
ReadProtoFromTextFileOrDie(filename.c_str(), proto);
}
// 将proto写入到txt文件
void WriteProtoToTextFile(const Message& proto, const char* filename);
inline void WriteProtoToTextFile(const Message& proto, const string& filename) {
WriteProtoToTextFile(proto, filename.c_str());
}
// 从bin读取proto的定义
bool ReadProtoFromBinaryFile(const char* filename, Message* proto);
// 从bin读取proto的定义
inline bool ReadProtoFromBinaryFile(const string& filename, Message* proto) {
return ReadProtoFromBinaryFile(filename.c_str(), proto);
}
// 从bin读取proto的定义,只是增加了检查而已
inline void ReadProtoFromBinaryFileOrDie(const char* filename, Message* proto) {
CHECK(ReadProtoFromBinaryFile(filename, proto));
}
// 从bin读取proto的定义,只是增加了检查而已
inline void ReadProtoFromBinaryFileOrDie(const string& filename,
Message* proto) {
ReadProtoFromBinaryFileOrDie(filename.c_str(), proto);
}
// 将proto写入到bin文件
void WriteProtoToBinaryFile(const Message& proto, const char* filename);
// 内联函数,将proto写入到bin文件
inline void WriteProtoToBinaryFile(
const Message& proto, const string& filename) {
WriteProtoToBinaryFile(proto, filename.c_str());
}
// 从文件读取数据到Datum
bool ReadFileToDatum(const string& filename, const int label, Datum* datum);
// 内联函数,从文件读取数据到Datum
inline bool ReadFileToDatum(const string& filename, Datum* datum) {
return ReadFileToDatum(filename, -1, datum);
}
// 从图像文件读取数据到Datum
bool ReadImageToDatum(const string& filename, const int label,
const int height, const int width, const bool is_color,
const std::string & encoding, Datum* datum);
// 内联函数,从图像文件(彩色还是黑白?)读取数据到Datum,指定图像大小
inline bool ReadImageToDatum(const string& filename, const int label,
const int height, const int width, const bool is_color, Datum* datum) {
return ReadImageToDatum(filename, label, height, width, is_color,
"", datum);
}
// 内联函数,从彩色图像文件读取数据到Datum,指定图像大小
inline bool ReadImageToDatum(const string& filename, const int label,
const int height, const int width, Datum* datum) {
return ReadImageToDatum(filename, label, height, width, true, datum);
}
// 内联函数,从图像文件(彩色还是黑白?)读取数据到Datum,自动获取图像大小
inline bool ReadImageToDatum(const string& filename, const int label,
const bool is_color, Datum* datum) {
return ReadImageToDatum(filename, label, 0, 0, is_color, datum);
}
// 内联函数,从彩色图像文件读取数据到Datum,自动获取图像大小
inline bool ReadImageToDatum(const string& filename, const int label,
Datum* datum) {
return ReadImageToDatum(filename, label, 0, 0, true, datum);
}
// 内联函数,从彩色图像文件读取数据到Datum,自动获取图像大小,指定编码格式
inline bool ReadImageToDatum(const string& filename, const int label,
const std::string & encoding, Datum* datum) {
return ReadImageToDatum(filename, label, 0, 0, true, encoding, datum);
}
// 对Datum进行解码
bool DecodeDatumNative(Datum* datum);
// 对彩色图像的Datum进行解码
bool DecodeDatum(Datum* datum, bool is_color);
#ifdef USE_OPENCV
// 将图像读取到CVMat,指定图像大小,是否彩色
cv::Mat ReadImageToCVMat(const string& filename,
const int height, const int width, const bool is_color);
// 将图像读取到CVMat,指定图像大小
cv::Mat ReadImageToCVMat(const string& filename,
const int height, const int width);
// 将图像读取到CVMat,指定是否彩色
cv::Mat ReadImageToCVMat(const string& filename,
const bool is_color);
// 将图像读取到CVMat
cv::Mat ReadImageToCVMat(const string& filename);
// 将Datum解码为为CVMat
cv::Mat DecodeDatumToCVMatNative(const Datum& datum);
// 将彩色图像的Datum解码为为CVMat
cv::Mat DecodeDatumToCVMat(const Datum& datum, bool is_color);
// 将CVMat转换为Datum
void CVMatToDatum(const cv::Mat& cv_img, Datum* datum);
#endif // USE_OPENCV
} // namespace caffe
#endif // CAFFE_UTIL_IO_H_实现:
hpp文件:
#ifndef CAFFE_UTIL_IO_H_
#define CAFFE_UTIL_IO_H_
#include <unistd.h>
#include <string>
#include "google/protobuf/message.h"
#include "caffe/blob.hpp"
#include "caffe/common.hpp"
#include "caffe/proto/caffe.pb.h"
namespace caffe {
using ::google::protobuf::Message;
// 内联函数,创建临时文件
inline void MakeTempFilename(string* temp_filename) {
temp_filename->clear();
*temp_filename = "/tmp/caffe_test.XXXXXX";
char* temp_filename_cstr = new char[temp_filename->size() + 1];
// NOLINT_NEXT_LINE(runtime/printf)
strcpy(temp_filename_cstr, temp_filename->c_str());
int fd = mkstemp(temp_filename_cstr);
CHECK_GE(fd, 0) << "Failed to open a temporary file at: " << *temp_filename;
close(fd);
*temp_filename = temp_filename_cstr;
delete[] temp_filename_cstr;
}
// 内联函数,创建临时目录
inline void MakeTempDir(string* temp_dirname) {
temp_dirname->clear();
*temp_dirname = "/tmp/caffe_test.XXXXXX";
char* temp_dirname_cstr = new char[temp_dirname->size() + 1];
// NOLINT_NEXT_LINE(runtime/printf)
strcpy(temp_dirname_cstr, temp_dirname->c_str());
char* mkdtemp_result = mkdtemp(temp_dirname_cstr);
CHECK(mkdtemp_result != NULL)
<< "Failed to create a temporary directory at: " << *temp_dirname;
*temp_dirname = temp_dirname_cstr;
delete[] temp_dirname_cstr;
}
// 从txt读取proto的定义
bool ReadProtoFromTextFile(const char* filename, Message* proto);
// 从text读取proto的定义
inline bool ReadProtoFromTextFile(const string& filename, Message* proto) {
return ReadProtoFromTextFile(filename.c_str(), proto);
}
// 从text读取proto的定义,只是增加了检查而已
inline void ReadProtoFromTextFileOrDie(const char* filename, Message* proto) {
CHECK(ReadProtoFromTextFile(filename, proto));
}
// 从text读取proto的定义,只是增加了检查而已
inline void ReadProtoFromTextFileOrDie(const string& filename, Message* proto) {
ReadProtoFromTextFileOrDie(filename.c_str(), proto);
}
// 将proto写入到txt文件
void WriteProtoToTextFile(const Message& proto, const char* filename);
inline void WriteProtoToTextFile(const Message& proto, const string& filename) {
WriteProtoToTextFile(proto, filename.c_str());
}
// 从bin读取proto的定义
bool ReadProtoFromBinaryFile(const char* filename, Message* proto);
// 从bin读取proto的定义
inline bool ReadProtoFromBinaryFile(const string& filename, Message* proto) {
return ReadProtoFromBinaryFile(filename.c_str(), proto);
}
// 从bin读取proto的定义,只是增加了检查而已
inline void ReadProtoFromBinaryFileOrDie(const char* filename, Message* proto) {
CHECK(ReadProtoFromBinaryFile(filename, proto));
}
// 从bin读取proto的定义,只是增加了检查而已
inline void ReadProtoFromBinaryFileOrDie(const string& filename,
Message* proto) {
ReadProtoFromBinaryFileOrDie(filename.c_str(), proto);
}
// 将proto写入到bin文件
void WriteProtoToBinaryFile(const Message& proto, const char* filename);
// 内联函数,将proto写入到bin文件
inline void WriteProtoToBinaryFile(
const Message& proto, const string& filename) {
WriteProtoToBinaryFile(proto, filename.c_str());
}
// 从文件读取数据到Datum
bool ReadFileToDatum(const string& filename, const int label, Datum* datum);
// 内联函数,从文件读取数据到Datum
inline bool ReadFileToDatum(const string& filename, Datum* datum) {
return ReadFileToDatum(filename, -1, datum);
}
// 从图像文件读取数据到Datum
bool ReadImageToDatum(const string& filename, const int label,
const int height, const int width, const bool is_color,
const std::string & encoding, Datum* datum);
// 内联函数,从图像文件(彩色还是黑白?)读取数据到Datum,指定图像大小
inline bool ReadImageToDatum(const string& filename, const int label,
const int height, const int width, const bool is_color, Datum* datum) {
return ReadImageToDatum(filename, label, height, width, is_color,
"", datum);
}
// 内联函数,从彩色图像文件读取数据到Datum,指定图像大小
inline bool ReadImageToDatum(const string& filename, const int label,
const int height, const int width, Datum* datum) {
return ReadImageToDatum(filename, label, height, width, true, datum);
}
// 内联函数,从图像文件(彩色还是黑白?)读取数据到Datum,自动获取图像大小
inline bool ReadImageToDatum(const string& filename, const int label,
const bool is_color, Datum* datum) {
return ReadImageToDatum(filename, label, 0, 0, is_color, datum);
}
// 内联函数,从彩色图像文件读取数据到Datum,自动获取图像大小
inline bool ReadImageToDatum(const string& filename, const int label,
Datum* datum) {
return ReadImageToDatum(filename, label, 0, 0, true, datum);
}
// 内联函数,从彩色图像文件读取数据到Datum,自动获取图像大小,指定编码格式
inline bool ReadImageToDatum(const string& filename, const int label,
const std::string & encoding, Datum* datum) {
return ReadImageToDatum(filename, label, 0, 0, true, encoding, datum);
}
// 对Datum进行解码
bool DecodeDatumNative(Datum* datum);
// 对彩色图像的Datum进行解码
bool DecodeDatum(Datum* datum, bool is_color);
#ifdef USE_OPENCV
// 将图像读取到CVMat,指定图像大小,是否彩色
cv::Mat ReadImageToCVMat(const string& filename,
const int height, const int width, const bool is_color);
// 将图像读取到CVMat,指定图像大小
cv::Mat ReadImageToCVMat(const string& filename,
const int height, const int width);
// 将图像读取到CVMat,指定是否彩色
cv::Mat ReadImageToCVMat(const string& filename,
const bool is_color);
// 将图像读取到CVMat
cv::Mat ReadImageToCVMat(const string& filename);
// 将Datum解码为为CVMat
cv::Mat DecodeDatumToCVMatNative(const Datum& datum);
// 将彩色图像的Datum解码为为CVMat
cv::Mat DecodeDatumToCVMat(const Datum& datum, bool is_color);
// 将CVMat转换为Datum
void CVMatToDatum(const cv::Mat& cv_img, Datum* datum);
#endif // USE_OPENCV
} // namespace caffe
#endif // CAFFE_UTIL_IO_H_实现:
#include <fcntl.h> #include <google/protobuf/io/coded_stream.h> #include <google/protobuf/io/zero_copy_stream_impl.h> #include <google/protobuf/text_format.h> #include <opencv2/core/core.hpp> #ifdef USE_OPENCV #include <opencv2/highgui/highgui.hpp> #include <opencv2/highgui/highgui_c.h> #include <opencv2/imgproc/imgproc.hpp> #endif // USE_OPENCV #include <stdint.h> #include <algorithm> #include <fstream> // NOLINT(readability/streams) #include <string> #include <vector> #include "caffe/common.hpp" #include "caffe/proto/caffe.pb.h" #include "caffe/util/io.hpp" const int kProtoReadBytesLimit = INT_MAX; // Max size of 2 GB minus 1 byte. namespace caffe { using google::protobuf::io::FileInputStream; using google::protobuf::io::FileOutputStream; using google::protobuf::io::ZeroCopyInputStream; using google::protobuf::io::CodedInputStream; using google::protobuf::io::ZeroCopyOutputStream; using google::protobuf::io::CodedOutputStream; using google::protobuf::Message; // 从文件读取Proto的txt文件 bool ReadProtoFromTextFile(const char* filename, Message* proto) { int fd = open(filename, O_RDONLY); CHECK_NE(fd, -1) << "File not found: " << filename; FileInputStream* input = new FileInputStream(fd);//新建一个FileInputStream对象 input // 注意如何使用protobuf去读取,解析input文件中的Message, 即使文件中参数定义顺序与Message中的参数定义顺序不一致,也可以解析。 bool success = google::protobuf::TextFormat::Parse(input, proto); delete input; close(fd); return success; } // 将proto写入到txt文件 void WriteProtoToTextFile(const Message& proto, const char* filename) { int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644); FileOutputStream* output = new FileOutputStream(fd); // 注意如何写入 CHECK(google::protobuf::TextFormat::Print(proto, output)); delete output; close(fd);// 和ReadProtoFromTextFile功能相反 } // 从bin读取proto的定义 bool ReadProtoFromBinaryFile(const char* filename, Message* proto) {//读取二进制文件 int fd = open(filename, O_RDONLY); CHECK_NE(fd, -1) << "File not found: " << filename; ZeroCopyInputStream* raw_input = new FileInputStream(fd); // 解码流com.google.protobuf.CodedInputStream CodedInputStream* coded_input = new CodedInputStream(raw_input); // 建立CodedInputStream类的对象coded_input coded_input->SetTotalBytesLimit(kProtoReadBytesLimit, 536870912); //折设置最大字节限制 bool success = proto->ParseFromCodedStream(coded_input); delete coded_input; delete raw_input; close(fd); return success; } // 将proto写入到bin文件 void WriteProtoToBinaryFile(const Message& proto, const char* filename) { fstream output(filename, ios::out | ios::trunc | ios::binary); CHECK(proto.SerializeToOstream(&output)); } #ifdef USE_OPENCV // 将图像读取到CVMat,指定图像大小,是否彩色 cv::Mat ReadImageToCVMat(const string& filename, const int height, const int width, const bool is_color) { //height,width都不为0则把图像resize 到height*width 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; } cv::Mat ReadImageToCVMat(const string& filename,//is_color 为1读入彩色图像,0灰度图 const int height, const int width) { return ReadImageToCVMat(filename, height, width, true); }//重载函数,读入彩色图 cv::Mat ReadImageToCVMat(const string& filename, const bool is_color) { return ReadImageToCVMat(filename, 0, 0, is_color); }//重载函数,读入图像但不resize cv::Mat ReadImageToCVMat(const string& filename) { return ReadImageToCVMat(filename, 0, 0, true); }//重载函数,读入彩色图像且不resize // Do the file extension and encoding match? // 看看是不是jpg还是jpeg的图像 static bool matchExt(const std::string & fn, std::string en) { size_t p = fn.rfind('.');//p 为文件名中“.”所在位置的索引 std::string ext = p != fn.npos ? fn.substr(p) : fn;//ext为文件后缀名".xxx" std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower); //把ext中的大写字母转化小写字母 std::transform(en.begin(), en.end(), en.begin(), ::tolower); if ( ext == en ) return true; if ( en == "jpg" && ext == "jpeg" ) return true; return false; } // 从图像文件读取数据到Datum bool ReadImageToDatum(const string& filename, const int label, const int height, const int width, const bool is_color, const std::string & encoding, Datum* datum) { cv::Mat cv_img = ReadImageToCVMat(filename, height, width, is_color); if (cv_img.data) { if (encoding.size()) { if ( (cv_img.channels() == 3) == is_color && !height && !width && matchExt(filename, encoding) ) return ReadFileToDatum(filename, label, datum); std::vector<uchar> buf; // 对数据解码 cv::imencode("."+encoding, cv_img, buf); datum->set_data(std::string(reinterpret_cast<char*>(&buf[0]), buf.size())); // 数据标签 datum->set_label(label); // 是否被编码 datum->set_encoded(true); return true; } CVMatToDatum(cv_img, datum);//cvmat转为Datum格式 datum->set_label(label); return true; } else { return false; } } #endif // USE_OPENCV // 从文件读取数据到Datum bool ReadFileToDatum(const string& filename, const int label, Datum* datum) { std::streampos size;//获取文件指针位置 size fstream file(filename.c_str(), ios::in|ios::binary|ios::ate); if (file.is_open()) { size = file.tellg();//代表当前get 流指针的位置 std::string buffer(size, ' '); file.seekg(0, ios::beg);//设置0输入文件流的起始位置 file.read(&buffer[0], size); file.close(); datum->set_data(buffer);//data_->assign(buffer) datum->set_label(label);//label_ = label datum->set_encoded(true); return true; } else { return false; } } #ifdef USE_OPENCV // 直接编码数据的Datum到CVMat cv::Mat DecodeDatumToCVMatNative(const Datum& datum) { cv::Mat cv_img; CHECK(datum.encoded()) << "Datum not encoded"; const string& data = datum.data(); std::vector<char> vec_data(data.c_str(), data.c_str() + data.size()); cv_img = cv::imdecode(vec_data, -1);//flag=-1 if (!cv_img.data) { LOG(ERROR) << "Could not decode datum "; } return cv_img; } // 直接编码彩色或者非彩色Datum到CVMat cv::Mat DecodeDatumToCVMat(const Datum& datum, bool is_color) { cv::Mat cv_img; CHECK(datum.encoded()) << "Datum not encoded"; const string& data = datum.data(); std::vector<char> vec_data(data.c_str(), data.c_str() + data.size()); int cv_read_flag = (is_color ? CV_LOAD_IMAGE_COLOR : CV_LOAD_IMAGE_GRAYSCALE); cv_img = cv::imdecode(vec_data, cv_read_flag);// flag为用户指定的,从内存都入图片 if (!cv_img.data) { LOG(ERROR) << "Could not decode datum "; } return cv_img;//将encode 的Datum转化为cvMat } // 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; } } // 将Datum进行解码 bool DecodeDatum(Datum* datum, bool is_color) { if (datum->encoded()) { cv::Mat cv_img = DecodeDatumToCVMat((*datum), is_color); CVMatToDatum(cv_img, datum); return true; } else { return false; } }//将encodedDatum转化为没有encode的Datum // 将CVMat转换到Datum void CVMatToDatum(const cv::Mat& cv_img, Datum* datum) { CHECK(cv_img.depth() == CV_8U) << "Image data type must be unsigned byte"; datum->set_channels(cv_img.channels()); datum->set_height(cv_img.rows); datum->set_width(cv_img.cols);//分别设置channel, height,width datum->clear_data(); datum->clear_float_data(); datum->set_encoded(false); int datum_channels = datum->channels(); int datum_height = datum->height(); int datum_width = datum->width(); int datum_size = datum_channels * datum_height * datum_width; std::string buffer(datum_size, ' ');//将buffer初始化为字符''的datum_size个副本 for (int h = 0; h < datum_height; ++h) { const uchar* ptr = cv_img.ptr<uchar>(h);//指向图像第h行的指针 int img_index = 0; for (int w = 0; w < datum_width; ++w) { for (int c = 0; c < datum_channels; ++c) { int datum_index = (c * datum_height + h) * datum_width + w; buffer[datum_index] = static_cast<char>(ptr[img_index++]); } } } datum->set_data(buffer); } #endif // USE_OPENCV } // namespace caffe
相关文章推荐
- jQuery实现图片轮播特性。使用animate函数
- html5学习系列之cd标签
- jquery 点击元素以外任意地方隐藏该元素的方法
- HTML页面布局
- leetcode:count the number of nodes
- 特殊字符\u2028导致的Javascript脚本异常
- js javascript:void(0) 真正含义
- 自己封装的JS分页功能[用于搭配后台使用]
- CSS --- 圣杯布局
- JSTL标签 参考手册
- JQuery日期插件datepicker的使用
- HTML学习(九)——其他标记
- 【笔记】 《js权威指南》- 第8章 函数 - 8.7 函数属性、方法和构造函数
- JavaScript之事件操作
- JavaScript DOM 编程之高级篇
- Javascript短路表达式
- 【笔记】 《js权威指南》- 第8章 函数 - 8.5 作为命名空间的函数 - 8.6 闭包
- Node.js中的etag包知识学习之express的配置etag
- 国内jQuery CDN
- css常用命名参考