From 25a1e4fa1187d00dda0c8bcce573ea02e811dbc9 Mon Sep 17 00:00:00 2001 From: dsarrut Date: Tue, 12 Jul 2011 08:12:47 +0200 Subject: [PATCH] add final opening --- .../clitkExtractMediastinalVesselsFilter.txx | 586 +++++++++++++++++- 1 file changed, 552 insertions(+), 34 deletions(-) diff --git a/segmentation/clitkExtractMediastinalVesselsFilter.txx b/segmentation/clitkExtractMediastinalVesselsFilter.txx index 2198529..29709f4 100644 --- a/segmentation/clitkExtractMediastinalVesselsFilter.txx +++ b/segmentation/clitkExtractMediastinalVesselsFilter.txx @@ -29,6 +29,14 @@ #include #include +template struct index_cmp { + index_cmp(const T varr) : arr(varr) {} + bool operator()(const size_t a, const size_t b) const + { return arr[a] < arr[b]; } + const T arr; +}; + + //-------------------------------------------------------------------- template clitk::ExtractMediastinalVesselsFilter:: @@ -49,6 +57,7 @@ ExtractMediastinalVesselsFilter(): SetMaxDistanceLeftToCarina(35); SetMaxDistanceRightToCarina(35); SetSoughtVesselSeedName("NoSeedNameGiven"); + SetFinalOpeningRadius(1); } //-------------------------------------------------------------------- @@ -112,24 +121,37 @@ GenerateOutputInformation() { // CCL. Erode and reconstruct all labels at the same time without // merging them. for(uint i=0; i KernelType; - KernelType structuringElement; - structuringElement.SetRadius(radius); - structuringElement.CreateStructuringElement(); + + /*// Erosion kernel + typedef itk::BinaryBallStructuringElement KernelType; + KernelType structuringElement; + structuringElement.SetRadius(radius); + structuringElement.CreateStructuringElement(); + */ // Erosion -> we break the connectivity between structure - typedef itk::BinaryErodeImageFilter ErodeFilterType; + MaskSliceType::SizeType r; + r[0] = r[1] = radius; + MaskSlicePointer eroded = clitk::Opening(slices_mask[i], + r, + GetBackgroundValue(), + GetForegroundValue()); + /* + //typedef itk::BinaryErodeImageFilter ErodeFilterType; + typedef itk::BinaryMorphologicalOpeningImageFilter ErodeFilterType; typename ErodeFilterType::Pointer eroder = ErodeFilterType::New(); eroder->SetInput(slices_mask[i]); eroder->SetBackgroundValue(GetBackgroundValue()); eroder->SetForegroundValue(GetForegroundValue()); - eroder->SetBoundaryToForeground(true); // ?? + //eroder->SetBoundaryToForeground(true); // ?? for BinaryErodeImageFilter eroder->SetKernel(structuringElement); eroder->Update(); MaskSlicePointer eroded = eroder->GetOutput(); + */ + + // Keep slice for debug debug_eroded.push_back(eroded); - + // Labelize (CCL) MaskSlicePointer labeled = clitk::Labelize(eroded, GetBackgroundValue(), true, 1); // Fully connected ! @@ -163,6 +185,14 @@ GenerateOutputInformation() { // superiorly. This is done by TrackBifurcationFromPoint MaskImagePointType SoughtVesselSeedPoint; GetAFDB()->GetPoint3D(m_SoughtVesselSeedName, SoughtVesselSeedPoint); + MaskImagePointType MaxSlicePoint; + if (GetAFDB()->TagExist(m_SoughtVesselSeedName+"Max")) { + GetAFDB()->GetPoint3D(m_SoughtVesselSeedName+"Max", MaxSlicePoint); + } + else { + MaxSlicePoint = SoughtVesselSeedPoint; + MaxSlicePoint[2] += 1000; + } // Find the label with the maximum value to set the result typedef itk::MinimumMaximumImageCalculator MinMaxFilterType; @@ -175,37 +205,39 @@ GenerateOutputInformation() { // components obtain when (hopefully!) the SoughtVessel // split into CommonArtery and SubclavianArtery. std::vector bifurcations; - TrackBifurcationFromPoint(r, m_slice_recon, SoughtVesselSeedPoint, newLabel, bifurcations); + // TrackBifurcationFromPoint(r, m_slice_recon, SoughtVesselSeedPoint, + // MaxSlicePoint, newLabel, bifurcations); + + TrackVesselsFromPoint(r, m_slice_recon, SoughtVesselSeedPoint, + MaxSlicePoint, newLabel); // Build the final 3D image from the previous slice by slice processing m_SoughtVessel = clitk::JoinSlices(m_slice_recon, m_Mask, 2); writeImage(m_SoughtVessel, "recon2.mhd"); // Set binary image, (remove other labels). - // TODO: keep labeled image to track SubclavianArtery and CommonArtery m_SoughtVessel = clitk::Binarize(m_SoughtVessel, newLabel, newLabel, GetBackgroundValue(), GetForegroundValue()); - writeImage(m_SoughtVessel, "afterbinarize.mhd"); - + // writeImage(m_SoughtVessel, "afterbinarize.mhd"); m_SoughtVessel = clitk::AutoCrop(m_SoughtVessel, GetBackgroundValue()); - writeImage(m_SoughtVessel, "afterautocrop.mhd"); + // writeImage(m_SoughtVessel, "afterautocrop.mhd"); // Clean the image : Opening (not in Z direction) typename MaskImageType::SizeType rad; - rad[0] = rad[1] = 2; + rad[0] = rad[1] = GetFinalOpeningRadius(); rad[2] = 0; m_SoughtVessel = clitk::Opening(m_SoughtVessel, rad, - GetBackgroundValue(), GetForegroundValue()); + GetBackgroundValue(), GetForegroundValue()); - writeImage(m_SoughtVessel, "afteropen.mhd"); + // writeImage(m_SoughtVessel, "afteropen.mhd"); // Clean the image : keep main CCL slice by slice m_SoughtVessel = clitk::SliceBySliceKeepMainCCL(m_SoughtVessel, - GetBackgroundValue(), - GetForegroundValue()); + GetBackgroundValue(), + GetForegroundValue()); } //-------------------------------------------------------------------- @@ -242,7 +274,7 @@ CropInputImage() { StartNewStep("Crop the input image: SI,AP limits with carina and crop with mediastinum"); /* Need : Trachea, Carina (roi not point), - */ + */ // Get Trachea and Carina MaskImagePointer Trachea = GetAFDB()->template GetImage ("Trachea"); @@ -271,7 +303,6 @@ CropInputImage() { m_Input = clitk::CropImageRemoveLowerThan(m_Input, 1, m_CarinaY-GetMaxDistanceAntToCarina(), false, GetBackgroundValue()); - // Crop Right double m_CarinaX = centroids[1][0]; m_Input = clitk::CropImageRemoveLowerThan(m_Input, 0, @@ -293,6 +324,7 @@ CropInputImage() { m_Input = clitk::ResizeImageLike(m_Input, m_Mediastinum, GetBackgroundValue()); */ + // writeImage(m_Input, "crop.mhd"); // End StopCurrentStep(m_Input); } @@ -306,6 +338,7 @@ clitk::ExtractMediastinalVesselsFilter:: TrackBifurcationFromPoint(MaskImagePointer & recon, std::vector & slices_recon, MaskImagePointType point3D, + MaskImagePointType pointMaxSlice, LabelType newLabel, std::vector & bifurcations) { StartNewStep("Track the SoughtVessel from the seed point"); @@ -316,6 +349,11 @@ TrackBifurcationFromPoint(MaskImagePointer & recon, int numberOfBifurcation = 0; typedef typename MaskSliceType::PointType SlicePointType; SlicePointType previousCenter; + + // Max slice + MaskImageIndexType indexMaxSlice; + recon->TransformPhysicalPointToIndex(pointMaxSlice, indexMaxSlice); + uint maxSlice = indexMaxSlice[2]; // Get current label at the point3D of interest uint currentSlice=index[2]; @@ -342,7 +380,9 @@ TrackBifurcationFromPoint(MaskImagePointer & recon, typename ShapeFilterType::Pointer statFilter = ShapeFilterType::New(); imageToLabelFilter->SetBackgroundValue(GetBackgroundValue()); imageToLabelFilter->SetInput(s); - statFilter->SetInput(imageToLabelFilter->GetOutput()); + statFilter->SetInput(imageToLabelFilter->GetOutput()); + // statFilter->SetComputeFeretDiameter( true ); + statFilter->ComputePerimeterOn(); // To be able to get proper Roundness value statFilter->Update(); typename LabelMapType::Pointer labelMap = statFilter->GetOutput(); @@ -364,19 +404,26 @@ TrackBifurcationFromPoint(MaskImagePointer & recon, centroids.push_back(center); centroids_label.push_back(label); labels_size.push_back(labelMap->GetLabelObject(label)->GetPhysicalSize()); + //DD(labels_size.back()); + //DD(labelMap->GetLabelObject(label)->GetRoundness()); + // previousCenter = centroids.back(); } } + // ------------------------- + // If no centroid were found if (centroids.size() == 0) { // Last attempt to find -> check if previous centroid is inside a CCL // if in s -> get value, getcentroid add. - DD(currentSlice); - DD("Last change to find"); + // DD(currentSlice); + //DD("Last change to find"); + //DD(previous_slice_label); + //DD(newLabel); typename MaskSliceType::IndexType previousCenterIndex; s->TransformPhysicalPointToIndex(previousCenter, previousCenterIndex); - DD(previousCenter); + //DD(previousCenter); LabelType labelInSlice = s->GetPixel(previousCenterIndex); - DD(labelInSlice); + //DD(labelInSlice); if (labelInSlice != GetBackgroundValue()) { centroids.push_back(labelMap->GetLabelObject(labelInSlice)->GetCentroid()); centroids_label.push_back(labelInSlice); @@ -384,16 +431,39 @@ TrackBifurcationFromPoint(MaskImagePointer & recon, } } - - // DD(centroids.size()); - + // Some centroid were found // If several centroids, we found a bifurcation if (centroids.size() > 1) { + // int n = centroids.size(); + // Debug point + std::vector d; + clitk::PointsUtils::Convert2DListTo3DList(centroids, currentSlice, m_Mask, d); + // DDV(d, d.size()); + + /* + // try one or all centroids + std::vector< + for(uint a<=0; a c; + if (a==nb) { for(uint x=0; x GetMaxNumberOfFoundBifurcation()) { found = true; - DD("max bif reach"); + //DD("max bif reach"); for(uint c=0; c::Convert2DTo3D(centroids[c], m_Mask, currentSlice, bif); @@ -408,16 +478,27 @@ TrackBifurcationFromPoint(MaskImagePointer & recon, indexOfLargest = b; } } + //DD(indexOfLargest); + //DD(labels_size[indexOfLargest]); SlicePointType c = centroids[indexOfLargest]; LabelType l = centroids_label[indexOfLargest]; + //DD(l); + //DD(c); centroids.clear(); centroids.push_back(c); + centroids_label.clear(); centroids_label.push_back(l); } } + + + /* ==> here all centroid are considered as ok.*/ + + // REMOVE IF CENTROID=1, REPLACE BY >0 // if only one centroids, we change the current image with the current label if (centroids.size() == 1) { + //DD(centroids_label[0]); s = clitk::SetBackground(s, s, centroids_label[0], newLabel, true); slices_recon[currentSlice] = s; previous_slice_label = newLabel; @@ -435,9 +516,9 @@ TrackBifurcationFromPoint(MaskImagePointer & recon, // It can happend that the centroid is inside the BG, so we keep // the largest CCL (the first); if (v == GetBackgroundValue()) { - DD(currentSlice); - DD("inside BG"); - DD(centroids[0]); + // DD(currentSlice); + // DD("inside BG"); + // DD(centroids[0]); v = 1; // largest one } @@ -454,12 +535,17 @@ TrackBifurcationFromPoint(MaskImagePointer & recon, } if (centroids.size() == 0) { - DD("ZERO"); + // DD("ZERO"); found = true; } if (currentSlice == slices_recon.size()-1) { - DD("end of slices"); + // DD("end of slices"); + found = true; + } + + if (currentSlice == maxSlice) { + // DD("end max slice"); found = true; } @@ -473,4 +559,436 @@ TrackBifurcationFromPoint(MaskImagePointer & recon, //-------------------------------------------------------------------- +//-------------------------------------------------------------------- +template +void +clitk::ExtractMediastinalVesselsFilter:: +TrackVesselsFromPoint(MaskImagePointer & recon, + std::vector & slices, + MaskImagePointType seedPoint, + MaskImagePointType pointMaxSlice, + LabelType newLabel) { + StartNewStep("Track the SoughtVessel from the seed point"); + + // Find first slice index + MaskImageIndexType seedIndex; + recon->TransformPhysicalPointToIndex(seedPoint, seedIndex); + // int numberOfBifurcation = 0; + typedef typename MaskSliceType::PointType SlicePointType; + SlicePointType previousCentroid; + previousCentroid[0] = seedPoint[0]; + previousCentroid[1] = seedPoint[1]; + + // Max slice + MaskImageIndexType indexMaxSlice; + recon->TransformPhysicalPointToIndex(pointMaxSlice, indexMaxSlice); + uint maxSlice = std::min((uint)indexMaxSlice[2], (uint)slices.size()); + // DD(maxSlice); + + // Get current label at the seedPoint of interest + uint currentSlice=seedIndex[2]; + bool found = false; + // LabelType previous_slice_label=recon->GetPixel(seedIndex); + + // Currrent label map variable + typedef itk::ShapeLabelObject< LabelType, 2> LabelObjectType; + typedef itk::LabelMap< LabelObjectType > LabelMapType; + typename LabelMapType::Pointer labelMap; + std::vector shapeObjectsList; + std::vector shapeObjectsSliceList; // keep slice, useful for 'union' + typename LabelObjectType::Pointer previousShapeObject; + + do { + // Debug + std::cout << std::endl; + //DD(currentSlice); + ImagePointType c; + clitk::PointsUtils::Convert2DTo3D(previousCentroid, m_Mask, currentSlice-1, c); + //DD(c); + + // Consider current reconstructed slice + MaskSlicePointer s = slices[currentSlice]; + MaskSlicePointer previous; + shapeObjectsList.clear(); + shapeObjectsSliceList.clear(); + + // Get shape of all labels in the current slice (it is already labelized) + + // Normal -> same CCL with different label + // PB -> sometimes same label in different CCL ! car growing + //ADD les deux l+s ? mais avec max entre chaque ccl number (bof) + /* + for each label in s -> map avec label in l; if different -> change + */ + MaskSlicePointer ll = clitk::Labelize(s, GetBackgroundValue(), true, 1); + // writeImage(s, "slice-"+toString(currentSlice)+".mhd"); + //writeImage(ll, "slice-label-"+toString(currentSlice)+".mhd"); + typedef itk::ImageRegionIteratorWithIndex IteratorType; + IteratorType its(s, s->GetLargestPossibleRegion()); + IteratorType itl(ll, ll->GetLargestPossibleRegion()); + std::map labelInL; + std::map > labelToChange; + its.GoToBegin(); + itl.GoToBegin(); + int currentLabel = newLabel+10; + while (!its.IsAtEnd()) { + LabelType labs = its.Get(); + if (labs != GetBackgroundValue()) { + LabelType labl = itl.Get(); + if (labelInL.find(labs) == labelInL.end()) { // Not found in map, first time + // DD("first"); + labelInL[labs] = labl; + //DD(labs); + //DD(labl); + } + else { + if (labelInL[labs] != labl) { // I found a labs with a different labl. Store it. + if (labelToChange[labs].find(labl) == labelToChange[labs].end()) { // if not already found + //DD("found"); + //DD(labs); + //DD(labl); + //DD(labelInL[labs]); + //DD(currentLabel); + labelToChange[labs][labl] = currentLabel; + ++currentLabel; + } + } + } + } + ++its; + ++itl; + } + + its.GoToBegin(); + itl.GoToBegin(); + while (!its.IsAtEnd()) { + LabelType labs = its.Get(); + if (labs != GetBackgroundValue()) { // if not BG + LabelType labl = itl.Get(); + if (labelToChange[labs].find(labl) != labelToChange[labs].end()) { // if some labs can change their label + its.Set(labelToChange[labs][labl]); // change with the label for + } + } + ++its; + ++itl; + } // end while + + // writeImage(s, "slice-final"+toString(currentSlice)+".mhd"); + + + labelMap = clitk::ComputeLabelMap(s, GetBackgroundValue(), true); + // DD(labelMap->GetNumberOfLabelObjects()); + + // If this is the first slice, get the object that contains the seed + if (currentSlice == seedIndex[2]) { + // DD("First slice"); + LabelType l = recon->GetPixel(seedIndex); + // DD(l); + shapeObjectsList.push_back(labelMap->GetLabelObject(l)); + shapeObjectsSliceList.push_back(s); + previous = s; + previousCentroid = shapeObjectsList[0]->GetCentroid(); + previousShapeObject = shapeObjectsList[0]; + } + else { + previous = slices[currentSlice-1]; + // Loop on labels to check if centroid is on the previous contour + for(uint c=0; cGetNumberOfLabelObjects(); c++) { + // Get the current label number + int label = labelMap->GetLabels()[c]; + //DD(label); + // Get the centroids + SlicePointType centroid = labelMap->GetLabelObject(label)->GetCentroid(); + // Convert centroid into index in previous slice (same coordinate) + typename MaskSliceType::IndexType centroidIndex; + previous->TransformPhysicalPointToIndex(centroid, centroidIndex); + LabelType labelInPreviousSlice = previous->GetPixel(centroidIndex); + // if this current centroid was in the current label, we keep it + //DD(labelInPreviousSlice); + if (labelInPreviousSlice == newLabel) { + shapeObjectsList.push_back(labelMap->GetLabelObject(label)); + shapeObjectsSliceList.push_back(s); + } + } + } + + + // Potentially the previous centroid could be inside another + // labels, we consider i + typename MaskSliceType::IndexType previousCentroidIndex; + s->TransformPhysicalPointToIndex(previousCentroid, previousCentroidIndex); + LabelType l = s->GetPixel(previousCentroidIndex); + //DD(l); + if (l != 0) { // if is not the background label + int index = -1; + for(uint c=0; cGetLabel() == l) { + index = c; + } + } + if (index == -1) { + //DD("not inside"); + shapeObjectsList.push_back(labelMap->GetLabelObject(l)); + shapeObjectsSliceList.push_back(s); + } + else { + // DD("already inside"); + } + } + + // for(uint c=0; cGetLabel() << " " + // << shapeObjectsList[c]->GetCentroid() << std::endl; + // } + + + // If several candidates, add one more with the union of all candidates + MaskSlicePointer temp; + if (shapeObjectsList.size() > 1) { + //DD("add union"); + // Copy the slice + temp = clitk::Clone(s); + // change label to a single label + LabelType l = newLabel+1; + for(uint c=0; cGetLabel(); + temp = clitk::SetBackground(temp, temp, ll, l, true); + } + // Compute Label object properties + labelMap = clitk::ComputeLabelMap(temp, GetBackgroundValue(), true); + shapeObjectsList.push_back(labelMap->GetLabelObject(l)); + shapeObjectsSliceList.push_back(temp); + } + + /* + for(uint c=0; cGetLabel() << " " + << shapeObjectsList[c]->GetCentroid() << std::endl; + } + */ + + + for(uint c=0; c::Convert2DTo3D(shapeObjectsList[c]->GetCentroid(), m_Mask, currentSlice, cc); + // std::cout << c << " " << shapeObjectsList[c]->GetLabel() << " " + // // << shapeObjectsList[c]->GetCentroid() << " " + // << cc << " " + // << shapeObjectsList[c]->GetPhysicalSize() << " " + // << shapeObjectsList[c]->GetRoundness() << std::endl; + } + + + if (shapeObjectsList.size() == 0) { + found = true; + } + else { + // Heuristic to select the good one. For each candidate, we consider the size + std::vector sizes; + std::vector roundness; + std::vector index_sizes; + std::vector index_roundness; + double previousSize = previousShapeObject->GetPhysicalSize(); + //DD(previousSize); + for(uint c=0; cGetPhysicalSize(); + sizes.push_back(fabs(previousSize-s)/previousSize); + roundness.push_back(fabs(1.0-shapeObjectsList[c]->GetRoundness())); + index_sizes.push_back(c); + index_roundness.push_back(c); + } + //DDV(sizes, sizes.size()); + //DDV(roundness, roundness.size()); + // DDV(index_sizes, index_sizes.size()); + // DDV(index_roundness, index_roundness.size()); + sort(index_sizes.begin(), index_sizes.end(), index_cmp&>(sizes)); + sort(index_roundness.begin(), index_roundness.end(), index_cmp&>(roundness)); + //DDV(index_sizes, index_sizes.size()); + // DDV(index_roundness, index_roundness.size()); + + // TEMPORARY GET THE FIRST + int best = index_sizes[0]; + // if (currentSlice == seedIndex[2]) { // first contour => idiot, first = single contour + // best = index_roundness[0]; // best is more round + // } + LabelType label = shapeObjectsList[best]->GetLabel(); + // DD(label); + s = shapeObjectsSliceList[best]; + s = clitk::SetBackground(s, s, label, newLabel, true); + + // HERE + + // It can happend that several CCL share this same label. To + // prevent this case, we only consider the one that contains + // the centroid. + + // TODO -> PREVIOUS CENTROID ??? + + MaskSlicePointer temp = clitk::Binarize(s, newLabel, newLabel, GetBackgroundValue(), GetForegroundValue()); + temp = clitk::Labelize(temp, GetBackgroundValue(), true, 1); + typename MaskSliceType::IndexType centroids_index; + temp->TransformPhysicalPointToIndex(shapeObjectsList[best]->GetCentroid(), centroids_index); + typename MaskSliceType::PixelType v = temp->GetPixel(centroids_index); + if (v == GetBackgroundValue()) { + // DD(currentSlice); + // DD("inside BG"); + //DD(centroids[0]); + v = 1; // largest one + } + + //DD(v); + temp = clitk::Binarize(temp, v, v, GetBackgroundValue(), newLabel); + //writeImage(temp, "relabel-"+toString(currentSlice)+".mhd"); + s = temp; + + + // end + slices[currentSlice] = s; + previousCentroid = shapeObjectsList[best]->GetCentroid(); + previousShapeObject = shapeObjectsList[best]; + } + + ++currentSlice; + + if (currentSlice == maxSlice) { + // DD("end max slice"); + found = true; + } + + } while (!found); + + /* + // ------------------------- + // If no centroid were found + if (shapeObjectsList.size() == 0) { + // Last attempt to find -> check if previous centroid is inside a CCL + // if in s -> get value, getcentroid add. + DD(currentSlice); + DD("Last change to find"); + DD(previous_slice_label); + DD(newLabel); + typename MaskSliceType::IndexType previousCentroidIndex; + s->TransformPhysicalPointToIndex(previousCentroid, previousCentroidIndex); + DD(previousCentroid); + LabelType labelInSlice = s->GetPixel(previousCentroidIndex); + DD(labelInSlice); + if (labelInSlice != GetBackgroundValue()) { + centroids.push_back(labelMap->GetLabelObject(labelInSlice)->GetCentroid()); + centroids_label.push_back(labelInSlice); + labels_size.push_back(labelMap->GetLabelObject(labelInSlice)->GetPhysicalSize()); + } + } + + // Some centroid were found + // If several centroids, we found a bifurcation + if (centroids.size() > 1) { + // int n = centroids.size(); + // Debug point + std::vector d; + clitk::PointsUtils::Convert2DListTo3DList(centroids, currentSlice, m_Mask, d); + DDV(d, d.size()); + + // new potential bifurcation found + numberOfBifurcation++; + // If the number of bifurcation is greater than the required one, we stop + if (numberOfBifurcation > GetMaxNumberOfFoundBifurcation()) { + found = true; + DD("max bif reach"); + for(uint c=0; c::Convert2DTo3D(centroids[c], m_Mask, currentSlice, bif); + bifurcations.push_back(bif); + } + } + // Else we continue along the main (largest) connected component + else { + int indexOfLargest = 0; + for(uint b=0; b labels_size[indexOfLargest]) { + indexOfLargest = b; + } + } + DD(indexOfLargest); + DD(labels_size[indexOfLargest]); + SlicePointType c = centroids[indexOfLargest]; + LabelType l = centroids_label[indexOfLargest]; + DD(l); + DD(c); + centroids.clear(); + centroids.push_back(c); + centroids_label.clear(); + centroids_label.push_back(l); + } + } + */ + + /* ==> here all centroid are considered as ok.*/ + + /* + // REMOVE IF CENTROID=1, REPLACE BY >0 + + // if only one centroids, we change the current image with the current label + if (centroids.size() == 1) { + DD(centroids_label[0]); + s = clitk::SetBackground(s, s, centroids_label[0], newLabel, true); + slices[currentSlice] = s; + previous_slice_label = newLabel; + // It can happend that several CCL share this same label. To + // prevent this case, we only consider the one that contains + // the centroid. + MaskSlicePointer temp = clitk::Binarize(s, newLabel, newLabel, GetBackgroundValue(), GetForegroundValue()); + // writeImage(temp, "bin-"+toString(currentSlice)+".mhd"); + temp = clitk::Labelize(temp, GetBackgroundValue(), true, 1); + //writeImage(temp, "label-"+toString(currentSlice)+".mhd"); + typename MaskSliceType::IndexType centroids_index; + temp->TransformPhysicalPointToIndex(centroids[0], centroids_index); + typename MaskSliceType::PixelType v = temp->GetPixel(centroids_index); + + // It can happend that the centroid is inside the BG, so we keep + // the largest CCL (the first); + if (v == GetBackgroundValue()) { + DD(currentSlice); + DD("inside BG"); + DD(centroids[0]); + v = 1; // largest one + } + + //DD(v); + temp = clitk::Binarize(temp, v, v, GetBackgroundValue(), newLabel); + //writeImage(temp, "relabel-"+toString(currentSlice)+".mhd"); + s = temp; + slices[currentSlice] = s; + + // I need to recompute the centroid if we have removed some + // connected component. + clitk::ComputeCentroids(s, GetBackgroundValue(), centroids); + previousCentroid = centroids[1]; + } + + if (centroids.size() == 0) { + DD("ZERO"); + found = true; + } + + if (currentSlice == slices.size()-1) { + DD("end of slices"); + found = true; + } + + if (currentSlice == maxSlice) { + DD("end max slice"); + found = true; + } + + // iterate + ++currentSlice; + } while (!found); + */ + + // End + StopCurrentStep(); +} +//-------------------------------------------------------------------- + + #endif //#define CLITKEXTRACTMEDIASTINALVESSELSFILTER_TXX -- 2.47.1