【问题标题】:pthread parallel processingpthread 并行处理
【发布时间】:2012-07-12 20:01:57
【问题描述】:

在线程上需要紧急帮助:这里的目标是 separtemask 将获取每个图像并分离不同的轮廓,并且对于图像中的每个轮廓,它将调用 handleobject 线程。所以每个for循环都会调用handeobject线程。但是,需要在每个线程中传递对象索引变量。但是只传递了 objectndex 的最后一个值,这是因为 speratemask 函数循环并替换了 obj.objindx 的值,并且只有 obj.objindx 的最后一个值是 传递给所有线程。反正有没有通过每个objectindex 句柄对象中的值。如果我们取消注释 pthread_join(tid[objectIndex],NULL); ,代码运行良好。但它不会给出并行程序

void separateMask(IplImage *maskImg)
{    
  for(r = contours; r != NULL; r = r->h_next)
  {
    cvSet(objectMaskImg, cvScalarAll(0), NULL);
    CvScalar externalColor = cvScalarAll(0xff);
    CvScalar holeColor = cvScalarAll(0x00);
    int maxLevel = -1; 
    int thinkness = CV_FILLED; 
    int lineType = 8; /* 8-connected */
    cvDrawContours(objectMaskImg, r, externalColor, holeColor, maxLevel, thinkness,lineType, cvPoint(0,0));;
    obj.objectMaskImg1[objectIndex]=(IplImage *) malloc(sizeof(IplImage));
    obj.objectMaskImg1[objectIndex]=objectMaskImg;
    obj.objindx=objectIndex;
    obj.intensityOut1=intensityOut;
    obj.tasOut1=tasOut;
    pthread_create(&tid[objectIndex],NULL,handleObject,(void *)&obj);
    //pthread_join(tid[objectIndex],NULL);
    printf("objectindx %d\n",obj.objindx);
    objectIndex++;

  }
  // cvReleaseImage(&objectMaskImg);
  //cvReleaseMemStorage(&storage);
  printf("Exitng Separatemask\n");

}


void* handleObject(void *arg)
{
  int i, j;
  handle *hndl;
  hndl=(handle *) malloc(sizeof(handle));
  hndl=(handle*)arg;
  pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;
  pthread_mutex_lock(&lock);
  IplImage *pImg;
  float statistics_ratio[3][9];
  pthread_t tid3;
  tas3 tas2;
  pImg = cvLoadImage("image.tif", CV_LOAD_IMAGE_ANYCOLOR | CV_LOAD_IMAGE_ANYDEPTH);
  if(pImg == NULL)
  {
    fprintf(stderr, "Fail to load image %s\n", "tiff file");
    return ;
  }
  tas2.pImg1=pImg;
  printf("tst%d\n",hndl->objindx);
  tas2.x=hndl->objindx;
  tas2.objectMaskImg1=hndl->objectMaskImg1[tas2.x];
  tas2.statistics_ratio[3][9]=statistics_ratio[3][9];
  double mean = average_intensity(pImg, tas2.objectMaskImg1); 
  int total = total_white(pImg, tas2.objectMaskImg1);
  pthread_mutex_unlock(&lock);

  printf("Exiting handle object thread_id %d\n\n", pthread_self());
}

【问题讨论】:

  • 我还有一个问题。我附加的代码仅识别未标记的轮廓,仅在 1 和零标记的掩码上执行。我的输入蒙版图像实际上标有每个轮廓的 1,2,3,4....。例如,第一个轮廓被标记为 1,第二个被标记为 2,而不是所有轮廓只有 1。如何修改我的代码,以便我可以根据标记的图像分别分离每个轮廓。示例轮廓 1 是一个单独的图像,轮廓 2 是另一个单独的图像。

标签: opencv pthreads


【解决方案1】:

这个函数似乎有问题

void* handleObject(void *arg)

首先

    pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;
    pthread_mutex_lock(&lock);

这是一个本地创建的互斥锁 - 但在线程函数中创建。所以你锁定它,但既然没有其他东西可以看到互斥锁,你为什么需要它???如果没有其他线程可以看到它,它不会提供同步功能。 其次

    float statistics_ratio[3][9];
    pthread_t tid3;
    tas3 tas2;
    pImg = cvLoadImage("image.tif", CV_LOAD_IMAGE_ANYCOLOR | CV_LOAD_IMAGE_ANYDEPTH);
    if(pImg == NULL){
        fprintf(stderr, "Fail to load image %s\n", "tiff file");
        return ;
    }
    tas2.pImg1=pImg;
    printf("tst%d\n",hndl->objindx);
    tas2.x=hndl->objindx;
    tas2.objectMaskImg1=hndl->objectMaskImg1[tas2.x];
    tas2.statistics_ratio[3][9]=statistics_ratio[3][9];

您创建了一个本地未初始化的二维浮点数组statistics_ratio,对其不做任何操作,然后将其分配给另一个本地创建的对象成员。这似乎毫无意义,另一个 pthread 实例 tid3 的声明也是如此。

这并不重要,因为没有其他东西可以看到线程,但是如果 pImg == NULL 没有首先解锁互斥锁,你会从这个函数内部返回。

很难看出您的代码为什么不起作用或它的用途是什么,但也许上面突出显示的内容可能会有所帮助。您在线程函数中创建了许多未使用的局部变量。我不确定你是否需要其中一些是全局的——尤其是互斥锁(如果你确实需要一个)。

【讨论】:

  • 感谢所有回复。我还有一个问题。我附加的代码仅识别未标记的轮廓,仅在 1 和零标记的掩码上执行。我的输入蒙版图像实际上标有每个轮廓的 1,2,3,4....。例如,第一个轮廓被标记为 1,第二个被标记为 2,而不是所有轮廓只有 1。如何修改我的代码,以便我可以根据标记的图像分别分离每个轮廓。示例轮廓 1 是一个单独的图像,轮廓 2 是另一个单独的图像。
  • 第二个答案比第一个更集中。但两者在不同的观点上都是正确的。感谢两者。
【解决方案2】:

我认为您最初的问题是您正在重用您传递给创建的线程的obj 结构,因此您将遇到数据竞争,其中刚刚创建的线程将读取已被用于的数据覆盖的信息另一个线程。

创建线程的循环具有以下结构:

for(r = contours; r != NULL; r = r->h_next)
{
    // initialize obj with information for the thread
    // ...

    // create a thread and pass it a pointer to obj
    pthread_create(&tid[objectIndex],NULL,handleObject,(void *)&obj);

    // some other bookkeeping
}

既然你在下一次循环迭代时立即重新初始化 obj,谁知道线程函数会得到什么数据?这就是为什么如果你在创建线程后加入线程,事情就会起作用的原因 - obj 结构保持稳定,因为循环阻塞直到线程完成。

将循环更改为如下所示:

for(r = contours; r != NULL; r = r->h_next)
{
    // instead of using `obj`, allocate a struct using malloc
    handle* threaddata = malloc(sizeof(handle); // note: I'm not sure if `handle` is the right type

    // initialize *threaddata with information for the thread
    // ...

    // create a thread and pass it the threaddata pointer
    pthread_create(&tid[objectIndex],NULL,handleObject,threaddata);

    // some other bookkeeping
}

然后free()线程函数中的数据在完成后使用(即线程创建代码创建并初始化数据块,然后将其所有权传递给线程)。

请注意,这可能不像通常那样简单,因为看起来您的 obj 结构中已经包含一些每个线程的信息(objectMaskImg1 元素看起来是一个数组,每个元素都是预期的对于单独的线程)。因此,您可能还需要对数据结构进行一些重构。

最后,还有其他几个彻底的错误,例如立即覆盖指向 malloc() 分配的块的指针:

obj.objectMaskImg1[objectIndex]=(IplImage *) malloc(sizeof(IplImage));
obj.objectMaskImg1[objectIndex]=objectMaskImg;

hndl=(handle *) malloc(sizeof(handle));
hndl=(handle*)arg;

除了 mathematician1975 (http://stackoverflow.com/a/11460092/12711) 提到的 handleObject() 线程函数中毫无意义地使用互斥锁。

线程函数中的相当一部分代码(复制或尝试在本地复制数据,互斥锁)似乎是在没有真正了解问题所在的情况下尝试解决问题的东西。我认为您确实需要了解各种数据的存储位置、如何复制它(而不是仅仅复制指向它的指针)以及如何管理数据的所有权。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-14
    • 1970-01-01
    • 1970-01-01
    • 2014-11-29
    • 1970-01-01
    • 2017-01-27
    • 1970-01-01
    相关资源
    最近更新 更多