Click here to Skip to main content
15,880,469 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
Hi all,
I have create this program to manage multiple threads multiple queues, for elaborate a series of images. Every thread pop an image from a queue, works on it, and push it in output queue.

Thanks to different advices received here from other users, I have create this code, but the threads behaviour it's strange: threads 1, 2, 3 don't elaborate all images that push thread 0.

I have check and re-check code, but I don't know where the problem is. Can someone help me? Help me to find where is the problem?

This is the code (UPDATED):

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

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;
	}
	~coda_concorr()
	{
              ReleaseMutex(mutex);
         }
void push(T& data)
	{
		WaitForSingleObject(mutex,INFINITE);
		 la_coda.push(data);
		ReleaseMutex(mutex);
	}
	bool vuota() const
	{
		
                WaitForSingleObject(mutex,INFINITE);
                bool RetCode = la_coda.empty();
                ReleaseMutex(mutex);
		return RetCode;
	}
	bool try_pop(T& popped)
    {
       WaitForSingleObject(mutex,INFINITE);       
       while (la_coda.empty()){
            ReleaseMutex(mutex);
            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 di popolamento coda
void puts (void* param){
	Args* arg = (Args*)param;
	int i=0;
    Mat image;
	while(arg->in.vuota()){
		Sleep(0.01);
		cout<<endl<<"Thread 0 in attesa di dati..elaborazioni fatte "<<i<<endl;
	}
	while(arg->in.try_pop(image)){
		arg->out->push(image);	
		i++;
	}
	//flag completato
	arg->out->complete=true;
	cout<<endl<<"Thread 0 terminato con "<<i<<" elaborazioni."<<endl;
	_endthread();
}

//funzione grey
void grey (void *param){
	Mat temp1,temp2;
	int add = 0;
	Args* arg = (Args*)param;
	//se la trova vuota
	while(arg->in.vuota()){
		Sleep(0.01);
		cout<<endl<<"Thread 1 in attesa di dati..elaborazioni fatte "<<add<<endl;
	}
	while(arg->in.try_pop(temp1)){
		threshold(temp1,temp2,128,255,THRESH_BINARY);
		arg->out->push(temp2);
		add++;
		}
		
	//flag completato
	arg->out->complete=true;
	cout<<endl<<"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(0.01);
		cout<<endl<<"Thread 2 in attesa..elaborazioni fatte "<<add<<endl;
	}
	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<<endl<<"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(0.01);
		cout<<endl<<"Thread 3 in attesa..elaborazioni fatte "<<add<<endl;
	}
	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<<endl<<"Thread 3 terminato con "<<add<<" elaborazioni."<<endl;
	_endthread();
}

//funzione tracciamento contorno immagini
void contorno (void *param){
	Mat tempA,tempB;
	Args* arg = (Args*)param;
}

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

	//array locali di ingresso e uscita
	Mat out;
	
	//dichiarazione variabili per contatore
	LARGE_INTEGER count1, count2, freq;
	double elapsed;

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

	cout<<endl<<"Elaborazione di immagini con 3 threads concorrenti e code dinamiche."<<endl;
	cout<<endl<<"Avvio elaborazione.."<<endl;

	//avvio contatori
	QueryPerformanceFrequency(&freq);	
	QueryPerformanceCounter (&count1);
	
        Mat temp[10];
	for(int i=0;i<10;i++){
		temp[i] = imread("C:/OPENCV/Test/imgtest/bird1.jpg",1);
		ingresso.push(temp[i]);
	}
	//puntatori per il passaggio alla coda successiva
	init.in=ingresso;
	init.out=&dati.in;
	dati.out=&dati2.in;
	dati2.out=&dati3.in;
	dati3.out=&uscita;

	//dichiarazione delle handle
	HANDLE handle0,handle1,handle2,handle3;

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

	cout<<endl<<"..Join dei threads..."<<endl;
	//join
	WaitForSingleObject(handle0,INFINITE);
	WaitForSingleObject(handle1,INFINITE);
	WaitForSingleObject(handle2,INFINITE);
	WaitForSingleObject(handle3,INFINITE);
	
	//chiusura contatori
	QueryPerformanceCounter (&count2);
	
//output di verifica disabilitato ora
	/*while(dati3.out->try_pop(out)){
		imshow("immagine",out);
		waitKey(50);
	}*/

	//calcolo tempo trascorso
	elapsed = (count2.QuadPart - count1.QuadPart) * 1000.0 / freq.QuadPart;
	//visualizzo
	cout <<endl<<"Tempo di esecuzione approssimativo: " <<elapsed<<" ms."<<endl;
    system("PAUSE");
	return 0;
}


How force threads next to zero, that always have to "check queue even it's empty, and works for all pushed images"? I'm desperate...the problem is in queue, in thread function or somewhere? Because every launch of program, different result...why?

Thanks in advance for your attention...please help me!!
Posted
Updated 17-Jun-13 2:20am
v8
Comments
pasztorpisti 12-Jun-13 7:48am    
An obvious bug is that try_pop() doesn't always release the mutex.
pasztorpisti 12-Jun-13 8:56am    
Are you serious that you can't fix it after my hint???
pasztorpisti 12-Jun-13 10:58am    
Releasing it before every return statement nut just before the return statement at the end of the function body.

1 solution

Quote:
for(int i=0;i<10;i++){
Mat temp[10];
temp[i] = imread("C:/OPENCV/Test/imgtest/bird1.jpg",1);
ingresso.push(temp[i]);
}

I guess is not related with the 'strange behaviour', however there are mistakes in the above lines, namely you are re-creating the temp array at each iteration, and, worse, it is a temporary you're passing by reference to the push function.
 
Share this answer
 
Comments
Domus1919 11-Jun-13 9:32am    
This piece is only for populating a queue now with 10 images...in future the images will be acquired from a webcam...The problem isn't in that code, because I've introduced it also for create 10 images (the same images, but it isn't a problem now) for works on..
CPallini 11-Jun-13 9:35am    
Anyway you have to fix it: it is really simple, put the
Mat temp[10];
outside (before) the for loop.
Domus1919 11-Jun-13 9:45am    
ok..I've updated the code...but my problem remain..how can solve it? Threads don't work well
Domus1919 17-Jun-13 8:26am    
nobody can help me?

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900