13 #define NPY_NO_DEPRECATED_API NPY_API_VERSION 14 #include <numpy/arrayobject.h> 41 PyErr_Fetch(&type, &value, &traceback);
42 PyErr_NormalizeException(&type, &value, &traceback);
45 fcn +=
"def get_pretty_traceback(exc_type, exc_value, exc_tb):\n";
46 fcn +=
" import sys, traceback\n";
47 fcn +=
" lines = []\n";
48 fcn +=
" lines = traceback.format_exception(exc_type, exc_value, exc_tb)\n";
49 fcn +=
" output = '\\n'.join(lines)\n";
50 fcn +=
" return output\n";
52 PyRun_SimpleString(fcn.c_str());
53 PyObject*
mod = PyImport_ImportModule(
"__main__");
54 PyObject* method = PyObject_GetAttrString(mod,
"get_pretty_traceback");
55 PyObject* outStr = PyObject_CallObject(method, Py_BuildValue(
"OOO", type, value, traceback));
66 const std::string & pythonMatcherPath,
70 const std::string & model) :
73 matchThreshold_(matchThreshold),
74 iterations_(iterations),
84 UERROR(
"Cannot initialize Python matcher, the path is not valid: \"%s\"",
path_.c_str());
94 if(!matcherPythonDir.empty())
96 PyRun_SimpleString(
"import sys");
97 PyRun_SimpleString(
uFormat(
"sys.path.append(\"%s\")", matcherPythonDir.c_str()).c_str());
109 UERROR(
"Module \"%s\" could not be imported! (File=\"%s\")", scriptName.c_str(),
path_.c_str());
127 const cv::Mat & descriptorsQuery,
128 const cv::Mat & descriptorsTrain,
129 const std::vector<cv::KeyPoint> & keypointsQuery,
130 const std::vector<cv::KeyPoint> & keypointsTrain,
131 const cv::Size & imageSize)
134 std::vector<cv::DMatch> matches;
138 UERROR(
"Python matcher module not loaded!");
142 if(!descriptorsQuery.empty() &&
143 descriptorsQuery.cols == descriptorsTrain.cols &&
144 descriptorsQuery.type() == CV_32F &&
145 descriptorsTrain.type() == CV_32F &&
146 descriptorsQuery.rows == (int)keypointsQuery.size() &&
147 descriptorsTrain.rows == (int)keypointsTrain.size() &&
148 imageSize.width>0 && imageSize.height>0)
155 PyObject * pFunc = PyObject_GetAttrString(
pModule_,
"init");
158 if(PyCallable_Check(pFunc))
164 UERROR(
"Call to \"init(...)\" in \"%s\" failed!",
path_.c_str());
177 UERROR(
"Cannot find method \"match(...)\" in %s",
path_.c_str());
189 UERROR(
"Cannot call method \"init(...)\" in %s",
path_.c_str());
197 UERROR(
"Cannot find method \"init(...)\"");
206 std::vector<float> descriptorsQueryV(descriptorsQuery.rows * descriptorsQuery.cols);
207 memcpy(descriptorsQueryV.data(), descriptorsQuery.data, descriptorsQuery.total()*
sizeof(float));
208 npy_intp dimsFrom[2] = {descriptorsQuery.rows, descriptorsQuery.cols};
209 PyObject* pDescriptorsQuery = PyArray_SimpleNewFromData(2, dimsFrom, NPY_FLOAT, (
void*)descriptorsQueryV.data());
212 npy_intp dimsTo[2] = {descriptorsTrain.rows, descriptorsTrain.cols};
213 std::vector<float> descriptorsTrainV(descriptorsTrain.rows * descriptorsTrain.cols);
214 memcpy(descriptorsTrainV.data(), descriptorsTrain.data, descriptorsTrain.total()*
sizeof(float));
215 PyObject* pDescriptorsTrain = PyArray_SimpleNewFromData(2, dimsTo, NPY_FLOAT, (
void*)descriptorsTrainV.data());
218 std::vector<float> keypointsQueryV(keypointsQuery.size()*2);
219 std::vector<float> scoresQuery(keypointsQuery.size());
220 for(
size_t i=0; i<keypointsQuery.size(); ++i)
222 keypointsQueryV[i*2] = keypointsQuery[i].pt.x;
223 keypointsQueryV[i*2+1] = keypointsQuery[i].pt.y;
224 scoresQuery[i] = keypointsQuery[i].response;
227 std::vector<float> keypointsTrainV(keypointsTrain.size()*2);
228 std::vector<float> scoresTrain(keypointsTrain.size());
229 for(
size_t i=0; i<keypointsTrain.size(); ++i)
231 keypointsTrainV[i*2] = keypointsTrain[i].pt.x;
232 keypointsTrainV[i*2+1] = keypointsTrain[i].pt.y;
233 scoresTrain[i] = keypointsTrain[i].response;
236 npy_intp dimsKpQuery[2] = {(int)keypointsQuery.size(), 2};
237 PyObject* pKeypointsQuery = PyArray_SimpleNewFromData(2, dimsKpQuery, NPY_FLOAT, (
void*)keypointsQueryV.data());
240 npy_intp dimsKpTrain[2] = {(int)keypointsTrain.size(), 2};
241 PyObject* pkeypointsTrain = PyArray_SimpleNewFromData(2, dimsKpTrain, NPY_FLOAT, (
void*)keypointsTrainV.data());
244 npy_intp dimsScoresQuery[1] = {(int)keypointsQuery.size()};
245 PyObject* pScoresQuery = PyArray_SimpleNewFromData(1, dimsScoresQuery, NPY_FLOAT, (
void*)scoresQuery.data());
248 npy_intp dimsScoresTrain[1] = {(int)keypointsTrain.size()};
249 PyObject* pScoresTrain = PyArray_SimpleNewFromData(1, dimsScoresTrain, NPY_FLOAT, (
void*)scoresTrain.data());
252 PyObject * pImageWidth = PyLong_FromLong(imageSize.width);
253 PyObject * pImageHeight = PyLong_FromLong(imageSize.height);
255 UDEBUG(
"Preparing data time = %fs", timer.
ticks());
257 PyObject *pReturn = PyObject_CallFunctionObjArgs(
pFunc_, pKeypointsQuery, pkeypointsTrain, pScoresQuery, pScoresTrain, pDescriptorsQuery, pDescriptorsTrain, pImageWidth, pImageHeight,
NULL);
260 UERROR(
"Failed to call match() function!");
265 UDEBUG(
"Python matching time = %fs", timer.
ticks());
267 PyArrayObject *np_ret =
reinterpret_cast<PyArrayObject*
>(pReturn);
270 int len1 = PyArray_SHAPE(np_ret)[0];
271 int len2 = PyArray_SHAPE(np_ret)[1];
272 int type = PyArray_TYPE(np_ret);
273 UDEBUG(
"Matches array %dx%d (type=%d)", len1, len2, type);
274 UASSERT_MSG(type == NPY_LONG || type == NPY_INT,
uFormat(
"Returned matches should type INT=5 or LONG=7, received type=%d", type).c_str());
277 long* c_out =
reinterpret_cast<long*
>(PyArray_DATA(np_ret));
278 for (
int i = 0; i < len1*len2; i+=2)
280 matches.push_back(cv::DMatch(c_out[i], c_out[i+1], 0));
285 int* c_out =
reinterpret_cast<int*
>(PyArray_DATA(np_ret));
286 for (
int i = 0; i < len1*len2; i+=2)
288 matches.push_back(cv::DMatch(c_out[i], c_out[i+1], 0));
294 Py_DECREF(pDescriptorsQuery);
295 Py_DECREF(pDescriptorsTrain);
296 Py_DECREF(pKeypointsQuery);
297 Py_DECREF(pkeypointsTrain);
298 Py_DECREF(pScoresQuery);
299 Py_DECREF(pScoresTrain);
300 Py_DECREF(pImageWidth);
301 Py_DECREF(pImageHeight);
303 UDEBUG(
"Fill matches (%d/%d) and cleanup time = %fs", matches.size(),
std::min(descriptorsQuery.rows, descriptorsTrain.rows), timer.
ticks());
308 UERROR(
"Invalid inputs! Supported python matchers require float descriptors.");
static std::string homeDir()
GLM_FUNC_DECL genType min(genType const &x, genType const &y)
GLM_FUNC_DECL genType mod(genType const &x, genType const &y)
static std::string getDir(const std::string &filePath)
Some conversion functions.
std::string getExtension()
std::list< std::string > uSplit(const std::string &str, char separator= ' ')
std::string getTraceback()
#define UASSERT(condition)
Wrappers of STL for convenient functions.
virtual ~PythonSingleTon()
#define UASSERT_MSG(condition, msg_str)
static PythonSingleTon g_python
PyMatcher(const std::string &pythonMatcherPath, float matchThreshold=0.2f, int iterations=20, bool cuda=true, const std::string &model="indoor")
std::string UTILITE_EXP uReplaceChar(const std::string &str, char before, char after)
ULogger class and convenient macros.
#define PyUnicode_FromString
std::string UTILITE_EXP uFormat(const char *fmt,...)
std::vector< cv::DMatch > match(const cv::Mat &descriptorsQuery, const cv::Mat &descriptorsTrain, const std::vector< cv::KeyPoint > &keypointsQuery, const std::vector< cv::KeyPoint > &keypointsTrain, const cv::Size &imageSize)