Commit 61d8719b authored by asciian's avatar asciian Committed by Dmitry Kurtaev

Reading net from std::ifstream

Remove some assertions

Replace std::ifstream to std::istream

Add test for new importer

Remove constructor to load file

Rename cfgStream and darknetModelStream to ifile

Add error notification to inform pathname to user

Use FileStorage instead of std::istream

Use FileNode instead of FileStorage

Fix typo
parent 0fd74fa1
...@@ -644,6 +644,14 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN ...@@ -644,6 +644,14 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
*/ */
CV_EXPORTS_W Net readNetFromDarknet(const String &cfgFile, const String &darknetModel = String()); CV_EXPORTS_W Net readNetFromDarknet(const String &cfgFile, const String &darknetModel = String());
/** @brief Reads a network model stored in <a href="https://pjreddie.com/darknet/">Darknet</a> model files.
* @param cfgFile file node to the .cfg file with text description of the network architecture.
* @param darknetModel file node to the .weights file with learned network.
* @returns Network object that ready to do forward, throw an exception in failure cases.
* @returns Net object.
*/
CV_EXPORTS_W Net readNetFromDarknet(const FileNode &cfgFile, const FileNode &darknetModel = FileNode());
/** @brief Reads a network model stored in <a href="http://caffe.berkeleyvision.org">Caffe</a> framework's format. /** @brief Reads a network model stored in <a href="http://caffe.berkeleyvision.org">Caffe</a> framework's format.
* @param prototxt path to the .prototxt file with text description of the network architecture. * @param prototxt path to the .prototxt file with text description of the network architecture.
* @param caffeModel path to the .caffemodel file with learned network. * @param caffeModel path to the .caffemodel file with learned network.
......
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#include "../precomp.hpp" #include "../precomp.hpp"
#include <iostream> #include <iostream>
#include <fstream>
#include <algorithm> #include <algorithm>
#include <vector> #include <vector>
#include <map> #include <map>
...@@ -66,14 +67,19 @@ public: ...@@ -66,14 +67,19 @@ public:
DarknetImporter() {} DarknetImporter() {}
DarknetImporter(const char *cfgFile, const char *darknetModel) DarknetImporter(std::istream &cfgStream, std::istream &darknetModelStream)
{ {
CV_TRACE_FUNCTION(); CV_TRACE_FUNCTION();
ReadNetParamsFromCfgFileOrDie(cfgFile, &net); ReadNetParamsFromCfgStreamOrDie(cfgStream, &net);
ReadNetParamsFromBinaryStreamOrDie(darknetModelStream, &net);
}
DarknetImporter(std::istream &cfgStream)
{
CV_TRACE_FUNCTION();
if (darknetModel && darknetModel[0]) ReadNetParamsFromCfgStreamOrDie(cfgStream, &net);
ReadNetParamsFromBinaryFileOrDie(darknetModel, &net);
} }
struct BlobNote struct BlobNote
...@@ -179,7 +185,38 @@ public: ...@@ -179,7 +185,38 @@ public:
Net readNetFromDarknet(const String &cfgFile, const String &darknetModel /*= String()*/) Net readNetFromDarknet(const String &cfgFile, const String &darknetModel /*= String()*/)
{ {
DarknetImporter darknetImporter(cfgFile.c_str(), darknetModel.c_str()); Net net;
std::ifstream cfgStream(cfgFile.c_str());
if(!cfgStream.is_open()) {
CV_Error(cv::Error::StsParseError, "Failed to parse NetParameter file: " + std::string(cfgFile));
return net;
}
DarknetImporter darknetImporter;
if (darknetModel != String()) {
std::ifstream darknetModelStream(darknetModel.c_str());
if(!darknetModelStream.is_open()){
CV_Error(cv::Error::StsParseError, "Failed to parse NetParameter file: " + std::string(darknetModel));
return net;
}
darknetImporter = DarknetImporter(cfgStream, darknetModelStream);
} else {
darknetImporter = DarknetImporter(cfgStream);
}
darknetImporter.populateNet(net);
return net;
}
Net readNetFromDarknet(const FileNode &cfgFile, const FileNode &darknetModel /*= FileNode()*/)
{
DarknetImporter darknetImporter;
if(darknetModel.empty()){
std::istringstream cfgStream((std::string)cfgFile);
darknetImporter = DarknetImporter(cfgStream);
}else{
std::istringstream cfgStream((std::string)cfgFile);
std::istringstream darknetModelStream((std::string)darknetModel);
darknetImporter = DarknetImporter(cfgStream, darknetModelStream);
}
Net net; Net net;
darknetImporter.populateNet(net); darknetImporter.populateNet(net);
return net; return net;
......
...@@ -476,68 +476,61 @@ namespace cv { ...@@ -476,68 +476,61 @@ namespace cv {
return dst; return dst;
} }
bool ReadDarknetFromCfgFile(const char *cfgFile, NetParameter *net) bool ReadDarknetFromCfgStream(std::istream &ifile, NetParameter *net)
{ {
std::ifstream ifile; bool read_net = false;
ifile.open(cfgFile); int layers_counter = -1;
if (ifile.is_open()) for (std::string line; std::getline(ifile, line);) {
{ line = escapeString(line);
bool read_net = false; if (line.empty()) continue;
int layers_counter = -1; switch (line[0]) {
for (std::string line; std::getline(ifile, line);) { case '\0': break;
line = escapeString(line); case '#': break;
if (line.empty()) continue; case ';': break;
switch (line[0]) { case '[':
case '\0': break; if (line == "[net]") {
case '#': break; read_net = true;
case ';': break; }
case '[': else {
if (line == "[net]") { // read section
read_net = true; read_net = false;
} ++layers_counter;
else { const size_t layer_type_size = line.find("]") - 1;
// read section CV_Assert(layer_type_size < line.size());
read_net = false; std::string layer_type = line.substr(1, layer_type_size);
++layers_counter; net->layers_cfg[layers_counter]["type"] = layer_type;
const size_t layer_type_size = line.find("]") - 1; }
CV_Assert(layer_type_size < line.size()); break;
std::string layer_type = line.substr(1, layer_type_size); default:
net->layers_cfg[layers_counter]["type"] = layer_type; // read entry
} const size_t separator_index = line.find('=');
break; CV_Assert(separator_index < line.size());
default: if (separator_index != std::string::npos) {
// read entry std::string name = line.substr(0, separator_index);
const size_t separator_index = line.find('='); std::string value = line.substr(separator_index + 1, line.size() - (separator_index + 1));
CV_Assert(separator_index < line.size()); name = escapeString(name);
if (separator_index != std::string::npos) { value = escapeString(value);
std::string name = line.substr(0, separator_index); if (name.empty() || value.empty()) continue;
std::string value = line.substr(separator_index + 1, line.size() - (separator_index + 1)); if (read_net)
name = escapeString(name); net->net_cfg[name] = value;
value = escapeString(value); else
if (name.empty() || value.empty()) continue; net->layers_cfg[layers_counter][name] = value;
if (read_net)
net->net_cfg[name] = value;
else
net->layers_cfg[layers_counter][name] = value;
}
} }
} }
std::string anchors = net->layers_cfg[net->layers_cfg.size() - 1]["anchors"];
std::vector<float> vec = getNumbers<float>(anchors);
std::map<std::string, std::string> &net_params = net->net_cfg;
net->width = getParam(net_params, "width", 416);
net->height = getParam(net_params, "height", 416);
net->channels = getParam(net_params, "channels", 3);
CV_Assert(net->width > 0 && net->height > 0 && net->channels > 0);
} }
else
return false; std::string anchors = net->layers_cfg[net->layers_cfg.size() - 1]["anchors"];
std::vector<float> vec = getNumbers<float>(anchors);
std::map<std::string, std::string> &net_params = net->net_cfg;
net->width = getParam(net_params, "width", 416);
net->height = getParam(net_params, "height", 416);
net->channels = getParam(net_params, "channels", 3);
CV_Assert(net->width > 0 && net->height > 0 && net->channels > 0);
int current_channels = net->channels; int current_channels = net->channels;
net->out_channels_vec.resize(net->layers_cfg.size()); net->out_channels_vec.resize(net->layers_cfg.size());
int layers_counter = -1; layers_counter = -1;
setLayersParams setParams(net); setLayersParams setParams(net);
...@@ -676,13 +669,8 @@ namespace cv { ...@@ -676,13 +669,8 @@ namespace cv {
return true; return true;
} }
bool ReadDarknetFromWeightsStream(std::istream &ifile, NetParameter *net)
bool ReadDarknetFromWeightsFile(const char *darknetModel, NetParameter *net)
{ {
std::ifstream ifile;
ifile.open(darknetModel, std::ios::binary);
CV_Assert(ifile.is_open());
int32_t major_ver, minor_ver, revision; int32_t major_ver, minor_ver, revision;
ifile.read(reinterpret_cast<char *>(&major_ver), sizeof(int32_t)); ifile.read(reinterpret_cast<char *>(&major_ver), sizeof(int32_t));
ifile.read(reinterpret_cast<char *>(&minor_ver), sizeof(int32_t)); ifile.read(reinterpret_cast<char *>(&minor_ver), sizeof(int32_t));
...@@ -778,19 +766,18 @@ namespace cv { ...@@ -778,19 +766,18 @@ namespace cv {
} }
void ReadNetParamsFromCfgFileOrDie(const char *cfgFile, darknet::NetParameter *net) void ReadNetParamsFromCfgStreamOrDie(std::istream &ifile, darknet::NetParameter *net)
{ {
if (!darknet::ReadDarknetFromCfgFile(cfgFile, net)) { if (!darknet::ReadDarknetFromCfgStream(ifile, net)) {
CV_Error(cv::Error::StsParseError, "Failed to parse NetParameter file: " + std::string(cfgFile)); CV_Error(cv::Error::StsParseError, "Failed to parse NetParameter stream");
} }
} }
void ReadNetParamsFromBinaryFileOrDie(const char *darknetModel, darknet::NetParameter *net) void ReadNetParamsFromBinaryStreamOrDie(std::istream &ifile, darknet::NetParameter *net)
{ {
if (!darknet::ReadDarknetFromWeightsFile(darknetModel, net)) { if (!darknet::ReadDarknetFromWeightsStream(ifile, net)) {
CV_Error(cv::Error::StsParseError, "Failed to parse NetParameter file: " + std::string(darknetModel)); CV_Error(cv::Error::StsParseError, "Failed to parse NetParameter stream");
} }
} }
} }
} }
...@@ -109,10 +109,9 @@ namespace cv { ...@@ -109,10 +109,9 @@ namespace cv {
}; };
} }
// Read parameters from a file into a NetParameter message. // Read parameters from a stream into a NetParameter message.
void ReadNetParamsFromCfgFileOrDie(const char *cfgFile, darknet::NetParameter *net); void ReadNetParamsFromCfgStreamOrDie(std::istream &ifile, darknet::NetParameter *net);
void ReadNetParamsFromBinaryFileOrDie(const char *darknetModel, darknet::NetParameter *net); void ReadNetParamsFromBinaryStreamOrDie(std::istream &ifile, darknet::NetParameter *net);
} }
} }
#endif #endif
...@@ -65,6 +65,18 @@ TEST(Test_Darknet, read_yolo_voc) ...@@ -65,6 +65,18 @@ TEST(Test_Darknet, read_yolo_voc)
ASSERT_FALSE(net.empty()); ASSERT_FALSE(net.empty());
} }
TEST(Test_Darknet, read_filestorage_yolo_voc)
{
std::ifstream ifile(_tf("yolo-voc.cfg").c_str());
std::stringstream buffer;
buffer << " " << ifile.rdbuf(); // FIXME: FileStorage drops first character.
FileStorage ofs(".xml", FileStorage::WRITE | FileStorage::MEMORY);
ofs.write("cfgFile", buffer.str());
FileStorage ifs(ofs.releaseAndGetString(), FileStorage::READ | FileStorage::MEMORY | FileStorage::FORMAT_XML);
Net net = readNetFromDarknet(ifs["cfgFile"]);
ASSERT_FALSE(net.empty());
}
class Test_Darknet_layers : public DNNTestLayer class Test_Darknet_layers : public DNNTestLayer
{ {
public: public:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment