多个图像队列,多个线程......怎么样? [英] Multiple queue of images, multiple threads...how?

查看:62
本文介绍了多个图像队列,多个线程......怎么样?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我有问题。我必须创建一个管理4个队列,3个线程的程序,就像我链接的图表一样。



这是我要做的事情的图表:



http://img839.imageshack.us/img839/3196/schemah.jpg [ ^ ]



我已经开始工作,但共享队列的并发只能用于2个线程三个不要。



我在这里发布我的代码,等待你的回复。看看我的代码,让我知道什么是错的。



我现在更新了我的代码..请帮帮我。在此先感谢。



  #include   <   opencv\cv.h   >  
#include < opencv \highgui.h >
#include < stdio.h >
#include < span class =code-preprocessor> < windows.h >
#include < process.h >
#include < 队列 >
# include < time.h >

使用 namespace std;
使用 命名空间 cv;


/ * inizio della parte relativa alla coda thread safe * /

template< typename T>
class coda_concorr
{
private
std ::队列< T> la_coda;
HANDLE互斥量;
public
bool 完成;
coda_concorr()
{
mutex = CreateMutex(NULL,FALSE,NULL);
complete = false ;
}
void push(T& data)
{
WaitForSingleObject(mutex,INFINITE);
la_coda.push(data);
ReleaseMutex(互斥);
}
bool vuota() const
{
bool RetCode;
WaitForSingleObject(mutex,INFINITE);
RetCode = la_coda.empty();
ReleaseMutex(互斥);
return RetCode;
}

bool try_pop(T& popped)
{
WaitForSingleObject(mutex,INFINITE);
while (la_coda.empty())
{
if (完整)
{
ReleaseMutex(互斥);
return false ;
}
else
{
ReleaseMutex(mutex);
睡眠( 100 ); // 未来的改进
WaitForSingleObject(互斥,INFINITE);
}
}

popped = la_coda.front();
la_coda.pop();
ReleaseMutex(互斥);
return true ;
}
};

// pacchetto per passaggio ai thread
struct Args
{
coda_concorr< cv :: Mat> ;
coda_concorr< cv :: Mat> *出; // puntatore a coda successiva
};







在宣布我要推出的3个功能之后:



< pre lang =c ++> // funzione grey
void gray( void * param){
Mat temp1,temp2;
Args * arg =(Args *)param;
if (!arg-> in.vuota()){
while (arg-> in.try_pop(temp1)){
cvtColor(temp1,temp2,CV_BGR2GRAY);
arg-> out-> push(temp2);
}
}
// flag completato
arg-> out-> complete = true ;
_endthread();

}

// funzione sogliatura
void soglia( void * param){
Mat temp1a,temp2a;
Args * arg =(Args *)param;
while (arg-> in.try_pop(temp1a)){
threshold(temp1a,temp2a, 128 255 ,THRESH_BINARY);
arg-> out-> push(temp2a);
}
// flag completato
arg-> out - > complete = true ;
_endthread();
}


// funzione erosione / dilate
void finitura( void * param){
Mat temp1b,temp2b, temp2c;
Args * arg =(Args *)param;
while (arg-> in.try_pop(temp1b)){
erode(temp1b,temp2b,cv :: Mat());
// dilate(temp2b,temp2c,Mat());
arg - > OUT->推(temp2b);
}
// flag completato
arg-> out - > complete = true ;
_endthread();
}







那么这是主要的:



 int main()
{
// dichiarazione delle到期代码principali
coda_concorr< cv :: Mat> INGRESSO;
coda_concorr< cv :: Mat> uscita;

//时钟
clock_t avvio;
clock_t罚款;


// array locali di ingresso e uscita
Mat inn [10];
Mat out;

// assegnazione 10 immagini di prova
inn [0] = imread(C:/OPENCV/Test/imgtest/bird1.jpg,1);
inn [1] = imread(C:/OPENCV/Test/imgtest/bird2.jpg,1);
inn [2] = imread(C:/OPENCV/Test/imgtest/bird3.jpg,1);
inn [3] = imread(C:/OPENCV/Test/imgtest/pig1.jpg,1);
inn [4] = imread(C:/OPENCV/Test/imgtest/pig2.jpg,1);
inn [5] = imread(C:/OPENCV/Test/imgtest/pig3.jpg,1);
inn [6] = imread(C:/OPENCV/Test/imgtest/spider1.jpg,1);
inn [7] = imread(C:/OPENCV/Test/imgtest/spider2.jpg,1);
inn [8] = imread(C:/OPENCV/Test/imgtest/spider3.jpg,1);
inn [9] = imread(C:/OPENCV/Test/imgtest/Nutella.jpg,1);


// dichiarazione代码
Args dati,dati2,dati3,dati4;

// inizio a contare tempo
avvio = clock();

// Popolamento coda ingresso
for(int i = 0; i< = 9; i ++){
dati.in.push(inn [i]);
}
// punta all'output successivo
dati.out =& dati2.in;
dati2.out =& dati3.in;
dati3.out =& uscita;

// dichiarazione delle maniglie
HANDLE handle1,handle2,handle3;

// dichiarazione dei threads
handle1 =(HANDLE)_beginthread(grey,0,& dati);
handle2 =(HANDLE)_beginthread(soglia,0,& dati2);
handle3 =(HANDLE)_beginthread(finitura,0,& dati3);

// join
WaitForSingleObject(handle1,INFINITE);
WaitForSingleObject(handle2,INFINITE);
WaitForSingleObject(handle3,INFINITE);

//罚款registrazione节奏
罚款= clock() - avvio;

double tempoimp = fine /(double)CLOCKS_PER_SEC;

//输出di verifica
while(dati3.out-> try_pop(out)){
imshow(immagine,out);
waitKey(100);
}

cout<< endl<<Cicli di clock:<< fine<< endl;
cout<<Secondi trascorsi:<< tempoimp<< endl;

system(PAUSE);
返回0;

}





我没有任何输出......有人能帮帮我吗?



环境是:Visual C ++ 2010,WIndows 7 64bit上的OpenCV 2.4.3。

解决方案

I我认为阻塞是由队列代码中的一些错误引起的:



  //  队列代码 
模板< typename T>
class coda_concorr
{
private
。 ..
// 代码不正确:
bool vuota() const
{
WaitForSingleObject(mutex,INFINITE);
return la_coda.empty();
ReleaseMutex(互斥); // 永远不会发布互斥锁
// 作为上一行中的函数返回和
// 永远不会调用ReleaseMutex。
}
// 固定代码:
bool vuota() const
{
bool RetCode;
WaitForSingleObject(mutex,INFINITE);
RetCode = la_coda.empty();
ReleaseMutex(互斥);
return RetCode;
}


// 错误代码:
bool try_pop(T& popped)
{
WaitForSingleObject(mutex,INFINITE);
if (la_coda.empty()){
return ; // 此处相同,互斥锁未发布
}
WaitForSingleObject的(互斥,无限); // 这是第二次使用互斥锁
// 这需要第二个ReleaseMutex()
// 正常运行
popped = la_coda.front();
la_coda.pop();
ReleaseMutex(互斥);
return true ;
}
// 固定代码:
bool try_pop(T& popped)
{
WaitForSingleObject(mutex,INFINITE);
if (la_coda.empty()){
ReleaseMutex(mutex);
return false ;
}
popped = la_coda.front();
la_coda.pop();
ReleaseMutex(互斥);
return true ;
}
};





< V2>另一个错误:

这里有错误的代码和解释,见下划线:

  int  main()
{
coda_concorr< cv :: Mat> INGRESSO;
coda_concorr< cv :: Mat> coda1;
coda_concorr< cv :: Mat> coda2;
coda_concorr< cv :: Mat> uscita;


// 确定第二个队列
< u> dati.out = coda1; // 这会创建一个coda1的副本
...
// 分享不工作的部分
dati2。 = coda1; // 这会创建第二个coda1副本,
// 它不会引用相同的队列
dati2.out = coda2;
...

}



因此两个线程都看到了coda1的不同副本,而你希望让它们看到相同的例如,coda1。

这里有一个解决问题的建议,使得队列成为一个指针,以便你可以链接Args结构:

 < span class =code-keyword> struct  Args 
{
coda_concorr< cv :: Mat> ;
coda_concorr< cv :: Mat> * 出; // 现在这是一个指针,指向
// 按顺序排列的下一个队列
};


void gray( void * param){
...
arg-> out-> push(temp2);
}
arg-> out-> complete = true ;
...
}
// 阈值功能
void soglia( void * param){
...
arg - > OUT->推(temp2a);
}
}
arg-> out-> complete = true ;
_endthread();
}


int main()
{
...
coda_concorr< cv :: Mat> coda1; // 不需要
...
< span class =code-comment> // 确定第二个队列
dati.out =& dati2。 in ; // 这会存储指向下一个的指针queue
...

dati2。 in =& coda1; < span class =code-comment> // 队列链接时不需要,见上文
dati2.out =& coda2 ;
...
// 输出
while (dati2.out-> try_pop(out)){
imshow( 想象,,出);
waitKey( 100 );
}
...
}





还有一个启动问题:当第二个线程启动并且其输入队列为空,它立即退出。当输入队列在执行期间变空时(即第二个线程执行速度比第一个线程快),也会发生同样的情况。

您必须更改排队的设计,以便区分队列由于前一步骤尚未完成从队列空完成所有工作所以空。

一个选项是添加一个队列状态,在生产者提供数据时设置,所以你的线程只在队列为空并且生产者已经表明它不会提供更多数据时才终止,否则线程会等到队列变为非空。



< V3>在队列try_pop方法中添加等待,这应该摆脱启动问题的立即终止:

  bool  try_pop(T& popped)
{
WaitForSingleObject(mutex,INFINITE);
while (la_coda.empty())
{
if (完整)
{
ReleaseMutex(互斥);
return false ;
}
else
{
ReleaseMutex(mutex);
睡眠( 100 ); // 未来的改进:这可以通过创建
// 表示队列不为空的事件。
// 我现在就保持这样简单。
// < span class =code-comment>我尽量避免混合功能与
// 性能改进。
WaitForSingleObject(互斥,INFINITE);
}
}

popped = la_coda.front();
la_coda.pop();
ReleaseMutex(互斥);
return true ;
}


经过多次尝试,这就是解决方案:



 / * programma di prova gestione thread e OpenCV con timer di evalutazione tempo 

impiegato v.1.0 * /

#include< opencv \\ \\cv.h>
#include< opencv \highgui.h>
#include< stdio.h>
#include< windows.h>
#include< process.h>
#include< queue>
#include< time.h>使用namespace std

;
使用命名空间cv;


/ * inizio della parte relativa alla coda thread safe * /

template< typename T>
class coda_concorr
{
private:
std :: queue< T> la_coda;
HANDLE互斥量;
public:
bool complete;
coda_concorr()
{
mutex = CreateMutex(NULL,FALSE,NULL);
complete = false;
}
void push(T& data)
{
WaitForSingleObject(mutex,INFINITE);
la_coda.push(data);
ReleaseMutex(互斥);
}
bool vuota()const
{
bool RetCode;
WaitForSingleObject(mutex,INFINITE);
RetCode = la_coda.empty();
ReleaseMutex(互斥);
返回RetCode;
}
bool try_pop(T& popped)
{
WaitForSingleObject(mutex,INFINITE);
while(la_coda.empty()){
// ReleaseMutex(mutex);
//睡眠(100);
// WaitForSingleObject(互斥,INFINITE);
返回false;
}
popped = la_coda.front();
la_coda.pop();
ReleaseMutex(互斥);
返回true;
}
};

// pacchetto per passaggio ai thread
struct Args
{
coda_concorr< cv :: Mat>在;
coda_concorr< cv :: Mat> *出; // puntatore a coda successiva
};

// funzione grey
void grey(void * param){
Mat temp1,temp2;
int add = 0;
Args * arg =(Args *)param;
while(arg-> in.try_pop(temp1)){
cvtColor(temp1,temp2,CV_BGR2GRAY);
arg-> out-> push(temp2);
add ++;
}
// flag completato
arg-> out-> complete = true;
cout<<Thread 1 terminato con<< add<<elaborazioni。<< endl;
_endthread();

}

// funzione sogliatura
void soglia(void * param){
Mat temp1a,temp2a;
int add = 0;
Args * arg =(Args *)param;
while(arg-> in.vuota()){
Sleep(50);
}
while(arg-> in.try_pop(temp1a)){
threshold(temp1a,temp2a,128,255,THRESH_BINARY);
arg-> out-> push(temp2a);
add ++;
}
// flag completato
arg-> out-> complete = true;
cout<<Thread 2 terminato con<< add<<elaborazioni。<< endl;
_endthread();
}


// funzione erosione / dilate
void finitura(void * param){
Mat temp1b,temp2b,temp2c;
int add = 0;
Args * arg =(Args *)param;
while(arg-> in.vuota()){
Sleep(40);
}
while(arg-> in.try_pop(temp1b)){
erode(temp1b,temp2b,cv :: Mat());
dilate(temp2b,temp2c,Mat());
arg-> out-> push(temp2c);
add ++;
}
// flag completato
arg-> out-> complete = true;
cout<<Thread 3 terminato con<< add<<elaborazioni。<< endl;
_endthread();
}



//主
int main()
{
// dichiarazione delle到期代码principali
coda_concorr< cv :: Mat> INGRESSO;
coda_concorr< cv :: Mat> uscita;

//时钟
clock_t avvio;
clock_t罚款;


// array locali di ingresso e uscita
Mat inn [10];
Mat out;

// inizio a contare tempo
avvio = clock();

// assegnazione 10 immagini di prova
inn [0] = imread(C:/OPENCV/Test/imgtest/bird1.jpg,1);
inn [1] = imread(C:/OPENCV/Test/imgtest/bird2.jpg,1);
inn [2] = imread(C:/OPENCV/Test/imgtest/bird3.jpg,1);
inn [3] = imread(C:/OPENCV/Test/imgtest/pig1.jpg,1);
inn [4] = imread(C:/OPENCV/Test/imgtest/pig2.jpg,1);
inn [5] = imread(C:/OPENCV/Test/imgtest/pig3.jpg,1);
inn [6] = imread(C:/OPENCV/Test/imgtest/spider1.jpg,1);
inn [7] = imread(C:/OPENCV/Test/imgtest/spider2.jpg,1);
inn [8] = imread(C:/OPENCV/Test/imgtest/spider3.jpg,1);
inn [9] = imread(C:/OPENCV/Test/imgtest/Nutella.jpg,1);


// dichiarazione代码
Args dati,dati2,dati3;



// Popolamento coda ingresso
for(int i = 0; i< = 9; i ++){
dati.in.push(旅店[I]);
}
// punta all'output successivo
dati.out =& dati2.in;
dati2.out =& dati3.in;
dati3.out =& uscita;
// dichiarazione delle maniglie
HANDLE handle1,handle2,handle3;

// dichiarazione dei threads
handle1 =(HANDLE)_beginthread(grey,0,& dati);
handle2 =(HANDLE)_beginthread(soglia,0,& dati2);
handle3 =(HANDLE)_beginthread(finitura,0,& dati3);

// join
WaitForSingleObject(handle1,INFINITE);
WaitForSingleObject(handle2,INFINITE);
WaitForSingleObject(handle3,INFINITE);


//罚款registrazione节奏
罚款= clock() - avvio;

double tempoimp = fine /(double)CLOCKS_PER_SEC;

//输出di verifica
/ *
while(dati3.out-> try_pop(out)){
imshow(immagine,out);
waitKey(100);
} * /

cout<< endl<<Cicli di clock:<< fine<< endl;
cout<<Secondi trascorsi:<< tempoimp<< endl;
system(PAUSE);


返回0;

}





管理共享元素的3个线程,共4个队列。


Hi,
I have a problem. I have to create a program that manage 4 queues, 3 threads, like in the diagram that I've linked.

THIS IS A DIAGRAM OF WHAT I HAVE TO DO:

http://img839.imageshack.us/img839/3196/schemah.jpg[^]

I have started to work on, but concurrency with "shared" queue works only with 2 threads and three don't.

I post here my code, wait for your response.Watch my code, give me an idea on what's wrong.

I HAVE UPDATE MY CODE NOW..Please help me. Thanks in advance.

#include <opencv\cv.h>
#include <opencv\highgui.h>
#include <stdio.h>
#include <windows.h>
#include <process.h>
#include <queue>
#include <time.h>

using namespace std;
using namespace cv;


/*inizio della parte relativa alla coda thread safe*/

template<typename T>
class coda_concorr
{
private:
	std::queue<T> la_coda;
	HANDLE mutex;
public:
	bool complete;
	coda_concorr()
	{
		mutex = CreateMutex(NULL,FALSE,NULL);
		complete = false;
	}
	void push(T& data)
	{
		WaitForSingleObject(mutex,INFINITE);
		la_coda.push(data);
		ReleaseMutex(mutex);
	}
	bool vuota() const
	{
		bool RetCode;
		WaitForSingleObject(mutex,INFINITE);
		RetCode= la_coda.empty();
		ReleaseMutex(mutex);
		return RetCode;
	}

	bool try_pop(T& popped)
    {
        WaitForSingleObject(mutex,INFINITE);
        while (la_coda.empty())
        {
            if (complete)
            {
                ReleaseMutex(mutex);
                return false;
            }
            else
            {
                ReleaseMutex(mutex);
                Sleep(100); // FUTURE IMPROVEMENT
                WaitForSingleObject(mutex,INFINITE);
            }
        }
 
        popped = la_coda.front();
        la_coda.pop();
        ReleaseMutex(mutex);
        return true;
    }
};

//pacchetto per passaggio ai thread
struct Args
{
	coda_concorr<cv::Mat> in;
	coda_concorr<cv::Mat> *out; //puntatore a coda successiva
};




After declare the 3 functions that I've to launch:

//funzione grey
void grey (void *param){
	Mat temp1,temp2;
	Args* arg = (Args*)param;
	if(!arg->in.vuota()){
	while(arg->in.try_pop(temp1)){
	cvtColor(temp1,temp2,CV_BGR2GRAY);
	arg->out->push(temp2);
	   }
	}
	//flag completato
	arg->out->complete=true;
	_endthread();
	
}

//funzione sogliatura
void soglia(void *param){
	Mat temp1a,temp2a;
	Args* arg = (Args*)param;
		while(arg->in.try_pop(temp1a)){
		threshold(temp1a,temp2a,128,255,THRESH_BINARY);
		arg->out->push(temp2a);
		}
		//flag completato
	 arg->out->complete=true;
	_endthread();
}


//funzione erosione/dilate
void finitura(void *param){
	Mat temp1b,temp2b,temp2c;
	Args* arg = (Args*)param;
		while(arg->in.try_pop(temp1b)){
		erode(temp1b,temp2b,cv::Mat());
		//dilate(temp2b,temp2c,Mat());
		arg->out->push(temp2b);
		}
		//flag completato
	 arg->out->complete=true;
	_endthread();
}




then this is main:

int main()
{
	//dichiarazione delle due code principali
	coda_concorr<cv::Mat> ingresso;
	coda_concorr<cv::Mat> uscita;

	//clock
	clock_t avvio;
	clock_t fine;

	
	//array locali di ingresso e uscita
	Mat inn[10];
	Mat out;

	//assegnazione 10 immagini di prova
	inn[0]=imread("C:/OPENCV/Test/imgtest/bird1.jpg",1);
	inn[1]=imread("C:/OPENCV/Test/imgtest/bird2.jpg",1);
	inn[2]=imread("C:/OPENCV/Test/imgtest/bird3.jpg",1);
	inn[3]=imread("C:/OPENCV/Test/imgtest/pig1.jpg",1);
	inn[4]=imread("C:/OPENCV/Test/imgtest/pig2.jpg",1);
	inn[5]=imread("C:/OPENCV/Test/imgtest/pig3.jpg",1);
	inn[6]=imread("C:/OPENCV/Test/imgtest/spider1.jpg",1);
	inn[7]=imread("C:/OPENCV/Test/imgtest/spider2.jpg",1);
	inn[8]=imread("C:/OPENCV/Test/imgtest/spider3.jpg",1);
	inn[9]=imread("C:/OPENCV/Test/imgtest/Nutella.jpg",1);

	
	//dichiarazione code
	Args dati,dati2,dati3,dati4;

	//inizio a contare tempo
	avvio = clock();

	//Popolamento coda ingresso
	for(int i=0;i<=9;i++){
		dati.in.push(inn[i]);
	}
	//punta all'output successivo
	dati.out=&dati2.in;
	dati2.out=&dati3.in;
	dati3.out=&uscita;
	
	//dichiarazione delle maniglie
	HANDLE handle1,handle2,handle3;

	//dichiarazione dei threads
	handle1 = (HANDLE) _beginthread(grey,0,&dati);
	handle2 = (HANDLE) _beginthread(soglia,0,&dati2);
	handle3 = (HANDLE) _beginthread(finitura,0,&dati3);

	//join
	WaitForSingleObject(handle1,INFINITE);
	WaitForSingleObject(handle2,INFINITE);
	WaitForSingleObject(handle3,INFINITE);
	
	//fine registrazione tempo
	fine = clock()-avvio;

	double tempoimp = fine / (double)CLOCKS_PER_SEC;

//output di verifica
	while (dati3.out->try_pop(out)){
		imshow("immagine",out);
		waitKey(100);
	}
	
	cout<<endl<<"Cicli di clock: "<<fine<<endl;
	cout<<"Secondi trascorsi: "<<tempoimp<<endl;

	system("PAUSE");
	return 0;

}



I don't have any output...Can someone help me?

Enviroment is: Visual C++ 2010, OpenCV 2.4.3 on WIndows 7 64bit.

解决方案

I think I see that the blocking is caused by some bugs within your queue code:

//queue code
template<typename T>
class coda_concorr
{
private:
    ...
    // incorrect code:
    bool vuota() const
    {
        WaitForSingleObject(mutex,INFINITE);
        return la_coda.empty();
        ReleaseMutex(mutex);  // The mutex is never released
                              // as the function return in the previous line and
                              // ReleaseMutex is never called.
    }
    // fixed code:
    bool vuota() const
    {
        bool RetCode;
        WaitForSingleObject(mutex,INFINITE);
        RetCode = la_coda.empty();
        ReleaseMutex(mutex);
        return RetCode;
    }

 
    // incorrect code:
    bool try_pop(T& popped)
    {
        WaitForSingleObject(mutex,INFINITE);
        if (la_coda.empty()){
            return false; // same here, the mutex is not released
        }
        WaitForSingleObject(mutex,INFINITE); // This takes the mutex a second time
                                             // It would require a second ReleaseMutex()
                                             // for proper operation
        popped = la_coda.front();
        la_coda.pop();
        ReleaseMutex(mutex);
        return true;
    }
    // fixed code:
    bool try_pop(T& popped)
    {
        WaitForSingleObject(mutex,INFINITE);
        if (la_coda.empty()){
            ReleaseMutex(mutex);
            return false;
        }
        popped = la_coda.front();
        la_coda.pop();
        ReleaseMutex(mutex);
        return true;
    }
};



<V2> Another bug:
Here the incorrect code with explanation, see underlined lines:

int main()
{
	coda_concorr<cv::Mat> ingresso;
	coda_concorr<cv::Mat> coda1;
	coda_concorr<cv::Mat> coda2;
	coda_concorr<cv::Mat> uscita;
 
	
//assing second queue	
dati.out=coda1; // This creates a copy of coda1	
...
	//share part that don't WORK
	dati2.in=coda1; // This creates a second copy of coda1,
                         // it does not reference the same queue
	dati2.out=coda2;
...
 
}


So both threads are seeing different copies of coda1 while you would like to have them see the same instance, coda1.
Here a proposal to fix the issue, make the out queue a pointer so you can link Args structures:

struct Args
{
	coda_concorr<cv::Mat> in;
	coda_concorr<cv::Mat> *out; // this is a pointer now, make it point to the
                                     // next queue in sequence
};


void grey (void *param){
...
            arg->out->push(temp2);
        }
        arg->out->complete=true;
...
}
//threshold funct
void soglia(void *param){
...
            arg->out->push(temp2a);
        }
    }
    arg->out->complete=true;
    _endthread();
}


int main()
{
...
	coda_concorr<cv::Mat> coda1; // Not needed
...
//assing second queue	
dati.out=&dati2.in; // This stores a pointer to the next queue	
...

	dati2.in=&coda1; // Not needed as the queues are linked, see above
	dati2.out=&coda2;
...
	//output
	while (dati2.out->try_pop(out)){
		imshow("immagine",out);
		waitKey(100);
	}
...
}



Also there is a startup issue: When the second thread starts and its input queue is empty, it immediately exits. The same happens when the input queue becomes empty during execution (i.e. the second thread executes faster than the first one).
You have to change the design of your queuing in way that you can distinguish a "queue empty due to all work done" from a "queue empty due to previous step not yet finished".
One option would be to have a queue state added that is set when the producer is done providing data, so your thread only terminates when the queue is empty and the producer has indicated that it will not provide further data, otherwise the thread waits until the queue becomes not-empty.

<V3> Add the waiting in the queue try_pop method, this should get rid of the immediate termination at startup issue:

bool try_pop(T& popped)
{
    WaitForSingleObject(mutex,INFINITE);
    while (la_coda.empty())
    {
        if (complete)
        {
            ReleaseMutex(mutex);
            return false;
        }
        else
        {
            ReleaseMutex(mutex);
            Sleep(100); // FUTURE IMPROVEMENT: This can be improved by creating
                        // an event signaling that the queue is not empty.
                        // I'll keep it like this for simplicity for now.
                        // I try to avoid mixing functionality re-work with
                        // performance improvements.
            WaitForSingleObject(mutex,INFINITE);
        }
    }

    popped = la_coda.front();
    la_coda.pop();
    ReleaseMutex(mutex);
    return true;
}


After more try, this is the solution:

/*programma di prova gestione thread e OpenCV con timer di evalutazione tempo 

impiegato v.1.0 */

#include <opencv\cv.h>
#include <opencv\highgui.h>
#include <stdio.h>
#include <windows.h>
#include <process.h>
#include <queue>
#include <time.h>

using namespace std;
using namespace cv;


/*inizio della parte relativa alla coda thread safe*/

template<typename T>
class coda_concorr
{
private:
	std::queue<T> la_coda;
	HANDLE mutex;
public:
	bool complete;
	coda_concorr()
	{
		mutex = CreateMutex(NULL,FALSE,NULL);
		complete = false;
	}
	void push(T& data)
	{
		WaitForSingleObject(mutex,INFINITE);
		la_coda.push(data);
		ReleaseMutex(mutex);
	}
	bool vuota() const
	{
		bool RetCode;
		WaitForSingleObject(mutex,INFINITE);
		RetCode= la_coda.empty();
		ReleaseMutex(mutex);
		return RetCode;
	}
	bool try_pop(T& popped)
    {
        WaitForSingleObject(mutex,INFINITE);
        while (la_coda.empty()){
            //ReleaseMutex(mutex);
            //Sleep(100);
			//WaitForSingleObject(mutex,INFINITE);
			return false;
        }
        popped = la_coda.front();
        la_coda.pop();
        ReleaseMutex(mutex);
        return true;
    }
};

//pacchetto per passaggio ai thread
struct Args
{
	coda_concorr<cv::Mat> in;
	coda_concorr<cv::Mat> *out; //puntatore a coda successiva
};

//funzione grey
void grey (void *param){
	Mat temp1,temp2;
	int add = 0;
	Args* arg = (Args*)param;
	while(arg->in.try_pop(temp1)){
	cvtColor(temp1,temp2,CV_BGR2GRAY);
	arg->out->push(temp2);
	add++;
	   }
	//flag completato
	arg->out->complete=true;
	cout<<"Thread 1 terminato con "<<add<<" elaborazioni."<<endl;
	_endthread();
	
}

//funzione sogliatura
void soglia(void *param){
	Mat temp1a,temp2a;
	int add=0;
	Args* arg = (Args*)param;
	while(arg->in.vuota()){
	Sleep(50);
	}
	while(arg->in.try_pop(temp1a)){
		threshold(temp1a,temp2a,128,255,THRESH_BINARY);
		arg->out->push(temp2a);
		add++;
		}
		//flag completato
	 arg->out->complete=true;
	 cout<<"Thread 2 terminato con "<<add<<" elaborazioni."<<endl;
	_endthread();
}


//funzione erosione/dilate
void finitura(void *param){
	Mat temp1b,temp2b,temp2c;
	int add = 0;
	Args* arg = (Args*)param;
	while(arg->in.vuota()){
	Sleep(40);
	}
	while(arg->in.try_pop(temp1b)){
		erode(temp1b,temp2b,cv::Mat());
		dilate(temp2b,temp2c,Mat());
		arg->out->push(temp2c);
		add++;
		}
		//flag completato
	 arg->out->complete=true;
	 cout<<"Thread 3 terminato con "<<add<<" elaborazioni."<<endl;
	_endthread();
}



//main
int main()
{
	//dichiarazione delle due code principali
	coda_concorr<cv::Mat> ingresso;
	coda_concorr<cv::Mat> uscita;

	//clock
	clock_t avvio;
	clock_t fine;

	
	//array locali di ingresso e uscita
	Mat inn[10];
	Mat out;
	
	//inizio a contare tempo
	avvio = clock();

	//assegnazione 10 immagini di prova
	inn[0]=imread("C:/OPENCV/Test/imgtest/bird1.jpg",1);
	inn[1]=imread("C:/OPENCV/Test/imgtest/bird2.jpg",1);
	inn[2]=imread("C:/OPENCV/Test/imgtest/bird3.jpg",1);
	inn[3]=imread("C:/OPENCV/Test/imgtest/pig1.jpg",1);
	inn[4]=imread("C:/OPENCV/Test/imgtest/pig2.jpg",1);
	inn[5]=imread("C:/OPENCV/Test/imgtest/pig3.jpg",1);
	inn[6]=imread("C:/OPENCV/Test/imgtest/spider1.jpg",1);
	inn[7]=imread("C:/OPENCV/Test/imgtest/spider2.jpg",1);
	inn[8]=imread("C:/OPENCV/Test/imgtest/spider3.jpg",1);
	inn[9]=imread("C:/OPENCV/Test/imgtest/Nutella.jpg",1);

	
	//dichiarazione code
	Args dati,dati2,dati3;

	

	//Popolamento coda ingresso
	for(int i=0;i<=9;i++){
		dati.in.push(inn[i]);
	}
	//punta all'output successivo
	dati.out=&dati2.in;
	dati2.out=&dati3.in;
	dati3.out=&uscita;
	//dichiarazione delle maniglie
	HANDLE handle1,handle2,handle3;

	//dichiarazione dei threads
	handle1 = (HANDLE) _beginthread(grey,0,&dati);
	handle2 = (HANDLE) _beginthread(soglia,0,&dati2);
	handle3 = (HANDLE) _beginthread(finitura,0,&dati3);

	//join
	WaitForSingleObject(handle1,INFINITE);
	WaitForSingleObject(handle2,INFINITE);
	WaitForSingleObject(handle3,INFINITE);
	
	
	//fine registrazione tempo
	fine = clock()-avvio;

	double tempoimp = fine / (double)CLOCKS_PER_SEC;

//output di verifica
	/*
	while(dati3.out->try_pop(out)){
		imshow("immagine",out);
		waitKey(100);
	}*/
	
	cout<<endl<<"Cicli di clock: "<<fine<<endl;
	cout<<"Secondi trascorsi: "<<tempoimp<<endl;
	system("PAUSE");
	
	
	return 0;

}



This manage 3 threads that works on shared elements, in 4 queues.


这篇关于多个图像队列,多个线程......怎么样?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆