diff --git a/bob/learn/misc/gaussian.cpp b/bob/learn/misc/gaussian.cpp new file mode 100644 index 0000000000000000000000000000000000000000..43a18509b77101b94d362f0a70d4f6fe329cb123 --- /dev/null +++ b/bob/learn/misc/gaussian.cpp @@ -0,0 +1,103 @@ +/** + * @author Tiago de Freitas Pereira <tiago.pereira@idiap.ch> + * @date Fri 21 Nov 10:38:48 2013 + * + * @brief Python API for bob::learn::em + * + * Copyright (C) 2011-2014 Idiap Research Institute, Martigny, Switzerland + */ + +#include "main.h" + +/******************************************************************/ +/************ Constructor Section *********************************/ +/******************************************************************/ + +static auto Gaussian_doc = bob::extension::ClassDoc( + BOB_EXT_MODULE_PREFIX ".Gaussian", + "This class implements a multivariate diagonal Gaussian distribution" +).add_constructor( + bob::extension::FunctionDoc( + "__init__", + "Constructs a new multivariate gaussian object", + "", + true + ) + .add_prototype("[n_inputs]") + //.add_prototype("tan_triggs", "") + //.add_parameter("gamma", "float", "[default: ``0.2``] The value of gamma for the gamma correction") + //.add_parameter("sigma0", "float", "[default: ``1.``] The standard deviation of the inner Gaussian") + //.add_parameter("sigma1", "float", "[default: ``2.``] The standard deviation of the outer Gaussian") + //.add_parameter("radius", "int", "[default: ``2``] The radius of the Difference of Gaussians filter along both axes (size of the kernel=2*radius+1)") + //.add_parameter("threshold", "float", "[default: ``10.``] The threshold used for the contrast equalization") + //.add_parameter("alpha", "float", "[default: ``0.1``] The alpha value used for the contrast equalization") + //.add_parameter("border", ":py:class:`bob.sp.BorderType`", "[default: ``bob.sp.BorderType.Mirror``] The extrapolation method used by the convolution at the border") + //.add_parameter("tan_triggs", ":py:class:`bob.ip.base.TanTriggs`", "The TanTriggs object to use for copy-construction") +); + + +static int PyBobLearnMiscGaussian_init(PyBobLearnMiscGaussianObject* self, PyObject* args, PyObject* kwargs) { + TRY + + char* kwlist1[] = {c("n_inputs")}; + //char* kwlist2[] = {c("tan_triggs"), NULL}; + + // get the number of command line arguments + Py_ssize_t nargs = (args?PyTuple_Size(args):0) + (kwargs?PyDict_Size(kwargs):0); + + + /* + PyObject* k = Py_BuildValue("s", kwlist2[0]); + auto k_ = make_safe(k); + if (nargs == 1 && ((args && PyTuple_Size(args) == 1 && PyBobIpBaseTanTriggs_Check(PyTuple_GET_ITEM(args,0))) || (kwargs && PyDict_Contains(kwargs, k)))){ + // copy construct + PyBobIpBaseTanTriggsObject* tt; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!", kwlist2, &PyBobIpBaseTanTriggs_Type, &tt)) return -1; + + self->cxx.reset(new bob::ip::base::TanTriggs(*tt->cxx)); + return 0; + }*/ + + size_t n_inputs=0; + self->cxx.reset(new bob::learn::misc::Gaussian(n_inputs)); + return 0; + + CATCH("cannot create Gaussian", -1) +} + + +/******************************************************************/ +/************ Module Section **************************************/ +/******************************************************************/ + +// Define the Gaussian type struct; will be initialized later +PyTypeObject PyBobLearnMiscGaussian_Type = { + PyVarObject_HEAD_INIT(0,0) + 0 +}; + +bool init_BobLearnMiscGaussian(PyObject* module) +{ + // initialize the type struct + PyBobLearnMiscGaussian_Type.tp_name = Gaussian_doc.name(); + PyBobLearnMiscGaussian_Type.tp_basicsize = sizeof(PyBobLearnMiscGaussianObject); + PyBobLearnMiscGaussian_Type.tp_flags = Py_TPFLAGS_DEFAULT; + PyBobLearnMiscGaussian_Type.tp_doc = Gaussian_doc.doc(); + + // set the functions + PyBobLearnMiscGaussian_Type.tp_new = PyType_GenericNew; + PyBobLearnMiscGaussian_Type.tp_init = reinterpret_cast<initproc>(PyBobLearnMiscGaussian_init); + //PyBobLearnMiscGaussian_Type.tp_dealloc = reinterpret_cast<destructor>(PyBobIpBaseTanTriggs_delete); + //PyBobLearnMiscGaussian_Type.tp_richcompare = reinterpret_cast<richcmpfunc>(PyBobIpBaseTanTriggs_RichCompare); + //PyBobLearnMiscGaussian_Type.tp_methods = PyBobIpBaseTanTriggs_methods; + //PyBobLearnMiscGaussian_Type.tp_getset = PyBobIpBaseTanTriggs_getseters; + //PyBobLearnMiscGaussian_Type.tp_call = reinterpret_cast<ternaryfunc>(PyBobIpBaseTanTriggs_process); + + // check that everything is fine + if (PyType_Ready(&PyBobLearnMiscGaussian_Type) < 0) return false; + + // add the type to the module + Py_INCREF(&PyBobLearnMiscGaussian_Type); + return PyModule_AddObject(module, "Gaussian", (PyObject*)&PyBobLearnMiscGaussian_Type) >= 0; +} + diff --git a/bob/learn/misc/include/bob.learn.misc/api.h b/bob/learn/misc/include/bob.learn.misc/api.h new file mode 100644 index 0000000000000000000000000000000000000000..44208e5cc7b7a10c8d7605396e3227b824fa289d --- /dev/null +++ b/bob/learn/misc/include/bob.learn.misc/api.h @@ -0,0 +1,127 @@ +/** + * @author Tiago de Freitas Pereira <tiago.pereira@idiap.ch> + * @date Fri 21 Nov 10:38:48 2013 + * + * @brief Python API for bob::learn::em + */ + +#ifndef BOB_LEARN_EM_API_H +#define BOB_LEARN_EM_API_H + +/* Define Module Name and Prefix for other Modules + Note: We cannot use BOB_EXT_* macros here, unfortunately */ +#define BOB_LEARN_EM_PREFIX "bob.learn.misc" +#define BOB_LEARN_EM_FULL_NAME "bob.learn.misc._library" + +#include <Python.h> + +#include <bob.learn.misc/config.h> +#include <boost/shared_ptr.hpp> + +/******************* + * C API functions * + *******************/ + +/* Enum defining entries in the function table */ +enum _PyBobLearnMisc_ENUM{ + PyBobLearnMisc_APIVersion_NUM = 0, + // bindings + ////PyBobIpBaseLBP_Type_NUM, + ////PyBobIpBaseLBP_Check_NUM, + ////PyBobIpBaseLBP_Converter_NUM, + // Total number of C API pointers + PyBobLearnMisc_API_pointers +}; + + +#ifdef BOB_LEARN_EM_MODULE + + /* This section is used when compiling `bob.io.base' itself */ + + /************** + * Versioning * + **************/ + + extern int PyBobLearnMisc_APIVersion; + +#else // BOB_LEARN_EM_MODULE + + /* This section is used in modules that use `bob.io.base's' C-API */ + +#if defined(NO_IMPORT_ARRAY) + extern void **PyBobLearnMisc_API; +#elif defined(PY_ARRAY_UNIQUE_SYMBOL) + void **PyBobLearnMisc_API; +#else + static void **PyBobLearnMisc_API=NULL; +#endif + + /************** + * Versioning * + **************/ + +#define PyBobLearnMisc_APIVersion (*(int *)PyBobLearnMisc_API[PyBobLearnMisc_APIVersion_NUM]) + +#if !defined(NO_IMPORT_ARRAY) + + /** + * Returns -1 on error, 0 on success. + */ + static int import_bob_learn_misc(void) { + + PyObject *c_api_object; + PyObject *module; + + module = PyImport_ImportModule(BOB_LEARN_EM_FULL_NAME); + + if (module == NULL) return -1; + + c_api_object = PyObject_GetAttrString(module, "_C_API"); + + if (c_api_object == NULL) { + Py_DECREF(module); + return -1; + } + +#if PY_VERSION_HEX >= 0x02070000 + if (PyCapsule_CheckExact(c_api_object)) { + PyBobLearnMisc_API = (void **)PyCapsule_GetPointer(c_api_object, PyCapsule_GetName(c_api_object)); + } +#else + if (PyCObject_Check(c_api_object)) { + PyBobLearnMisc_API = (void **)PyCObject_AsVoidPtr(c_api_object); + } +#endif + + Py_DECREF(c_api_object); + Py_DECREF(module); + + if (!PyBobLearnMisc_API) { + PyErr_SetString(PyExc_ImportError, "cannot find C/C++ API " +#if PY_VERSION_HEX >= 0x02070000 + "capsule" +#else + "cobject" +#endif + " at `" BOB_LEARN_EM_FULL_NAME "._C_API'"); + return -1; + } + + /* Checks that the imported version matches the compiled version */ + int imported_version = *(int*)PyBobLearnMisc_API[PyBobLearnMisc_APIVersion_NUM]; + + if (BOB_LEARN_MISC_API_VERSION != imported_version) { + PyErr_Format(PyExc_ImportError, BOB_LEARN_EM_FULL_NAME " import error: you compiled against API version 0x%04x, but are now importing an API with version 0x%04x which is not compatible - check your Python runtime environment for errors", BOB_LEARN_MISC_API_VERSION, imported_version); + return -1; + } + + /* If you get to this point, all is good */ + return 0; + + } + +#endif //!defined(NO_IMPORT_ARRAY) + +#endif /* BOB_LEARN_EM_MODULE */ + +#endif /* BOB_LEARN_EM_API_H */ diff --git a/bob/learn/misc/main.cpp b/bob/learn/misc/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..388a218c99b16c28b92ac46f90ac42607f3baec1 --- /dev/null +++ b/bob/learn/misc/main.cpp @@ -0,0 +1,89 @@ +/** + * @author Tiago de Freitas Pereira <tiago.pereira@idiap.ch> + * @date Fri Nov 21 12:39:21 CET 2014 + * + * @brief Bindings to bob::learn::misc routines + */ + +#ifdef NO_IMPORT_ARRAY +#undef NO_IMPORT_ARRAY +#endif +#include "main.h" + +static PyMethodDef module_methods[] = {}; + + +PyDoc_STRVAR(module_docstr, "Bob EM based Machine Learning Routines"); + +int PyBobLearnMisc_APIVersion = BOB_LEARN_MISC_API_VERSION; + + +#if PY_VERSION_HEX >= 0x03000000 +static PyModuleDef module_definition = { + PyModuleDef_HEAD_INIT, + BOB_EXT_MODULE_NAME, + module_docstr, + -1, + module_methods, + 0, 0, 0, 0 +}; +#endif + +static PyObject* create_module (void) { + +# if PY_VERSION_HEX >= 0x03000000 + PyObject* module = PyModule_Create(&module_definition); +# else + PyObject* module = Py_InitModule3(BOB_EXT_MODULE_NAME, module_methods, module_docstr); +# endif + if (!module) return 0; + auto module_ = make_safe(module); ///< protects against early returns + + if (PyModule_AddStringConstant(module, "__version__", BOB_EXT_MODULE_VERSION) < 0) return 0; + if (!init_BobLearnMiscGaussian(module)) return 0; + + static void* PyBobLearnMisc_API[PyBobLearnMisc_API_pointers]; + + /* exhaustive list of C APIs */ + + /************** + * Versioning * + **************/ + + PyBobLearnMisc_API[PyBobLearnMisc_APIVersion_NUM] = (void *)&PyBobLearnMisc_APIVersion; + + +#if PY_VERSION_HEX >= 0x02070000 + + /* defines the PyCapsule */ + + PyObject* c_api_object = PyCapsule_New((void *)PyBobLearnMisc_API, + BOB_EXT_MODULE_PREFIX "." BOB_EXT_MODULE_NAME "._C_API", 0); + +#else + + PyObject* c_api_object = PyCObject_FromVoidPtr((void *)PyBobLearnMisc_API, 0); + +#endif + + if (!c_api_object) return 0; + + if (PyModule_AddObject(module, "_C_API", c_api_object) < 0) return 0; + + + /* imports bob.learn.misc's C-API dependencies */ + if (import_bob_blitz() < 0) return 0; + if (import_bob_core_random() < 0) return 0; + if (import_bob_io_base() < 0) return 0; + + Py_INCREF(module); + return module; + +} + +PyMODINIT_FUNC BOB_EXT_ENTRY_NAME (void) { +# if PY_VERSION_HEX >= 0x03000000 + return +# endif + create_module(); +} diff --git a/bob/learn/misc/main.h b/bob/learn/misc/main.h new file mode 100644 index 0000000000000000000000000000000000000000..bb40bec0d83308713311ab3ae30e47f4b6a2dffa --- /dev/null +++ b/bob/learn/misc/main.h @@ -0,0 +1,72 @@ +/** + * @author Tiago de Freitas Pereira <tiago.pereira@idiap.ch> + * @date Fri Nov 21 10:31:25 CET 2014 + * + * @brief Header file for bindings to bob::learn::em + */ + +#ifndef BOB_LEARN_EM_MAIN_H +#define BOB_LEARN_EM_MAIN_H + +#include <bob.blitz/cppapi.h> +#include <bob.blitz/cleanup.h> +#include <bob.core/random_api.h> +#include <bob.io.base/api.h> +#include <bob.extension/documentation.h> + +#define BOB_LEARN_EM_MODULE +#include <bob.learn.misc/api.h> + +#include <bob.learn.misc/Gaussian.h> + + +#if PY_VERSION_HEX >= 0x03000000 +#define PyInt_Check PyLong_Check +#define PyInt_AS_LONG PyLong_AS_LONG +#define PyString_Check PyUnicode_Check +#define PyString_AS_STRING(x) PyBytes_AS_STRING(make_safe(PyUnicode_AsUTF8String(x)).get()) +#endif + +#define TRY try{ + +#define CATCH(message,ret) }\ + catch (std::exception& e) {\ + PyErr_SetString(PyExc_RuntimeError, e.what());\ + return ret;\ + } \ + catch (...) {\ + PyErr_Format(PyExc_RuntimeError, "%s " message ": unknown exception caught", Py_TYPE(self)->tp_name);\ + return ret;\ + } + +#define CATCH_(message, ret) }\ + catch (std::exception& e) {\ + PyErr_SetString(PyExc_RuntimeError, e.what());\ + return ret;\ + } \ + catch (...) {\ + PyErr_Format(PyExc_RuntimeError, message ": unknown exception caught");\ + return ret;\ + } + +static inline char* c(const char* o){return const_cast<char*>(o);} /* converts const char* to char* */ + +/// inserts the given key, value pair into the given dictionaries +static inline int insert_item_string(PyObject* dict, PyObject* entries, const char* key, Py_ssize_t value){ + auto v = make_safe(Py_BuildValue("n", value)); + if (PyDict_SetItemString(dict, key, v.get()) < 0) return -1; + return PyDict_SetItemString(entries, key, v.get()); +} + +// Gaussian +typedef struct { + PyObject_HEAD + boost::shared_ptr<bob::learn::misc::Gaussian> cxx; +} PyBobLearnMiscGaussianObject; + +extern PyTypeObject PyBobLearnMiscGaussian_Type; +bool init_BobLearnMiscGaussian(PyObject* module); +int PyBobLearnMiscGaussian_Check(PyObject* o); + + +#endif // BOB_LEARN_EM_MAIN_H