1

I have locally added a module to OpenCV 3.0 beta (in a local contrib repository) that is working fine in C++. Now I am trying to make it work in Python, without success.

As suggested here I replaced my CV_EXPORTS by CV_EXPORTS_W and added the macro CV_WRAP to the functions in my classes I want to be able to call in Python (as explained here).

Also I found out by looking in source code that I have to add some WRAP python in the CMakeLists.txt of my module that look like that :

set(the_description "Extended video processing module. Includes an object tracker")
set(OPENCV_MODULE_IS_PART_OF_WORLD OFF)
ocv_define_module(xvideo opencv_core opencv_imgproc opencv_highgui WRAP python)

target_link_libraries(opencv_xvideo)

But it looks like I am still missing something since my classes and methods does not exist in Python. For example, the following code :

import numpy as np
import cv2
frameManager = cv2.FrameManager.create()

produces the following error :

AttributeError: 'module' object has no attribute 'FrameManager'

As a complementary info, I found out that my classes appear in the generated file (at compilation) build/modules/python2/pyopencv_generated_include.h :

...
#include "opencv2/xvideo/framemanager.hpp"
...

but do not appear in the other pyopencv_generated_*.h files.

Do you have any info on what I'm missing here ? or do you know a guide on how to extend OpenCV 3.0 with new modules ? (didn't find any)

8
  • hmm, according to docs , it all looks correct so far. still - if you had a static create() method in your FrameManager, wouldn't that be translated as frameManager = cv2.FrameManager_create() ? Commented Jun 2, 2015 at 6:36
  • That's the case effectively, I will try your proposition Commented Jun 2, 2015 at 6:38
  • Got same error but with FrameManager_create instead of FrameManager Commented Jun 2, 2015 at 6:40
  • 1
    Ok I will try that and tell if it works. Thanks again (just realized you also answer my other questions ^^) Commented Jun 2, 2015 at 6:47
  • 1
    Ok tried the nested namespace but still the error AttributeError: 'module' object has no attribute 'xvideo'. It seems that already existing modules have something more I don't, I can't figure out what :( Commented Jun 2, 2015 at 7:25

2 Answers 2

1

ok, seems i have to try my own dogfood here..

xvideo/include/opencv2/xvideo.hpp:

#ifndef __OPENCV_xvideo_HPP__
#define __OPENCV_xvideo_HPP__

/** @defgroup xvideo Additional video processing algorithms
*/

#include "opencv2/core.hpp"

namespace cv {
namespace xvideo {

    struct CV_EXPORTS_W FrameManager
    {
        CV_WRAP void foo(InputArray inp, float v);

        CV_WRAP static Ptr<FrameManager> create();
    };
}
}

xvideo/src/framemanager.cpp:

#include "opencv2/xvideo.hpp"

namespace cv
{
namespace xvideo
{


    void FrameManager::foo(InputArray inp, float v) {}

    Ptr<FrameManager> FrameManager::create() { return makePtr<FrameManager>(); }

}
}

same CmakeLists.txt, you were using.

now run cmake(-gui) , see, that BUILD_opencv_xvideo=ON, configure,generate.

then rebuild, and don't forget to run make install (or build the INSTALL proj. in VS)

>>> help(cv2.xvideo)
Help on module cv2.xvideo in cv2:

NAME
    cv2.xvideo

FILE
    (built-in)

FUNCTIONS
    FrameManager_create(...)
        FrameManager_create() -> retval


>>> fm = cv2.xvideo.FrameManager_create()
>>> help(fm)
Help on xvideo_FrameManager object:

class xvideo_FrameManager(__builtin__.object)
 |  Methods defined here:
 |
 |  __repr__(...)
 |      x.__repr__() <==> repr(x)
 |
 |  foo(...)
 |      foo(inp, v) -> None
 |
 |  ----------------------------------------------------------------------
 |  Data and other attributes defined here:
 |
 |  __new__ = <built-in method __new__ of type object>
 |      T.__new__(S, ...) -> a new object with type S, a subtype of T
Sign up to request clarification or add additional context in comments.

11 Comments

ok thank you so much, that means it can work but it also means I did something wrong although I don't find what (did not forgot to install). I will try to work on that to explain why mine does not work and will keep you updated.
By the way, was your module done in the official OpenCV repository or the contrib one ?
It appears that I solved this problem by using the class String instead of std::string but I am not sure where this class is defined (If it is raw C++, id did not know I'm quite new to C++). I found one declaration in file platforms/android/service/engine/jni/Tests/gtest/gtest.h but it does not seem to be that. Anyway it solved my problem, let's go to the next one ^^.
Actually I did. Anyway, I'm continuing my transformation crusade. Will keep you updated when I am finished.
I wish I could ^^. It's a private project in the context of my internship. But once I find out what is wrong I will try to make an answer as thorough as possible.
|
1

Starting from the previous answer (thanks @berak) I transformed that code to little by little get to my very code. As far as I got I can say at least 2 things :

Do not use a reference to an abstract pure class :

Transform myFunction(abstractType &myObject) to myFunction(Ptr<abstractType> myObject) where Ptr are OpenCV smart pointers.

Do not forget to help OpenCV for output function arguments passed by reference :

For example : myFunction(CV_OUT SomeType &output). PS : There is also the CV_IN_OUT keyword. See here for more details.

I still have problems with nested namespaces :

I was using some argument of function of the type std::string. It appears that at compilation step, the generated files (pyopencv_generated_*.h) for bindings are not correct (they used string instead of std::string) producing an error when creating the file cv2.so : error: ‘string’ was not declared in this scope. I bypassed that error by using the class String instead of std::string which seems to be part of OpenCV.

But since I did not really solve the problem, now I have the same error but with some std::vector<...> argument. Unfortunately, I can not give a link to the bitbucket of the project (private) but I made a simple sample code facing the same error if someone knows what is wrong. There is the sample code :

xxxvideo/include/opencv2/xxxvideo.hpp :

#ifndef __OPENCV_XXXVIDEO_HPP__
#define __OPENCV_XXXVIDEO_HPP__

/** @defgroup xxxvideo Additional video processing algorithms
*/

#include "opencv2/core.hpp"
#include <string>
#include <vector>
//#include "xxxvideo/framemanager_all.hpp"

namespace cv {
namespace xxxvideo {

class CV_EXPORTS_W DynamicState : public Algorithm
{
    public:
        virtual ~DynamicState(){};
        CV_WRAP virtual Mat toMatrix();
};

class CV_EXPORTS_W DynamicModel : public Algorithm
{
    public:
        virtual ~DynamicModel(){};
        CV_WRAP virtual std::vector< Ptr<DynamicState> > getAllStates();
};

}}

#endif

xxxvideo/src/dynamicmodelimpl.cpp :

#include "opencv2/xxxvideo.hpp"

using namespace std;
using namespace cv;
using namespace cv::xxxvideo;

vector< Ptr<DynamicState> > DynamicModel::getAllStates()
{
    vector< Ptr<DynamicState> > states;
    return states;
}

Mat DynamicState::toMatrix()
{
    Mat m;
    return m;
}

xxxvideo/CMakeLists.txt :

set(the_description "Exxxtended video processing module. Includes an object tracker")
set(OPENCV_MODULE_IS_PART_OF_WORLD OFF)
ocv_define_module(xxxvideo opencv_core opencv_imgproc opencv_highgui WRAP python)

target_link_libraries(opencv_xxxvideo)

And there is the error I get :

[ 98%] Generating pyopencv_generated_include.h, pyopencv_generated_funcs.h, pyopencv_generated_types.h, pyopencv_generated_type_reg.h, pyopencv_generated_ns_reg.h
Scanning dependencies of target opencv_python2
[ 98%] Building CXX object modules/python2/CMakeFiles/opencv_python2.dir/__/src2/cv2.cpp.o
In file included from /home/matthieu/libs/opencv/opencv-trunk/modules/python/src2/cv2.cpp:1217:0:
/home/matthieu/libs/opencv/opencv-trunk/build/modules/python2/pyopencv_generated_types.h: In function ‘PyObject* pyopencv_cv_xxxvideo_xxxvideo_DynamicModel_getAllStates(PyObject*, PyObject*, PyObject*)’:
/home/matthieu/libs/opencv/opencv-trunk/build/modules/python2/pyopencv_generated_types.h:15927:5: error: ‘vector_Ptr_DynamicState’ was not declared in this scope
     vector_Ptr_DynamicState retval;
     ^

If you have any idea on what is wrong, help is welcomed ;)

################## EDIT : ##################

So I went looking into how Python bindings are generated (starting of an explanation can be found here). The relevant files are in the folder modules/python/src2. I found 2 things that might be related to my problem.

First, all vector<...> types used in OpenCV seems to be defined in file cv2.cpp between lines 87 and 110 :

typedef std::vector<uchar> vector_uchar;
typedef std::vector<char> vector_char;
typedef std::vector<int> vector_int;
typedef std::vector<float> vector_float;
typedef std::vector<double> vector_double;
typedef std::vector<Point> vector_Point;
typedef std::vector<Point2f> vector_Point2f;
typedef std::vector<Vec2f> vector_Vec2f;
typedef std::vector<Vec3f> vector_Vec3f;
typedef std::vector<Vec4f> vector_Vec4f;
typedef std::vector<Vec6f> vector_Vec6f;
typedef std::vector<Vec4i> vector_Vec4i;
typedef std::vector<Rect> vector_Rect;
typedef std::vector<KeyPoint> vector_KeyPoint;
typedef std::vector<Mat> vector_Mat;
typedef std::vector<DMatch> vector_DMatch;
typedef std::vector<String> vector_String;
typedef std::vector<Scalar> vector_Scalar;

typedef std::vector<std::vector<char> > vector_vector_char;
typedef std::vector<std::vector<Point> > vector_vector_Point;
typedef std::vector<std::vector<Point2f> > vector_vector_Point2f;
typedef std::vector<std::vector<Point3f> > vector_vector_Point3f;
typedef std::vector<std::vector<DMatch> > vector_vector_DMatch;

Second, the std:: namespace is removed from the argument types in file hdr_parser.py in function def parse_arg(self, arg_str, argno): on line 204 :

arg_type = self.batch_replace(arg_type, [("std::", ""), ("cv::", ""), ("::", "_")])

My partial solution :

Looking into this and in my error I came up with the idea of adding one typedef in the file xxxvideo.hpp just after definition of class DynamicState :

typedef std::vector< cv::Ptr<DynamicState> >  vector_Ptr_DynamicState;

Compilation errors are gone, but now, I have an error when I import cv2 in python :

>>> import cv2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: /usr/local/opencv/opencv-trunk/lib/python2.7/dist-packages/cv2.so: undefined symbol: _ZTIN2cv8xxxvideo12DynamicStateE

Again, if someone has any idea on what I should do, or if you could relay my question to someone who might, I would be grateful.

################## EDIT (Again): ##################

Actually my error vanished after another round of cmake .., make, ,sudo make install. This seems to have corrected the error.

3 Comments

do not use namespace cv::xxxvideo , but put the code inside namespace cv { namespace xxxvideo { ... }} (in the very same way you did in the header. else your linker thinks, it is in global [it is not])
@berak Thank you for that explanation but the error remains (the same). would you know where to focus my search if you don't know why ?
@berak As a starting point, I found that link on how OpenCV generates the bindings so I went looking into those files (in folder modules/python/src2). I remarked 2 things that could be in relation with my problem (but I might be wrong). In file cv2.cpp, between lines 87 and 110, there are typedefs of std::vector<...> types. And in file hdr_parser.py, in function parse_arg(...) there is that line : arg_type = self.batch_replace(arg_type, [("std::", ""), ("cv::", ""), ("::", "_")]). Will keep you updated.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.