2014-10-15 2 views
0

Я застрял в неприятной проблеме оптимизации в своем программном обеспечении для анализа КТ. Я использую ITK для выполнения тяжелой фильтрации данных, и, наконец, используя itk binaryImageToshapeLabelMapFilter, я выделяю отдельные области и сохраняю координаты каждой точки, принадлежащей им, в текстовый файл (тогда это будет вход другого отдельного программное обеспечение уже сделано)записывая данные метки ITK в файл как можно быстрее

Проблема заключается в том, что фаза записи в файл занимает в случае очень больших областей намного больше времени, чем сама фильтрация (у меня случилось, что некоторые данные были отфильтрованы за 30 минут и записаны в файл в другой дополнительный час).

В следующем коде я уже пытался избежать промывки в конце каждой строки («\ n», а не endl), но ничего не меняется. Есть ли у вас какие-либо идеи о том, как я могу значительно улучшить запись в файл этих данных?

С уважением, Emiliano

ofstream outFile; 
string labelsFile = subFolderPath+"/regionLabels_"+volumeCompleteName+".lri"; 
outFile.open(labelsFile.c_str()); 
outFile << "LabelIndexes - v1.0" << "\n"; 
outFile << "Dataset Origin : "<< originX << "," << originY << "," << originZ << "\n"; 

int cloud = 0; 

for(unsigned int i = 0; i < binaryImageToShapeLabelMapFilter->GetOutput()->GetNumberOfLabelObjects(); i++){ 
    BinaryImageToShapeLabelMapFilterType::OutputImageType::LabelObjectType* labelObject = binaryImageToShapeLabelMapFilter->GetOutput()->GetNthLabelObject(i); 
    if(labelObject->GetNumberOfPixels()>4500){ 
     outFile << "Region " << cloud << "\n"; 
     outFile << "Centroid " << labelObject->GetCentroid() << "\n"; 
     outFile << labelObject->GetNumberOfPixels() << "\n"; 
     for(int j=0;j<labelObject->Size();j++){ 
      //Only save the labels for voxels at least 2 voxels distant from the edge of the dataset 
      if(labelObject->GetIndex(j)[0]>2 && labelObject->GetIndex(j)[1]>2 && labelObject->GetIndex(j)[2]>2){ 
       if(labelObject->GetIndex(j)[0]<(maxX-2) && labelObject->GetIndex(j)[1]<(maxY-2) && labelObject->GetIndex(j)[2]<(maxZ-2)){ 
        outFile << labelObject->GetIndex(j) << "\n"; 
       } 
      } 
     } 
     cloud++; 
    } 
} 
outFile << "EndOfFile" << "\n"; 
outFile.flush(); 
outFile.close(); 
cout << "All labels indices saved to file : " << labelsFile << endl; 

Один последний дополнительный вопрос. У меня не было времени попробовать с набором данных, который уже был отфильтрован с помощью более старого метода, но последние 2, которые я фильтровал с новым, кажется, что половина каждого региона теряется. Я злоупотребляю индексами, используя это следующим образом:

FILE* fout = fopen(labelsFile.c_str(), "w"); 
fprintf(fout,"LabelIndexes - v1.0\n"); 
fprintf(fout,"Dataset Origin : %d,%d,%d\n",originX,originY,originZ); 

for(unsigned int i = 0; i < binaryImageToShapeLabelMapFilter->GetOutput()->GetNumberOfLabelObjects(); i++){ 
    BinaryImageToShapeLabelMapFilterType::OutputImageType::LabelObjectType* labelObject = binaryImageToShapeLabelMapFilter->GetOutput()->GetNthLabelObject(i); 
    if(labelObject->GetNumberOfPixels()>4500){ 
     fprintf(fout,"Region %d \n",cloud); 
     double c1 = labelObject->GetCentroid()[0]; 
     double c2 = labelObject->GetCentroid()[0]; 
     double c3 = labelObject->GetCentroid()[0]; 
     fprintf(fout,"Centroid [%f, %f, %f]\n",c1,c2,c3); 
     fprintf(fout,"%u\n",(long)labelObject->GetNumberOfPixels()); 
     for (int l = 0; l < labelObject->GetNumberOfLines(); ++l){ 
      LabelObjectLine<3> line = labelObject->GetLine(l); 
      OutputImageType::IndexType startIndex = line.GetIndex(); 
      int i1 = startIndex[0]; 
      int i2 = startIndex[1]; 
      int i3 = startIndex[2]; 
      if(i1>2 && i2>2 && i3>2 && i1<(maxX-2) && i2<(maxY-2) && i3<(maxZ-2))fprintf(fout,"[%d, %d, %d]\n",i1,i2,i3); 
     } 
     cloud++; 
    } 
} 

ответ

1

Вы пробовали профилировать код? Вероятно, это скажет вам, где будет время вычисления.

Однако, я думаю, что это происходит в многочисленных вызовах labelObject :: GetIndex. Если вы посмотрите на реализацию LabelObject :: GetIndex, вы увидите, что он находится в порядке количества строк в объекте метки. Вы называете это 7 раз за индекс. Просто сохраните результаты этого вызова функции в переменной, что даст вам 7-кратное ускорение.

Однако рассмотрим вычислительную стоимость цикла! Цикл над числом индексов в объекте метки, а затем коэффициент умножения вызова GetIndex. Это приводит к тому, что порядок вычисления значительно превышает количество индексов в объекте метки.

Лучше было бы использовать метод LabelObject :: GetLine и алгоритм, основанный на линии:

for (l = 0; l < labelObject.GetNumberOfLines(); ++l) 
    line = labelObject.GetLine(l) 
    startIndex = line.GetIndex(); 
    endIndex = startIndex; 
    endIndex[0] = endIndex[0] + line.GetLength() - 1 
    // determine which indexes to print. 

позволит снизить вычислительную сложность вплоть до количества строк. Меня не удивило бы, если бы это заняло меньше минуты с этим заявлением.

+0

я попытаюсь сразу же, вчера я пытался переписать все это в C (fprintf, и т.д.) и буферные индексы тоже, но результаты не намного более обнадеживающие. Я дам вам знать как можно скорее! Благодаря! – drHogan

+0

Вы полностью сделали свой день с этим решением. И, сделав мой последний день перед праздником в неделю, вы сделали меня всерьез счастливым и более расслабленным! мы действительно снизились до менее 1 минуты. Ура! – drHogan

+0

Я редактировал вопрос, чтобы задать дополнительную информацию – drHogan

0

В конце концов я злоупотреблял индексами, решение blowekamp в противном случае было оптимальным. Вот рабочая версия цикла (взял некоторую неприятную отладку, чтобы получить эту проблему):

for(unsigned int i = 0; i < binaryImageToShapeLabelMapFilter->GetOutput()->GetNumberOfLabelObjects(); i++){ 
     BinaryImageToShapeLabelMapFilterType::OutputImageType::LabelObjectType* labelObject = binaryImageToShapeLabelMapFilter->GetOutput()->GetNthLabelObject(i); 
     if(labelObject->GetNumberOfPixels()>4500){ 
      fprintf(fout,"Region %d \n",cloud); 
      double c1 = labelObject->GetCentroid()[0]; 
      double c2 = labelObject->GetCentroid()[1]; 
      double c3 = labelObject->GetCentroid()[2]; 
      fprintf(fout,"Centroid [%f, %f, %f]\n",c1,c2,c3); 
      fprintf(fout,"%u\n",(long)labelObject->GetNumberOfPixels()); 
      for (int l = 0; l < labelObject->GetNumberOfLines(); ++l){ 
       LabelObjectLine<3> line = labelObject->GetLine(l); 
       OutputImageType::IndexType startIndex = line.GetIndex(); 
       long lastIndex = startIndex[0]+line.GetLength(); 
       for(OutputImageType::IndexType idx = startIndex;idx[0]<lastIndex;idx[0]++){ 
        int i1 = idx[0]; 
        int i2 = idx[1]; 
        int i3 = idx[2]; 
        if(i1>2 && i2>2 && i3>2 && i1<(maxX-2) && i2<(maxY-2) && i3<(maxZ-2))fprintf(fout,"[%d, %d, %d]\n",i1,i2,i3); 
       } 
      } 
      cloud++; 
     } 
    } 
fprintf(fout,"EndOfFile"); 
fclose(fout); 
Смежные вопросы