//--------------------------------------------------------------------
void clitk::AnatomicalFeatureDatabase::GetPoint3D(std::string tag, PointType3D & p)
{
- if (m_MapOfTag.find(tag) == m_MapOfTag.end()) {
+ if (!TagExist(tag)) {
clitkExceptionMacro("Could not find the tag <" << tag << "> of type Point3D in the DB");
+ return;
}
- else {
- std::string s = m_MapOfTag[tag];
-
- // construct a stream from the string
- std::stringstream strstr(s);
-
- // use stream iterators to copy the stream to the vector as
- // whitespace separated strings
- std::istream_iterator<std::string> it(strstr);
- std::istream_iterator<std::string> end;
- std::vector<std::string> results(it, end);
- // parse the string into 3 doubles
- for(int i=0; i<3; i++) {
+ std::string s = m_MapOfTag[tag];
+
+ // construct a stream from the string
+ std::stringstream strstr(s);
- if (!clitk::fromString<double>(p[i], results[i].c_str())) {
- clitkExceptionMacro("Error while reading Point3D, could not convert '"
- << results[i].c_str() << "' into double.");
- }
+ // use stream iterators to copy the stream to the vector as
+ // whitespace separated strings
+ std::istream_iterator<std::string> it(strstr);
+ std::istream_iterator<std::string> end;
+ std::vector<std::string> results(it, end);
- // p[i] = atof(results[i].c_str());
- }
+ // parse the string into 3 doubles
+ for(int i=0; i<3; i++) {
- /*
- // boost
- #include <boost/foreach.hpp>
- #include <boost/tokenizer.hpp>
- // parse the string into 3 doubles
- boost::char_separator<char> sep(", ");
- boost::tokenizer<boost::char_separator<char> > tokens(s, sep);
- int i=0;
- BOOST_FOREACH(std::string t, tokens) {
- std::cout << t << "." << std::endl;
- p[i] = atof(t.c_str());
- i++;
+ if (!clitk::fromString<double>(p[i], results[i].c_str())) {
+ clitkExceptionMacro("Error while reading Point3D, could not convert '"
+ << results[i].c_str() << "' into double.");
}
- */
}
}
//--------------------------------------------------------------------
//--------------------------------------------------------------------
+//--------------------------------------------------------------------
+bool clitk::AnatomicalFeatureDatabase::TagExist(std::string tag)
+{
+ return (m_MapOfTag.find(tag) != m_MapOfTag.end());
+}
+//--------------------------------------------------------------------
+
+//--------------------------------------------------------------------
+void clitk::AnatomicalFeatureDatabase::SetDouble(std::string tag, double value)
+{
+ m_MapOfTag[tag] = clitk::toString(value);
+}
+//--------------------------------------------------------------------
+
+//--------------------------------------------------------------------
+double clitk::AnatomicalFeatureDatabase::GetDouble(std::string tag)
+{
+ if (!TagExist(tag)) {
+ clitkExceptionMacro("Could not find the tag <" << tag << "> of type Double in the DB");
+ return -1;
+ }
+ double a;
+ if (!clitk::fromString<double>(a, m_MapOfTag[tag])) {
+ clitkExceptionMacro("Error while reading Double (tag='" << tag << "'), could not convert '"
+ << m_MapOfTag[tag] << "' into double.");
+ }
+ return a;
+}
+//--------------------------------------------------------------------
void SetPoint3D(TagType tag, PointType3D & p);
void GetPoint3D(TagType tag, PointType3D & p);
double GetPoint3D(std::string tag, int dim);
+ bool TagExist(std::string tag);
// Set Get image
void SetImageFilename(TagType tag, std::string f);
template<class ImageType>
- typename ImageType::Pointer GetImage(TagType tag);
+ typename ImageType::Pointer GetImage(TagType tag, bool reload=false);
template<class ImageType>
void SetImage(TagType tag,
std::string f,
//--------------------------------------------------------------------
template<class ImageType>
typename ImageType::Pointer AnatomicalFeatureDatabase::
-GetImage(std::string tag)
+GetImage(std::string tag, bool reload)
{
if (m_MapOfTag.find(tag) == m_MapOfTag.end()) {
clitkExceptionMacro("Could not find the tag <" << tag << "> of type 'Image' in the DB ('"
}
else {
typename ImageType::Pointer image;
- if (m_MapOfImage[tag]) {
+ if ((!reload) && (m_MapOfImage[tag])) {
image = static_cast<ImageType *>(m_MapOfImage[tag]);
}
else {
image = readImage<ImageType>(s);
// I add a reference count because the cache is not a smartpointer
image->SetReferenceCount(image->GetReferenceCount()+1);
- // Insert into the cache
+ // Insert into the cache
+ m_MapOfImage.erase(tag);
m_MapOfImage[tag] = &(*image); // pointer
}
return image;
clitkExceptionMacro("Could not find the tag <" << tag << "> of type Image Filename in the DB");
}
else {
- DD("TODO");
- exit(0);
- if (m_MapOfImage[tag]) {
- DD(m_MapOfImage[tag]->GetReferenceCount());
- ImageType * image = static_cast<ImageType*>(m_MapOfImage[tag]);
- image->SetReferenceCount(image->GetReferenceCount()-1);
- m_MapOfImage.erase(tag);
- /*
- DD(image->GetReferenceCount());
- image->Delete();
- */
- // DD(image->GetReferenceCount());
- }
- else {
- // Do nothing in this case (image not loaded)
- }
+ typename ImageType::Pointer image = GetImage<ImageType>(tag);
+ DD(image->GetReferenceCount());
+ image->SetReferenceCount(image->GetReferenceCount()-1);
+ m_MapOfImage.erase(tag);
}
}
//--------------------------------------------------------------------
// clitk
#include "clitkConnectedComponentLabeling_ggo.h"
#include "clitkConnectedComponentLabelingGenericFilter.h"
+#include "clitkMemoryUsage.h"
//--------------------------------------------------------------------
int main(int argc, char * argv[])
{
+ clitk::PrintMemory(true, "start");
// Init command line
GGO(clitkConnectedComponentLabeling, args_info);
CLITK_INIT;
// Filter
+ clitk::PrintMemory(true, "before filter");
typedef clitk::ConnectedComponentLabelingGenericFilter<args_info_clitkConnectedComponentLabeling> FilterType;
FilterType::Pointer filter = FilterType::New();
filter->SetArgsInfo(args_info);
+ clitk::PrintMemory(true, "before update");
try {
filter->Update();
} catch(std::runtime_error e) {
std::cout << e.what() << std::endl;
}
+ clitk::PrintMemory(true, "after filter");
+
return EXIT_SUCCESS;
} // This is the end, my friend
//--------------------------------------------------------------------
// clitk
#include "clitkImageCommon.h"
+#include "clitkSegmentationUtils.h"
// itk
#include "itkConnectedComponentImageFilter.h"
// Output image type
typedef itk::Image<int, ImageType::ImageDimension> OutputImageType;
-
- // Create CCL filter
- DD("CCL");
- typedef itk::ConnectedComponentImageFilter<ImageType, OutputImageType> ConnectFilterType;
- typename ConnectFilterType::Pointer connectFilter = ConnectFilterType::New();
- connectFilter->SetInput(input);
- connectFilter->SetBackgroundValue(mArgsInfo.inputBG_arg);
- connectFilter->SetFullyConnected(mArgsInfo.full_flag);
-
- // TODO SetBackgroud to zero forr relabel ?
-
-
- // Sort by size and remove too small area.
- typedef itk::RelabelComponentImageFilter<OutputImageType, OutputImageType> RelabelFilterType;
- typename RelabelFilterType::Pointer relabelFilter = RelabelFilterType::New();
- // relabelFilter->InPlaceOn();
- relabelFilter->SetInput(connectFilter->GetOutput());
- relabelFilter->SetMinimumObjectSize(mArgsInfo.minSize_arg);
- relabelFilter->Update();
-
- DD(mArgsInfo.inputBG_arg);
- DD(mArgsInfo.full_flag);
- DD(mArgsInfo.minSize_arg);
-
- // Set information
- const std::vector<typename RelabelFilterType::ObjectSizeType> & a = relabelFilter->GetSizeOfObjectsInPixels();
- m_SizeOfObjectsInPixels.resize(a.size());
- for(unsigned int i=0; i<a.size(); i++) m_SizeOfObjectsInPixels[i] = a[i];
- m_SizeOfObjectsInPhysicalUnits = relabelFilter->GetSizeOfObjectsInPhysicalUnits();
- m_OriginalNumberOfObjects = relabelFilter->GetOriginalNumberOfObjects();
- DD(m_OriginalNumberOfObjects);
- DD(m_SizeOfObjectsInPhysicalUnits.size());
+ PrintMemory(true, "initial");
+
+ typename OutputImageType::Pointer output;
+ {
+ typename OutputImageType::Pointer temp;
+ {
+ // Create CCL filter
+ typedef itk::ConnectedComponentImageFilter<ImageType, OutputImageType> ConnectFilterType;
+ typename ConnectFilterType::Pointer connectFilter = ConnectFilterType::New();
+ // connectFilter->ReleaseDataFlagOn(); // release earlier
+ connectFilter->SetInput(input);
+ connectFilter->SetBackgroundValue(mArgsInfo.inputBG_arg);
+ connectFilter->SetFullyConnected(mArgsInfo.full_flag);
+ // connectFilter->SetNumberOfThreads(8);
+ connectFilter->Update();
+ temp = connectFilter->GetOutput();
+ PrintMemory(true, "after udpate");
+ }
+ PrintMemory(true, "after CCL block");
+ DD(input->GetReferenceCount());
+ DD(temp->GetReferenceCount());
+
+ // Sort by size and remove too small area.
+ typedef itk::RelabelComponentImageFilter<OutputImageType, OutputImageType> RelabelFilterType;
+ typename RelabelFilterType::Pointer relabelFilter = RelabelFilterType::New();
+ // relabelFilter->SetInput(connectFilter->GetOutput());
+ relabelFilter->SetInput(temp);
+ relabelFilter->SetMinimumObjectSize(mArgsInfo.minSize_arg);
+ relabelFilter->Update();
+
+ DD(mArgsInfo.inputBG_arg);
+ DD(mArgsInfo.full_flag);
+ DD(mArgsInfo.minSize_arg);
+
+ // Set information
+ const std::vector<typename RelabelFilterType::ObjectSizeType> & a
+ = relabelFilter->GetSizeOfObjectsInPixels();
+ m_SizeOfObjectsInPixels.resize(a.size());
+ for(unsigned int i=0; i<a.size(); i++) m_SizeOfObjectsInPixels[i] = a[i];
+ m_SizeOfObjectsInPhysicalUnits = relabelFilter->GetSizeOfObjectsInPhysicalUnits();
+ m_OriginalNumberOfObjects = relabelFilter->GetOriginalNumberOfObjects();
+ DD(m_OriginalNumberOfObjects);
+ DD(m_SizeOfObjectsInPhysicalUnits.size());
+
+ output = relabelFilter->GetOutput();
+ }
+ PrintMemory(true, "after block");
// Write/Save results
- typename OutputImageType::Pointer output = relabelFilter->GetOutput();
this->template SetNextOutput<OutputImageType>(output);
+ PrintMemory(true, "end filter ");
}
//--------------------------------------------------------------------
--- /dev/null
+
+#include <itkBinaryDilateImageFilter.h>
+#include <itkMirrorPadImageFilter.h>
+
+//--------------------------------------------------------------------
+template <class ImageType>
+void
+clitk::ExtractLymphStationsFilter<ImageType>::
+ExtractStation_3P_SetDefaultValues()
+{
+}
+//--------------------------------------------------------------------
+
+//--------------------------------------------------------------------
+template <class ImageType>
+void
+clitk::ExtractLymphStationsFilter<ImageType>::
+ExtractStation_3P_SI_Limits()
+{
+ /*
+ Apex of the chest & Carina.
+ */
+ StartNewStep("[Station 3P] Inf/Sup limits with apex of the chest and carina");
+
+ writeImage<MaskImageType>(m_Working_Support, "support.mhd");
+
+ // Get Carina position (has been determined in Station8)
+ m_CarinaZ = GetAFDB()->GetDouble("CarinaZ");
+ DD(m_CarinaZ);
+
+ // Get Apex of the Chest
+ MaskImagePointer Lungs = GetAFDB()->template GetImage<MaskImageType>("Lungs");
+ DD("lung ok");
+ MaskImagePointType p;
+ bool found = clitk::FindExtremaPointInAGivenDirection<MaskImageType>(Lungs,
+ GetBackgroundValue(),
+ 1, true, p);
+ DD(found);
+ DD(p);
+ double m_ApexOfTheChest = p[2];
+ DD(m_ApexOfTheChest);
+
+ /* Crop support :
+ Superior limit = carina
+ Inferior limit = Apex of the chest */
+ m_Working_Support =
+ clitk::CropImageAlongOneAxis<MaskImageType>(m_Working_Support, 2,
+ m_ApexOfTheChest,
+ m_CarinaZ, true,
+ GetBackgroundValue());
+
+ StopCurrentStep<MaskImageType>(m_Working_Support);
+ m_ListOfStations["3P"] = m_Working_Support;
+}
+//--------------------------------------------------------------------
#include <itkBinaryDilateImageFilter.h>
#include <itkMirrorPadImageFilter.h>
+//--------------------------------------------------------------------
+template <class ImageType>
+void
+clitk::ExtractLymphStationsFilter<ImageType>::
+ExtractStation_8_SetDefaultValues()
+{
+ SetDistanceMaxToAnteriorPartOfTheSpine(10);
+ MaskImagePointType p;
+ p[0] = 15; p[1] = 2; p[2] = 1;
+ SetEsophagusDiltationForAnt(p);
+ p[0] = 5; p[1] = 10; p[2] = 1;
+ SetEsophagusDiltationForRight(p);
+ SetFuzzyThresholdForS8(0.5);
+}
+//--------------------------------------------------------------------
+
//--------------------------------------------------------------------
template <class ImageType>
void
// Get Carina Z position
MaskImagePointer Carina = GetAFDB()->template GetImage<MaskImageType>("Carina");
- clitk::PrintMemory(GetVerboseMemoryFlag(), "after read Carina");
+
+ // CHANGE TO -> OriginOfRightMiddleLobeBronchus ???
+
std::vector<MaskImagePointType> centroids;
clitk::ComputeCentroids<MaskImageType>(Carina, GetBackgroundValue(), centroids);
- DD(centroids[1]);
m_CarinaZ = centroids[1][2];
- DD(m_CarinaZ);
// add one slice to include carina ?
m_CarinaZ += m_Mediastinum->GetSpacing()[2];
- DD(m_CarinaZ);
// We dont need Carina structure from now
Carina->Delete();
- clitk::PrintMemory(GetVerboseMemoryFlag(), "after delete Carina");
+ GetAFDB()->SetDouble("CarinaZ", m_CarinaZ);
// Get left lower lobe bronchus (L), take the upper border
// Get right bronchus intermedius (RML), take the lower border
MaskImagePointer Lungs = GetAFDB()->template GetImage<MaskImageType>("Lungs");
// It should be already croped, so I took the origin and add 10mm above
m_DiaphragmInferiorLimit = Lungs->GetOrigin()[2]+10;
- DD(m_DiaphragmInferiorLimit);
- clitk::PrintMemory(GetVerboseMemoryFlag(), "after read Lung");
- Lungs->Delete(); // we don't need it, release memory
- clitk::PrintMemory(GetVerboseMemoryFlag(), "after release Lung");
+ // Lungs->Delete(); // we don't need it, release memory -> it we want to release, also free in AFDB
+ clitk::PrintMemory(GetVerboseMemoryFlag(), "after reading lungs");
+ GetAFDB()->template ReleaseImage<MaskImageType>("Lungs");
+ clitk::PrintMemory(GetVerboseMemoryFlag(), "after release lungs");
/* Crop support :
Superior limit = carina
// Ant limit from carina (start) to end of S7 = originRMLB
// Get Trachea
MaskImagePointer Trachea = GetAFDB()->template GetImage<MaskImageType>("Trachea");
- clitk::PrintMemory(GetVerboseMemoryFlag(), "after read Trachea");
MaskImagePointer m_Working_Trachea =
clitk::CropImageAbove<MaskImageType>(Trachea, 2, m_CarinaZ, true, // AutoCrop
GetBackgroundValue());
- clitk::PrintMemory(GetVerboseMemoryFlag(), "after crop");
// Seprate into two main bronchi
MaskImagePointer LeftBronchus;
// Labelize and consider the two first (main) labels
m_Working_Trachea = Labelize<MaskImageType>(m_Working_Trachea, 0, true, 1);
- clitk::PrintMemory(GetVerboseMemoryFlag(), "after labelize");
// Carina position must at the first slice that separate the two
// main bronchus (not superiorly). We thus first check that the
MaskImagePointer OriginOfRightMiddleLobeBronchus =
GetAFDB()->template GetImage<MaskImageType>("OriginOfRightMiddleLobeBronchus");
- clitk::PrintMemory(GetVerboseMemoryFlag(), "after read OriginOfRightMiddleLobeBronchus");
std::vector<MaskImagePointType> centroids;
clitk::ComputeCentroids<MaskImageType>(OriginOfRightMiddleLobeBronchus, GetBackgroundValue(), centroids);
- DD(centroids.size());
- DD(centroids[0]); // BG
- DD(centroids[1]);
m_OriginOfRightMiddleLobeBronchusZ = centroids[1][2];
- DD(m_OriginOfRightMiddleLobeBronchusZ);
// add one slice to include carina ?
m_OriginOfRightMiddleLobeBronchusZ += LeftBronchus->GetSpacing()[2];
- DD(m_OriginOfRightMiddleLobeBronchusZ);
- DD(OriginOfRightMiddleLobeBronchus->GetReferenceCount());
// We dont need Carina structure from now
OriginOfRightMiddleLobeBronchus->Delete();
- clitk::PrintMemory(GetVerboseMemoryFlag(), "after delete OriginOfRightMiddleLobeBronchus");
LeftBronchus =
clitk::CropImageBelow<MaskImageType>(LeftBronchus, 2,
GetBackgroundValue(), 1, 10);
writeImage<MaskImageType>(m_Working_Support, "after.mhd");
-HERE
-
// Keep main 3D CCL :
m_Working_Support = Labelize<MaskImageType>(m_Working_Support, 0, false, 10);
m_Working_Support = KeepLabels<MaskImageType>(m_Working_Support,
{
//--------------------------------------------------------------------
- StartNewStep("[Station8] Left and Right limits arround esophagus (below Carina)");
+ StartNewStep("[Station8] Ant part (not post to Esophagus)");
/*
Consider Esophagus, dilate it and remove ant part. It remains part
on L & R, than can be partly removed by cutting what remains at
MaskImagePointer Esophagus = GetAFDB()->template GetImage<MaskImageType>("Esophagus");
clitk::PrintMemory(GetVerboseMemoryFlag(), "after read Esophagus");
+ // In images from the original article, Atlas – UM, the oesophagus
+ //was included in nodal stations 3p and 8. Having said that, in the
+ //description for station 8, it indicates that “the delineation of
+ //station 8 is limited to the soft tissues surrounding the
+ //oesophagus”. In the recent article, The IASLC Lung Cancer Staging
+ //Project (J Thorac Oncol 4:5, 568-77), the images drawn by
+ //Dr. Aletta Frasier exclude this structure. From an oncological
+ //prospective, the oesophagus should be excluded from these nodal
+ //stations.
+ typedef clitk::BooleanOperatorLabelImageFilter<MaskImageType> BoolFilterType;
+ typename BoolFilterType::Pointer boolFilter = BoolFilterType::New();
+ boolFilter->InPlaceOn();
+ boolFilter->SetInput1(m_Working_Support);
+ boolFilter->SetInput2(Esophagus);
+ boolFilter->SetOperationType(BoolFilterType::AndNot);
+ boolFilter->Update();
+ m_Working_Support = boolFilter->GetOutput();
+
// Crop Esophagus : keep only below the OriginOfRightMiddleLobeBronchusZ
Esophagus =
clitk::CropImageAbove<MaskImageType>(Esophagus, 2,
radiusInMM,
GetBackgroundValue(),
GetForegroundValue(), true);
- clitk::PrintMemory(GetVerboseMemoryFlag(), "after dilate Esophagus");
writeImage<MaskImageType>(Esophagus, "enlarged-eso.mhd");
- // Remove Anterior part according to this dilatated esophagus
+ // Remove Anterior part according to this dilatated esophagus. Note:
+ // because we crop Esophagus with ORML, the support will also be
+ // croped in the same way. Here it is a desired feature. If we dont
+ // want, use SetIgnoreEmptySliceObject(true)
+
+ // In the new IASCL definition, it is not clear if sup limits is
+ // around carina or On the right, it is “the lower border of the
+ // bronchus intermedius”, indicated on the image set as a point
+ // (“lower border of the bronchus intermedius”)
+
typedef clitk::SliceBySliceRelativePositionFilter<MaskImageType> RelPosFilterType;
typename RelPosFilterType::Pointer relPosFilter = RelPosFilterType::New();
relPosFilter->VerboseStepFlagOff();
relPosFilter->SetIntermediateSpacing(3);
relPosFilter->ResampleBeforeRelativePositionFilterOn();
relPosFilter->SetFuzzyThreshold(GetFuzzyThresholdForS8());
- relPosFilter->RemoveObjectFlagOff();
+ relPosFilter->RemoveObjectFlagOff(); // Do not exclude here because it is dilated
relPosFilter->Update();
m_Working_Support = relPosFilter->GetOutput();
- clitk::PrintMemory(GetVerboseMemoryFlag(), "after SbS Rel pos Post");
// AutoCrop (OR SbS ?)
m_Working_Support = clitk::AutoCrop<MaskImageType>(m_Working_Support, GetBackgroundValue());
- writeImage<MaskImageType>(m_Working_Support, "step1.4.1.mhd");
-
- clitk::PrintMemory(GetVerboseMemoryFlag(), "after autocrop");
+ StopCurrentStep<MaskImageType>(m_Working_Support);
+ //--------------------------------------------------------------------
+ StartNewStep("[Station8] Left and Right limits arround esophagus (below Carina)");
// Estract slices for current support for slice by slice processing
std::vector<typename MaskSliceType::Pointer> slices;
clitk::ExtractSlices<MaskImageType>(m_Working_Support, 2, slices);
- clitk::PrintMemory(GetVerboseMemoryFlag(), "after support slices");
// Estract slices of Esophagus (resize like support before to have the same set of slices)
MaskImagePointer EsophagusForSlice = clitk::ResizeImageLike<MaskImageType>(Esophagus, m_Working_Support, GetBackgroundValue());
- clitk::PrintMemory(GetVerboseMemoryFlag(), "after Eso resize");
std::vector<typename MaskSliceType::Pointer> eso_slices;
clitk::ExtractSlices<MaskImageType>(EsophagusForSlice, 2, eso_slices);
- clitk::PrintMemory(GetVerboseMemoryFlag(), "after Eso slices");
// Estract slices of Vertebral (resize like support before to have the same set of slices)
MaskImagePointer VertebralBody = GetAFDB()->template GetImage<MaskImageType>("VertebralBody");
- clitk::PrintMemory(GetVerboseMemoryFlag(), "after Read VertebralBody");
VertebralBody = clitk::ResizeImageLike<MaskImageType>(VertebralBody, m_Working_Support, GetBackgroundValue());
- clitk::PrintMemory(GetVerboseMemoryFlag(), "after VertebralBody Resize");
std::vector<typename MaskSliceType::Pointer> vert_slices;
clitk::ExtractSlices<MaskImageType>(VertebralBody, 2, vert_slices);
- clitk::PrintMemory(GetVerboseMemoryFlag(), "after VertebralBody slices");
// Estract slices of Aorta (resize like support before to have the same set of slices)
MaskImagePointer Aorta = GetAFDB()->template GetImage<MaskImageType>("Aorta");
- clitk::PrintMemory(GetVerboseMemoryFlag(), "after Read Aorta");
Aorta = clitk::ResizeImageLike<MaskImageType>(Aorta, m_Working_Support, GetBackgroundValue());
- clitk::PrintMemory(GetVerboseMemoryFlag(), "after Aorta Resize");
std::vector<typename MaskSliceType::Pointer> aorta_slices;
clitk::ExtractSlices<MaskImageType>(Aorta, 2, aorta_slices);
- clitk::PrintMemory(GetVerboseMemoryFlag(), "after Aorta slices");
// Extract slices of Mediastinum (resize like support before to have the same set of slices)
m_Mediastinum = GetAFDB()->template GetImage<MaskImageType>("Mediastinum");
- clitk::PrintMemory(GetVerboseMemoryFlag(), "after read Mediastinum");
m_Mediastinum = clitk::ResizeImageLike<MaskImageType>(m_Mediastinum, m_Working_Support, GetBackgroundValue());
- clitk::PrintMemory(GetVerboseMemoryFlag(), "after resize Mediastinum");
std::vector<typename MaskSliceType::Pointer> mediast_slices;
clitk::ExtractSlices<MaskImageType>(m_Mediastinum, 2, mediast_slices);
- clitk::PrintMemory(GetVerboseMemoryFlag(), "after Mediastinum slices");
-
- writeImage<MaskImageType>(EsophagusForSlice, "slices_eso.mhd");
- writeImage<MaskImageType>(VertebralBody, "slices_vert.mhd");
- writeImage<MaskImageType>(Aorta, "slices_aorta.mhd");
- writeImage<MaskImageType>(m_Mediastinum, "slices_medias.mhd");
- writeImage<MaskImageType>(m_Working_Support, "slices_support.mhd");
-
// List of points
std::vector<MaskImagePointType> p_RightMostAnt;
// Right is at left on screen, coordinate decrease
// Left is at right on screen, coordinate increase
- // Find right limit of Esophagus and Aorta
- clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(eso_slices[i], GetBackgroundValue(), 0, true, sp_maxRight_Eso);
- clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(aorta_slices[i], GetBackgroundValue(), 0, true, sp_maxRight_Aorta);
- clitk::PointsUtils<MaskImageType>::Convert2DTo3D(sp_maxRight_Eso, EsophagusForSlice, i, p);
- clitk::PointsUtils<MaskImageType>::Convert2DTo3D(sp_maxRight_Aorta, Aorta, i, pp);
- pp[0] -= 2; // Add a margin of 2 mm to include the 'wall'
- p_AllPoints.push_back(p);
- p_AllPoints.push_back(pp);
- if (p[0]<pp[0]) p_RightMostAnt.push_back(p); // Insert point most at right
- else p_RightMostAnt.push_back(pp);
-
// Find limit of Vertebral -> only at most Post part of current
// slice support. First found most ant point in VertebralBody
typedef MaskSliceType SliceType;
// the VertebralBody is not delineated enough inferiorly ... in
// those cases, we consider the first found slice.
std::cerr << "No foreground pixels in this VertebralBody slices !?? I try with the previous/next slice" << std::endl;
- DD(i);
int j=i++;
bool found = false;
while (!found) {
//clitkExceptionMacro("No foreground pixels in this VertebralBody slices ??");
j++;
}
- DD(j);
}
p_slice_ant[1] += GetDistanceMaxToAnteriorPartOfTheSpine(); // Consider offset
else { // in that case, we are probably below the diaphragm, so we
// add aribtrarly few mm
sp_maxRight_Vertebra[0] -= 2; // Leave 2 mm around the VertebralBody
+ clitk::PointsUtils<MaskImageType>::Convert2DTo3D(sp_maxRight_Vertebra, m_Mediastinum, i, p);
}
p_RightMostPost.push_back(p);
p_AllPoints.push_back(p);
else { // in that case, we are probably below the diaphragm, so we
// add aribtrarly few mm
sp_maxLeft_Vertebra[0] += 2; // Leave 2 mm around the VertebralBody
+ clitk::PointsUtils<MaskImageType>::Convert2DTo3D(sp_maxLeft_Vertebra, m_Mediastinum, i, p);
}
p_LeftMostPost.push_back(p);
p_AllPoints.push_back(p);
+ // Find right limit of Esophagus and Aorta
+ clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(eso_slices[i], GetBackgroundValue(), 0, true, sp_maxRight_Eso);
+ bool f = clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(aorta_slices[i], GetBackgroundValue(), 0, true, sp_maxRight_Aorta);
+ clitk::PointsUtils<MaskImageType>::Convert2DTo3D(sp_maxRight_Eso, EsophagusForSlice, i, p);
+ clitk::PointsUtils<MaskImageType>::Convert2DTo3D(sp_maxRight_Aorta, Aorta, i, pp);
+ pp[0] -= 2; // Add a margin of 2 mm to include the Aorta 'wall'
+ p_AllPoints.push_back(p);
+ if (f) {
+ p_AllPoints.push_back(pp);
+ MaskImagePointType A = p_RightMostPost.back();
+ MaskImagePointType B = p;
+ MaskImagePointType C = pp;
+ double s = (B[0] - A[0]) * (C[1] - A[1]) - (B[1] - A[1]) * (C[0] - A[0]);
+ if (s>0) p_RightMostAnt.push_back(p);
+ else p_RightMostAnt.push_back(pp);
+ }
+ else {
+ p_RightMostAnt.push_back(p);
+ }
+
// --------------------------------------------------------------------------
// Find the limit on the Left: most left point between Eso and
// Vertebra. (Left is left on screen, coordinate increase)
// Find left limit of Esophagus
clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(eso_slices[i], GetBackgroundValue(), 0, false, sp_maxLeft_Eso);
- clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(aorta_slices[i], GetBackgroundValue(), 0, false, sp_maxLeft_Aorta);
+ f = clitk::FindExtremaPointInAGivenDirection<MaskSliceType>(aorta_slices[i], GetBackgroundValue(), 0, false, sp_maxLeft_Aorta);
clitk::PointsUtils<MaskImageType>::Convert2DTo3D(sp_maxLeft_Eso, EsophagusForSlice, i, p);
clitk::PointsUtils<MaskImageType>::Convert2DTo3D(sp_maxLeft_Aorta, Aorta, i, pp);
p_AllPoints.push_back(p);
pp[0] += 2; // Add a margin of 2 mm to include the 'wall'
- p_AllPoints.push_back(pp);
- if (p[0]>pp[0]) p_LeftMostAnt.push_back(p); // Insert point most at right
- else p_LeftMostAnt.push_back(pp);
+ if (f) { // not below Aorta
+ p_AllPoints.push_back(pp);
+ MaskImagePointType A = p_LeftMostPost.back();
+ MaskImagePointType B = p;
+ MaskImagePointType C = pp;
+ double s = (B[0] - A[0]) * (C[1] - A[1]) - (B[1] - A[1]) * (C[0] - A[0]);
+ if (s<0) p_LeftMostAnt.push_back(p); // Insert point most at Left
+ else p_LeftMostAnt.push_back(pp);
+ }
+ else {
+ p_LeftMostAnt.push_back(p);
+ }
} // End of slice loop
clitk::WriteListOfLandmarks<MaskImageType>(p_AllPoints, "LR-Eso-Vert.txt");
clitk::SliceBySliceSetBackgroundFromLineSeparation<MaskImageType>(m_Working_Support,
p_LeftMostAnt, p_LeftMostPost,
GetBackgroundValue(), 0, -10);
- // DEBUG
+ // END
+ StopCurrentStep<MaskImageType>(m_Working_Support);
m_ListOfStations["8"] = m_Working_Support;
return;
}
option "afdb" a "Input Anatomical Feature DB" string no
option "input" i "Input filename" string no
option "output" o "Output lungs mask filename" string no
+option "station" - "Force to compute station even if already exist in the DB" string no multiple
section "Options for Station 8"
option "maxAntSpine" - "Distance max to anterior part of the spine in mm" double no default="10"
itkGetConstMacro(FuzzyThreshold, double);
itkSetMacro(Station7Filename, std::string);
itkGetConstMacro(Station7Filename, std::string);
+
+ bool GetComputeStation(std::string s);
+ void AddComputeStation(std::string station) ;
protected:
ExtractLymphStationsFilter();
MaskImagePointer m_Working_Support;
std::map<std::string, MaskImagePointer> m_ListOfStations;
MaskImagePixelType m_BackgroundValue;
- MaskImagePixelType m_ForegroundValue;
+ MaskImagePixelType m_ForegroundValue;
+ std::map<std::string, bool> m_ComputeStationMap;
+
+ bool CheckForStation(std::string station);
// Station 8
double m_DistanceMaxToAnteriorPartOfTheSpine;
MaskImagePointType m_EsophagusDiltationForRight;
MaskImagePointer EnlargeEsophagusDilatationRadiusInferiorly(MaskImagePointer & eso);
void ExtractStation_8();
+ void ExtractStation_8_SetDefaultValues();
void ExtractStation_8_SI_Limits();
void ExtractStation_8_Post_Limits();
void ExtractStation_8_Ant_Limits();
void ExtractStation_8_LR_Limits();
void ExtractStation_8_LR_Limits_old();
+
+ // Station 3P
+ void ExtractStation_3P();
+ void ExtractStation_3P_SetDefaultValues();
+ void ExtractStation_3P_SI_Limits();
// Station 7
void ExtractStation_7();
#ifndef ITK_MANUAL_INSTANTIATION
#include "clitkExtractLymphStationsFilter.txx"
#include "clitkExtractLymphStation_8.txx"
+#include "clitkExtractLymphStation_3P.txx"
#include "clitkExtractLymphStation_7.txx"
#include "clitkExtractLymphStation_4RL.txx"
#endif
SetBackgroundValue(0);
SetForegroundValue(1);
- // Station 8
- SetDistanceMaxToAnteriorPartOfTheSpine(10);
- MaskImagePointType p;
- p[0] = 15; p[1] = 2; p[2] = 1;
- SetEsophagusDiltationForAnt(p);
- p[0] = 5; p[1] = 10; p[2] = 1;
- SetEsophagusDiltationForRight(p);
- SetFuzzyThresholdForS8(0.5);
+ // Default values
+ ExtractStation_8_SetDefaultValues();
+ ExtractStation_3P_SetDefaultValues();
// Station 7
SetFuzzyThreshold(0.5);
ExtractStation_8();
StopSubStep();
- // Compute some interesting points in trachea
- // ( ALTERNATIVE -> SKELETON ANALYSIS ?
- // Pb : not sufficient for mostXX points ... )
+ DD(GetCurrentStepNumber());
- /* ==> todo (but why ???)
- ComputeTracheaCentroidsAboveCarina();
- ComputeBronchusExtremaPointsBelowCarina();
- */
+ // Extract Station3P
+ StartNewStep("Station 3P");
+ StartSubStep();
+ ExtractStation_3P();
+ StopSubStep();
if (0) { // temporary suppress
// Extract Station7
//--------------------------------------------------------------------
template <class TImageType>
-void
+bool
clitk::ExtractLymphStationsFilter<TImageType>::
-ExtractStation_8() {
+CheckForStation(std::string station)
+{
+ // Compute Station name
+ std::string s = "Station"+station;
+
- // Check if m_ListOfStations["8"] exist. If yes -> use it as initial
- // support instead of m_Mediastinum
- if (m_ListOfStations["8"]) {
- DD("Station 8 support already exist -> use it");
- m_Working_Support = m_ListOfStations["8"];
+ // Check if station already exist in DB
+ bool found = false;
+ if (GetAFDB()->TagExist(s)) {
+ m_ListOfStations[station] = GetAFDB()->template GetImage<MaskImageType>(s);
+ found = true;
}
- else m_Working_Support = m_Mediastinum;
- ExtractStation_8_SI_Limits();
- ExtractStation_8_Post_Limits();
- ExtractStation_8_Ant_Limits();
- ExtractStation_8_LR_Limits();
- // ExtractStation_8_LR_Limits();
+ // Define the starting support
+ if (found && GetComputeStation("8")) {
+ std::cout << "Station " << station << " already exists, but re-computation forced." << std::endl;
+ }
+ if (!found || GetComputeStation("8")) {
+ m_Working_Support = m_Mediastinum = GetAFDB()->template GetImage<MaskImageType>("Mediastinum", true);
+ return true;
+ }
+ else {
+ std::cout << "Station " << station << " found. I used it" << std::endl;
+ return false;
+ }
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TImageType>
+bool
+clitk::ExtractLymphStationsFilter<TImageType>::
+GetComputeStation(std::string station)
+{
+ return (m_ComputeStationMap.find(station) != m_ComputeStationMap.end());
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TImageType>
+void
+clitk::ExtractLymphStationsFilter<TImageType>::
+AddComputeStation(std::string station)
+{
+ m_ComputeStationMap[station] = true;
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TImageType>
+void
+clitk::ExtractLymphStationsFilter<TImageType>::
+ExtractStation_8()
+{
+ if (CheckForStation("8")) {
+ ExtractStation_8_SI_Limits();
+ ExtractStation_8_Post_Limits();
+ ExtractStation_8_Ant_Limits();
+ ExtractStation_8_LR_Limits();
+ // Store image filenames into AFDB
+ writeImage<MaskImageType>(m_ListOfStations["8"], "seg/Station8.mhd");
+ GetAFDB()->SetImageFilename("Station8", "seg/Station8.mhd");
+ WriteAFDB();
+ }
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template <class TImageType>
+void
+clitk::ExtractLymphStationsFilter<TImageType>::
+ExtractStation_3P()
+{
+ if (CheckForStation("3P")) {
+ ExtractStation_3P_SI_Limits();
+ // Store image filenames into AFDB
+ writeImage<MaskImageType>(m_ListOfStations["3P"], "seg/Station3P.mhd");
+ GetAFDB()->SetImageFilename("Station3P", "seg/Station3P.mhd");
+ }
}
//--------------------------------------------------------------------
//--------------------------------------------------------------------
+//--------------------------------------------------------------------
+
+
//--------------------------------------------------------------------
template <class TImageType>
void
}
}
f->SetEsophagusDiltationForRight(p);
+
+ for(uint i=0; i<mArgsInfo.station_given; i++)
+ f->AddComputeStation(mArgsInfo.station_arg[i]);
}
//--------------------------------------------------------------------
void WriteAFDB();
void LoadAFDB();
+
AnatomicalFeatureDatabase * GetAFDB();
void SetAFDB(AnatomicalFeatureDatabase * a) { m_AFDB = a; }
#ifndef clitkRegionGrowingGenericFilter_txx
#define clitkRegionGrowingGenericFilter_txx
-/* =================================================
- * @file clitkRegionGrowingGenericFilter.txx
- * @author
- * @date
- *
- * @brief
- *
- ===================================================*/
-
-
namespace clitk
{