3

我必须创建一个程序,该程序使用线程用 OpenCV 精心制作 10 张图像。为此,我认为将工作分解为 3 个线程,并使用 4 个队列来包含初始 10 个图像,以及在细化过程中的中间图像。

这是我必须做的图表:

线程和数据floyd的关系图

现在,我认为为此我可以使用 std::queue 来管理队列,因此将队列对象传递给每个线程。问题是:

1)我必须用push、pop方法创建一个类“队列”线程安全,对吧?使用互斥变量来重新定义多线程和同步...

2) Evey 线程在 2 个队列上工作:从一个队列 POP 和 PUSH 到另一个队列。所以每个线程都是消费者/生产者......如何将输入和输出中队列类的两个对象指针传递给每个线程?(有两个对象,所以有两个指针)?

使用我的代码,第二个线程看到输入队列总是空的。有人可以帮助我吗?给我一个关于这个问题的想法?

这是我的代码,不适用于两个线程(第二个线程看到输入队列总是空的:

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

 using namespace std;
 using namespace cv;


/* thread safe queue*/

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);
        if (la_coda.empty())
        {
            ReleaseMutex(mutex);
            return false;
        }
        popped = la_coda.front();
        la_coda.pop();
        ReleaseMutex(mutex);
        return true;
    }
};

//packet passing to threads
struct Args
{
    coda_concorr<cv::Mat> in;
    coda_concorr<cv::Mat> out;
};

//grey decrease funct
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);
        }
    arg->out.complete=true;
    }
    else{
        Sleep(100);
    }
    _endthread();
}
//threshold funct
void soglia(void *param){
    Mat temp1a,temp2a;
    Args* arg = (Args*)param;
    if(arg->in.vuota()){
    while(arg->in.vuota()){
            cout<<endl<<"Coda vuota"<<endl;
            Sleep(100);
        }
    }
    else{
        while(arg->in.try_pop(temp1a)){
        threshold(temp1a,temp2a,128,255,THRESH_BINARY);
        arg->out.push(temp2a);
            }
     }
     arg->out.complete=true;
    _endthread();
}
int main()
{
    coda_concorr<cv::Mat> ingresso;
    coda_concorr<cv::Mat> coda1;
    coda_concorr<cv::Mat> coda2;
    coda_concorr<cv::Mat> uscita;


    //in array
    Mat inn[10];
    Mat out;

    //assing images
    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);



    Args dati,dati2;
    //populating queue 
    for(int i=0;i<=9;i++){
        dati.in.push(inn[i]);
    }
//assing second queue   
dati.out=coda1;

    HANDLE handle1,handle2;

    handle1 = (HANDLE) _beginthread(grey,0,&dati);

    //share part that don't WORK
    dati2.in=coda1;
    dati2.out=coda2;

    handle2 = (HANDLE) _beginthread(soglia,0,&dati2);



    WaitForSingleObject(handle2,INFINITE);
    WaitForSingleObject(handle1,INFINITE);



    //output
    while (dati2.out.try_pop(out)){
        imshow("immagine",out);
        waitKey(100);
    }

    system("PAUSE");
    return 0;

}

在此先感谢您的时间。

4

2 回答 2

2

对于第 1 点/,您确实需要一些同步对象,或使用消息传递库,如评论中所建议的那样。

对于第 2 点/,您的多线程库可以为您提供将参数传递给线程函数的能力。

  • 声明一个包含对两个队列的引用的小类,一个队列,一个队列。
  • 在您的主程序中,为每个线程实例化您需要的所有队列和一个小类的实例,并将它们传递给每个线程的输入输出队列。
  • 启动您的线程,将小类的实例作为回调函数参数传递。您现在可以访问每个线程进出队列。

编辑(因为你编辑了你的问题)

bool vuota() const
{
    WaitForSingleObject(mutex,INFINITE);
    return la_coda.empty();
    ReleaseMutex(mutex);
}

是错的。

bool vuota() const
{
    WaitForSingleObject(mutex,INFINITE);
    bool tmp = la_coda.empty();
    ReleaseMutex(mutex);
    return tmp;
}

同样的情况发生在bool try_pop(T& popped). 在离开函数之前检查您是否释放了互斥锁。

于 2013-05-31T07:38:42.523 回答
1

如果线程 2 等待线程 1 工作,而线程 3 等待线程 2,那么线程没有意义。一个线程运行所有三个函数是最好的方法。

现在,您假设线程 2 正在处理第一个图像,而 T1 可以处理第二个图像。但...

在这种情况下

  • 线程 2 和 3 必须等待第一张图片
  • 如果任何线程总是比其他线程快,它将停止等待工作。

这里正确的做法是只使用两个队列(In/Out),并有多个线程来分析不同的图像。因此,T1, T2, .. Tn 将从 IN 中获取图像,对其进行完全处理,然后将结果存储在 OUT 中。

甚至有可能摆脱结果队列,并将它们直接发送到某个地方(文件、显示器等)。只要确保同步目标对象。

于 2013-05-31T11:59:38.783 回答