Path: blob/master/modules/dnn/misc/python/pyopencv_dnn.hpp
16358 views
#ifdef HAVE_OPENCV_DNN1typedef dnn::DictValue LayerId;2typedef std::vector<dnn::MatShape> vector_MatShape;3typedef std::vector<std::vector<dnn::MatShape> > vector_vector_MatShape;456template<>7bool pyopencv_to(PyObject *o, dnn::DictValue &dv, const char *name)8{9CV_UNUSED(name);10if (!o || o == Py_None)11return true; //Current state will be used12else if (PyLong_Check(o))13{14dv = dnn::DictValue((int64)PyLong_AsLongLong(o));15return true;16}17else if (PyInt_Check(o))18{19dv = dnn::DictValue((int64)PyInt_AS_LONG(o));20return true;21}22else if (PyFloat_Check(o))23{24dv = dnn::DictValue(PyFloat_AS_DOUBLE(o));25return true;26}27else if (PyString_Check(o))28{29dv = dnn::DictValue(String(PyString_AsString(o)));30return true;31}32else33return false;34}3536template<>37bool pyopencv_to(PyObject *o, std::vector<Mat> &blobs, const char *name) //required for Layer::blobs RW38{39return pyopencvVecConverter<Mat>::to(o, blobs, ArgInfo(name, false));40}4142template<typename T>43PyObject* pyopencv_from(const dnn::DictValue &dv)44{45if (dv.size() > 1)46{47std::vector<T> vec(dv.size());48for (int i = 0; i < dv.size(); ++i)49vec[i] = dv.get<T>(i);50return pyopencv_from_generic_vec(vec);51}52else53return pyopencv_from(dv.get<T>());54}5556template<>57PyObject* pyopencv_from(const dnn::DictValue &dv)58{59if (dv.isInt()) return pyopencv_from<int>(dv);60if (dv.isReal()) return pyopencv_from<float>(dv);61if (dv.isString()) return pyopencv_from<String>(dv);62CV_Error(Error::StsNotImplemented, "Unknown value type");63return NULL;64}6566template<>67PyObject* pyopencv_from(const dnn::LayerParams& lp)68{69PyObject* dict = PyDict_New();70for (std::map<String, dnn::DictValue>::const_iterator it = lp.begin(); it != lp.end(); ++it)71{72CV_Assert(!PyDict_SetItemString(dict, it->first.c_str(), pyopencv_from(it->second)));73}74return dict;75}7677class pycvLayer CV_FINAL : public dnn::Layer78{79public:80pycvLayer(const dnn::LayerParams ¶ms, PyObject* pyLayer) : Layer(params)81{82PyGILState_STATE gstate;83gstate = PyGILState_Ensure();8485PyObject* args = PyTuple_New(2);86CV_Assert(!PyTuple_SetItem(args, 0, pyopencv_from(params)));87CV_Assert(!PyTuple_SetItem(args, 1, pyopencv_from(params.blobs)));88o = PyObject_CallObject(pyLayer, args);8990Py_DECREF(args);91PyGILState_Release(gstate);92if (!o)93CV_Error(Error::StsError, "Failed to create an instance of custom layer");94}9596static void registerLayer(const std::string& type, PyObject* o)97{98std::map<std::string, std::vector<PyObject*> >::iterator it = pyLayers.find(type);99if (it != pyLayers.end())100it->second.push_back(o);101else102pyLayers[type] = std::vector<PyObject*>(1, o);103}104105static void unregisterLayer(const std::string& type)106{107std::map<std::string, std::vector<PyObject*> >::iterator it = pyLayers.find(type);108if (it != pyLayers.end())109{110if (it->second.size() > 1)111it->second.pop_back();112else113pyLayers.erase(it);114}115}116117static Ptr<dnn::Layer> create(dnn::LayerParams ¶ms)118{119std::map<std::string, std::vector<PyObject*> >::iterator it = pyLayers.find(params.type);120if (it == pyLayers.end())121CV_Error(Error::StsNotImplemented, "Layer with a type \"" + params.type +122"\" is not implemented");123CV_Assert(!it->second.empty());124return Ptr<dnn::Layer>(new pycvLayer(params, it->second.back()));125}126127virtual bool getMemoryShapes(const std::vector<std::vector<int> > &inputs,128const int,129std::vector<std::vector<int> > &outputs,130std::vector<std::vector<int> > &) const CV_OVERRIDE131{132PyGILState_STATE gstate;133gstate = PyGILState_Ensure();134135PyObject* args = PyList_New(inputs.size());136for(size_t i = 0; i < inputs.size(); ++i)137PyList_SET_ITEM(args, i, pyopencv_from_generic_vec(inputs[i]));138139PyObject* res = PyObject_CallMethodObjArgs(o, PyString_FromString("getMemoryShapes"), args, NULL);140Py_DECREF(args);141PyGILState_Release(gstate);142if (!res)143CV_Error(Error::StsNotImplemented, "Failed to call \"getMemoryShapes\" method");144CV_Assert(pyopencv_to_generic_vec(res, outputs, ArgInfo("", 0)));145return false;146}147148virtual void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays) CV_OVERRIDE149{150PyGILState_STATE gstate;151gstate = PyGILState_Ensure();152153std::vector<Mat> inputs, outputs;154inputs_arr.getMatVector(inputs);155outputs_arr.getMatVector(outputs);156157PyObject* args = pyopencv_from(inputs);158PyObject* res = PyObject_CallMethodObjArgs(o, PyString_FromString("forward"), args, NULL);159Py_DECREF(args);160PyGILState_Release(gstate);161if (!res)162CV_Error(Error::StsNotImplemented, "Failed to call \"forward\" method");163164std::vector<Mat> pyOutputs;165CV_Assert(pyopencv_to(res, pyOutputs, ArgInfo("", 0)));166167CV_Assert(pyOutputs.size() == outputs.size());168for (size_t i = 0; i < outputs.size(); ++i)169{170CV_Assert(pyOutputs[i].size == outputs[i].size);171CV_Assert(pyOutputs[i].type() == outputs[i].type());172pyOutputs[i].copyTo(outputs[i]);173}174}175176private:177// Map layers types to python classes.178static std::map<std::string, std::vector<PyObject*> > pyLayers;179PyObject* o; // Instance of implemented python layer.180};181182std::map<std::string, std::vector<PyObject*> > pycvLayer::pyLayers;183184static PyObject *pyopencv_cv_dnn_registerLayer(PyObject*, PyObject *args, PyObject *kw)185{186const char *keywords[] = { "type", "class", NULL };187char* layerType;188PyObject *classInstance;189190if (!PyArg_ParseTupleAndKeywords(args, kw, "sO", (char**)keywords, &layerType, &classInstance))191return NULL;192if (!PyCallable_Check(classInstance)) {193PyErr_SetString(PyExc_TypeError, "class must be callable");194return NULL;195}196197pycvLayer::registerLayer(layerType, classInstance);198dnn::LayerFactory::registerLayer(layerType, pycvLayer::create);199Py_RETURN_NONE;200}201202static PyObject *pyopencv_cv_dnn_unregisterLayer(PyObject*, PyObject *args, PyObject *kw)203{204const char *keywords[] = { "type", NULL };205char* layerType;206207if (!PyArg_ParseTupleAndKeywords(args, kw, "s", (char**)keywords, &layerType))208return NULL;209210pycvLayer::unregisterLayer(layerType);211dnn::LayerFactory::unregisterLayer(layerType);212Py_RETURN_NONE;213}214215#endif // HAVE_OPENCV_DNN216217218