以尽可能最快的方式将ITK标签数据写入文件

时间:2014-10-15 10:17:00

标签: file optimization ofstream itk

我的CT分析软件中存在一个令人讨厌的优化问题。我使用ITK对数据执行一些重度过滤,最后通过使用itk binaryImageToshapeLabelMapFilter我隔离一些单独的区域并将属于它们的每个点的坐标保存到文本文件中(然后将其作为另一个单独的输入)已经制作的软件)

问题是,写入文件的阶段,在非常大的区域的情况下,比过滤本身要长得多(我碰巧在30分钟内过滤了一些数据集并在另外一小时写入文件)

在下面的代码中,我已经尝试避免在每一行的末尾刷新(" \ n"而不是endl),但似乎没有任何改变。您对如何大规模改进此数据的写入文件有任何想法吗?

此致 埃米利亚诺

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++;
    }
}

2 个答案:

答案 0 :(得分: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.

将计算复杂度降低到行数。如果这个用户花了不到一分钟就不会让我感到惊讶。

答案 1 :(得分:0)

最后我误用了指数,其他方法是最佳的。这是循环的工作版本(进行了一些讨厌的调试以解决问题):

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);