Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/dnn/src/darknet/darknet_importer.cpp
16339 views
1
/*M///////////////////////////////////////////////////////////////////////////////////////
2
//
3
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4
//
5
// By downloading, copying, installing or using the software you agree to this license.
6
// If you do not agree to this license, do not download, install,
7
// copy or use the software.
8
//
9
//
10
// License Agreement
11
// For Open Source Computer Vision Library
12
// (3-clause BSD License)
13
//
14
// Copyright (C) 2017, Intel Corporation, all rights reserved.
15
// Third party copyrights are property of their respective owners.
16
//
17
// Redistribution and use in source and binary forms, with or without modification,
18
// are permitted provided that the following conditions are met:
19
//
20
// * Redistributions of source code must retain the above copyright notice,
21
// this list of conditions and the following disclaimer.
22
//
23
// * Redistributions in binary form must reproduce the above copyright notice,
24
// this list of conditions and the following disclaimer in the documentation
25
// and/or other materials provided with the distribution.
26
//
27
// * Neither the names of the copyright holders nor the names of the contributors
28
// may be used to endorse or promote products derived from this software
29
// without specific prior written permission.
30
//
31
// This software is provided by the copyright holders and contributors "as is" and
32
// any express or implied warranties, including, but not limited to, the implied
33
// warranties of merchantability and fitness for a particular purpose are disclaimed.
34
// In no event shall copyright holders or contributors be liable for any direct,
35
// indirect, incidental, special, exemplary, or consequential damages
36
// (including, but not limited to, procurement of substitute goods or services;
37
// loss of use, data, or profits; or business interruption) however caused
38
// and on any theory of liability, whether in contract, strict liability,
39
// or tort (including negligence or otherwise) arising in any way out of
40
// the use of this software, even if advised of the possibility of such damage.
41
//
42
//M*/
43
44
#include "../precomp.hpp"
45
46
#include <iostream>
47
#include <fstream>
48
#include <algorithm>
49
#include <vector>
50
#include <map>
51
52
#include "darknet_io.hpp"
53
54
55
namespace cv {
56
namespace dnn {
57
CV__DNN_INLINE_NS_BEGIN
58
59
namespace
60
{
61
62
class DarknetImporter
63
{
64
darknet::NetParameter net;
65
66
public:
67
68
DarknetImporter() {}
69
70
DarknetImporter(std::istream &cfgStream, std::istream &darknetModelStream)
71
{
72
CV_TRACE_FUNCTION();
73
74
ReadNetParamsFromCfgStreamOrDie(cfgStream, &net);
75
ReadNetParamsFromBinaryStreamOrDie(darknetModelStream, &net);
76
}
77
78
DarknetImporter(std::istream &cfgStream)
79
{
80
CV_TRACE_FUNCTION();
81
82
ReadNetParamsFromCfgStreamOrDie(cfgStream, &net);
83
}
84
85
struct BlobNote
86
{
87
BlobNote(const std::string &_name, int _layerId, int _outNum) :
88
name(_name), layerId(_layerId), outNum(_outNum) {}
89
90
std::string name;
91
int layerId, outNum;
92
};
93
94
std::vector<BlobNote> addedBlobs;
95
std::map<String, int> layerCounter;
96
97
void populateNet(Net dstNet)
98
{
99
CV_TRACE_FUNCTION();
100
101
int layersSize = net.layer_size();
102
layerCounter.clear();
103
addedBlobs.clear();
104
addedBlobs.reserve(layersSize + 1);
105
106
//setup input layer names
107
{
108
std::vector<String> netInputs(net.input_size());
109
for (int inNum = 0; inNum < net.input_size(); inNum++)
110
{
111
addedBlobs.push_back(BlobNote(net.input(inNum), 0, inNum));
112
netInputs[inNum] = net.input(inNum);
113
}
114
dstNet.setInputsNames(netInputs);
115
}
116
117
for (int li = 0; li < layersSize; li++)
118
{
119
const darknet::LayerParameter &layer = net.layer(li);
120
String name = layer.name();
121
String type = layer.type();
122
LayerParams layerParams = layer.getLayerParams();
123
124
int repetitions = layerCounter[name]++;
125
if (repetitions)
126
name += cv::format("_%d", repetitions);
127
128
int id = dstNet.addLayer(name, type, layerParams);
129
130
// iterate many bottoms layers (for example for: route -1, -4)
131
for (int inNum = 0; inNum < layer.bottom_size(); inNum++)
132
addInput(layer.bottom(inNum), id, inNum, dstNet, layer.name());
133
134
for (int outNum = 0; outNum < layer.top_size(); outNum++)
135
addOutput(layer, id, outNum);
136
}
137
138
addedBlobs.clear();
139
}
140
141
void addOutput(const darknet::LayerParameter &layer, int layerId, int outNum)
142
{
143
const std::string &name = layer.top(outNum);
144
145
bool haveDups = false;
146
for (int idx = (int)addedBlobs.size() - 1; idx >= 0; idx--)
147
{
148
if (addedBlobs[idx].name == name)
149
{
150
haveDups = true;
151
break;
152
}
153
}
154
155
if (haveDups)
156
{
157
bool isInplace = layer.bottom_size() > outNum && layer.bottom(outNum) == name;
158
if (!isInplace)
159
CV_Error(Error::StsBadArg, "Duplicate blobs produced by multiple sources");
160
}
161
162
addedBlobs.push_back(BlobNote(name, layerId, outNum));
163
}
164
165
void addInput(const std::string &name, int layerId, int inNum, Net &dstNet, std::string nn)
166
{
167
int idx;
168
for (idx = (int)addedBlobs.size() - 1; idx >= 0; idx--)
169
{
170
if (addedBlobs[idx].name == name)
171
break;
172
}
173
174
if (idx < 0)
175
{
176
CV_Error(Error::StsObjectNotFound, "Can't find output blob \"" + name + "\"");
177
return;
178
}
179
180
dstNet.connect(addedBlobs[idx].layerId, addedBlobs[idx].outNum, layerId, inNum);
181
}
182
};
183
184
static Net readNetFromDarknet(std::istream &cfgFile, std::istream &darknetModel)
185
{
186
Net net;
187
DarknetImporter darknetImporter(cfgFile, darknetModel);
188
darknetImporter.populateNet(net);
189
return net;
190
}
191
192
static Net readNetFromDarknet(std::istream &cfgFile)
193
{
194
Net net;
195
DarknetImporter darknetImporter(cfgFile);
196
darknetImporter.populateNet(net);
197
return net;
198
}
199
200
}
201
202
Net readNetFromDarknet(const String &cfgFile, const String &darknetModel /*= String()*/)
203
{
204
std::ifstream cfgStream(cfgFile.c_str());
205
if (!cfgStream.is_open())
206
{
207
CV_Error(cv::Error::StsParseError, "Failed to parse NetParameter file: " + std::string(cfgFile));
208
}
209
if (darknetModel != String())
210
{
211
std::ifstream darknetModelStream(darknetModel.c_str(), std::ios::binary);
212
if (!darknetModelStream.is_open())
213
{
214
CV_Error(cv::Error::StsParseError, "Failed to parse NetParameter file: " + std::string(darknetModel));
215
}
216
return readNetFromDarknet(cfgStream, darknetModelStream);
217
}
218
else
219
return readNetFromDarknet(cfgStream);
220
}
221
222
struct BufferStream : public std::streambuf
223
{
224
BufferStream(const char* s, std::size_t n)
225
{
226
char* ptr = const_cast<char*>(s);
227
setg(ptr, ptr, ptr + n);
228
}
229
};
230
231
Net readNetFromDarknet(const char *bufferCfg, size_t lenCfg, const char *bufferModel, size_t lenModel)
232
{
233
BufferStream cfgBufferStream(bufferCfg, lenCfg);
234
std::istream cfgStream(&cfgBufferStream);
235
if (lenModel)
236
{
237
BufferStream weightsBufferStream(bufferModel, lenModel);
238
std::istream weightsStream(&weightsBufferStream);
239
return readNetFromDarknet(cfgStream, weightsStream);
240
}
241
else
242
return readNetFromDarknet(cfgStream);
243
}
244
245
Net readNetFromDarknet(const std::vector<uchar>& bufferCfg, const std::vector<uchar>& bufferModel)
246
{
247
const char* bufferCfgPtr = reinterpret_cast<const char*>(&bufferCfg[0]);
248
const char* bufferModelPtr = bufferModel.empty() ? NULL :
249
reinterpret_cast<const char*>(&bufferModel[0]);
250
return readNetFromDarknet(bufferCfgPtr, bufferCfg.size(),
251
bufferModelPtr, bufferModel.size());
252
}
253
254
CV__DNN_INLINE_NS_END
255
}} // namespace
256
257