opencv 3.0 beta 创建新模块(可在 Python 中使用)

Posted

技术标签:

【中文标题】opencv 3.0 beta 创建新模块(可在 Python 中使用)【英文标题】:opencv 3.0 beta create new module (usable in Python) 【发布时间】:2015-06-02 06:19:02 【问题描述】:

我已在本地向 OpenCV 3.0 beta(在本地 contrib 存储库中)添加了一个模块,该模块在 C++ 中运行良好。现在我试图让它在 Python 中工作,但没有成功。

按照here 的建议,我将CV_EXPORTS 替换为CV_EXPORTS_W,并将宏CV_WRAP 添加到我希望能够在Python 中调用的类中的函数中(如here 所述)。

我还通过查看源代码发现,我必须在我的模块的CMakeLists.txt 中添加一些WRAP python,看起来像这样:

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)

但看起来我仍然缺少一些东西,因为我的类和方法在 Python 中不存在。例如以下代码:

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

产生以下错误:

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

作为补充信息,我发现我的类出现在生成的文件中(编译时)build/modules/python2/pyopencv_generated_include.h

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

但不会出现在其他 pyopencv_generated_*.h 文件中。

你有关于我在这里缺少什么的任何信息吗?或者您知道如何使用新模块扩展 OpenCV 3.0 的指南吗? (没找到)

【问题讨论】:

hmm, according to docs ,到目前为止一切看起来都是正确的。仍然 - 如果您的 FrameManager 中有一个静态 create() 方法,那不会被翻译为 frameManager = cv2.FrameManager_create() 吗? 有效就是这样,我会试试你的提议 遇到同样的错误,但使用FrameManager_create 而不是FrameManager 好的,我会试试看它是否有效。再次感谢(刚刚意识到你也回答了我的其他问题^^) 好的,尝试了嵌套命名空间,但仍然是错误AttributeError: 'module' object has no attribute 'xvideo'。似乎已经存在的模块有更多我没有的东西,我不知道是什么:( 【参考方案1】:

好吧,看来我得在这里尝试我自己的狗粮了..

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>(); 



相同的 CmakeLists.txt,你正在使用。

现在运行 cmake(-gui) ,看,BUILD_opencv_xvideo=ON,配置,生成。

然后重建,别忘了运行make install(或在VS中构建INSTALL项目)

>>> 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

【讨论】:

好的,非常感谢,这意味着它可以工作,但这也意味着我做错了什么,虽然我没有找到什么(没有忘记安装)。我会尽力解释为什么我的不起作用,并会及时通知您。 顺便问一下,您的模块是在官方 OpenCV 存储库还是在 contrib 中完成的? 看来我通过使用类String而不是std::string解决了这个问题,但我不确定这个类是在哪里定义的(如果它是原始C++,我不知道我'我对 C++ 很陌生)。我在文件platforms/android/service/engine/jni/Tests/gtest/gtest.h 中找到了一个声明,但似乎并非如此。无论如何它解决了我的问题,让我们去下一个^^。 其实我做到了。无论如何,我正在继续我的转型运动。完成后会及时通知您。 我希望我能 ^^。这是我实习期间的一个私人项目。但是,一旦我发现问题所在,我会尽可能彻底地给出答案。【参考方案2】:

从上一个答案开始(感谢@berak),我将代码一点一点地转换为我的代码。据我所知,我至少可以说两件事:

不要使用对抽象纯类的引用:

myFunction(abstractType &amp;myObject) 转换为myFunction(Ptr&lt;abstractType&gt; myObject),其中Ptr 是OpenCV 智能指针。

不要忘记帮助 OpenCV 输出通过引用传递的函数参数:

例如:myFunction(CV_OUT SomeType &amp;output)。 PS:还有CV_IN_OUT关键字。详情请见here。

我仍然有嵌套命名空间的问题:

我使用了std::string 类型的函数参数。似乎在编译步骤,为绑定生成的文件(pyopencv_generated_*.h)不正确(他们使用string 而不是std::string)在创建文件cv2.so 时产生错误:error: ‘string’ was not declared in this scope。我通过使用 String 类而不是 std::string 来绕过该错误,这似乎是 OpenCV 的一部分。

但是由于我并没有真正解决问题,所以现在我遇到了同样的错误,但带有一些 std::vector&lt;...&gt; 参数。不幸的是,我无法提供项目的 bitbucket 的链接(私有),但如果有人知道出了什么问题,我制作了一个简单的示例代码,面临同样的错误。有示例代码:

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)

我得到了错误:

[ 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;
     ^

如果您对哪里出了问题有任何想法,欢迎提供帮助;)

################## 编辑:##################

所以我研究了 Python 绑定是如何生成的(可以在 here 找到解释的开头)。相关文件位于文件夹modules/python/src2 中。我发现 2 件事可能与我的问题有关。

首先,OpenCV 中使用的所有 vector&lt;...&gt; 类型似乎都在文件 cv2.cpp 的第 87 行和第 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;

其次,std:: 命名空间从文件 hdr_parser.py 中函数 def parse_arg(self, arg_str, argno): 的第 204 行的参数类型中删除:

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

我的部分解决方案:

在我的错误中,我想出了在文件xxxvideo.hpp 中添加一个typedef 的想法,就在类DynamicState 的定义之后:

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

编译错误消失了,但是现在我在python中import cv2时出现错误:

>>> 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

再次,如果有人对我应该做什么有任何想法,或者如果您可以将我的问题转达给可能的人,我将不胜感激。

################## 编辑(再次):##################

实际上我的错误在另一轮cmake .., make, ,sudo make install 之后消失了。这似乎已经纠正了错误。

【讨论】:

不要使用 namespace cv::xxxvideo ,而是将代码 inside namespace cv namespace xxxvideo ... (与您在标题中所做的相同。否则你的链接器认为,它在全球[它不是]) @berak 感谢您的解释,但错误仍然存​​在(相同)。如果您不知道为什么,您会知道我的搜索重点在哪里吗? @berak 作为起点,我找到了关于 OpenCV 如何生成绑定的that 链接,因此我查看了这些文件(在文件夹modules/python/src2 中)。我提到了两件可能与我的问题有关的事情(但我可能错了)。在文件cv2.cpp 的第87 行和第110 行之间,有std::vector&lt;...&gt; 类型的typedef。在文件hdr_parser.py 中,在函数parse_arg(...) 中有那一行:arg_type = self.batch_replace(arg_type, [("std::", ""), ("cv::", ""), ("::", "_")])。会及时通知您。

以上是关于opencv 3.0 beta 创建新模块(可在 Python 中使用)的主要内容,如果未能解决你的问题,请参考以下文章

使用 opencv 3.0 beta 进行鱼眼镜头校准

为啥 OpenCV 3.0 beta 中的对象检测删除了尺度级联和精明修剪功能?

OpenCV 3.0 和 c++ (windows)

Tesseract + opencv 3.0 + windows,文本模块体积小,链接错误

OpenCV 3.0 线迭代器

Visual Studio 2015编译安装OpenCV 3.0和opencv_contrib