dnn: fix LayerFactory initialization

pull/9009/head
Alexander Alekhin 8 years ago
parent 82ec76c123
commit 00dd433368
  1. 7
      modules/dnn/include/opencv2/dnn/dnn.hpp
  2. 77
      modules/dnn/include/opencv2/dnn/layer.details.hpp
  3. 68
      modules/dnn/include/opencv2/dnn/layer.hpp
  4. 51
      modules/dnn/src/dnn.cpp
  5. 92
      modules/dnn/src/init.cpp
  6. 5
      modules/dnn/src/precomp.hpp
  7. 2
      samples/dnn/caffe_googlenet.cpp
  8. 2
      samples/dnn/fcn_semsegm.cpp
  9. 2
      samples/dnn/squeezenet_halide.cpp
  10. 2
      samples/dnn/ssd_object_detection.cpp

@ -73,13 +73,6 @@ namespace dnn //! This namespace is used for dnn module functionlaity.
DNN_TARGET_OPENCL DNN_TARGET_OPENCL
}; };
/** @brief Initialize dnn module and built-in layers.
*
* This function automatically called on most of OpenCV builds,
* but you need to call it manually on some specific configurations (iOS for example).
*/
CV_EXPORTS_W void initModule();
/** @brief This class provides all data needed to initialize layer. /** @brief This class provides all data needed to initialize layer.
* *
* It includes dictionary with scalar params (which can be readed by using Dict interface), * It includes dictionary with scalar params (which can be readed by using Dict interface),

@ -0,0 +1,77 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
//
#ifndef OPENCV_DNN_LAYER_DETAILS_HPP
#define OPENCV_DNN_LAYER_DETAILS_HPP
#include <opencv2/dnn/layer.hpp>
namespace cv
{
namespace dnn
{
/** @brief Registers layer constructor in runtime.
* @param type string, containing type name of the layer.
* @param constuctorFunc pointer to the function of type LayerRegister::Constuctor, which creates the layer.
* @details This macros must be placed inside the function code.
*/
#define CV_DNN_REGISTER_LAYER_FUNC(type, constuctorFunc) \
cv::dnn::LayerFactory::registerLayer(#type, constuctorFunc);
/** @brief Registers layer class in runtime.
* @param type string, containing type name of the layer.
* @param class C++ class, derived from Layer.
* @details This macros must be placed inside the function code.
*/
#define CV_DNN_REGISTER_LAYER_CLASS(type, class) \
cv::dnn::LayerFactory::registerLayer(#type, cv::dnn::details::_layerDynamicRegisterer<class>);
/** @brief Registers layer constructor on module load time.
* @param type string, containing type name of the layer.
* @param constuctorFunc pointer to the function of type LayerRegister::Constuctor, which creates the layer.
* @details This macros must be placed outside the function code.
*/
#define CV_DNN_REGISTER_LAYER_FUNC_STATIC(type, constuctorFunc) \
static cv::dnn::details::_LayerStaticRegisterer __LayerStaticRegisterer_##type(#type, constuctorFunc);
/** @brief Registers layer class on module load time.
* @param type string, containing type name of the layer.
* @param class C++ class, derived from Layer.
* @details This macros must be placed outside the function code.
*/
#define CV_DNN_REGISTER_LAYER_CLASS_STATIC(type, class) \
Ptr<Layer> __LayerStaticRegisterer_func_##type(LayerParams &params) \
{ return Ptr<Layer>(new class(params)); } \
static cv::dnn::details::_LayerStaticRegisterer __LayerStaticRegisterer_##type(#type, __LayerStaticRegisterer_func_##type);
namespace details {
template<typename LayerClass>
Ptr<Layer> _layerDynamicRegisterer(LayerParams &params)
{
return Ptr<Layer>(LayerClass::create(params));
}
//allows automatically register created layer on module load time
class _LayerStaticRegisterer
{
String type;
public:
_LayerStaticRegisterer(const String &layerType, LayerFactory::Constuctor layerConstuctor)
{
this->type = layerType;
LayerFactory::registerLayer(layerType, layerConstuctor);
}
~_LayerStaticRegisterer()
{
LayerFactory::unregisterLayer(type);
}
};
}}} //namespace
#endif

@ -61,88 +61,26 @@ public:
//! Each Layer class must provide this function to the factory //! Each Layer class must provide this function to the factory
typedef Ptr<Layer>(*Constuctor)(LayerParams &params); typedef Ptr<Layer>(*Constuctor)(LayerParams &params);
//! Registers the layer class with typename @p type and specified @p constructor. //! Registers the layer class with typename @p type and specified @p constructor. Thread-safe.
static void registerLayer(const String &type, Constuctor constructor); static void registerLayer(const String &type, Constuctor constructor);
//! Unregisters registered layer with specified type name. //! Unregisters registered layer with specified type name. Thread-safe.
static void unregisterLayer(const String &type); static void unregisterLayer(const String &type);
/** @brief Creates instance of registered layer. /** @brief Creates instance of registered layer.
* @param type type name of creating layer. * @param type type name of creating layer.
* @param params parameters which will be used for layer initialization. * @param params parameters which will be used for layer initialization.
* @note Thread-safe.
*/ */
static Ptr<Layer> createLayerInstance(const String &type, LayerParams& params); static Ptr<Layer> createLayerInstance(const String &type, LayerParams& params);
private: private:
LayerFactory(); LayerFactory();
struct Impl;
static Ptr<Impl> impl();
}; };
/** @brief Registers layer constructor in runtime.
* @param type string, containing type name of the layer.
* @param constuctorFunc pointer to the function of type LayerRegister::Constuctor, which creates the layer.
* @details This macros must be placed inside the function code.
*/
#define REG_RUNTIME_LAYER_FUNC(type, constuctorFunc) \
cv::dnn::LayerFactory::registerLayer(#type, constuctorFunc);
/** @brief Registers layer class in runtime.
* @param type string, containing type name of the layer.
* @param class C++ class, derived from Layer.
* @details This macros must be placed inside the function code.
*/
#define REG_RUNTIME_LAYER_CLASS(type, class) \
cv::dnn::LayerFactory::registerLayer(#type, _layerDynamicRegisterer<class>);
/** @brief Registers layer constructor on module load time.
* @param type string, containing type name of the layer.
* @param constuctorFunc pointer to the function of type LayerRegister::Constuctor, which creates the layer.
* @details This macros must be placed outside the function code.
*/
#define REG_STATIC_LAYER_FUNC(type, constuctorFunc) \
static cv::dnn::_LayerStaticRegisterer __LayerStaticRegisterer_##type(#type, constuctorFunc);
/** @brief Registers layer class on module load time.
* @param type string, containing type name of the layer.
* @param class C++ class, derived from Layer.
* @details This macros must be placed outside the function code.
*/
#define REG_STATIC_LAYER_CLASS(type, class) \
Ptr<Layer> __LayerStaticRegisterer_func_##type(LayerParams &params) \
{ return Ptr<Layer>(new class(params)); } \
static _LayerStaticRegisterer __LayerStaticRegisterer_##type(#type, __LayerStaticRegisterer_func_##type);
//! @} //! @}
//! @} //! @}
template<typename LayerClass>
Ptr<Layer> _layerDynamicRegisterer(LayerParams &params)
{
return Ptr<Layer>(LayerClass::create(params));
}
//allows automatically register created layer on module load time
class _LayerStaticRegisterer
{
String type;
public:
_LayerStaticRegisterer(const String &layerType, LayerFactory::Constuctor layerConstuctor)
{
this->type = layerType;
LayerFactory::registerLayer(layerType, layerConstuctor);
}
~_LayerStaticRegisterer()
{
LayerFactory::unregisterLayer(type);
}
};
} }
} }
#endif #endif

@ -1931,42 +1931,69 @@ bool Layer::getMemoryShapes(const std::vector<MatShape> &inputs,
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
struct LayerFactory::Impl : public std::map<String, LayerFactory::Constuctor> static Mutex& getLayerFactoryMutex()
{ {
}; static Mutex* volatile instance = NULL;
if (instance == NULL)
{
cv::AutoLock lock(getInitializationMutex());
if (instance == NULL)
instance = new Mutex();
}
return *instance;
}
typedef std::map<String, LayerFactory::Constuctor> LayerFactory_Impl;
static LayerFactory_Impl& getLayerFactoryImpl_()
{
static LayerFactory_Impl impl;
return impl;
}
Ptr<LayerFactory::Impl> LayerFactory::impl () static LayerFactory_Impl& getLayerFactoryImpl()
{
static LayerFactory_Impl* volatile instance = NULL;
if (instance == NULL)
{ {
// allocate on first use cv::AutoLock lock(getLayerFactoryMutex());
static Ptr<LayerFactory::Impl> impl_(new LayerFactory::Impl()); if (instance == NULL)
return impl_; {
instance = &getLayerFactoryImpl_();
initializeLayerFactory();
}
}
return *instance;
} }
void LayerFactory::registerLayer(const String &_type, Constuctor constructor) void LayerFactory::registerLayer(const String &_type, Constuctor constructor)
{ {
cv::AutoLock lock(getLayerFactoryMutex());
String type = _type.toLowerCase(); String type = _type.toLowerCase();
Impl::iterator it = impl()->find(type); LayerFactory_Impl::const_iterator it = getLayerFactoryImpl().find(type);
if (it != impl()->end() && it->second != constructor) if (it != getLayerFactoryImpl().end() && it->second != constructor)
{ {
CV_Error(cv::Error::StsBadArg, "Layer \"" + type + "\" already was registered"); CV_Error(cv::Error::StsBadArg, "Layer \"" + type + "\" already was registered");
} }
impl()->insert(std::make_pair(type, constructor)); getLayerFactoryImpl().insert(std::make_pair(type, constructor));
} }
void LayerFactory::unregisterLayer(const String &_type) void LayerFactory::unregisterLayer(const String &_type)
{ {
cv::AutoLock lock(getLayerFactoryMutex());
String type = _type.toLowerCase(); String type = _type.toLowerCase();
impl()->erase(type); getLayerFactoryImpl().erase(type);
} }
Ptr<Layer> LayerFactory::createLayerInstance(const String &_type, LayerParams& params) Ptr<Layer> LayerFactory::createLayerInstance(const String &_type, LayerParams& params)
{ {
cv::AutoLock lock(getLayerFactoryMutex());
String type = _type.toLowerCase(); String type = _type.toLowerCase();
Impl::const_iterator it = LayerFactory::impl()->find(type); LayerFactory_Impl::const_iterator it = getLayerFactoryImpl().find(type);
if (it != impl()->end()) if (it != getLayerFactoryImpl().end())
{ {
return it->second(params); return it->second(params);
} }

@ -40,68 +40,62 @@
//M*/ //M*/
#include "precomp.hpp" #include "precomp.hpp"
#include <opencv2/dnn/layer.details.hpp>
namespace cv namespace cv
{ {
namespace dnn namespace dnn
{ {
struct AutoInitializer static Mutex* __initialization_mutex = NULL;
Mutex& getInitializationMutex()
{ {
bool status; if (__initialization_mutex == NULL)
__initialization_mutex = new Mutex();
AutoInitializer() : status(false) return *__initialization_mutex;
{
initModule();
} }
}; // force initialization (single-threaded environment)
Mutex* __initialization_mutex_initializer = &getInitializationMutex();
static AutoInitializer init;
void initModule() void initializeLayerFactory()
{ {
if (init.status) CV_DNN_REGISTER_LAYER_CLASS(Slice, SliceLayer);
return; CV_DNN_REGISTER_LAYER_CLASS(Split, SplitLayer);
CV_DNN_REGISTER_LAYER_CLASS(Concat, ConcatLayer);
REG_RUNTIME_LAYER_CLASS(Slice, SliceLayer); CV_DNN_REGISTER_LAYER_CLASS(Reshape, ReshapeLayer);
REG_RUNTIME_LAYER_CLASS(Split, SplitLayer); CV_DNN_REGISTER_LAYER_CLASS(Flatten, FlattenLayer);
REG_RUNTIME_LAYER_CLASS(Concat, ConcatLayer);
REG_RUNTIME_LAYER_CLASS(Reshape, ReshapeLayer);
REG_RUNTIME_LAYER_CLASS(Flatten, FlattenLayer);
REG_RUNTIME_LAYER_CLASS(Convolution, ConvolutionLayer); CV_DNN_REGISTER_LAYER_CLASS(Convolution, ConvolutionLayer);
REG_RUNTIME_LAYER_CLASS(Deconvolution, DeconvolutionLayer); CV_DNN_REGISTER_LAYER_CLASS(Deconvolution, DeconvolutionLayer);
REG_RUNTIME_LAYER_CLASS(Pooling, PoolingLayer); CV_DNN_REGISTER_LAYER_CLASS(Pooling, PoolingLayer);
REG_RUNTIME_LAYER_CLASS(LRN, LRNLayer); CV_DNN_REGISTER_LAYER_CLASS(LRN, LRNLayer);
REG_RUNTIME_LAYER_CLASS(InnerProduct, InnerProductLayer); CV_DNN_REGISTER_LAYER_CLASS(InnerProduct, InnerProductLayer);
REG_RUNTIME_LAYER_CLASS(Softmax, SoftmaxLayer); CV_DNN_REGISTER_LAYER_CLASS(Softmax, SoftmaxLayer);
REG_RUNTIME_LAYER_CLASS(MVN, MVNLayer); CV_DNN_REGISTER_LAYER_CLASS(MVN, MVNLayer);
REG_RUNTIME_LAYER_CLASS(ReLU, ReLULayer); CV_DNN_REGISTER_LAYER_CLASS(ReLU, ReLULayer);
REG_RUNTIME_LAYER_CLASS(ChannelsPReLU, ChannelsPReLULayer); CV_DNN_REGISTER_LAYER_CLASS(ChannelsPReLU, ChannelsPReLULayer);
REG_RUNTIME_LAYER_CLASS(Sigmoid, SigmoidLayer); CV_DNN_REGISTER_LAYER_CLASS(Sigmoid, SigmoidLayer);
REG_RUNTIME_LAYER_CLASS(TanH, TanHLayer); CV_DNN_REGISTER_LAYER_CLASS(TanH, TanHLayer);
REG_RUNTIME_LAYER_CLASS(BNLL, BNLLLayer); CV_DNN_REGISTER_LAYER_CLASS(BNLL, BNLLLayer);
REG_RUNTIME_LAYER_CLASS(AbsVal, AbsLayer); CV_DNN_REGISTER_LAYER_CLASS(AbsVal, AbsLayer);
REG_RUNTIME_LAYER_CLASS(Power, PowerLayer); CV_DNN_REGISTER_LAYER_CLASS(Power, PowerLayer);
REG_RUNTIME_LAYER_CLASS(BatchNorm, BatchNormLayer); CV_DNN_REGISTER_LAYER_CLASS(BatchNorm, BatchNormLayer);
REG_RUNTIME_LAYER_CLASS(MaxUnpool, MaxUnpoolLayer); CV_DNN_REGISTER_LAYER_CLASS(MaxUnpool, MaxUnpoolLayer);
REG_RUNTIME_LAYER_CLASS(Dropout, BlankLayer); CV_DNN_REGISTER_LAYER_CLASS(Dropout, BlankLayer);
REG_RUNTIME_LAYER_CLASS(Identity, BlankLayer); CV_DNN_REGISTER_LAYER_CLASS(Identity, BlankLayer);
REG_RUNTIME_LAYER_CLASS(Crop, CropLayer); CV_DNN_REGISTER_LAYER_CLASS(Crop, CropLayer);
REG_RUNTIME_LAYER_CLASS(Eltwise, EltwiseLayer); CV_DNN_REGISTER_LAYER_CLASS(Eltwise, EltwiseLayer);
REG_RUNTIME_LAYER_CLASS(Permute, PermuteLayer); CV_DNN_REGISTER_LAYER_CLASS(Permute, PermuteLayer);
REG_RUNTIME_LAYER_CLASS(PriorBox, PriorBoxLayer); CV_DNN_REGISTER_LAYER_CLASS(PriorBox, PriorBoxLayer);
REG_RUNTIME_LAYER_CLASS(DetectionOutput, DetectionOutputLayer); CV_DNN_REGISTER_LAYER_CLASS(DetectionOutput, DetectionOutputLayer);
REG_RUNTIME_LAYER_CLASS(NormalizeBBox, NormalizeBBoxLayer); CV_DNN_REGISTER_LAYER_CLASS(NormalizeBBox, NormalizeBBoxLayer);
REG_RUNTIME_LAYER_CLASS(Normalize, NormalizeBBoxLayer); CV_DNN_REGISTER_LAYER_CLASS(Normalize, NormalizeBBoxLayer);
REG_RUNTIME_LAYER_CLASS(Shift, ShiftLayer); CV_DNN_REGISTER_LAYER_CLASS(Shift, ShiftLayer);
REG_RUNTIME_LAYER_CLASS(Padding, PaddingLayer); CV_DNN_REGISTER_LAYER_CLASS(Padding, PaddingLayer);
REG_RUNTIME_LAYER_CLASS(Scale, ScaleLayer); CV_DNN_REGISTER_LAYER_CLASS(Scale, ScaleLayer);
init.status = true;
} }
} }} //namespace
}

@ -43,3 +43,8 @@
#include "cvconfig.h" #include "cvconfig.h"
#include <opencv2/dnn.hpp> #include <opencv2/dnn.hpp>
#include <opencv2/dnn/all_layers.hpp> #include <opencv2/dnn/all_layers.hpp>
namespace cv { namespace dnn {
Mutex& getInitializationMutex();
void initializeLayerFactory();
}} // namespace

@ -84,8 +84,6 @@ static std::vector<String> readClassNames(const char *filename = "synset_words.t
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
cv::dnn::initModule(); //Required if OpenCV is built as static libs
String modelTxt = "bvlc_googlenet.prototxt"; String modelTxt = "bvlc_googlenet.prototxt";
String modelBin = "bvlc_googlenet.caffemodel"; String modelBin = "bvlc_googlenet.caffemodel";
String imageFile = (argc > 1) ? argv[1] : "space_shuttle.jpg"; String imageFile = (argc > 1) ? argv[1] : "space_shuttle.jpg";

@ -85,8 +85,6 @@ static void colorizeSegmentation(const Mat &score, const vector<cv::Vec3b> &colo
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
cv::dnn::initModule(); //Required if OpenCV is built as static libs
String modelTxt = fcnType + "-heavy-pascal.prototxt"; String modelTxt = fcnType + "-heavy-pascal.prototxt";
String modelBin = fcnType + "-heavy-pascal.caffemodel"; String modelBin = fcnType + "-heavy-pascal.caffemodel";
String imageFile = (argc > 1) ? argv[1] : "rgb.jpg"; String imageFile = (argc > 1) ? argv[1] : "rgb.jpg";

@ -53,8 +53,6 @@ static std::vector<std::string> readClassNames(const char *filename = "synset_wo
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
initModule(); // Required if OpenCV is built as static libs.
std::string modelTxt = "train_val.prototxt"; std::string modelTxt = "train_val.prototxt";
std::string modelBin = "squeezenet_v1.1.caffemodel"; std::string modelBin = "squeezenet_v1.1.caffemodel";
std::string imageFile = (argc > 1) ? argv[1] : "space_shuttle.jpg"; std::string imageFile = (argc > 1) ? argv[1] : "space_shuttle.jpg";

@ -62,8 +62,6 @@ int main(int argc, char** argv)
return 0; return 0;
} }
cv::dnn::initModule(); //Required if OpenCV is built as static libs
String modelConfiguration = parser.get<string>("proto"); String modelConfiguration = parser.get<string>("proto");
String modelBinary = parser.get<string>("model"); String modelBinary = parser.get<string>("model");

Loading…
Cancel
Save