#include "itkOrientImageFilter.h"
#include "itkSpatialOrientationAdapter.h"
#include "itkImageDuplicator.h"
+#include "itkRelabelComponentImageFilter.h"
+
#include <fcntl.h>
//--------------------------------------------------------------------
SetForegroundValue(1);
SetMinimalComponentSize(100);
VerboseRegionGrowingFlagOff();
+ RemoveSmallLabelBeforeSeparationFlagOn();
// Step 1 default values
SetUpperThreshold(-300);
TracheaVolumeMustBeCheckedFlagOn();
SetNumSlices(50);
SetMaxElongation(0.5);
- SetSeedPreProcessingThreshold(-400);
-
+ SetSeedPreProcessingThreshold(-400);
// Step 3 default values
SetNumberOfHistogramBins(500);
template <class ImageType>
void
clitk::ExtractLungFilter<ImageType>::
-AddSeed(InternalIndexType s)
+//AddSeed(InternalIndexType s)
+AddSeed(InputImagePointType s)
+{
+ m_SeedsInMM.push_back(s);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class ImageType>
+void
+clitk::ExtractLungFilter<ImageType>::
+AddSeedInPixels(InternalIndexType s)
{
m_Seeds.push_back(s);
}
StartNewStep("Search for the trachea");
SearchForTrachea();
PrintMemory(GetVerboseMemoryFlag(), "After SearchForTrachea");
+ if (m_Seeds.empty()) {
+ clitkExceptionMacro("No seeds for trachea... Aborting.");
+ }
//--------------------------------------------------------------------
//--------------------------------------------------------------------
//--------------------------------------------------------------------
//--------------------------------------------------------------------
StartNewStep("Separate Left/Right lungs");
- PrintMemory(GetVerboseMemoryFlag(), "Before Separate");
+ PrintMemory(GetVerboseMemoryFlag(), "Before Separate");
// Initial label
working_mask = Labelize<MaskImageType>(working_mask,
GetBackgroundValue(),
statisticsImageFilter->SetInput(working_mask);
statisticsImageFilter->Update();
unsigned int initialNumberOfLabels = statisticsImageFilter->GetMaximum();
- working_mask = statisticsImageFilter->GetOutput();
-
+ working_mask = statisticsImageFilter->GetOutput();
PrintMemory(GetVerboseMemoryFlag(), "After count label");
+
+ // If already 2 labels, but a too big differences, remove the
+ // smalest one (sometimes appends with the stomach
+ if (initialNumberOfLabels >1) {
+ if (GetRemoveSmallLabelBeforeSeparationFlag()) {
+ typedef itk::RelabelComponentImageFilter<MaskImageType, MaskImageType> RelabelFilterType;
+ typename RelabelFilterType::Pointer relabelFilter = RelabelFilterType::New();
+ relabelFilter->SetInput(working_mask);
+ relabelFilter->SetMinimumObjectSize(10);
+ relabelFilter->Update();
+ const std::vector<float> & a = relabelFilter->GetSizeOfObjectsInPhysicalUnits();
+ std::vector<MaskImagePixelType> remove_label;
+ for(unsigned int i=1; i<a.size(); i++) {
+ if (a[i] < 0.5*a[0]) { // more than 0.5 difference
+ remove_label.push_back(i+1); // label zero is BG
+ }
+ }
+ working_mask =
+ clitk::RemoveLabels<MaskImageType>(working_mask, GetBackgroundValue(), remove_label);
+ statisticsImageFilter->SetInput(working_mask);
+ statisticsImageFilter->Update();
+ initialNumberOfLabels = statisticsImageFilter->GetMaximum();
+ }
+ }
// Decompose the first label
if (initialNumberOfLabels<2) {
it.GoToBegin();
while (!it.IsAtEnd()) {
if(it.Get() < GetUpperThresholdForTrachea() ) {
- AddSeed(it.GetIndex());
+ AddSeedInPixels(it.GetIndex());
// DD(it.GetIndex());
}
++it;
opening->Update();
typename SlicerFilterType::Pointer slicer = SlicerFilterType::New();
+ slicer->SetDirectionCollapseToIdentity();
slicer->SetInput(opening->GetOutput());
// label result
for (unsigned int j = 0; j < nlables; j++) {
shape = label_map->GetNthLabelObject(j);
if (shape->Size() > 150 && shape->Size() <= max_size) {
-#if ITK_VERSION_MAJOR < 4
- double e = 1 - 1/shape->GetBinaryElongation();
-#else
double e = 1 - 1/shape->GetElongation();
-#endif
//double area = 1 - r->Area() ;
if (e < max_elongation) {
nshapes++;
prev_e_centre= max_e_centre;
}
+ else {
+ if (GetVerboseRegionGrowingFlag()) {
+ cout << "No shapes found at slice " << index[2] << std::endl;
+ }
+ }
}
size_t longest = 0;
}
}
- if (GetVerboseRegionGrowingFlag())
- std::cout << "seed at: " << trachea_centre << std::endl;
- m_Seeds.push_back(trachea_centre);
+ if (longest > 0) {
+ if (GetVerboseRegionGrowingFlag())
+ std::cout << "seed at: " << trachea_centre << std::endl;
+ m_Seeds.push_back(trachea_centre);
+ }
}
return (m_Seeds.size() != 0);
f->SetUpper(GetUpperThresholdForTrachea());
f->SetMinimumLowerThreshold(-2000);
// f->SetMaximumUpperThreshold(0); // MAYBE TO CHANGE ???
- f->SetMaximumUpperThreshold(-700); // MAYBE TO CHANGE ???
+ f->SetMaximumUpperThreshold(-300); // MAYBE TO CHANGE ???
f->SetAdaptLowerBorder(false);
f->SetAdaptUpperBorder(true);
f->SetMinimumSize(5000);
f->SetVerbose(GetVerboseRegionGrowingFlag());
for(unsigned int i=0; i<m_Seeds.size();i++) {
f->AddSeed(m_Seeds[i]);
- // DD(m_Seeds[i]);
+ //DD(m_Seeds[i]);
}
f->Update();
PrintMemory(GetVerboseMemoryFlag(), "After RG update");
// compute trachea volume
// if volume not plausible -> skip more slices and restart
+ // If initial seed, convert from mm to pixels
+ if (m_SeedsInMM.size() > 0) {
+ for(unsigned int i=0; i<m_SeedsInMM.size(); i++) {
+ InputImageIndexType index;
+ working_input->TransformPhysicalPointToIndex(m_SeedsInMM[i], index);
+ m_Seeds.push_back(index);
+ }
+ }
+
bool has_seed;
bool stop = false;
double volume = 0.0;
std::cout << "\t Found trachea with volume " << volume << " cc." << std::endl;
}
}
- else {
- if (GetVerboseStepFlag()) {
- std::cout << "\t The volume of the trachea (" << volume
- << " cc) seems not correct. I skip some slices (" << skip << ") and restart to find seeds."
- << std::endl;
- }
- skip += 5;
- stop = false;
- // empty the list of seed
- m_Seeds.clear();
+ else
+ if (GetTracheaSeedAlgorithm() == 0) {
+ if (GetVerboseStepFlag()) {
+ std::cout << "\t The volume of the trachea (" << volume
+ << " cc) seems not correct. I skip some slices (" << skip << ") and restart to find seeds."
+ << std::endl;
+ }
+ skip += 5;
+ stop = false;
+ // empty the list of seed
+ m_Seeds.clear();
}
if (skip > 0.5 * working_input->GetLargestPossibleRegion().GetSize()[2]) {
// we want to skip more than a half of the image, it is probably a bug