Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/dnn/misc/python/pyopencv_dnn.hpp
16358 views
1
#ifdef HAVE_OPENCV_DNN
2
typedef dnn::DictValue LayerId;
3
typedef std::vector<dnn::MatShape> vector_MatShape;
4
typedef std::vector<std::vector<dnn::MatShape> > vector_vector_MatShape;
5
6
7
template<>
8
bool pyopencv_to(PyObject *o, dnn::DictValue &dv, const char *name)
9
{
10
CV_UNUSED(name);
11
if (!o || o == Py_None)
12
return true; //Current state will be used
13
else if (PyLong_Check(o))
14
{
15
dv = dnn::DictValue((int64)PyLong_AsLongLong(o));
16
return true;
17
}
18
else if (PyInt_Check(o))
19
{
20
dv = dnn::DictValue((int64)PyInt_AS_LONG(o));
21
return true;
22
}
23
else if (PyFloat_Check(o))
24
{
25
dv = dnn::DictValue(PyFloat_AS_DOUBLE(o));
26
return true;
27
}
28
else if (PyString_Check(o))
29
{
30
dv = dnn::DictValue(String(PyString_AsString(o)));
31
return true;
32
}
33
else
34
return false;
35
}
36
37
template<>
38
bool pyopencv_to(PyObject *o, std::vector<Mat> &blobs, const char *name) //required for Layer::blobs RW
39
{
40
return pyopencvVecConverter<Mat>::to(o, blobs, ArgInfo(name, false));
41
}
42
43
template<typename T>
44
PyObject* pyopencv_from(const dnn::DictValue &dv)
45
{
46
if (dv.size() > 1)
47
{
48
std::vector<T> vec(dv.size());
49
for (int i = 0; i < dv.size(); ++i)
50
vec[i] = dv.get<T>(i);
51
return pyopencv_from_generic_vec(vec);
52
}
53
else
54
return pyopencv_from(dv.get<T>());
55
}
56
57
template<>
58
PyObject* pyopencv_from(const dnn::DictValue &dv)
59
{
60
if (dv.isInt()) return pyopencv_from<int>(dv);
61
if (dv.isReal()) return pyopencv_from<float>(dv);
62
if (dv.isString()) return pyopencv_from<String>(dv);
63
CV_Error(Error::StsNotImplemented, "Unknown value type");
64
return NULL;
65
}
66
67
template<>
68
PyObject* pyopencv_from(const dnn::LayerParams& lp)
69
{
70
PyObject* dict = PyDict_New();
71
for (std::map<String, dnn::DictValue>::const_iterator it = lp.begin(); it != lp.end(); ++it)
72
{
73
CV_Assert(!PyDict_SetItemString(dict, it->first.c_str(), pyopencv_from(it->second)));
74
}
75
return dict;
76
}
77
78
class pycvLayer CV_FINAL : public dnn::Layer
79
{
80
public:
81
pycvLayer(const dnn::LayerParams &params, PyObject* pyLayer) : Layer(params)
82
{
83
PyGILState_STATE gstate;
84
gstate = PyGILState_Ensure();
85
86
PyObject* args = PyTuple_New(2);
87
CV_Assert(!PyTuple_SetItem(args, 0, pyopencv_from(params)));
88
CV_Assert(!PyTuple_SetItem(args, 1, pyopencv_from(params.blobs)));
89
o = PyObject_CallObject(pyLayer, args);
90
91
Py_DECREF(args);
92
PyGILState_Release(gstate);
93
if (!o)
94
CV_Error(Error::StsError, "Failed to create an instance of custom layer");
95
}
96
97
static void registerLayer(const std::string& type, PyObject* o)
98
{
99
std::map<std::string, std::vector<PyObject*> >::iterator it = pyLayers.find(type);
100
if (it != pyLayers.end())
101
it->second.push_back(o);
102
else
103
pyLayers[type] = std::vector<PyObject*>(1, o);
104
}
105
106
static void unregisterLayer(const std::string& type)
107
{
108
std::map<std::string, std::vector<PyObject*> >::iterator it = pyLayers.find(type);
109
if (it != pyLayers.end())
110
{
111
if (it->second.size() > 1)
112
it->second.pop_back();
113
else
114
pyLayers.erase(it);
115
}
116
}
117
118
static Ptr<dnn::Layer> create(dnn::LayerParams &params)
119
{
120
std::map<std::string, std::vector<PyObject*> >::iterator it = pyLayers.find(params.type);
121
if (it == pyLayers.end())
122
CV_Error(Error::StsNotImplemented, "Layer with a type \"" + params.type +
123
"\" is not implemented");
124
CV_Assert(!it->second.empty());
125
return Ptr<dnn::Layer>(new pycvLayer(params, it->second.back()));
126
}
127
128
virtual bool getMemoryShapes(const std::vector<std::vector<int> > &inputs,
129
const int,
130
std::vector<std::vector<int> > &outputs,
131
std::vector<std::vector<int> > &) const CV_OVERRIDE
132
{
133
PyGILState_STATE gstate;
134
gstate = PyGILState_Ensure();
135
136
PyObject* args = PyList_New(inputs.size());
137
for(size_t i = 0; i < inputs.size(); ++i)
138
PyList_SET_ITEM(args, i, pyopencv_from_generic_vec(inputs[i]));
139
140
PyObject* res = PyObject_CallMethodObjArgs(o, PyString_FromString("getMemoryShapes"), args, NULL);
141
Py_DECREF(args);
142
PyGILState_Release(gstate);
143
if (!res)
144
CV_Error(Error::StsNotImplemented, "Failed to call \"getMemoryShapes\" method");
145
CV_Assert(pyopencv_to_generic_vec(res, outputs, ArgInfo("", 0)));
146
return false;
147
}
148
149
virtual void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays) CV_OVERRIDE
150
{
151
PyGILState_STATE gstate;
152
gstate = PyGILState_Ensure();
153
154
std::vector<Mat> inputs, outputs;
155
inputs_arr.getMatVector(inputs);
156
outputs_arr.getMatVector(outputs);
157
158
PyObject* args = pyopencv_from(inputs);
159
PyObject* res = PyObject_CallMethodObjArgs(o, PyString_FromString("forward"), args, NULL);
160
Py_DECREF(args);
161
PyGILState_Release(gstate);
162
if (!res)
163
CV_Error(Error::StsNotImplemented, "Failed to call \"forward\" method");
164
165
std::vector<Mat> pyOutputs;
166
CV_Assert(pyopencv_to(res, pyOutputs, ArgInfo("", 0)));
167
168
CV_Assert(pyOutputs.size() == outputs.size());
169
for (size_t i = 0; i < outputs.size(); ++i)
170
{
171
CV_Assert(pyOutputs[i].size == outputs[i].size);
172
CV_Assert(pyOutputs[i].type() == outputs[i].type());
173
pyOutputs[i].copyTo(outputs[i]);
174
}
175
}
176
177
private:
178
// Map layers types to python classes.
179
static std::map<std::string, std::vector<PyObject*> > pyLayers;
180
PyObject* o; // Instance of implemented python layer.
181
};
182
183
std::map<std::string, std::vector<PyObject*> > pycvLayer::pyLayers;
184
185
static PyObject *pyopencv_cv_dnn_registerLayer(PyObject*, PyObject *args, PyObject *kw)
186
{
187
const char *keywords[] = { "type", "class", NULL };
188
char* layerType;
189
PyObject *classInstance;
190
191
if (!PyArg_ParseTupleAndKeywords(args, kw, "sO", (char**)keywords, &layerType, &classInstance))
192
return NULL;
193
if (!PyCallable_Check(classInstance)) {
194
PyErr_SetString(PyExc_TypeError, "class must be callable");
195
return NULL;
196
}
197
198
pycvLayer::registerLayer(layerType, classInstance);
199
dnn::LayerFactory::registerLayer(layerType, pycvLayer::create);
200
Py_RETURN_NONE;
201
}
202
203
static PyObject *pyopencv_cv_dnn_unregisterLayer(PyObject*, PyObject *args, PyObject *kw)
204
{
205
const char *keywords[] = { "type", NULL };
206
char* layerType;
207
208
if (!PyArg_ParseTupleAndKeywords(args, kw, "s", (char**)keywords, &layerType))
209
return NULL;
210
211
pycvLayer::unregisterLayer(layerType);
212
dnn::LayerFactory::unregisterLayer(layerType);
213
Py_RETURN_NONE;
214
}
215
216
#endif // HAVE_OPENCV_DNN
217
218