/* use this function to compute one associative measurement */ float NuclearAssociationRules::ComputeOneAssocMeasurement(itk::SmartPointer<TargImageType> trgIm, int ruleID, int objID) { //fisrt, get the bounding box around the object //The bounding box is defined by the area around the object such that the object+outerdistance are included int imBounds[6] = {0,x_Size,0,y_Size,0,z_Size}; LabelGeometryType::BoundingBoxType bbox = labGeometryFilter->GetBoundingBox(objID); //make sure the object exists int valid = 0; for(int dim=0; dim < imDim*2; ++dim) { if(bbox[dim] > 0) valid = 1; } if(valid == 0) return -1; std::vector< int > retBbox(0); int dist, val; dist = assocRulesList[ruleID].GetOutDistance(); for(int dim=0; dim < imDim*2; ++dim) { if(dim%2 == 0) //even { val = int(bbox[dim])-dist-1; if(val<imBounds[dim]) val=imBounds[dim]; } else //odd { val = int(bbox[dim])+dist+1; if(val>=imBounds[dim]) val=imBounds[dim]-1; } retBbox.push_back( val ); } //the bounding box defines the region of interest we need (from both segmentation and target images) //so, use it to get sub images DistImageType::Pointer subSegImg = DistImageType::New(); LabImageType::IndexType start; start[0] = 0; // first index on X start[1] = 0; // first index on Y start[2] = 0; // first index on Z LabImageType::SizeType size; size[0] = retBbox[1]-retBbox[0]+1; // size along X size[1] = retBbox[3]-retBbox[2]+1; // size along Y if(imDim == 3) size[2] = retBbox[5]-retBbox[4]+1; // size along Z else size[2] = 1; LabImageType::RegionType region; region.SetSize( size ); region.SetIndex( start ); subSegImg->SetRegions( region ); subSegImg->Allocate(); subSegImg->FillBuffer(0); subSegImg->Update(); LabImageType::IndexType start2; start2[0] = retBbox[0]; // first index on X start2[1] = retBbox[2]; // first index on Y if(imDim == 3) start2[2] = retBbox[4]; // first index on Z else start2[2] = 0; LabImageType::RegionType region2; region2.SetSize( size ); region2.SetIndex( start2 ); labImage->SetRequestedRegion(region2); trgIm->SetRequestedRegion(region2); typedef itk::ImageRegionIteratorWithIndex< LabImageType > IteratorType; IteratorType iterator1(labImage, labImage->GetRequestedRegion()); typedef itk::ImageRegionIteratorWithIndex< DistImageType > IteratorType2; IteratorType2 iterator2(subSegImg, subSegImg->GetRequestedRegion()); //in the sub-segmentation image, we need to mask out any pixel from another object int counter = 0; while ( ! iterator1.IsAtEnd()) { int V = iterator1.Get(); if(V == objID) { iterator2.Set(255.0); counter++; //just for debuging purposes,, will be removed } else iterator2.Set(0.0); ++iterator1; ++iterator2; } //Let's try this (for debugging): save the binary mask /* typedef itk::Image< unsigned short, 3 > OutputImageType; typedef itk::CastImageFilter< DistImageType, OutputImageType > CastType; CastType::Pointer cast = CastType::New(); cast->SetInput( subSegImg ); cast->Update(); typedef itk::ImageFileWriter< OutputImageType > WriterType; WriterType::Pointer writer = WriterType::New( ); writer->SetInput( cast->GetOutput() ); writer->SetFileName( "c:/bin_mask.tif" ); writer->Update(); */ //Compute the distance transform in the sub-segmentation image region DTFilter::Pointer dt_obj= DTFilter::New() ; dt_obj->SetInput(subSegImg) ; //dt_obj->SetInsideValue(255.0); //dt_obj->SetOutsideValue(0.0); try{ dt_obj->Update() ; } catch( itk::ExceptionObject & err ){ std::cout << "Error in Distance Transform: " << err << std::endl; return 0; } //Let's try this (for debugging): save the distance map ////typedef itk::Image< unsigned short, 3 > OutputImageType; ////typedef itk::CastImageFilter< DistImageType, OutputImageType > CastType; ////CastType::Pointer cast = CastType::New(); //cast->SetInput( dt_obj->GetOutput() ); //cast->Update(); ////typedef itk::ImageFileWriter< OutputImageType > WriterType; ////WriterType::Pointer writer = WriterType::New( ); //writer->SetInput( cast->GetOutput() ); //writer->SetFileName( "c:/dist_map.tif" ); //writer->Update(); //now, mask out all the pixels (in the sub-seg image) that are not in the region of interest as defined by the association rule and get the intensities of the needed pixels from the target image. The intensities are saved into an std vector IteratorType2 iterator3(dt_obj->GetOutput(), dt_obj->GetOutput()->GetRequestedRegion()); IteratorType iterator4(trgIm, trgIm->GetRequestedRegion()); std::vector<int> trgInt; int counter_in = 0; int counter_at = 0; int counter_ot = 0; while ( ! iterator3.IsAtEnd()) { int V = (int)iterator3.Get(); if(V<0) counter_in++; if(V==0) counter_at++; if(V>0) counter_ot++; //if it is outside with distance less than outDistance away if(V>0 && V<=assocRulesList[ruleID].GetOutDistance()) trgInt.push_back(iterator4.Get()); //if it is inside and the whole cell is used else if(V<=0 && assocRulesList[ruleID].IsUseWholeObject()) trgInt.push_back(iterator4.Get()); //if it is inside with distance less than in Distance else if(V<=0 && abs(V)<=assocRulesList[ruleID].GetInDistance()) trgInt.push_back(iterator4.Get()); ++iterator3; ++iterator4; } if(!trgInt.size()) return 0; //Finally, given the list of intensities compute the associative measrement based on the type defined by the association rule switch(assocRulesList[ruleID].GetAssocType()) { case ASSOC_MIN: return FindMin(trgInt); break; case ASSOC_MAX: return FindMax(trgInt); break; case ASSOC_TOTAL: return ComputeTotal(trgInt); break; case ASSOC_AVERAGE: return ComputeAverage(trgInt); break; default: return ComputeAverage(trgInt); } //we will never go here, just silencing a compiler warning return 0.0; }
USImageType::PixelType returnthresh( itk::SmartPointer<USImageType> input_image, int num_bin_levs, int num_in_fg ){ //Instantiate the different image and filter types that will be used typedef itk::ImageRegionConstIterator< USImageType > ConstIteratorType; typedef itk::Statistics::Histogram< float > HistogramType; typedef itk::OtsuMultipleThresholdsCalculator< HistogramType > CalculatorType; std::cout<<"Starting threshold computation\n"; //Create a temporary histogram container: const int numBins = itk::NumericTraits<USImageType::PixelType>::max(); double *tempHist; tempHist = (double*) malloc( sizeof(double) * numBins ); for(USImageType::PixelType i=0; i<numBins; ++i) tempHist[i] = 0; USImageType::PixelType maxval = itk::NumericTraits<USImageType::PixelType>::ZeroValue(); USImageType::PixelType minval = itk::NumericTraits<USImageType::PixelType>::max(); //Populate the histogram (assume pixel type is actually is some integer type): ConstIteratorType it( input_image, input_image->GetRequestedRegion() ); for ( it.GoToBegin(); !it.IsAtEnd(); ++it ){ USImageType::PixelType pix = it.Get(); ++tempHist[pix]; if( pix > maxval ) maxval = pix; if( pix < minval ) minval = pix; } //return max of type if there is no variation in the staining if( (maxval-minval)<3 ) return itk::NumericTraits<USImageType::PixelType>::max(); const USImageType::PixelType numBinsPresent = maxval+1; //Find max value in the histogram double floatIntegerMax = itk::NumericTraits<USImageType::PixelType>::max(); double max = 0.0; for(USImageType::PixelType i=0; i<numBinsPresent; ++i) if( tempHist[i] > max ) max = tempHist[i]; double scaleFactor = 1; if(max >= floatIntegerMax) scaleFactor = floatIntegerMax / max; HistogramType::Pointer histogram = HistogramType::New() ; // initialize histogram HistogramType::SizeType size; HistogramType::MeasurementVectorType lowerBound; HistogramType::MeasurementVectorType upperBound; lowerBound.SetSize(1); upperBound.SetSize(1); size.SetSize(1); lowerBound.Fill(0.0); upperBound.Fill((double)maxval); size.Fill(numBinsPresent); histogram->SetMeasurementVectorSize(1); histogram->Initialize(size, lowerBound, upperBound ) ; USImageType::PixelType i=0; for (HistogramType::Iterator iter = histogram->Begin(); iter != histogram->End(); ++iter ){ float norm_freq = (float)(tempHist[i] * scaleFactor); iter.SetFrequency(norm_freq); ++i; } std::cout<<"Histogram computed\n"; CalculatorType::Pointer calculator = CalculatorType::New(); calculator->SetNumberOfThresholds( num_bin_levs ); calculator->SetInputHistogram( histogram ); calculator->Update(); const CalculatorType::OutputType &thresholdVector = calculator->GetOutput(); CalculatorType::OutputType::const_iterator itNum = thresholdVector.begin(); float thresh; for(USImageType::PixelType i=0; i < num_in_fg; ++itNum, ++i) thresh = (static_cast<float>(*itNum)); std::cout<<"Threshold computed: "<<thresh<<std::endl; return (USImageType::PixelType)(thresh+0.5); }