[Insight-users] Example on how to parallelize a simple neighborhood filter
lynx.abraxas at freenet.de
lynx.abraxas at freenet.de
Tue Dec 15 16:02:52 EST 2009
Hello again!
Since my last post below I got a bit further. Since I skip the neighborhood
evaluation where voxels of the mask are I don't think the parallelization by
subregion (as mentioned in the users guide) is a good choise for my problem.
So I've put my voxel operation in the iteration into a separate function. I'm
now wondering:
- Should I use pthreads or just a simple fork/child process to distribute each
voxel analysis on a separate core (of a 8 core machine)?
- Would I have to make a full copy of each iterator since they get increased
during the execution of other threads?
- Is there a much better way to go than mine?
Thanks for any help or hints on this.
Lynx
-------------- next part --------------
//calculate the mean of a masked binary image within a neighborhood
//optimized to only look at the neighborhood if the centre pixel is not from the mask
//mean_masked parallelized
#include "itkImage.h"
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkNeighborhoodAlgorithm.h"
#include <math.h>
#include "itkConstantBoundaryCondition.h"
#include "itkConstShapedNeighborhoodIterator.h"
#include "itkImageRegionIterator.h"
const unsigned int Dimension = 3;
typedef unsigned char IPixelType;
//typedef float OPixelType; //code needs to be modified for float!!!
typedef unsigned char OPixelType; //easier to use
const IPixelType foreground_value, background_value, maskground_value; //*ground_value does not change during iteration -> global vars.
int operate_on_voxel(it, out, np){//*ground_value does not change during iteration -> global vars.
unsigned int sum_f, sum_b, tot;
IPixelType value;
ShapedNeighborhoodIteratorType::ConstIterator ci;
if (it.GetCenterPixel() == maskground_value){
out.Set(0);
return(0);
}
sum_f= 0;
sum_b= 0;
for (ci = it.Begin(); ci != it.End(); ci++){
value= ci.Get();
if (value == foreground_value)
sum_f++;
else if (value == background_value) //else if is quicker than a pure if!!!
sum_b++;
}
tot= sum_f + sum_b;
if (tot)
//out.Set(static_cast<OPixelType>( static_cast<float>(sum_f) / tot * std::numeric_limits<OPixelType>::max())); //include scaling
out.Set(static_cast<OPixelType>( sum_f * std::numeric_limits<OPixelType>::max() / tot)); //quicker?
else out.Set(0);
return(1);
}
int main( int argc, char ** argv )
{
if ( argc < 7 ){
std::cerr << "Missing parameters. " << std::endl;
std::cerr << "Usage: " << std::endl;
std::cerr << argv[0]
<< " inputImageFile outputImageFile element_radius foreground background maskground"
<< std::endl;
return -1;
}
foreground_value = atoi(argv[4]);
background_value = atoi(argv[5]);
maskground_value = atoi(argv[6]); //maskground is just needed for const boundary cond.
typedef itk::Image<IPixelType, Dimension> ImageType;
typedef itk::Image<OPixelType, Dimension> OImageType;
itk::ConstantBoundaryCondition<ImageType> BC;
//BoundaryConditionType BoundaryCondition= BoundaryConditionType::New();
BC.SetConstant(maskground_value);
//typedef itk::ConstShapedNeighborhoodIterator<ImageType, BoundaryCondition> ShapedNeighborhoodIteratorType;
typedef itk::ConstShapedNeighborhoodIterator<ImageType> ShapedNeighborhoodIteratorType;
typedef itk::ImageRegionIterator<ImageType> IteratorType;
typedef itk::ImageRegionIterator<OImageType> OIteratorType;
OIteratorType out;
typedef itk::ImageFileReader< ImageType > ReaderType;
ReaderType::Pointer reader = ReaderType::New();
reader->SetFileName( argv[1] );
try {
reader->Update();
}
catch ( itk::ExceptionObject &err){
std::cout << "ExceptionObject caught !" << std::endl;
std::cout << err << std::endl;
return -1;
}
OImageType::Pointer output = OImageType::New();
output->SetRegions(reader->GetOutput()->GetRequestedRegion());
output->Allocate();
unsigned int element_radius = ::atoi( argv[3] );
ShapedNeighborhoodIteratorType::RadiusType radius;
radius.Fill(element_radius);
typedef itk::NeighborhoodAlgorithm::ImageBoundaryFacesCalculator<ImageType> FaceCalculatorType;
FaceCalculatorType faceCalculator;
FaceCalculatorType::FaceListType faceList;
FaceCalculatorType::FaceListType::iterator fit;
faceList = faceCalculator( reader->GetOutput(), output->GetRequestedRegion(), radius );
const float rad = static_cast<float>(element_radius);
unsigned int nop, count, ll; //for progress info
count= 0;
nop = reader->GetOutput()->GetRequestedRegion().GetNumberOfPixels();
ll = nop / 10000;
std::cout << "Total number of voxels: " << nop << std::endl << std::flush;
//split up the input region into border regions and a (big) none border region
for ( fit=faceList.begin(); fit != faceList.end(); ++fit){
ShapedNeighborhoodIteratorType it( radius, reader->GetOutput(), *fit );//iterate over each subregion
it.OverrideBoundaryCondition(&BC); // assign the boundary condition
out = OIteratorType( output, *fit );
// Creates a circular structuring element by activating all the pixels less
// than radius distance from the center of the neighborhood.
ShapedNeighborhoodIteratorType::OffsetType off;
for (float z = -rad; z <= rad; z++){
for (float y = -rad; y <= rad; y++){
for (float x = -rad; x <= rad; x++){
float dis = vcl_sqrt( x*x + y*y + z*z);
if (dis <= rad){
off[0] = static_cast<int>(x);
off[1] = static_cast<int>(y);
off[2] = static_cast<int>(z);
it.ActivateOffset(off); //if segfaults comment this! Why???
//because 3 dim (z, off[2]) was missing!!!!!!!
}
}
}
}
////now do the actual voxel iteration
it.GoToBegin();
out.GoToBegin();
np= 0; //reset number of processes
while(!it.IsAtEnd()){
count++;
if (np < max_p){
np++;
operate_on_voxel(it, out, np);//does it need a full copy of it and out since the pointers change during execution of thread?!?
++it;
++out;
}
else
wait(); //waiting sensible?
//print out some progess info
if ( count % ll == 0 ){
fprintf(stderr, "\rFilter progress: %6.2f%%", 100.0 * count / nop);
std::cerr.flush();
}
}
}
}
typedef itk::ImageFileWriter<OImageType> WriterType;
WriterType::Pointer writer = WriterType::New();
writer->SetFileName( argv[2] );
writer->SetInput( output );
try {
writer->Update();
}
catch ( itk::ExceptionObject &err) {
std::cout << "ExceptionObject caught !" << std::endl;
std::cout << err << std::endl;
return -1;
}
return 0;
}
More information about the Insight-users
mailing list