Reputation: 3
I have implemented a simple program containing a single producer and consumer. In this program producer thread is grabbing frame from Camera's Live stream and saving it in queue as well as in a folder, whereas in Main thread(Consumer) i am getting this frame and saving it, In order to see that the Frame got by the consumer is same as the one that is pushed by the producer. But the results are not same. Can anyone help me out in identifying my mistake?
#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;
}
Upvotes: 0
Views: 4030
Reputation: 1420
You are probably having problems with opencv cleverly avoiding copying data. copyTo does not allocate new data if it does not need to, which means that your producers might share the same memory block. I see that you are trying to use release to avoid this, but try clone to get a deep copy instead! This will also eliminate the need to explicitly call release.
capture >> Image;
p.setVariables(i,name,Image.clone());
As a side note, you are accessing the queue by without locking it in your consumer thread in the header of the inner loop. A cleaner way would be to move the locking and unlocking outside of the inner loop.
Upvotes: 1
Reputation: 836
Can you check if the content of field 'img' in Producer object copied in queue whose name is Producers is correctly copied.
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;
}
If it is ok, try your producer-consumer without Producer class but with Mat directly. Hoping this advice can help you.
Upvotes: 0