1 #define NPY_NO_DEPRECATED_API NPY_API_VERSION
5 #include <structmember.h>
6 #include <numpy/arrayobject.h>
21 #define SUPPORTED_TAG_FAMILIES(_) \
32 #define TAG_CREATE_FAMILY(name) \
33 else if (0 == strcmp(family, #name)) self->tf = name ## _create();
34 #define TAG_SET_DESTROY_FUNC(name) \
35 else if (0 == strcmp(family, #name)) self->destroy_func = name ## _destroy;
36 #define FAMILY_STRING(name) " " #name "\n"
45 #define SET_SIGINT() struct sigaction sigaction_old; \
47 if( 0 != sigaction(SIGINT, \
48 &(struct sigaction){ .sa_handler = SIG_DFL }, \
51 PyErr_SetString(PyExc_RuntimeError, "sigaction() failed"); \
55 #define RESET_SIGINT() do { \
56 if( 0 != sigaction(SIGINT, \
57 &sigaction_old, NULL )) \
58 PyErr_SetString(PyExc_RuntimeError, "sigaction-restore failed"); \
61 #define PYMETHODDEF_ENTRY(function_prefix, name, args) {#name, \
62 (PyCFunction)function_prefix ## name, \
64 function_prefix ## name ## _docstring}
83 if(
self == NULL)
goto done;
88 const char* family = NULL;
95 PyObject* py_refine_edges = NULL;
96 PyObject* py_debug = NULL;
98 char* keywords[] = {
"family",
107 if(!PyArg_ParseTupleAndKeywords( args, kwargs,
"s|iiffOO",
120 if(py_refine_edges != NULL)
123 debug = PyObject_IsTrue(py_debug);
129 PyErr_Format(PyExc_RuntimeError,
"Unrecognized tag family name: '%s'. Families I know about:\n%s",
139 PyErr_SetString(PyExc_RuntimeError,
"apriltag_detector_create() failed!");
144 self->td->quad_decimate = decimate;
145 self->td->quad_sigma = blur;
146 self->td->nthreads = Nthreads;
148 self->td->debug = debug;
152 PyErr_SetString(PyExc_RuntimeError,
"Unable to add family to detector. \"maxhamming\" parameter should not exceed 3");
155 PyErr_Format(PyExc_RuntimeError,
"Unable to add family to detector due to insufficient memory to allocate the tag-family decoder. Try reducing \"maxhamming\" from %d or choose an alternative tag family",maxhamming);
173 self->destroy_func(self->tf);
181 return (PyObject*)
self;
195 self->destroy_func(self->tf);
199 Py_TYPE(
self)->tp_free((PyObject*)
self);
207 PyObject* result = NULL;
208 PyArrayObject* xy_c = NULL;
209 PyArrayObject* xy_lb_rb_rt_lt = NULL;
210 PyArrayObject* image = NULL;
211 PyObject* detections_tuple = NULL;
213 #ifdef _POSIX_C_SOURCE
216 if(!PyArg_ParseTuple( args,
"O&",
217 PyArray_Converter, &image ))
220 npy_intp* dims = PyArray_DIMS (image);
221 npy_intp* strides = PyArray_STRIDES(image);
222 int ndims = PyArray_NDIM (image);
225 PyErr_Format(PyExc_RuntimeError,
"The input image array must have exactly 2 dims; got %d",
229 if( PyArray_TYPE(image) != NPY_UINT8 )
231 PyErr_SetString(PyExc_RuntimeError,
"The input image array must contain 8-bit unsigned data");
234 if( strides[ndims-1] != 1 )
236 PyErr_SetString(PyExc_RuntimeError,
"Image rows must live in contiguous memory");
243 .stride = strides[0],
244 .buf = PyArray_DATA(image)};
249 if (N == 0 && errno == EAGAIN){
250 PyErr_Format(PyExc_RuntimeError,
"Unable to create %d threads for detector", self->td->nthreads);
254 detections_tuple = PyTuple_New(N);
255 if(detections_tuple == NULL)
257 PyErr_Format(PyExc_RuntimeError,
"Error creating output tuple of size %d", N);
261 for (
int i=0; i < N; i++)
263 xy_c = (PyArrayObject*)PyArray_SimpleNew(1, ((npy_intp[]){2}), NPY_FLOAT64);
266 PyErr_SetString(PyExc_RuntimeError,
"Could not allocate xy_c array");
269 xy_lb_rb_rt_lt = (PyArrayObject*)PyArray_SimpleNew(2, ((npy_intp[]){4,2}), NPY_FLOAT64);
270 if(xy_lb_rb_rt_lt == NULL)
272 PyErr_SetString(PyExc_RuntimeError,
"Could not allocate xy_lb_rb_rt_lt array");
279 *(
double*)PyArray_GETPTR1(xy_c, 0) = det->
c[0];
280 *(
double*)PyArray_GETPTR1(xy_c, 1) = det->
c[1];
282 for(
int j=0; j<4; j++)
284 *(
double*)PyArray_GETPTR2(xy_lb_rb_rt_lt, j, 0) = det->
p[j][0];
285 *(
double*)PyArray_GETPTR2(xy_lb_rb_rt_lt, j, 1) = det->
p[j][1];
288 PyTuple_SET_ITEM(detections_tuple, i,
289 Py_BuildValue(
"{s:i,s:f,s:i,s:N,s:N}",
294 "lb-rb-rt-lt", xy_lb_rb_rt_lt));
296 xy_lb_rb_rt_lt = NULL;
300 result = detections_tuple;
301 detections_tuple = NULL;
305 Py_XDECREF(xy_lb_rb_rt_lt);
307 Py_XDECREF(detections_tuple);
309 #ifdef _POSIX_C_SOURCE
316 #include "apriltag_detect_docstring.h"
317 #include "apriltag_py_type_docstring.h"
321 {NULL, NULL, 0, NULL}
326 PyVarObject_HEAD_INIT(NULL, 0)
327 .tp_name =
"apriltag",
332 .tp_flags = Py_TPFLAGS_DEFAULT,
333 .tp_doc = apriltag_py_type_docstring
337 { {NULL, NULL, 0, NULL}
341 #if PY_MAJOR_VERSION == 2
343 PyMODINIT_FUNC initapriltag(
void)
348 PyObject* module = Py_InitModule3(
"apriltag",
methods,
349 "AprilTags visual fiducial system detector");
352 PyModule_AddObject(module,
"apriltag", (PyObject *)&
apriltagType);
361 PyModuleDef_HEAD_INIT,
363 "AprilTags visual fiducial system detector",
381 PyModule_AddObject(module,
"apriltag", (PyObject *)&
apriltagType);