制作cv :: Mat的队列

时间:2013-12-30 10:28:41

标签: c++ multithreading opencv boost queue

我已经实现了一个包含单个生产者和消费者的简单程序。在这个程序中,生产者线程从Camera的Live流中抓取帧并将其保存在队列和文件夹中,而在主线程(消费者)中我得到这个帧并保存它,以便看到Frame得到了消费者与生产者推动的消费者相同。但结果并不相同。任何人都可以帮我识别我的错误吗?

#include "stdafx.h"
#include <cv.h>
#include <highgui.h>
#include <string>
#include <iostream>
#include <queue>
#include <deque>
#include <time.h>
#include "Producer.h"
#include "boost\thread.hpp"
using namespace cv;
using namespace std;

queue<Producer> Producers;
boost::mutex sharedMutex;

void threadFunction()
{
    Producer p;
    string name="Havard";
    VideoCapture capture("rtsp://192.168.10.20:1125/Master-0?profile=Master-0");
    stringstream filenamep;
    SYSTEMTIME st;
    Mat Image;
    Mat Image2;
    for(int i=0;i<200;i++)
    {
        sharedMutex.lock();
        capture >> Image;
        Image.copyTo(Image2);
        p.setVariables(i,name,Image2);
        Producers.push(p);
        filenamep << "D:/MultiThreading/MakingThreadSafeQueue/Images/" << p.count << "p.jpg";
        imwrite(filenamep.str(),Image2);
        sharedMutex.unlock();
        filenamep.str("");
        Image.release();
        Image2.release();
    }
}


int _tmain(int argc, _TCHAR* argv[])
{
    Mat ImgC;
    Producer p2;
    boost::thread producerThread(&threadFunction);
    stringstream filename;
    while(1)
    {
    Sleep(500);
    while(!Producers.empty())
    {
    sharedMutex.lock();
    p2=Producers.front();
    p2.img.copyTo(ImgC);
    imshow("Frame",p2.img);
    filename << "D:/MultiThreading/MakingThreadSafeQueue/Images/" << p2.count << ".jpg";
    imwrite(filename.str(),ImgC);
    Producers.pop();
    sharedMutex.unlock();
    ImgC.release();
    p2.img.release();
    filename.str("");
    }
    char c=cvWaitKey(1);
    if(c==27) break;
    }
    return 0;
} 

2 个答案:

答案 0 :(得分:1)

你可能遇到了opencv巧妙地避免复制数据的问题。如果不需要,copyTo不会分配新数据,这意味着您的生产者可能共享相同的内存块。我发现您尝试使用release来避免这种情况,但请尝试使用clone来获取深层副本!这也将消除显式调用release的需要。

    capture >> Image;
    p.setVariables(i,name,Image.clone());

作为旁注,您正在访问队列,而不是将其锁定在内部循环的标头中的消费者线程中。更简洁的方法是将锁定和解锁移动到内环之外。

答案 1 :(得分:0)

您是否可以检查在名为Producers的队列中复制的Producer对象中的字段'img'的内容是否被正确复制。

Mat diff, Image2gray, tempGray;

cvtColor(Image2, Image2gray, CV_BGR2GRAY);
cvtColor(Producers.back().img, tempGray, CV_BGR2GRAY);
compare(Image2gray, tempGray, diff, CMP_EQ);
if (countNonZero(diff) == Image2.total())
{
    cout << "ok" << endl;
}

如果没问题,请尝试没有Producer类但直接使用Mat的生产者 - 消费者。 希望这个建议可以帮助你。