5

OpenCV 可以与 pythonbindings 一起使用,并且效果很好。但是我想知道(真的希望)是否也可以在 python 中使用OpenCv 的缝合器。我已经尝试了几件事,但无法让它工作。如果有可能,我可能需要进行额外的导入,但我无法弄清楚,谷歌也没有给我答案。希望你们中有一个opencv-python大师可以帮助我。

4

1 回答 1

1

好的,所以,我终于想通了。到目前为止,我只移植了带有两个参数的stitch 方法,请问我是否在公开其他可能需要的内容时遇到了麻烦。

构建它的最简单方法是以与位置无关的方式(gcc 的 -fPIC 选项)将所有内容编译到动态库中,同时链接 opencv_core 和 opencv_stitching 库。您还必须为要构建的任何版本的 python 添加包含目录,以便它可以找到正确的 Python.h 标头。

如果构建正确,您将能够像使用 python 模块一样使用编译后的库。

不幸的是,由于它们不提供对构造函数的访问,我不得不满足于制作事物的全局实例。如果有另一种优雅的方式,我全是耳朵(眼睛)。这意味着每当您调用 .Stitcher() 构造函数时,它将返回相同的实例(有一个单独的实例在构造期间尝试使用 GPU,请为此使用 .Stitcher(True) )。

这是我的 pythonPort.h 文件:

/* 
 * File:   pythonPort.h
 * Author: algomorph
 *
 * Created on December 5, 2012, 10:18 AM
 */

#ifndef PYTHONPORT_H
#define PYTHONPORT_H

#define MODULESTR "mycv"


#include "Python.h"
#include "numpy/ndarrayobject.h"
#include <opencv2/core/core.hpp>
#include <opencv2/stitching/stitcher.hpp>
/*
//include your own custom extensions here
#include "savgol.h"
#include "filters.hpp"
*/
#include "pythonPortAux.h"

#endif

MODULESTR 应该是您想要命名模块的任何名称。我保持它与它编译的库的名称相同。

您必须从 cv2.cpp 文件中复制所需的任何 opencv_to 和 opencv_from 例程,并将其放入我的 pythonPortAux.h 之类的文件中。我的有很多从那里开始的例程,你可以在这个链接中找到它。MKTYPE2 宏也在那里。

其余的在下面的 pythonPort.cpp 文件中(我还有其他东西,这只是与 Stitcher 相关的部分):

#include "pythonPort.h"

struct pycvex_Stitcher_t
{
    PyObject_HEAD
    Ptr<cv::Stitcher> v;
};

static PyTypeObject pycvex_Stitcher_Type =
{
    PyObject_HEAD_INIT(&PyType_Type)
    0,
    MODULESTR".Stitcher",
    sizeof(pycvex_Stitcher_t),
};

static void pycvex_Stitcher_dealloc(PyObject* self)
{
    //((pycvex_Stitcher_t*)self)->v.release();
    PyObject_Del(self);
}

static PyObject* pyopencv_from(const Ptr<cv::Stitcher>& r)
{
    pycvex_Stitcher_t *m = PyObject_NEW(pycvex_Stitcher_t, &pycvex_Stitcher_Type);
    new (&(m->v)) Ptr<cv::Stitcher>(); // init Ptr with placement new
    m->v = r;
    return (PyObject*)m;
}

static bool pyopencv_to(PyObject* src, Ptr<cv::Stitcher>& dst, const char* name="<unknown>")
{
    if( src == NULL || src == Py_None )
        return true;
    if(!PyObject_TypeCheck(src, &pycvex_Stitcher_Type))
    {
        failmsg("Expected cv::Stitcher for argument '%s'", name);
        return false;
    }
    dst = ((pycvex_Stitcher_t*)src)->v;
    return true;
}

static PyObject* pycvex_Stitcher_repr(PyObject* self)
{
    char str[1000];
    sprintf(str, "<Stitcher %p>", self);
    return PyString_FromString(str);
}

Stitcher gStitcher = cv::Stitcher::createDefault(false);
Stitcher gStitcherGPU = cv::Stitcher::createDefault(true);

static PyObject* pycvex_Stitcher_Stitcher(PyObject* , PyObject* args, PyObject* kw)
{
    PyErr_Clear();
    {
        pycvex_Stitcher_t* self = 0;
        bool try_use_gpu = false;

        const char* keywords[] = { "img", "pt1", "pt2","connectivity","leftToRight", NULL };
        if (PyArg_ParseTupleAndKeywords(args, kw, "|b:Stitcher",
                (char**) keywords, &try_use_gpu)){
            self = PyObject_NEW(pycvex_Stitcher_t, &pycvex_Stitcher_Type);
            if (self)
                ERRWRAP2(
                        if(try_use_gpu)
                            self->v = &gStitcherGPU;
                        else
                            self->v = &gStitcher;
                        );
            return (PyObject*) self;
        }
    }
    return NULL;
}
static PyGetSetDef pycvex_Stitcher_getseters[] =
{
    {NULL}  /* Sentinel */
};

static PyObject* pycvex_Stitcher_stitch(PyObject* self, PyObject* args, PyObject* kw){
    if(!PyObject_TypeCheck(self, &pycvex_Stitcher_Type))
        return failmsgp("Incorrect type of self (must be 'Stitcher' or its derivative)");
    Stitcher* _self_ = ((pycvex_Stitcher_t*)self)->v;
    //Stitcher::Status status;
    int status;

    PyObject* pyobj_images = NULL;
    vector<Mat> images = vector<Mat>();
    Mat pano;

    const char* keywords[] = { "images", NULL };
    if( PyArg_ParseTupleAndKeywords(args, kw, "O:Stitcher.stitch", (char**)keywords, &pyobj_images) &&
        pyopencv_to(pyobj_images, images, ArgInfo("images", false)))
    {
        ERRWRAP2( status = (int)_self_->stitch(images, pano));
        return Py_BuildValue("(NN)", pyopencv_from(status), pyopencv_from(pano));
    }

    return NULL;
}

static PyMethodDef pycvex_Stitcher_methods[] =
{
    {"stitch", (PyCFunction)pycvex_Stitcher_stitch, METH_KEYWORDS, "stitch(image) -> status, pano"},
    {NULL, NULL}
};

static void pycvex_Stitcher_specials(void)
{
    pycvex_Stitcher_Type.tp_base = NULL;
    pycvex_Stitcher_Type.tp_dealloc = pycvex_Stitcher_dealloc;
    pycvex_Stitcher_Type.tp_repr = pycvex_Stitcher_repr;
    pycvex_Stitcher_Type.tp_getset = pycvex_Stitcher_getseters;
    pycvex_Stitcher_Type.tp_methods = pycvex_Stitcher_methods;
}


static PyMethodDef methods[] = {
    {"Stitcher",(PyCFunction)pycvex_Stitcher_Stitcher, METH_KEYWORDS, "Stitcher([tryUseGpu=False]) -> <Stitcher object>"},
    {NULL, NULL}
};

extern "C"{
    #if defined WIN32 || defined _WIN32
    __declspec(dllexport)
    #endif
    void initcvex()
    {
      MKTYPE2(Stitcher);
      import_array();
      PyObject* m = Py_InitModule(MODULESTR, methods);
      PyObject* d = PyModule_GetDict(m);
      //PyDict_SetItemString(d, "__version__", PyString_FromString(CV_VERSION))
      opencv_error = PyErr_NewException((char*)MODULESTR".error", NULL, NULL);
      PyDict_SetItemString(d, "error", opencv_error);
    }
}
于 2012-12-20T21:04:47.037 回答