许多cv :: VideoCapture()构造之后来自cv :: VideoCapture :: grab()的Segfault

时间:2013-12-05 12:36:47

标签: opencv

我在以下代码中从cv :: VideoCapture :: grab()(实际上是>>运算符)获得了segfault。

超过100次循环后发生错误。

while(1) {
    boost::timer te;

    // create VideoCapture instance
    cv::VideoCapture cap(0);
    if(!cap.isOpened()) { /* shutdown code */ }
    cv::Mat frame;
    std::vector<uchar> buf;

    // get the latest frame from camera
    cap >> frame;

    // save frame as png image
    cv::imencode(".png", frame, buf);
    std::string data(buf.begin(), buf.end());
    my.saveImage(data);

    // release capture device
    cap.release();

    // wait 1 second
    boost::asio::deadline_timer t(io, boost::posix_time::milliseconds(1000.0 - te.elapsed() * 1000));
    t.wait();
}

gdb的错误是

(gdb) where
#0  0xb7dcfe75 in ?? () from /usr/lib/libopencv_highgui.so.2.3
#1  0xb7dcff03 in CvCaptureCAM_V4L_CPP::grabFrame() () from /usr/lib/libopencv_highgui.so.2.3
#2  0xb7dbd783 in cvGrabFrame () from /usr/lib/libopencv_highgui.so.2.3
#3  0xb7dbd7bf in cv::VideoCapture::grab() () from /usr/lib/libopencv_highgui.so.2.3
#4  0xb7dbd562 in cv::VideoCapture::operator>>(cv::Mat&) () from /usr/lib/libopencv_highgui.so.2.3
#5  0x0804a464 in main (argv=3, argc=0xbfffea44) at main.cpp:31

valgrind的错误是

==28670== Invalid write of size 4
==28670==    at 0x4242E75: ??? (in /usr/lib/libopencv_highgui.so.2.3.1)
==28670==    by 0x4242F02: CvCaptureCAM_V4L_CPP::grabFrame() (in /usr/lib/libopencv_highgui.so.2.3.1)
==28670==    by 0x46A14D2: (below main) (libc-start.c:226)
==28670==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==28670==
==28670==
==28670== Process terminating with default action of signal 11 (SIGSEGV)
==28670==  Access not within mapped region at address 0x0
==28670==    at 0x4242E75: ??? (in /usr/lib/libopencv_highgui.so.2.3.1)
==28670==    by 0x4242F02: CvCaptureCAM_V4L_CPP::grabFrame() (in /usr/lib/libopencv_highgui.so.2.3.1)
==28670==    by 0x46A14D2: (below main) (libc-start.c:226)
==28670==  If you believe this happened as a result of a stack
==28670==  overflow in your program's main thread (unlikely but
==28670==  possible), you can try to increase the size of the
==28670==  main thread stack using the --main-stacksize= flag.
==28670==  The main thread stack size used in this run was 8388608.

我有两个问题。

  • 定期拍摄快照的最佳做法是什么?
  • 如何避免此错误?

其他信息:

1 个答案:

答案 0 :(得分:0)

首先,不要每次都创建新的捕获。它不是那么麻烦,而且是一项非常昂贵的操作。

// create VideoCapture instance
cv::VideoCapture cap(0);

while(cap.isOpened()) 
{
    boost::timer te;

    cv::Mat frame;
    std::vector<uchar> buf;

    // get the latest frame from camera
    cap >> frame;

    if ( ! frame.empty() )  // check it, please
    {
        // save frame as png image
        cv::imencode(".png", frame, buf);
        std::string data(buf.begin(), buf.end());
        my.saveImage(data);
    }

    // wait 1 second
    boost::asio::deadline_timer t(io, boost::posix_time::milliseconds(1000.0 - te.elapsed() * 1000));
    t.wait();
}
//cap.release(); // can care for itself

然后,将图像编码为std :: string可能会导致许多意外的文件截断(不知道,my.saveImage()正在做什么,但是零在图像中完全合法,但不是在字符串,对吗?)

为什么不在这里使用imwrite()?

最后但并非最不重要,2.3.1 非常旧,更好地更新到2.4.7