Skip to content

Commit 2ae8490

Browse files
committed
Merge pull request opencv#9009 from alalek:fix_dnn_initialization
2 parents 8b3d660 + 00dd433 commit 2ae8490

File tree

10 files changed

+168
-142
lines changed

10 files changed

+168
-142
lines changed

modules/dnn/include/opencv2/dnn/dnn.hpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,6 @@ namespace dnn //! This namespace is used for dnn module functionlaity.
7373
DNN_TARGET_OPENCL
7474
};
7575

76-
/** @brief Initialize dnn module and built-in layers.
77-
*
78-
* This function automatically called on most of OpenCV builds,
79-
* but you need to call it manually on some specific configurations (iOS for example).
80-
*/
81-
CV_EXPORTS_W void initModule();
82-
8376
/** @brief This class provides all data needed to initialize layer.
8477
*
8578
* It includes dictionary with scalar params (which can be readed by using Dict interface),
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// This file is part of OpenCV project.
2+
// It is subject to the license terms in the LICENSE file found in the top-level directory
3+
// of this distribution and at http://opencv.org/license.html.
4+
//
5+
#ifndef OPENCV_DNN_LAYER_DETAILS_HPP
6+
#define OPENCV_DNN_LAYER_DETAILS_HPP
7+
8+
#include <opencv2/dnn/layer.hpp>
9+
10+
namespace cv
11+
{
12+
namespace dnn
13+
{
14+
15+
/** @brief Registers layer constructor in runtime.
16+
* @param type string, containing type name of the layer.
17+
* @param constuctorFunc pointer to the function of type LayerRegister::Constuctor, which creates the layer.
18+
* @details This macros must be placed inside the function code.
19+
*/
20+
#define CV_DNN_REGISTER_LAYER_FUNC(type, constuctorFunc) \
21+
cv::dnn::LayerFactory::registerLayer(#type, constuctorFunc);
22+
23+
/** @brief Registers layer class in runtime.
24+
* @param type string, containing type name of the layer.
25+
* @param class C++ class, derived from Layer.
26+
* @details This macros must be placed inside the function code.
27+
*/
28+
#define CV_DNN_REGISTER_LAYER_CLASS(type, class) \
29+
cv::dnn::LayerFactory::registerLayer(#type, cv::dnn::details::_layerDynamicRegisterer<class>);
30+
31+
/** @brief Registers layer constructor on module load time.
32+
* @param type string, containing type name of the layer.
33+
* @param constuctorFunc pointer to the function of type LayerRegister::Constuctor, which creates the layer.
34+
* @details This macros must be placed outside the function code.
35+
*/
36+
#define CV_DNN_REGISTER_LAYER_FUNC_STATIC(type, constuctorFunc) \
37+
static cv::dnn::details::_LayerStaticRegisterer __LayerStaticRegisterer_##type(#type, constuctorFunc);
38+
39+
/** @brief Registers layer class on module load time.
40+
* @param type string, containing type name of the layer.
41+
* @param class C++ class, derived from Layer.
42+
* @details This macros must be placed outside the function code.
43+
*/
44+
#define CV_DNN_REGISTER_LAYER_CLASS_STATIC(type, class) \
45+
Ptr<Layer> __LayerStaticRegisterer_func_##type(LayerParams &params) \
46+
{ return Ptr<Layer>(new class(params)); } \
47+
static cv::dnn::details::_LayerStaticRegisterer __LayerStaticRegisterer_##type(#type, __LayerStaticRegisterer_func_##type);
48+
49+
namespace details {
50+
51+
template<typename LayerClass>
52+
Ptr<Layer> _layerDynamicRegisterer(LayerParams &params)
53+
{
54+
return Ptr<Layer>(LayerClass::create(params));
55+
}
56+
57+
//allows automatically register created layer on module load time
58+
class _LayerStaticRegisterer
59+
{
60+
String type;
61+
public:
62+
63+
_LayerStaticRegisterer(const String &layerType, LayerFactory::Constuctor layerConstuctor)
64+
{
65+
this->type = layerType;
66+
LayerFactory::registerLayer(layerType, layerConstuctor);
67+
}
68+
69+
~_LayerStaticRegisterer()
70+
{
71+
LayerFactory::unregisterLayer(type);
72+
}
73+
};
74+
75+
}}} //namespace
76+
77+
#endif

modules/dnn/include/opencv2/dnn/layer.hpp

Lines changed: 3 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -61,88 +61,26 @@ class CV_EXPORTS LayerFactory
6161
//! Each Layer class must provide this function to the factory
6262
typedef Ptr<Layer>(*Constuctor)(LayerParams &params);
6363

64-
//! Registers the layer class with typename @p type and specified @p constructor.
64+
//! Registers the layer class with typename @p type and specified @p constructor. Thread-safe.
6565
static void registerLayer(const String &type, Constuctor constructor);
6666

67-
//! Unregisters registered layer with specified type name.
67+
//! Unregisters registered layer with specified type name. Thread-safe.
6868
static void unregisterLayer(const String &type);
6969

7070
/** @brief Creates instance of registered layer.
7171
* @param type type name of creating layer.
7272
* @param params parameters which will be used for layer initialization.
73+
* @note Thread-safe.
7374
*/
7475
static Ptr<Layer> createLayerInstance(const String &type, LayerParams& params);
7576

7677
private:
7778
LayerFactory();
78-
79-
struct Impl;
80-
static Ptr<Impl> impl();
8179
};
8280

83-
/** @brief Registers layer constructor in runtime.
84-
* @param type string, containing type name of the layer.
85-
* @param constuctorFunc pointer to the function of type LayerRegister::Constuctor, which creates the layer.
86-
* @details This macros must be placed inside the function code.
87-
*/
88-
#define REG_RUNTIME_LAYER_FUNC(type, constuctorFunc) \
89-
cv::dnn::LayerFactory::registerLayer(#type, constuctorFunc);
90-
91-
/** @brief Registers layer class in runtime.
92-
* @param type string, containing type name of the layer.
93-
* @param class C++ class, derived from Layer.
94-
* @details This macros must be placed inside the function code.
95-
*/
96-
#define REG_RUNTIME_LAYER_CLASS(type, class) \
97-
cv::dnn::LayerFactory::registerLayer(#type, _layerDynamicRegisterer<class>);
98-
99-
/** @brief Registers layer constructor on module load time.
100-
* @param type string, containing type name of the layer.
101-
* @param constuctorFunc pointer to the function of type LayerRegister::Constuctor, which creates the layer.
102-
* @details This macros must be placed outside the function code.
103-
*/
104-
#define REG_STATIC_LAYER_FUNC(type, constuctorFunc) \
105-
static cv::dnn::_LayerStaticRegisterer __LayerStaticRegisterer_##type(#type, constuctorFunc);
106-
107-
/** @brief Registers layer class on module load time.
108-
* @param type string, containing type name of the layer.
109-
* @param class C++ class, derived from Layer.
110-
* @details This macros must be placed outside the function code.
111-
*/
112-
#define REG_STATIC_LAYER_CLASS(type, class) \
113-
Ptr<Layer> __LayerStaticRegisterer_func_##type(LayerParams &params) \
114-
{ return Ptr<Layer>(new class(params)); } \
115-
static _LayerStaticRegisterer __LayerStaticRegisterer_##type(#type, __LayerStaticRegisterer_func_##type);
116-
117-
11881
//! @}
11982
//! @}
12083

121-
122-
template<typename LayerClass>
123-
Ptr<Layer> _layerDynamicRegisterer(LayerParams &params)
124-
{
125-
return Ptr<Layer>(LayerClass::create(params));
126-
}
127-
128-
//allows automatically register created layer on module load time
129-
class _LayerStaticRegisterer
130-
{
131-
String type;
132-
public:
133-
134-
_LayerStaticRegisterer(const String &layerType, LayerFactory::Constuctor layerConstuctor)
135-
{
136-
this->type = layerType;
137-
LayerFactory::registerLayer(layerType, layerConstuctor);
138-
}
139-
140-
~_LayerStaticRegisterer()
141-
{
142-
LayerFactory::unregisterLayer(type);
143-
}
144-
};
145-
14684
}
14785
}
14886
#endif

modules/dnn/src/dnn.cpp

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1937,42 +1937,69 @@ bool Layer::getMemoryShapes(const std::vector<MatShape> &inputs,
19371937

19381938
//////////////////////////////////////////////////////////////////////////
19391939

1940-
struct LayerFactory::Impl : public std::map<String, LayerFactory::Constuctor>
1940+
static Mutex& getLayerFactoryMutex()
19411941
{
1942-
};
1942+
static Mutex* volatile instance = NULL;
1943+
if (instance == NULL)
1944+
{
1945+
cv::AutoLock lock(getInitializationMutex());
1946+
if (instance == NULL)
1947+
instance = new Mutex();
1948+
}
1949+
return *instance;
1950+
}
1951+
1952+
typedef std::map<String, LayerFactory::Constuctor> LayerFactory_Impl;
1953+
1954+
static LayerFactory_Impl& getLayerFactoryImpl_()
1955+
{
1956+
static LayerFactory_Impl impl;
1957+
return impl;
1958+
}
19431959

1944-
Ptr<LayerFactory::Impl> LayerFactory::impl ()
1960+
static LayerFactory_Impl& getLayerFactoryImpl()
19451961
{
1946-
// allocate on first use
1947-
static Ptr<LayerFactory::Impl> impl_(new LayerFactory::Impl());
1948-
return impl_;
1962+
static LayerFactory_Impl* volatile instance = NULL;
1963+
if (instance == NULL)
1964+
{
1965+
cv::AutoLock lock(getLayerFactoryMutex());
1966+
if (instance == NULL)
1967+
{
1968+
instance = &getLayerFactoryImpl_();
1969+
initializeLayerFactory();
1970+
}
1971+
}
1972+
return *instance;
19491973
}
19501974

19511975
void LayerFactory::registerLayer(const String &_type, Constuctor constructor)
19521976
{
1977+
cv::AutoLock lock(getLayerFactoryMutex());
19531978
String type = _type.toLowerCase();
1954-
Impl::iterator it = impl()->find(type);
1979+
LayerFactory_Impl::const_iterator it = getLayerFactoryImpl().find(type);
19551980

1956-
if (it != impl()->end() && it->second != constructor)
1981+
if (it != getLayerFactoryImpl().end() && it->second != constructor)
19571982
{
19581983
CV_Error(cv::Error::StsBadArg, "Layer \"" + type + "\" already was registered");
19591984
}
19601985

1961-
impl()->insert(std::make_pair(type, constructor));
1986+
getLayerFactoryImpl().insert(std::make_pair(type, constructor));
19621987
}
19631988

19641989
void LayerFactory::unregisterLayer(const String &_type)
19651990
{
1991+
cv::AutoLock lock(getLayerFactoryMutex());
19661992
String type = _type.toLowerCase();
1967-
impl()->erase(type);
1993+
getLayerFactoryImpl().erase(type);
19681994
}
19691995

19701996
Ptr<Layer> LayerFactory::createLayerInstance(const String &_type, LayerParams& params)
19711997
{
1998+
cv::AutoLock lock(getLayerFactoryMutex());
19721999
String type = _type.toLowerCase();
1973-
Impl::const_iterator it = LayerFactory::impl()->find(type);
2000+
LayerFactory_Impl::const_iterator it = getLayerFactoryImpl().find(type);
19742001

1975-
if (it != impl()->end())
2002+
if (it != getLayerFactoryImpl().end())
19762003
{
19772004
return it->second(params);
19782005
}

modules/dnn/src/init.cpp

Lines changed: 44 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -40,68 +40,62 @@
4040
//M*/
4141

4242
#include "precomp.hpp"
43+
#include <opencv2/dnn/layer.details.hpp>
4344

4445
namespace cv
4546
{
4647
namespace dnn
4748
{
4849

49-
struct AutoInitializer
50+
static Mutex* __initialization_mutex = NULL;
51+
Mutex& getInitializationMutex()
5052
{
51-
bool status;
52-
53-
AutoInitializer() : status(false)
54-
{
55-
initModule();
56-
}
57-
};
53+
if (__initialization_mutex == NULL)
54+
__initialization_mutex = new Mutex();
55+
return *__initialization_mutex;
56+
}
57+
// force initialization (single-threaded environment)
58+
Mutex* __initialization_mutex_initializer = &getInitializationMutex();
5859

59-
static AutoInitializer init;
6060

61-
void initModule()
61+
void initializeLayerFactory()
6262
{
63-
if (init.status)
64-
return;
65-
66-
REG_RUNTIME_LAYER_CLASS(Slice, SliceLayer);
67-
REG_RUNTIME_LAYER_CLASS(Split, SplitLayer);
68-
REG_RUNTIME_LAYER_CLASS(Concat, ConcatLayer);
69-
REG_RUNTIME_LAYER_CLASS(Reshape, ReshapeLayer);
70-
REG_RUNTIME_LAYER_CLASS(Flatten, FlattenLayer);
63+
CV_DNN_REGISTER_LAYER_CLASS(Slice, SliceLayer);
64+
CV_DNN_REGISTER_LAYER_CLASS(Split, SplitLayer);
65+
CV_DNN_REGISTER_LAYER_CLASS(Concat, ConcatLayer);
66+
CV_DNN_REGISTER_LAYER_CLASS(Reshape, ReshapeLayer);
67+
CV_DNN_REGISTER_LAYER_CLASS(Flatten, FlattenLayer);
7168

72-
REG_RUNTIME_LAYER_CLASS(Convolution, ConvolutionLayer);
73-
REG_RUNTIME_LAYER_CLASS(Deconvolution, DeconvolutionLayer);
74-
REG_RUNTIME_LAYER_CLASS(Pooling, PoolingLayer);
75-
REG_RUNTIME_LAYER_CLASS(LRN, LRNLayer);
76-
REG_RUNTIME_LAYER_CLASS(InnerProduct, InnerProductLayer);
77-
REG_RUNTIME_LAYER_CLASS(Softmax, SoftmaxLayer);
78-
REG_RUNTIME_LAYER_CLASS(MVN, MVNLayer);
69+
CV_DNN_REGISTER_LAYER_CLASS(Convolution, ConvolutionLayer);
70+
CV_DNN_REGISTER_LAYER_CLASS(Deconvolution, DeconvolutionLayer);
71+
CV_DNN_REGISTER_LAYER_CLASS(Pooling, PoolingLayer);
72+
CV_DNN_REGISTER_LAYER_CLASS(LRN, LRNLayer);
73+
CV_DNN_REGISTER_LAYER_CLASS(InnerProduct, InnerProductLayer);
74+
CV_DNN_REGISTER_LAYER_CLASS(Softmax, SoftmaxLayer);
75+
CV_DNN_REGISTER_LAYER_CLASS(MVN, MVNLayer);
7976

80-
REG_RUNTIME_LAYER_CLASS(ReLU, ReLULayer);
81-
REG_RUNTIME_LAYER_CLASS(ChannelsPReLU, ChannelsPReLULayer);
82-
REG_RUNTIME_LAYER_CLASS(Sigmoid, SigmoidLayer);
83-
REG_RUNTIME_LAYER_CLASS(TanH, TanHLayer);
84-
REG_RUNTIME_LAYER_CLASS(BNLL, BNLLLayer);
85-
REG_RUNTIME_LAYER_CLASS(AbsVal, AbsLayer);
86-
REG_RUNTIME_LAYER_CLASS(Power, PowerLayer);
87-
REG_RUNTIME_LAYER_CLASS(BatchNorm, BatchNormLayer);
88-
REG_RUNTIME_LAYER_CLASS(MaxUnpool, MaxUnpoolLayer);
89-
REG_RUNTIME_LAYER_CLASS(Dropout, BlankLayer);
90-
REG_RUNTIME_LAYER_CLASS(Identity, BlankLayer);
77+
CV_DNN_REGISTER_LAYER_CLASS(ReLU, ReLULayer);
78+
CV_DNN_REGISTER_LAYER_CLASS(ChannelsPReLU, ChannelsPReLULayer);
79+
CV_DNN_REGISTER_LAYER_CLASS(Sigmoid, SigmoidLayer);
80+
CV_DNN_REGISTER_LAYER_CLASS(TanH, TanHLayer);
81+
CV_DNN_REGISTER_LAYER_CLASS(BNLL, BNLLLayer);
82+
CV_DNN_REGISTER_LAYER_CLASS(AbsVal, AbsLayer);
83+
CV_DNN_REGISTER_LAYER_CLASS(Power, PowerLayer);
84+
CV_DNN_REGISTER_LAYER_CLASS(BatchNorm, BatchNormLayer);
85+
CV_DNN_REGISTER_LAYER_CLASS(MaxUnpool, MaxUnpoolLayer);
86+
CV_DNN_REGISTER_LAYER_CLASS(Dropout, BlankLayer);
87+
CV_DNN_REGISTER_LAYER_CLASS(Identity, BlankLayer);
9188

92-
REG_RUNTIME_LAYER_CLASS(Crop, CropLayer);
93-
REG_RUNTIME_LAYER_CLASS(Eltwise, EltwiseLayer);
94-
REG_RUNTIME_LAYER_CLASS(Permute, PermuteLayer);
95-
REG_RUNTIME_LAYER_CLASS(PriorBox, PriorBoxLayer);
96-
REG_RUNTIME_LAYER_CLASS(DetectionOutput, DetectionOutputLayer);
97-
REG_RUNTIME_LAYER_CLASS(NormalizeBBox, NormalizeBBoxLayer);
98-
REG_RUNTIME_LAYER_CLASS(Normalize, NormalizeBBoxLayer);
99-
REG_RUNTIME_LAYER_CLASS(Shift, ShiftLayer);
100-
REG_RUNTIME_LAYER_CLASS(Padding, PaddingLayer);
101-
REG_RUNTIME_LAYER_CLASS(Scale, ScaleLayer);
102-
103-
init.status = true;
89+
CV_DNN_REGISTER_LAYER_CLASS(Crop, CropLayer);
90+
CV_DNN_REGISTER_LAYER_CLASS(Eltwise, EltwiseLayer);
91+
CV_DNN_REGISTER_LAYER_CLASS(Permute, PermuteLayer);
92+
CV_DNN_REGISTER_LAYER_CLASS(PriorBox, PriorBoxLayer);
93+
CV_DNN_REGISTER_LAYER_CLASS(DetectionOutput, DetectionOutputLayer);
94+
CV_DNN_REGISTER_LAYER_CLASS(NormalizeBBox, NormalizeBBoxLayer);
95+
CV_DNN_REGISTER_LAYER_CLASS(Normalize, NormalizeBBoxLayer);
96+
CV_DNN_REGISTER_LAYER_CLASS(Shift, ShiftLayer);
97+
CV_DNN_REGISTER_LAYER_CLASS(Padding, PaddingLayer);
98+
CV_DNN_REGISTER_LAYER_CLASS(Scale, ScaleLayer);
10499
}
105100

106-
}
107-
}
101+
}} //namespace

modules/dnn/src/precomp.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,8 @@
4343
#include "cvconfig.h"
4444
#include <opencv2/dnn.hpp>
4545
#include <opencv2/dnn/all_layers.hpp>
46+
47+
namespace cv { namespace dnn {
48+
Mutex& getInitializationMutex();
49+
void initializeLayerFactory();
50+
}} // namespace

samples/dnn/caffe_googlenet.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,6 @@ static std::vector<String> readClassNames(const char *filename = "synset_words.t
8484

8585
int main(int argc, char **argv)
8686
{
87-
cv::dnn::initModule(); //Required if OpenCV is built as static libs
88-
8987
String modelTxt = "bvlc_googlenet.prototxt";
9088
String modelBin = "bvlc_googlenet.caffemodel";
9189
String imageFile = (argc > 1) ? argv[1] : "space_shuttle.jpg";

0 commit comments

Comments
 (0)