提交 00dd4333 编写于 作者: A Alexander Alekhin

dnn: fix LayerFactory initialization

上级 82ec76c1
......@@ -73,13 +73,6 @@ namespace dnn //! This namespace is used for dnn module functionlaity.
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.
*
* It includes dictionary with scalar params (which can be readed by using Dict interface),
......
// 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
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);
//! Unregisters registered layer with specified type name.
//! Unregisters registered layer with specified type name. Thread-safe.
static void unregisterLayer(const String &type);
/** @brief Creates instance of registered layer.
* @param type type name of creating layer.
* @param params parameters which will be used for layer initialization.
* @note Thread-safe.
*/
static Ptr<Layer> createLayerInstance(const String &type, LayerParams& params);
private:
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
......@@ -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()
{
// allocate on first use
static Ptr<LayerFactory::Impl> impl_(new LayerFactory::Impl());
return impl_;
static LayerFactory_Impl* volatile instance = NULL;
if (instance == NULL)
{
cv::AutoLock lock(getLayerFactoryMutex());
if (instance == NULL)
{
instance = &getLayerFactoryImpl_();
initializeLayerFactory();
}
}
return *instance;
}
void LayerFactory::registerLayer(const String &_type, Constuctor constructor)
{
cv::AutoLock lock(getLayerFactoryMutex());
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");
}
impl()->insert(std::make_pair(type, constructor));
getLayerFactoryImpl().insert(std::make_pair(type, constructor));
}
void LayerFactory::unregisterLayer(const String &_type)
{
cv::AutoLock lock(getLayerFactoryMutex());
String type = _type.toLowerCase();
impl()->erase(type);
getLayerFactoryImpl().erase(type);
}
Ptr<Layer> LayerFactory::createLayerInstance(const String &_type, LayerParams& params)
{
cv::AutoLock lock(getLayerFactoryMutex());
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);
}
......
......@@ -40,68 +40,62 @@
//M*/
#include "precomp.hpp"
#include <opencv2/dnn/layer.details.hpp>
namespace cv
{
namespace dnn
{
struct AutoInitializer
static Mutex* __initialization_mutex = NULL;
Mutex& getInitializationMutex()
{
bool status;
AutoInitializer() : status(false)
{
initModule();
}
};
if (__initialization_mutex == NULL)
__initialization_mutex = new Mutex();
return *__initialization_mutex;
}
// force initialization (single-threaded environment)
Mutex* __initialization_mutex_initializer = &getInitializationMutex();
static AutoInitializer init;
void initModule()
void initializeLayerFactory()
{
if (init.status)
return;
REG_RUNTIME_LAYER_CLASS(Slice, SliceLayer);
REG_RUNTIME_LAYER_CLASS(Split, SplitLayer);
REG_RUNTIME_LAYER_CLASS(Concat, ConcatLayer);
REG_RUNTIME_LAYER_CLASS(Reshape, ReshapeLayer);
REG_RUNTIME_LAYER_CLASS(Flatten, FlattenLayer);
CV_DNN_REGISTER_LAYER_CLASS(Slice, SliceLayer);
CV_DNN_REGISTER_LAYER_CLASS(Split, SplitLayer);
CV_DNN_REGISTER_LAYER_CLASS(Concat, ConcatLayer);
CV_DNN_REGISTER_LAYER_CLASS(Reshape, ReshapeLayer);
CV_DNN_REGISTER_LAYER_CLASS(Flatten, FlattenLayer);
REG_RUNTIME_LAYER_CLASS(Convolution, ConvolutionLayer);
REG_RUNTIME_LAYER_CLASS(Deconvolution, DeconvolutionLayer);
REG_RUNTIME_LAYER_CLASS(Pooling, PoolingLayer);
REG_RUNTIME_LAYER_CLASS(LRN, LRNLayer);
REG_RUNTIME_LAYER_CLASS(InnerProduct, InnerProductLayer);
REG_RUNTIME_LAYER_CLASS(Softmax, SoftmaxLayer);
REG_RUNTIME_LAYER_CLASS(MVN, MVNLayer);
CV_DNN_REGISTER_LAYER_CLASS(Convolution, ConvolutionLayer);
CV_DNN_REGISTER_LAYER_CLASS(Deconvolution, DeconvolutionLayer);
CV_DNN_REGISTER_LAYER_CLASS(Pooling, PoolingLayer);
CV_DNN_REGISTER_LAYER_CLASS(LRN, LRNLayer);
CV_DNN_REGISTER_LAYER_CLASS(InnerProduct, InnerProductLayer);
CV_DNN_REGISTER_LAYER_CLASS(Softmax, SoftmaxLayer);
CV_DNN_REGISTER_LAYER_CLASS(MVN, MVNLayer);
REG_RUNTIME_LAYER_CLASS(ReLU, ReLULayer);
REG_RUNTIME_LAYER_CLASS(ChannelsPReLU, ChannelsPReLULayer);
REG_RUNTIME_LAYER_CLASS(Sigmoid, SigmoidLayer);
REG_RUNTIME_LAYER_CLASS(TanH, TanHLayer);
REG_RUNTIME_LAYER_CLASS(BNLL, BNLLLayer);
REG_RUNTIME_LAYER_CLASS(AbsVal, AbsLayer);
REG_RUNTIME_LAYER_CLASS(Power, PowerLayer);
REG_RUNTIME_LAYER_CLASS(BatchNorm, BatchNormLayer);
REG_RUNTIME_LAYER_CLASS(MaxUnpool, MaxUnpoolLayer);
REG_RUNTIME_LAYER_CLASS(Dropout, BlankLayer);
REG_RUNTIME_LAYER_CLASS(Identity, BlankLayer);
CV_DNN_REGISTER_LAYER_CLASS(ReLU, ReLULayer);
CV_DNN_REGISTER_LAYER_CLASS(ChannelsPReLU, ChannelsPReLULayer);
CV_DNN_REGISTER_LAYER_CLASS(Sigmoid, SigmoidLayer);
CV_DNN_REGISTER_LAYER_CLASS(TanH, TanHLayer);
CV_DNN_REGISTER_LAYER_CLASS(BNLL, BNLLLayer);
CV_DNN_REGISTER_LAYER_CLASS(AbsVal, AbsLayer);
CV_DNN_REGISTER_LAYER_CLASS(Power, PowerLayer);
CV_DNN_REGISTER_LAYER_CLASS(BatchNorm, BatchNormLayer);
CV_DNN_REGISTER_LAYER_CLASS(MaxUnpool, MaxUnpoolLayer);
CV_DNN_REGISTER_LAYER_CLASS(Dropout, BlankLayer);
CV_DNN_REGISTER_LAYER_CLASS(Identity, BlankLayer);
REG_RUNTIME_LAYER_CLASS(Crop, CropLayer);
REG_RUNTIME_LAYER_CLASS(Eltwise, EltwiseLayer);
REG_RUNTIME_LAYER_CLASS(Permute, PermuteLayer);
REG_RUNTIME_LAYER_CLASS(PriorBox, PriorBoxLayer);
REG_RUNTIME_LAYER_CLASS(DetectionOutput, DetectionOutputLayer);
REG_RUNTIME_LAYER_CLASS(NormalizeBBox, NormalizeBBoxLayer);
REG_RUNTIME_LAYER_CLASS(Normalize, NormalizeBBoxLayer);
REG_RUNTIME_LAYER_CLASS(Shift, ShiftLayer);
REG_RUNTIME_LAYER_CLASS(Padding, PaddingLayer);
REG_RUNTIME_LAYER_CLASS(Scale, ScaleLayer);
init.status = true;
CV_DNN_REGISTER_LAYER_CLASS(Crop, CropLayer);
CV_DNN_REGISTER_LAYER_CLASS(Eltwise, EltwiseLayer);
CV_DNN_REGISTER_LAYER_CLASS(Permute, PermuteLayer);
CV_DNN_REGISTER_LAYER_CLASS(PriorBox, PriorBoxLayer);
CV_DNN_REGISTER_LAYER_CLASS(DetectionOutput, DetectionOutputLayer);
CV_DNN_REGISTER_LAYER_CLASS(NormalizeBBox, NormalizeBBoxLayer);
CV_DNN_REGISTER_LAYER_CLASS(Normalize, NormalizeBBoxLayer);
CV_DNN_REGISTER_LAYER_CLASS(Shift, ShiftLayer);
CV_DNN_REGISTER_LAYER_CLASS(Padding, PaddingLayer);
CV_DNN_REGISTER_LAYER_CLASS(Scale, ScaleLayer);
}
}
}
}} //namespace
......@@ -43,3 +43,8 @@
#include "cvconfig.h"
#include <opencv2/dnn.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)
{
cv::dnn::initModule(); //Required if OpenCV is built as static libs
String modelTxt = "bvlc_googlenet.prototxt";
String modelBin = "bvlc_googlenet.caffemodel";
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)
{
cv::dnn::initModule(); //Required if OpenCV is built as static libs
String modelTxt = fcnType + "-heavy-pascal.prototxt";
String modelBin = fcnType + "-heavy-pascal.caffemodel";
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)
{
initModule(); // Required if OpenCV is built as static libs.
std::string modelTxt = "train_val.prototxt";
std::string modelBin = "squeezenet_v1.1.caffemodel";
std::string imageFile = (argc > 1) ? argv[1] : "space_shuttle.jpg";
......
......@@ -62,8 +62,6 @@ int main(int argc, char** argv)
return 0;
}
cv::dnn::initModule(); //Required if OpenCV is built as static libs
String modelConfiguration = parser.get<string>("proto");
String modelBinary = parser.get<string>("model");
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册