X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=segmentation%2FclitkExtractMediastinalVesselsFilter.txx;h=537b14867b1d3cfa74692b8e4326f4d65873f04f;hb=5a7da4aedae5c204bc55c187717193e5950f9a44;hp=2198529b8c60cd667e1362ae0ab9767ceaa8f8dd;hpb=a515cd4eb114c9310570341ca29f35484356a1e8;p=clitk.git diff --git a/segmentation/clitkExtractMediastinalVesselsFilter.txx b/segmentation/clitkExtractMediastinalVesselsFilter.txx index 2198529..537b148 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,8 @@ ExtractMediastinalVesselsFilter(): SetMaxDistanceLeftToCarina(35); SetMaxDistanceRightToCarina(35); SetSoughtVesselSeedName("NoSeedNameGiven"); + SetFinalOpeningRadius(1); + VerboseTrackingFlagOff(); } //-------------------------------------------------------------------- @@ -112,24 +122,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 +186,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 +206,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"); + // 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 +275,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"); @@ -262,6 +295,10 @@ CropInputImage() { m_Input = clitk::CropImageRemoveLowerThan(m_Input, 2, m_CarinaZ, false, GetBackgroundValue()); + // // Get seed, crop around + // MaskImagePointType SoughtVesselSeedPoint; + // GetAFDB()->GetPoint3D(m_SoughtVesselSeedName, SoughtVesselSeedPoint); + // Crop post double m_CarinaY = centroids[1][1]; m_Input = clitk::CropImageRemoveGreaterThan(m_Input, 1, @@ -271,7 +308,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 +329,7 @@ CropInputImage() { m_Input = clitk::ResizeImageLike(m_Input, m_Mediastinum, GetBackgroundValue()); */ + // writeImage(m_Input, "crop.mhd"); // End StopCurrentStep(m_Input); } @@ -306,6 +343,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,14 +354,30 @@ 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]; bool found = false; LabelType previous_slice_label=recon->GetPixel(index); + + + if (GetVerboseTrackingFlag()) { + std::cout << "TrackBifurcationFromPoint " << std::endl; + std::cout << "\t point3D = " << point3D << std::endl; + std::cout << "\t pointMaxSlice = " << pointMaxSlice << std::endl; + std::cout << "\t newLabel = " << newLabel << std::endl; + } + // DD(slices_recon.size()); do { - // DD(currentSlice); + if (GetVerboseTrackingFlag()) { + std::cout << "currentSlice = " << currentSlice << std::endl; + } // Consider current reconstructed slice MaskSlicePointer s = slices_recon[currentSlice]; MaskSlicePointer previous; @@ -342,7 +396,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 +420,29 @@ 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 (GetVerboseTrackingFlag()) { + std::cout << "no centroid" << std::endl; + } + // 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 +450,42 @@ TrackBifurcationFromPoint(MaskImagePointer & recon, } } - - // DD(centroids.size()); - + // Some centroid were found // If several centroids, we found a bifurcation if (centroids.size() > 1) { + if (GetVerboseTrackingFlag()) { + std::cout << "Centroid" << centroids.size() << std::endl; + } + // 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 +500,31 @@ 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) { + if (GetVerboseTrackingFlag()) { + std::cout << "Centroid" << centroids.size() << std::endl; + } + + //DD(centroids_label[0]); s = clitk::SetBackground(s, s, centroids_label[0], newLabel, true); slices_recon[currentSlice] = s; previous_slice_label = newLabel; @@ -435,9 +542,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 } @@ -453,13 +560,22 @@ TrackBifurcationFromPoint(MaskImagePointer & recon, previousCenter = centroids[1]; } + if (GetVerboseTrackingFlag()) { + std::cout << "End iteration c=" << centroids.size() << std::endl; + } + 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 +589,447 @@ 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; + + if (GetVerboseTrackingFlag()) { + std::cout << "TrackBifurcationFromPoint " << std::endl; + std::cout << "\t seedPoint = " << seedPoint << std::endl; + std::cout << "\t pointMaxSlice = " << pointMaxSlice << std::endl; + std::cout << "\t newLabel = " << newLabel << std::endl; + } + + do { + // Debug + //std::cout << std::endl; + //DD(currentSlice); + ImagePointType c; + clitk::PointsUtils::Convert2DTo3D(previousCentroid, m_Mask, currentSlice-1, c); + //DD(c); + + if (GetVerboseTrackingFlag()) { + std::cout << "Loop slice = " << currentSlice << " c = " << c << std::endl; + } + + // 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