2013-02-11 62 views
3

我想換我的C++ OpenCV的代碼boost::python,並學習如何做到這一點,我想一個玩具示例,其中如何用Boost :: Python包裝C++ OpenCV代碼?

  • 我用Boost.Numpy項目給我提供boost::numpy::ndarray

  • 要包裝的C++函數square()需要boost::numpy::ndarray並通過對其中的每個元素進行平方來修改它。

  • 導出的Python模塊名稱被稱爲test

  • square() C++函數被導出與所導出模塊中的square名稱。

  • 我是不是使用bjam因爲IMO太複雜了,只是不管用什麼。我正在使用好舊的make

現在,這裏是代碼:

// test.cpp 
#include <boost/python.hpp> 
#include <boost/numpy.hpp> 
#include <boost/scoped_array.hpp> 
#include <opencv2/imgproc/imgproc.hpp> 
#include <iostream> 

namespace py = boost::python; 
namespace np = boost::numpy; 

void square(np::ndarray& array) 
{ 
    if (array.get_dtype() != np::dtype::get_builtin<int>()) 
    { 
     PyErr_SetString(PyExc_TypeError, "Incorrect array data type."); 
     py::throw_error_already_set(); 
    } 
    size_t rows = array.shape(0), cols = array.shape(1); 
    size_t stride_row = array.strides(0)/sizeof(int), 
      stride_col = array.strides(1)/sizeof(int); 
    cv::Mat mat(rows, cols, CV_32S); 
    int *row_iter = reinterpret_cast<int*>(array.get_data()); 
    for (int i = 0; i < rows; i++, row_iter += stride_row) 
    { 
     int *col_iter = row_iter; 
     int *mat_row = (int*)mat.ptr(i); 
     for (int j = 0; j < cols; j++, col_iter += stride_col) 
     { 
      *(mat_row + j) = (*col_iter) * (*col_iter); 
     } 
    } 

    for (int i = 0; i < rows; i++, row_iter += stride_row) 
    { 
     int *col_iter = row_iter; 
     int *mat_row = (int*)mat.ptr(i); 
     for (int j = 0; j < cols; j++, col_iter += stride_col) 
     { 
      *col_iter = *(mat_row + j); 
     } 
    } 
} 


BOOST_PYTHON_MODULE(test) 
{ 
    using namespace boost::python; 
    def("square", square); 
} 

而這裏的Makefile文件:

PYTHON_VERSION = 2.7 
PYTHON_INCLUDE = /usr/include/python$(PYTHON_VERSION) 

BOOST_INC = /usr/local/include 
BOOST_LIB = /usr/local/lib 
OPENCV_LIB = $$(pkg-config --libs opencv) 
OPENCV_INC = $$(pkg-config --cflags opencv) 

TARGET = test 

$(TARGET).so: $(TARGET).o 
     g++ -shared -Wl,--export-dynamic \ 
     $(TARGET).o -L$(BOOST_LIB) -lboost_python \ 
     $(OPENCV_LIB) \ 
     -L/usr/lib/python$(PYTHON_VERSION)/config -lpython$(PYTHON_VERSION) \ 
     -o $(TARGET).so 

$(TARGET).o: $(TARGET).cpp 
     g++ -I$(PYTHON_INCLUDE) $(OPENCV_INC) -I$(BOOST_INC) -fPIC -c $(TARGET).cpp 

有了這個計劃,我可以輸入maketest.so被創建。但是,當我嘗試導入它,

In [1]: import test 
--------------------------------------------------------------------------- 
ImportError        Traceback (most recent call last) 
<ipython-input-1-73ae3ffe1045> in <module>() 
----> 1 import test 

ImportError: ./test.so: undefined symbol:  _ZN5boost6python9converter21object_manager_traitsINS_5numpy7ndarrayEE10get_pytypeEv 

In [2]: 

這是一個連接錯誤,我似乎無法修復。任何人都可以請幫助我發生了什麼事? 你有沒有(鏈接到)已經集成了OpenCV,numpy和Boost.Python而沒有像Py ++之類的東西的代碼?

+0

我試了一下沒有升壓,並且得到了類似的錯誤。 Boost很好,但是最新的OpneCV版本帶有非常好的Python綁定。他們使用Python/C API來提供您可以獲得的最佳性能。你爲什麼要使用提升? – Froyo 2013-02-11 08:55:24

+0

我已經實現了細化算法,它需要逐個像素進行大量迭代。與C++循環相比,Python中的循環非常慢,我不必擔心寫入n個雙循環。當我檢查時,即使某些操作使用numpy向量操作進行了矢量化,Python版本的速度比C++版本低很多。 – 2013-02-11 12:07:05

+0

是的。誠然。如果你正在Python中使用它,它會花費很多時間。 – Froyo 2013-02-11 15:34:43

回答

2

好吧我解決了這個問題。這是一個簡單的問題,但一個昏昏欲睡的大腦和服務bjam讓我無視它。在Makefile中,我忘了把-lboost_numpy鏈接到我的lib的Boost.Numpy庫。所以,修改後的Makefile看起來像這樣:

PYTHON_VERSION = 2.7 
PYTHON_INCLUDE = /usr/include/python$(PYTHON_VERSION) 

BOOST_INC = /usr/local/include 
BOOST_LIB = /usr/local/lib 
OPENCV_LIB = $$(pkg-config --libs opencv) 
OPENCV_INC = $$(pkg-config --cflags opencv) 

TARGET = test 

$(TARGET).so: $(TARGET).o 
     g++ -shared -Wl,--export-dynamic \ 
     $(TARGET).o -L$(BOOST_LIB) -lboost_python -lboost_numpy \ 
     $(OPENCV_LIB) \ 
     -L/usr/lib/python$(PYTHON_VERSION)/config -lpython$(PYTHON_VERSION) \ 
     -o $(TARGET).so 

$(TARGET).o: $(TARGET).cpp 
     g++ -I$(PYTHON_INCLUDE) $(OPENCV_INC) -I$(BOOST_INC) -fPIC -c $(TARGET).cpp 
+0

+1 - 很高興看到你解決了它。如果它適合你,你可以接受你自己的答案,並將此會話標記爲「回答」。 – 2013-02-12 11:25:31

+0

我會的。我需要等待一天,然後才能接受我自己的答案:) – 2013-02-12 11:34:04

+0

OK.Fine。我剛纔提到它。無論如何,好工作! – 2013-02-12 11:35:41