PyDescriptor.cpp
Go to the documentation of this file.
1 
2 #include <python/PyDescriptor.h>
6 #include <rtabmap/utilite/UStl.h>
9 
10 #include <pybind11/embed.h>
11 
12 #define NPY_NO_DEPRECATED_API NPY_API_VERSION
13 #include <numpy/arrayobject.h>
14 
15 namespace rtabmap
16 {
17 
19  const ParametersMap & parameters) :
20  GlobalDescriptorExtractor(parameters),
21  pModule_(0),
22  pFunc_(0),
23  dim_(Parameters::defaultPyDescriptorDim())
24 {
25  UDEBUG("");
26  this->parseParameters(parameters);
27 }
28 
30 {
31  UDEBUG("");
32  pybind11::gil_scoped_acquire acquire;
33 
34  if(pFunc_)
35  {
36  Py_DECREF(pFunc_);
37  }
38  if(pModule_)
39  {
40  Py_DECREF(pModule_);
41  }
42 }
43 
45 {
46  UDEBUG("");
47  std::string previousPath = path_;
48  Parameters::parse(parameters, Parameters::kPyDescriptorPath(), path_);
49  Parameters::parse(parameters, Parameters::kPyDescriptorDim(), dim_);
51  UINFO("path = %s", path_.c_str());
52  UINFO("dim = %d", dim_);
53  UTimer timer;
54 
55  pybind11::gil_scoped_acquire acquire;
56 
57  if(pModule_)
58  {
59  if(!previousPath.empty() && previousPath.compare(path_)!=0)
60  {
61  UDEBUG("we changed script (old=%s), we need to reload (new=%s)",
62  previousPath.c_str(), path_.c_str());
63  if(pFunc_)
64  {
65  Py_DECREF(pFunc_);
66  }
67  pFunc_=0;
68  Py_DECREF(pModule_);
69  pModule_ = 0;
70  }
71  }
72 
73  if(pModule_==0)
74  {
75  UASSERT(pFunc_ == 0);
76  if(path_.empty())
77  {
78  return;
79  }
80  std::string matcherPythonDir = UDirectory::getDir(path_);
81  if(!matcherPythonDir.empty())
82  {
83  PyRun_SimpleString("import sys");
84  PyRun_SimpleString(uFormat("sys.path.append(\"%s\")", matcherPythonDir.c_str()).c_str());
85  }
86 
87  _import_array();
88 
89  std::string scriptName = uSplit(UFile::getName(path_), '.').front();
90  PyObject * pName = PyUnicode_FromString(scriptName.c_str());
91  UDEBUG("PyImport_Import() beg");
92  pModule_ = PyImport_Import(pName);
93  UDEBUG("PyImport_Import() end");
94 
95  Py_DECREF(pName);
96 
97  if(!pModule_)
98  {
99  UERROR("Module \"%s\" could not be imported! (File=\"%s\")", scriptName.c_str(), path_.c_str());
100  UERROR("%s", getPythonTraceback().c_str());
101  }
102  else
103  {
104  PyObject * pFunc = PyObject_GetAttrString(pModule_, "init");
105  if(pFunc)
106  {
107  if(PyCallable_Check(pFunc))
108  {
109  PyObject * result = PyObject_CallFunction(pFunc, "i", dim_);
110 
111  if(result == NULL)
112  {
113  UERROR("Call to \"init(...)\" in \"%s\" failed!", path_.c_str());
114  UERROR("%s", getPythonTraceback().c_str());
115  }
116  Py_DECREF(result);
117 
118  pFunc_ = PyObject_GetAttrString(pModule_, "extract");
119  if(pFunc_ && PyCallable_Check(pFunc_))
120  {
121  // we are ready!
122  }
123  else
124  {
125  UERROR("Cannot find method \"extract(...)\" in %s", path_.c_str());
126  UERROR("%s", getPythonTraceback().c_str());
127  if(pFunc_)
128  {
129  Py_DECREF(pFunc_);
130  pFunc_ = 0;
131  }
132  }
133  }
134  else
135  {
136  UERROR("Cannot call method \"init(...)\" in %s", path_.c_str());
137  UERROR("%s", getPythonTraceback().c_str());
138  }
139  Py_DECREF(pFunc);
140  }
141  else
142  {
143  UERROR("Cannot find method \"init(...)\"");
144  UERROR("%s", getPythonTraceback().c_str());
145  }
146  }
147  }
148 }
149 
151  const SensorData & data) const
152 {
153  UDEBUG("");
154  UTimer timer;
156 
157  if(!pModule_)
158  {
159  UERROR("Python module not loaded!");
160  return descriptor;
161  }
162 
163  if(!pFunc_)
164  {
165  UERROR("Python function not loaded!");
166  return descriptor;
167  }
168 
169  pybind11::gil_scoped_acquire acquire;
170 
171  if(!data.imageRaw().empty())
172  {
173  std::vector<unsigned char> descriptorsQueryV(data.imageRaw().total()*data.imageRaw().channels());
174  memcpy(descriptorsQueryV.data(), data.imageRaw().data, data.imageRaw().total()*data.imageRaw().channels()*sizeof(char));
175  npy_intp dimsFrom[3] = {data.imageRaw().rows, data.imageRaw().cols, data.imageRaw().channels()};
176  PyObject* pImageQuery = PyArray_SimpleNewFromData(3, dimsFrom, NPY_BYTE, (void*)data.imageRaw().data);
177  UASSERT(pImageQuery);
178 
179  UDEBUG("Preparing data time = %fs", timer.ticks());
180 
181  PyObject *pReturn = PyObject_CallFunctionObjArgs(pFunc_, pImageQuery, NULL);
182  if(pReturn == NULL)
183  {
184  UERROR("Failed to call extract() function!");
185  UERROR("%s", getPythonTraceback().c_str());
186  }
187  else
188  {
189  UDEBUG("Python extraction time = %fs", timer.ticks());
190 
191  PyArrayObject *np_ret = reinterpret_cast<PyArrayObject*>(pReturn);
192 
193  // Convert back to C++ array and print.
194  int len1 = PyArray_SHAPE(np_ret)[0];
195  int dim = PyArray_SHAPE(np_ret)[1];
196  int type = PyArray_TYPE(np_ret);
197  UDEBUG("Descriptor array %dx%d (type=%d)", len1, dim, type);
198  UASSERT(len1 == 1);
199  UASSERT_MSG(type == NPY_FLOAT, uFormat("Returned descriptor should type FLOAT=11, received type=%d", type).c_str());
200 
201  float* d_out = reinterpret_cast<float*>(PyArray_DATA(np_ret));
202  descriptor = GlobalDescriptor(1, cv::Mat(1, dim, CV_32FC1, d_out).clone());
203 
204  //std::cout << descriptor.data() << std::endl;
205 
206  Py_DECREF(pReturn);
207  }
208 
209  Py_DECREF(pImageQuery);
210  }
211  else
212  {
213  UERROR("Invalid inputs! Missing image.");
214  }
215  return descriptor;
216 }
217 
218 }
rtabmap::SensorData
Definition: SensorData.h:51
UFile::getName
std::string getName()
Definition: UFile.h:135
PyDescriptor.h
rtabmap::GlobalDescriptorExtractor
Definition: GlobalDescriptorExtractor.h:40
UINFO
#define UINFO(...)
timer
rtabmap_netvlad.descriptor
def descriptor
Definition: rtabmap_netvlad.py:81
PyUnicode_FromString
#define PyUnicode_FromString
UDirectory.h
rtabmap::PyDescriptor::PyDescriptor
PyDescriptor(const ParametersMap &parameters=ParametersMap())
Definition: PyDescriptor.cpp:18
type
rtabmap::PyDescriptor::path_
std::string path_
Definition: PyDescriptor.h:32
rtabmap::ParametersMap
std::map< std::string, std::string > ParametersMap
Definition: Parameters.h:43
UTimer.h
rtabmap::Parameters::parse
static bool parse(const ParametersMap &parameters, const std::string &key, bool &value)
Definition: Parameters.cpp:500
rtabmap::PyDescriptor::dim
float dim() const
Definition: PyDescriptor.h:23
rtabmap::getPythonTraceback
std::string getPythonTraceback()
Definition: PythonInterface.cpp:30
UDirectory::homeDir
static std::string homeDir()
Definition: UDirectory.cpp:355
data
int data[]
rtabmap::PyDescriptor::parseParameters
virtual void parseParameters(const ParametersMap &parameters)
Definition: PyDescriptor.cpp:44
UDirectory::getDir
static std::string getDir(const std::string &filePath)
Definition: UDirectory.cpp:273
UConversion.h
Some conversion functions.
rtabmap::PyDescriptor::pFunc_
PyObject * pFunc_
Definition: PyDescriptor.h:31
rtabmap::PyDescriptor::dim_
int dim_
Definition: PyDescriptor.h:33
UASSERT
#define UASSERT(condition)
rtabmap::Parameters
Definition: Parameters.h:170
rtabmap::GlobalDescriptor
Definition: GlobalDescriptor.h:35
rtabmap::PyDescriptor::~PyDescriptor
virtual ~PyDescriptor()
Definition: PyDescriptor.cpp:29
UASSERT_MSG
#define UASSERT_MSG(condition, msg_str)
Definition: ULogger.h:67
uFormat
std::string UTILITE_EXPORT uFormat(const char *fmt,...)
Definition: UConversion.cpp:365
uReplaceChar
std::string UTILITE_EXPORT uReplaceChar(const std::string &str, char before, char after)
Definition: UConversion.cpp:33
ULogger.h
ULogger class and convenient macros.
rtabmap::PyDescriptor::extract
virtual GlobalDescriptor extract(const SensorData &data) const
Definition: PyDescriptor.cpp:150
uSplit
std::list< std::string > uSplit(const std::string &str, char separator=' ')
Definition: UStl.h:564
embed.h
c_str
const char * c_str(Args &&...args)
UStl.h
Wrappers of STL for convenient functions.
UDEBUG
#define UDEBUG(...)
UTimer
Definition: UTimer.h:46
NULL
#define NULL
UFile.h
rtabmap
Definition: CameraARCore.cpp:35
UERROR
#define UERROR(...)
result
RESULT & result
rtabmap::PyDescriptor::pModule_
PyObject * pModule_
Definition: PyDescriptor.h:30


rtabmap
Author(s): Mathieu Labbe
autogenerated on Thu Jul 25 2024 02:50:14