【问题标题】:Opencv Segmentation Fault using pthread to capture frames C++Opencv Segmentation Fault 使用 pthread 捕获帧 C++
【发布时间】:2017-10-30 07:43:47
【问题描述】:

我在尝试运行我的程序时收到分段错误。在修改我的程序以从不同线程上的两个摄像头捕获帧后,我只收到分段错误。我在两个线程上都使用了相同的函数,我想知道这是否是问题所在。

Main.c

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>
#include <opencv2/opencv.hpp>
#include "ThreadedWebcamCapture.h"

pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;

int main(){
    ThreadedCapture Capture1;
    Capture1.STOP = 0;
    Capture1.CAP_NUMBER = 1;
    Capture1.X_RESOLUTION = 640;
    Capture1.Y_RESOLUTION = 480;

    ThreadedCapture Capture2;
    Capture2.STOP = 0;
    Capture2.CAP_NUMBER = 0;
    Capture2.X_RESOLUTION = 640;
    Capture2.Y_RESOLUTION = 480;

    pthread_t Capture1Thread;
    int Capture1ThreadRetCode;

    pthread_t Capture2Thread;
    int Capture2ThreadRetCode;

    printf("[INFO]Creating Threads\n");
    Capture1ThreadRetCode = pthread_create(&Capture1Thread, NULL, &Capture_Thread, (void *)&Capture1);
    printf("[INFO]Created Thread 1");
    Capture2ThreadRetCode = pthread_create(&Capture2Thread, NULL, &Capture_Thread, (void *)&Capture2); //I think the error is occurring here
    if(Capture1ThreadRetCode || Capture2ThreadRetCode != 0){
        printf("[ERROR]Thread Creation Failed!\n");
        exit(EXIT_FAILURE);
    }
    //cv::namedWindow("Window", cv::WINDOW_AUTOSIZE);
    int NumberOfFrames;
    time_t Seconds1;
    Seconds1 = time(NULL);
    cv::Mat Output;
    while(1 == 1){
        pthread_mutex_lock(&mutex1);
        if(!Capture1.FRAME.empty() || !Capture2.FRAME.empty()){
            cv::hconcat(Capture1.FRAME, Capture2.FRAME, Output);
        }
        pthread_mutex_unlock(&mutex1);
        if(!Output.empty()){
            NumberOfFrames = NumberOfFrames + 1;
            cv::imshow("Window", Output);
        }
        if(cv::waitKeyEx(1) >= 0){
            Capture1.STOP = 1;
            Capture2.STOP = 1;
            break;
        }
    }
    time_t Seconds2;
    Seconds2 = time(NULL);
    int Seconds = Seconds2 - Seconds1;
    int FPS = NumberOfFrames / Seconds;
    printf("[INFO]FPS %d\n", FPS);
    pthread_join(Capture1Thread, NULL);
    pthread_join(Capture2Thread, NULL);
    printf("[INFO]Done\n");
    return(0);
}

cvthreads.c

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <opencv2/opencv.hpp>
#include "ThreadedWebcamCapture.h"

void *Capture_Thread(void* Test){
    ThreadedCapture *Testing = (ThreadedCapture *) Test;
    cv::VideoCapture CAP ((*Testing).CAP_NUMBER);
    CAP.set(CV_CAP_PROP_FRAME_WIDTH, (*Testing).X_RESOLUTION);
    CAP.set(CV_CAP_PROP_FRAME_HEIGHT, (*Testing).Y_RESOLUTION);
    while((*Testing).STOP != 1){
        CAP.read((*Testing).FRAME);
    }
    return(NULL);
}

ThreadedWebcamCapture.h

#ifndef _THREADEDWEBCAMCAPTURE_H_
#define _THREADEDWEBCAMCAPTURE_H_

void *Capture_Thread(void* Test);

typedef struct ThreadedCaptures  {
    int STOP;
    int CAP_NUMBER;
    int X_RESOLUTION;
    int Y_RESOLUTION;
    cv::Mat FRAME;
} ThreadedCapture;

#endif

【问题讨论】:

  • 您能否在调试器中运行该程序并告诉我们您的哪一行代码导致了段错误?您甚至可以粘贴整个堆栈跟踪。
  • 这是我运行它时遇到的错误,但是当我在 gdb 中运行它时它没有错误。
  • *** `./app' 中的错误:双重释放或损坏(fasttop):0x00007f30d0001a40 *** 分段错误(核心转储)
  • strace的输出在这里pastebin.com/06ZiA2vc
  • 只是一个疯狂的初步猜测,但 Posix 不喜欢让您多次调用 pthread_mutex_init 并且您已经对互斥锁使用静态初始化。以下是 Posix 关于多次调用它的说法:“尝试初始化已经初始化的互斥体会导致未定义的行为。”

标签: c++ linux segmentation-fault pthreads opencv3.0


【解决方案1】:

您的问题在于 cv::hconcat 函数,特别是传递两个具有不同行数的 cv::Mat 对象。如果您查看cv::hconcat 函数的documentation,它表示给定的两个矩阵必须具有相同的行数。您还可以看到,在 strace 结果的最后几行中,有一个断言错误,指出发送到cv::hconcat 的行数不相等。

"OpenCV Error: Assertion failed ("..., 205OpenCV Error: Assertion failed (src[i].dims <= 2 && src[i].rows == src[0].rows && src[i].type() == src[0].type()) in hconcat, file /builddir/build/BUILD/opencv-3.2.0/modules/core/src/matrix.cpp, line 2865

现在,此错误的原因在于以下几行:

if(!Capture1.FRAME.empty() || !Capture2.FRAME.empty()){
    cv::hconcat(Capture1.FRAME, Capture2.FRAME, Output);
}

如果任何矩阵不为空,则执行水平串联操作。但是,这意味着其中一个矩阵的大小可能为 640x480,而另一个矩阵的大小可能为 0x0。在这种情况下,cv::hconcat 会抛出一个断言错误并且你的程序会崩溃。要修复它,请尝试将条件更改为

if(!Capture1.FRAME.empty() && !Capture2.FRAME.empty()){
    cv::hconcat(Capture1.FRAME, Capture2.FRAME, Output);
}

只有当两个矩阵都不为空时才执行操作。它们应该具有相同的行数,因为您构建的 ThreadedCapture 对象具有相同的行数。

参考文献

【讨论】:

  • 程序启动时我仍然遇到分段错误,但这只是有时,所以我的代码中肯定有另一个问题,我将再次对其运行 strace。
  • 您是否尝试过从循环中删除 pthread_mutex_init 调用?
  • 是的,我完全删除了该行,现在程序运行有时我更新了上面的代码以反映有关 pthread_mutex_init 的更改
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-15
  • 2015-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多