2012-04-25 123 views
3

每當我用ctypes將共享庫(.so)加載到Python中並調用其中一個使用OpenCV過濾器引擎的過程(如cvErode或cvDilate)時,解釋器段錯誤深入OpenCV代碼。 如果我在C程序中加載與dlopen相同的庫,並調用相同的過程,一切正常。在共享庫中調用opencv通過python ctypes使用時的段錯誤

我讀過另一篇文章,它可能與gcc使用的ABI有關,python必須使用與編譯python解釋器的gcc相同版本進行編譯才能正常工作。但在我的情況下,它都是4.4.5,所以這不應該是一個問題。 OpenCV庫也用相同版本的gcc編譯。

如何共享庫建:

g++ -g -shared -lopencv_core -lopencv_imgproc -lopencv_calib3d -lopencv_video -lopencv_features2d -lopencv_ml -lopencv_highgui -lopencv_objdetect -lopencv_contrib -lopencv_legacy -o thumbsplit.so thumbsplit.cpp 

如何共享庫被包裹:

extern "C" { 

int is_thumbsheet(char * image_path){ 
    Image image; 
    image.read(image_path); 
    int width = image.columns(); 
    int height = image.rows(); 
    int BOUND_CHANGE = 7000; 
    int test_height = 0; 

    if(width > height){ 
     return 0; 
    }else{ 
     test_height = width; 
    } 
    vector<int> test_rows = getRows(image, width, test_height, BOUND_CHANGE); 
    vector<int> test_cols = getCols(image, width, test_height, BOUND_CHANGE); 

    vector<Box> test_boxes = createBoxes(test_rows,test_cols,width,height); 
    if(test_boxes.size() > 6){ 
     return 1; 
    }else{ 
     return 0; 
    } 
} 

int cut_thumbs(char * image_path, char * thumb_path){ 
    Image image; 
    image.read(image_path); 
    int width = image.columns(); 
    int height = image.rows(); 
    int BOUND_CHANGE = 7000; 
    vector<int> rows = getRows(image, width, height, BOUND_CHANGE); 
    vector<int> cols = getCols(image, width, height, BOUND_CHANGE); 

    //drawDebugLines(rows, cols, width, height); 

    vector<Box> boxes = createBoxes(rows,cols,width,height); 
    //printBoxes(boxes); 
    char path[0x100]; 
    for(int i=0 ; i < boxes.size() ; i++){ 
     sprintf(path, "%s%d.jpg", thumb_path, i); 
     boxes[i].saveBox(image, path); 
    } 


    return 0; 
} 

} // C 

如何共享庫的程序被加載在Python:

import ctypes, os 

def load_lib(): 
lib_path = "%s/%s"%(os.path.realpath(os.path.dirname(__file__)), "thumbsplit.so") 
lib = ctypes.CDLL(lib_path) 
return lib 

def is_thumbsheet(image_path): 

lib = load_lib() 
if lib.is_thumbsheet(image_path): 
    return True 
else: 
    return False 

def cut_thumbs(image_path, thumbs_path): 

lib = load_lib() 
lib.cut_thumbs(image_path, thumbs_path) 

is_thumbsheet("/home/rolf/test/imageproc/full9.jpg") # this segfaults 

GDB輸出:

$ gdb python 
GNU gdb (GDB) 7.0.1-debian 
Copyright (C) 2009 Free Software Foundation, Inc. 
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> 
This is free software: you are free to change and redistribute it. 
There is NO WARRANTY, to the extent permitted by law. Type "show copying" 
and "show warranty" for details. 
This GDB was configured as "i486-linux-gnu". 
For bug reporting instructions, please see: 
<http://www.gnu.org/software/gdb/bugs/>... 
Reading symbols from /usr/bin/python...(no debugging symbols found)...done. 
(gdb) run thumbsheet.py 
Starting program: /usr/bin/python thumbsheet.py 
[Thread debugging using libthread_db enabled] 
0xb6330a12 

Program received signal SIGSEGV, Segmentation fault. 
0xb76fe2dc in cv::FilterEngine::start(cv::Size_<int>, cv::Rect_<int>, int)() from /usr/local/lib/libopencv_imgproc.so.2.3 
(gdb) info stack 
#0 0xb76fe2dc in cv::FilterEngine::start(cv::Size_<int>, cv::Rect_<int>, int)() from /usr/local/lib/libopencv_imgproc.so.2.3 
#1 0xb76feb41 in cv::FilterEngine::start(cv::Mat const&, cv::Rect_<int> const&, bool, int)() 
    from /usr/local/lib/libopencv_imgproc.so.2.3 
#2 0xb770a52b in cv::FilterEngine::apply(cv::Mat const&, cv::Mat&, cv::Rect_<int> const&, cv::Point_<int>, bool)() 
    from /usr/local/lib/libopencv_imgproc.so.2.3 
#3 0xb764bf8a in cv::morphOp(int, cv::_InputArray const&, cv::_OutputArray const&, cv::_InputArray const&, cv::Point_<int>, int, int, cv::Scalar_<double> const&)() from /usr/local/lib/libopencv_imgproc.so.2.3 
#4 0xb764d2ce in cv::erode(cv::_InputArray const&, cv::_OutputArray const&, cv::_InputArray const&, cv::Point_<int>, int, int, cv::Scalar_<double> const&)() from /usr/local/lib/libopencv_imgproc.so.2.3 
#5 0xb764d62e in cvErode() from /usr/local/lib/libopencv_imgproc.so.2.3 
#6 0xb7fd7adb in seperate::findSeperatedBoxes (img=0x8351d70) at seperate.cpp:189 
#7 0xb7fd7fcf in seperate::trySeperatedBoxes (img=0x8351d70, percentage_boxed=0xbfffefec) at seperate.cpp:202 
#8 0xb7fda00c in is_thumbsheet (image_path=0xb7c1bf74 "/home/rolf/test/imageproc/full9.jpg") at thumbsplit.cpp:39 
#9 0xb7a047df in ffi_call_SYSV() from /usr/lib/python2.6/lib-dynload/_ctypes.so 
#10 0xb7a0461e in ffi_call() from /usr/lib/python2.6/lib-dynload/_ctypes.so 
#11 0xb79ff27d in _CallProc() from /usr/lib/python2.6/lib-dynload/_ctypes.so 
#12 0xb79f6d7e in ??() from /usr/lib/python2.6/lib-dynload/_ctypes.so 
#13 0x0806232a in PyObject_Call() 
#14 0x080e016b in PyEval_EvalFrameEx() 
#15 0x080e18b0 in PyEval_EvalFrameEx() 
#16 0x080e2507 in PyEval_EvalCodeEx() 
#17 0x080e2607 in PyEval_EvalCode() 
#18 0x080ffcbd in PyRun_FileExFlags() 
#19 0x080fff22 in PyRun_SimpleFileExFlags() 
#20 0x0805dd81 in Py_Main() 
#21 0x0805cf6b in main() 
(gdb) x/i 0xb76fe2dc 
0xb76fe2dc <_ZN2cv12FilterEngine5startENS_5Size_IiEENS_5Rect_IiEEi+1212>: movdqa %xmm3,0x30(%esp) 
(gdb) 

GCC/G ++版本:

$ python 
Python 2.6.6 (r266:84292, Dec 27 2010, 00:02:40) 
[GCC 4.4.5] on linux2 

$ gcc --version 
gcc (Debian 4.4.5-8) 4.4.5 

$ g++ --version 
g++ (Debian 4.4.5-8) 4.4.5 

OpenCV的是2.3.1版和使用該版本的gcc從源建(4.4.5-8)

+1

你確實知道,有OpenCV的Python綁定? http://code.google.com/p/pyopencv/ – vartec 2012-04-25 14:07:39

+0

是的,但我寧願爲了速度的原因而在c/C++中執行所有圖像處理。並非全部都是在OpenCV內部完成的。 – Rolf 2012-04-25 15:00:25

+0

如果你編寫一個C程序來加載和使用你的庫,你會知道這個問題是在你的OpenCV代碼中,還是在用Python加載庫的代碼中。 – karlphillip 2012-04-25 15:00:38

回答

0

我找到解決方案。對於SSE指令,堆棧需要重新排列爲16個字節。如果我使用-mstackrealign構建共享庫,它將完美加載並從python調用。

Qt, GCC, SSE and stack alignment

相關問題