Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
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):
 
#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 11-Jun-13 3:15am
Edited 17-Jun-13 3:20am
v8
Comments
pasztorpisti at 12-Jun-13 7:48am
   
An obvious bug is that try_pop() doesn't always release the mutex.
pasztorpisti at 12-Jun-13 8:56am
   
Are you serious that you can't fix it after my hint???
pasztorpisti at 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

Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

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.
  Permalink  
Comments
Domus1919 at 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 at 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 at 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 at 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)

  Print Answers RSS
0 OriginalGriff 406
1 /\jmot 180
2 Suraj Sahoo | Coding Passion 170
3 BillWoodruff 159
4 Afzaal Ahmad Zeeshan 154
0 OriginalGriff 8,344
1 Sergey Alexandrovich Kryukov 7,407
2 DamithSL 5,634
3 Maciej Los 5,024
4 Manas Bhardwaj 4,986


Advertise | Privacy | Mobile
Web02 | 2.8.1411023.1 | Last Updated 17 Jun 2013
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100