【问题标题】:Making Queue of cv::Mat制作 cv::Mat 的队列
【发布时间】:2013-12-30 10:28:41
【问题描述】:

我已经实现了一个包含单个生产者和消费者的简单程序。在这个程序中,生产者线程从相机的实时流中抓取帧并将其保存在队列和文件夹中,而在主线程(消费者)中,我正在获取此帧并保存它,以便查看该帧由消费者与生产者推送的消费者相同。但结果并不相同。谁能帮我找出我的错误?

#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;
} 

【问题讨论】:

    标签: c++ multithreading opencv boost queue


    【解决方案1】:

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

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

    作为旁注,您访问队列时没有将其锁定在内部循环标头中的使用者线程中。一种更简洁的方法是将锁定和解锁移到内部循环之外。

    【讨论】:

      【解决方案2】:

      您能否检查复制到名称为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 的生产者-消费者。 希望这个建议可以帮助到你。

      【讨论】:

      • 感谢您的建议。我检查了它们都是一样的。但是当我制作 cv::Mat 队列时,它仍然给出相同的结果:(
      猜你喜欢
      • 2014-06-21
      • 1970-01-01
      • 1970-01-01
      • 2016-12-29
      • 2023-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多