C++ 从缓冲区写入和读取Opencv

C++ 从缓冲区写入和读取Opencv,c++,opencv,video-capture,C++,Opencv,Video Capture,我有两个任务(线程),每个任务在不同的处理器(核心)上运行,第一个任务使用OpenCVvideocapture()重复捕获图像 我只使用了这两行代码进行捕获: cv::Mat frame; capture.read(frame); 现在,我想使用第二个任务显示捕获的图像。在第二个任务代码中执行imshow功能后: cv::imshow("Display window", frame); 我得到以下输出错误: OpenCV Error: Assertion failed (size.width

我有两个任务(线程),每个任务在不同的处理器(核心)上运行,第一个任务使用OpenCV
videocapture()
重复捕获图像

我只使用了这两行代码进行捕获:

cv::Mat frame;
capture.read(frame);
现在,我想使用第二个任务显示捕获的图像。在第二个任务代码中执行
imshow
功能后:

cv::imshow("Display window", frame);
我得到以下输出错误:

OpenCV Error: Assertion failed (size.width>0 && size.height>0) in imshow, file /build/opencv-L2vuMj/opencv-3.2.0+dfsg/modules/highgui/src/window.cpp, line 304
terminate called after throwing an instance of 'cv::Exception'
what():  /build/opencv-L2vuMj/opencv-3.2.0+dfsg/modules/highgui/src/window.cpp:304: error: (-215) size.width>0 && size.height>0 in function imshow
那么,我怎样才能避免这个错误呢

完整的代码托管在

你可以试试这个。如果你写waitKey();代码希望按任意键获取帧和显示帧。

返回bool指示读取是否成功

您正在将一个空的
帧传递给
cv::imshow()
。在尝试显示之前,请尝试检查读取是否成功

cv::Mat frame;
if(capture.read(frame))
{
    cv::imshow(frame);
}
编辑 OP发布了一个代码链接。在他的程序中,
frame
被声明为全局变量。行内
120
捕获。读取(帧)
写入帧,行内
140
imshow(帧)
读取
而不使用互斥锁-这是一种数据竞争。正确的代码应符合以下要求:

#include <mutex>
#include <opencv2/opencv.hpp>

std::mutex mutex;
cv::Mat frame;

{
    mutex.lock();
    capture.read(frame);
    mutex.unlock();
}
{
    mutex.lock();
    cv::imshow(frame);
    mutex.unlock();
}
#包括
#包括
std::互斥互斥;
cv::垫架;
{
mutex.lock();
捕获。读取(帧);
mutex.unlock();
}
{
mutex.lock();
cv::imshow(框架);
mutex.unlock();
}

代码的问题在于存在数据竞争。。假设显示线程首先锁定帧,并在读取帧之前尝试显示它,以便看到问题 如果你想要一个同步的解决方案,你可以使用pthread条件&等待直到一个图像被读取来通知你的显示函数,否则你将有一个活动的等待

// in the declaration part 
// Declaration of thread condition variable 
pthread_cond_t cond1 = PTHREAD_COND_INITIALIZER; 

//in the display function 

ptask DisplyingImageTask()
{

    int task_job = 0;

    while (1)
    {
        std::cout << "The job " << task_job << " of Task T" << ptask_get_index()
                  << " is running on core " << sched_getcpu() << " at time : "
                  << ptask_gettime(MILLI) << std::endl;

        cv::namedWindow("Display window", cv::WINDOW_AUTOSIZE);

        pthread_mutex_lock(&frame_rw);
        //wait for the read function to send a signal
        pthread_cond_wait(&cond1, &frame_rw);

        cv::imshow("Display window", frame);        
        cv::waitKey(1);

        pthread_mutex_unlock(&frame_rw);

        ptask_wait_for_period();
        task_job++;
    }

}

// in the Read function

ptask CapturingImageTask()
{

    int task_job = 0;

    while (1)
    {
        std::cout << "The job " << task_job << " of Task T" << ptask_get_index()
                  << " is running on core " << sched_getcpu() << " at time : "
                  << ptask_gettime(MILLI) << std::endl;

        pthread_mutex_lock(&frame_rw);
        capture.read(frame);
        //after capturing the frame signal the display function & everything should be synchronize as you want 
        pthread_cond_signal(&cond1);  

        pthread_mutex_unlock(&frame_rw);

        ptask_wait_for_period();
        task_job++;
    }

}
//在声明部分
//线程条件变量的声明
pthread_cond_t cond1=pthread_cond_初始值设定项;
//在显示功能中
ptask displayingimagetask()
{
int task_job=0;
而(1)
{

std::cout正如其他人提到的,尝试使用互斥锁

在尝试显示cv::Mat之前,您还可以在其上设置一个条件:

if (frame.data()) 
    imshow("window", frame);
这将检查要显示的帧是否有数据,从而避免错误


同样,此条件只是为了避免imshow错误,而不是为了解决原始问题,如其他答案中所述,原始问题是两个线程之间的数据竞争。

感谢您的回答。这并不是我所需要的。捕获和显示被视为一个不同的过程。因此,请描述公共Mat值并分配帧to Mat值。然后您可以在另一个进程中读取Mat值。我确实检查过,仅使用一个同时执行捕获和显示的任务是成功的。但是,对于两个“任务”,您会遇到此错误?如果您的“任务”如果是两个并行线程,那么您可能正在进行数据竞争。实际上,任务是以不同的偏移量同时启动的。在您的程序中,
frame
被声明为全局变量。在
120行中,您正在写入
frame
,在
140行中,您基本上无法读取它(
imshow
)而不使用-这是一种数据竞争。请参阅我编辑的文章。我对
pthread
不太熟悉,所以我不能告诉你太多。但我很高兴它现在可以工作。访问“frame”互斥,因此线程不能修改和镜像,而另一个线程可以显示它。虽然互斥可以工作,但另一个选项是使用2到8个Mat的向量,并以循环方式将图像读取到Mat中…第一个图像进入Mat 0,第二个图像进入Mat 1,第三个图像进入Mat 2并使用condwait()在显示任务中等待每个Mat。这允许捕获和显示任务同时进行。@MarkSetchell,这不是有点贪婪吗?贪婪?在什么意义上?全彩1080p图像只有6MB。许多人的笔记本电脑上有8GB的RAM,只是为了运行字处理程序,所以这不到内存的0.1%RAM和图像处理比Microsoft Word更值得使用RAM!即使是Raspberry Pi也有1GB的RAM,那么6MB是多少?如果是这样,使用双缓冲是绝对理想的。如果您的相机可以达到30fps,这意味着需要33ms才能获得一帧。如果使用互斥,这意味着这些33ms完全无法显示任务!如果您有两个缓冲区,您的相机可以在显示当前帧的同时获取下一帧。我刚刚使用了您的解决方案,效果非常好。谢谢。您对@MarkSetchell在上述评论中提到的双缓冲技术有何建议?我完全同意他的建议。这将使工作更多同步我对OpenCV一无所知,但文档中说,
capture.read
返回一个
bool
,表示成功或失败,所以…检查该值不是一个好主意吗?
if (frame.data()) 
    imshow("window", frame);