2012-08-07 9 views
5

OpenCV kann mit den Pythonbindungen verwendet werden und es funktioniert ganz gut. Allerdings habe ich mich gefragt (hoffe wirklich), ob es möglich ist, OpenCv's stitcher auch in Python zu verwenden. Ich habe mehrere Dinge ausprobiert, aber ich konnte es nicht zur Arbeit bringen. Wenn es überhaupt möglich ist, muss ich wahrscheinlich einen zusätzlichen Import machen, aber ich kann es nicht herausfinden und google gibt mir auch die Antwort nicht. Ich hoffe, es gibt einen Open-C-Python-Guru unter euch, der mir helfen kann.Verwenden Sie opencv Stitcher von Python

+0

Hey, ich weiß, es ist wahrscheinlich ein bisschen spät für Sie, aber ich bin gerade in Position, wenn ich den opencv Stitcher mit Python benutzen will. Ich habe herausgefunden, wie man andere opencv-Klassen "missing" von der OpenCV-Python-API portieren kann, und ich habe es schon einmal gemacht. Wenn ich Stitcher zu Python exportiere, werde ich es am Ende von heute haben. –

Antwort

1

Okay, also habe ich es endlich herausgefunden. Bis jetzt habe ich nur die Stichmethode mit zwei Argumenten portiert, frag mich, ob du Probleme hast, was sonst noch benötigt wird.

Die einfachste Möglichkeit besteht darin, alles positionsunabhängig (-fPIC-Option für gcc) in eine dynamische Bibliothek zu kompilieren, während opencv_core- und opencv_stitching-Bibliotheken verknüpft werden. Sie müssen auch das Include-Verzeichnis für jede Version von Python hinzufügen, gegen die Sie bauen, damit es den richtigen Python.h-Header finden kann.

Wenn Sie korrekt erstellen, können Sie die kompilierte Bibliothek genauso verwenden wie ein Python-Modul.

Leider, da sie keinen Zugriff auf den Konstruktor bieten, musste ich mich damit begnügen, eine globale Instanz der Sache zu machen. Wenn es einen anderen eleganten Weg gibt, bin ich ganz Ohr (Augen). Das heißt, wenn Sie den Konstruktor ".Stitcher()" aufrufen, gibt es dieselbe Instanz zurück (es gibt eine separate Instanz, die während der Konstruktion versucht, GPU zu verwenden, verwenden Sie dazu .Stitcher (True)).

Hier ist meine pythonPort.h Datei:

/* 
* 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 sollte sein, was auch immer Sie Ihr Modul nennen wollen. Ich habe es so behalten wie der Name der Bibliothek, die es kompiliert.

Sie müssen kopieren, was opencv_to und opencv_from Routinen benötigen Sie aus der cv2.cpp Datei und in etwas wie meine pythonPortAux.h setzen. Meins hat viele Routinen von dort, Sie können es at this link finden. MKTYPE2 Makro ist auch da.

Der Rest ist hier in der pythonPort.cpp unter Datei (ich habe es noch andere Dinge, das ist nur der Stitcher-relevante Teil):

#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); 
    } 
} 
+0

Sieht so aus, als könnte das nützlich sein, aber ich bekomme Probleme. Wo sind 'filters.hpp' und' savgol.h'? Ich bekomme auch Fehler bezüglich 'python27_d.lib'. Irgendwelche Vorschläge? – speedplane

+0

Entschuldigung, Sie brauchen diese nicht (filters.hpp und savgol.h). Dies waren nur Erweiterungen, die ich zu opencv für Berkley Kantenerkennung hinzugefügt habe. Ich habe sie aus dem obigen Code kommentiert. –

+0

Wie für python27_d.lib - dieses Problem tritt auf Windows-Plattformen auf, wenn Sie versuchen, etwas zu kompilieren, das auf opencv im Debug-Modus verweist. Bei einer typischen Python-Windows-Installation ist diese Bibliothek nicht enthalten. Sie können das Python-Bindings-Projekt von opencv für die Verwendung von python2.lib manuell neu konfigurieren oder versuchen, stattdessen auf den Release-Build zu verweisen. Wenn Sie wirklich beabsichtigen, es zu verwenden, konsultieren Sie diesen SO-Post: http://stackoverflow.com/questions/10315662/how-to-obtain-pre-built-debug-version-of-python-library-eg-python27 -d-dll –