Вызов функции работает в C, но Segfaults в Python при доступе к Prosilica GigE Camera с Python с использованием OpenCV

Общая проблема, которую я пытаюсь отладить, заключается в том, почему программа на C может без проблем вызывать функцию, но когда та же функция вызывается в Python, это вызывает segfault.

Я пытаюсь получить привязки Python OpenCV для доступа к камере AVT GigE GC1360H, используя modules/highgui/src/cap_pvapi.cpp. Я могу безупречно читать и отображать кадры с камеры в C, но когда я пытаюсь прочитать кадр в Python, интерпретатор segfaults. Вызов VideoCapture.open(0) в Python успешно инициализирует камеру в режиме Mono8, а просмотр ifconfig показывает данные, поступающие с камеры. Я могу запустить тот же самый код Python, используя свою веб-камеру v4l вместо камеры AVT, и она отлично работает. Я использую OpenCV 2.3.1 на Gentoo Linux 3.2.12 x64. Вот код Python, который я использую на Python 2.7.2:

import cv2

if __name__ == '__main__':
    cv2.namedWindow("Cam", 1)
    capture = cv2.VideoCapture()
    capture.open(0) # This successfully opens the Camera and ifconfig
shows data being transferred
    while True:
        img = capture.read()[1] # This is where it segfaults

        cv2.imshow("Cam", img)
        if cv2.waitKey(10) == 27: break

    cv2.destroyWindow("Cam")

Я подключил gdb к интерпретатору Python и выяснил, что он segfaults при вызове PvCaptureQueueFrame() внутри CvCaptureCAM_PvAPI::grabFrame() в исходном коде OpenCV. Вот результат этого:

alex@Wassenberg ~ $ gdb python GNU gdb (Gentoo 7.3.1 p2) 7.3.1 Copyright (C) 2011 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 "x86_64-pc-linux-gnu". For bug reporting instructions, please see: <http://bugs.gentoo.org/>... Reading symbols from /usr/bin/python...(no debugging symbols found)...done. (gdb) run ./pyview.py Starting program: /usr/bin/python ./pyview.py process 8921 is executing new program: /usr/bin/python2.7 [Thread debugging using libthread_db enabled] [New Thread 0x7fffe3c10700 (LWP 8929)] [New Thread 0x7fffe340f700 (LWP 8930)] [New Thread 0x7fffe2c0e700 (LWP 8931)] [New Thread 0x7fffe240d700 (LWP 8932)] [Thread 0x7fffe240d700 (LWP 8932) exited] [New Thread 0x7fffe240d700 (LWP 8933)] [Thread 0x7fffe240d700 (LWP 8933) exited] [New Thread 0x7fffe240d700 (LWP 8940)] [Thread 0x7fffe240d700 (LWP 8940) exited] [New Thread 0x7fffe240d700 (LWP 8941)] [New Thread 0x7fffe1c0c700 (LWP 8942)] [New Thread 0x7fffe0eb9700 (LWP 8948)] [New Thread 0x7fffdbfff700 (LWP 8949)]

Program received signal SIGSEGV, Segmentation fault. 0x00007ffff007c8ea in PvCaptureQueueFrame () from /usr/local/lib/libPvAPI.so (gdb) bt
#0  0x00007ffff007c8ea in PvCaptureQueueFrame () from /usr/local/lib/libPvAPI.so
#1  0x00007ffff55dd123 in CvCaptureCAM_PvAPI::grabFrame() () from /usr/lib64/libopencv_highgui.so.2.3
#2  0x00007ffff55dde31 in cvGrabFrame () from /usr/lib64/libopencv_highgui.so.2.3
#3  0x00007ffff55dde4d in cv::VideoCapture::grab() () from /usr/lib64/libopencv_highgui.so.2.3
#4  0x00007ffff55ddaf2 in cv::VideoCapture::read(cv::Mat&) () from /usr/lib64/libopencv_highgui.so.2.3
#5  0x00007ffff6b355c5 in ?? () from /usr/lib64/python2.7/site-packages/cv2.so
#6  0x00007ffff7afdfdc in PyEval_EvalFrameEx () from /usr/lib64/libpython2.7.so.1.0
#7  0x00007ffff7aff88d in PyEval_EvalCodeEx () from /usr/lib64/libpython2.7.so.1.0
#8  0x00007ffff7aff9a2 in PyEval_EvalCode () from /usr/lib64/libpython2.7.so.1.0
#9  0x00007ffff7b19afc in ?? () from /usr/lib64/libpython2.7.so.1.0
#10 0x00007ffff7b1a930 in PyRun_FileExFlags () from /usr/lib64/libpython2.7.so.1.0
#11 0x00007ffff7b1b50f in PyRun_SimpleFileExFlags () from /usr/lib64/libpython2.7.so.1.0
#12 0x00007ffff7b2c823 in Py_Main () from /usr/lib64/libpython2.7.so.1.0
#13 0x00007ffff74902ad in __libc_start_main () from /lib64/libc.so.6
#14 0x00000000004008a9 in _start () (gdb)

Любое понимание этой проблемы будет оценено. В конечном счете, этот вопрос сводится к тому, почему C может без проблем вызывать функцию grabFrame(), кроме как с ошибками Python. Я склонен думать, что проблема заключается в том, как генерируются привязки Python к C, но я не знаком с тем, как это делает OpenCV. Любые идеи, почему GrapeFrame() и PvCaptureQueueFrame() будут нормально работать в C, но не в Python?

Для справки вот программа C, которая может успешно прочитать камеру AVT:

#include <opencv2/imgproc/imgproc_c.h>
#include "opencv2/highgui/highgui.hpp"
#include <stdio.h>

int main(int argc, char** argv)
{
      printf("Press ESC to exit\n");
      cvNamedWindow( "First Example of PVAPI Integrated", CV_WINDOW_AUTOSIZE );
      CvCapture* capture = cvCreateCameraCapture( CV_CAP_PVAPI );
      assert( capture != NULL );

      IplImage* frame;

      while(1)
      {
            frame = cvQueryFrame(capture);

            if(!frame) break;
            cvShowImage( "First Example of PVAPI Integrated", frame);
            char c = cvWaitKey(50);
            if( c == 27) break;
      }
      cvReleaseCapture( &capture );
      cvDestroyWindow( "First Example of PVAPI Integrated" );
}

Скомпилировано с gcc 4.5.3-r2:

gcc -I/usr/include/opencv -o main ./main.c -lopencv_core -lopencv_imgproc -lopencv_highgui -lopencv_ml -lopencv_video -lopencv_features2d -lopencv_calib3d -lopencv_objdetect -lopencv_contrib -lopencv_legacy -lopencv_flann


person user1547129    schedule 23.07.2012    source источник


Ответы (1)


Я исправил проблему, единственная разница между кодом C и кодом Python заключалась в аргументе, переданном в cvCreateCameraCapture() (capture.open() в Python). Передача 0 в эту функцию (как я сделал в Python) должна заставить ее сканировать любое видеоустройство, которое поддерживает OpenCV, что она и сделала. Передача CV_CAP_PVAPI (как я сделал в C) должна ограничить этот поиск только устройствами Prosilica. Хотя они должны давать одинаковые результаты (они оба нашли одну и ту же камеру), при передаче 0 камера не инициализировалась и не была готова принять tPvFrames в очереди. Передача 800 в Capture.open() устранила проблему, так как 800 — это значение CV_CAP_PVAPI.

person user1547129    schedule 24.07.2012