/* * airwaysTree.txx * * Created on: May 3, 2014 * Author: caceres@creatis.insa-lyon.fr * Modifications by: Alfredo Morales Pinzón */ #ifndef _AIRWAYS_TREE_TXX_ #define _AIRWAYS_TREE_TXX_ #include "airwaysTree.h" namespace airways { AirwaysTree::AirwaysTree() : m_root(NULL) { } //Ceron AirwaysTree::AirwaysTree(TInputImage::Pointer img, TInputImage::Pointer img_skele, Node* root, bool shouldUpdate){ this->m_root = root; this->m_root->SetLevel(0); this->m_img = img; this->m_skeleton = img_skele; //TODO: Should this calculate levels and populate edges and nodes vectors? FillTree(root); if(shouldUpdate) this->UpdateEdges(); } void AirwaysTree::FillTree(Node* node){ //std::cout << "Calls fill tree for " << node->GetCoords() << std::endl; this->m_nodes.push_back(node); node->SetId(this->m_nodes.size()); if(node->GetEdge() != NULL){ this->m_edges.push_back(node->GetEdge()); node->GetEdge()->UpdateEdgeInfo(); } int level = node->GetLevel(); //std::cout << "Node is at level " << level << std::endl; vec_nodes::const_iterator it = node->GetChildren().begin(); for (; it != node->GetChildren().end(); ++it){ (*it)->SetLevel(level+1); this->FillTree(*it); } } AirwaysTree::AirwaysTree(TInputImage::Pointer img, TInputImage::Pointer img_sk, Node* root) { this->m_root = root; this->m_root->SetLevel(0); this->m_skeleton = img_sk; this->m_img = img; this->UpdateEdges(); } AirwaysTree::AirwaysTree(TInputImage::Pointer image_airwaySegmentation, TInputImage::Pointer image_skeletonDM, EdgeVector& vector_edges, Edge* edge_trachea) { std::cout << "AirwaysTree::AirwaysTree(TInputImage::Pointer img, TInputImage::Pointer img_sk, EdgeVector& tEdgeVector, Edge* trachea)" << std::endl; std::cout << "Edges to add:" << vector_edges.size() << std::endl; if(edge_trachea == NULL) std::cout << "The trachea edge is NULL" << std::endl; // Set the attribtes this->m_skeleton = image_skeletonDM; this->m_img = image_airwaySegmentation; this->m_root = edge_trachea->m_source; this->m_root->SetLevel(0); this->m_nodes.push_back(edge_trachea->m_source); // Add the first node, the root to the nodes of the tree edge_trachea->m_source->SetId(this->m_nodes.size());// Set the root id // Insert the trachea edge this->Insert(edge_trachea); // Insert all edges unsigned int iniSize = vector_edges.size(); while (!vector_edges.empty()) { bool oneEdgeAdded = false; EdgeVector::iterator it = vector_edges.begin(); while (it != vector_edges.end()) { if (this->Insert(*it)) { std::cout << "Edges added: [" << (*it)->GetSource()->GetCoords() << "]->[" << (*it)->GetTarget()->GetCoords() << "], missing: " << vector_edges.size()-1 << std::endl; oneEdgeAdded = true; it = vector_edges.erase(it); } else ++it; } //while // If there are edges to be added but they could not be added if(!oneEdgeAdded) { std::cout << "Edges not added:" << vector_edges.size() << std::endl; for (EdgeVector::iterator it = vector_edges.begin(); it != vector_edges.end(); ++it) std::cout << "Edge missing: [" << (*it)->GetSource()->GetCoords() << "]->[" << (*it)->GetTarget()->GetCoords() << "]" << std::endl; break; } // AMP: I did not find any explanation for this "exception" /*count++; if (count == iniSize) { std::cout << "handled exception: arwaysTree.txx, AirwaysTree" << std::endl; break; } //if */ } //while this->UpdateEdges(); std::cout << "AirwaysTree::AirwaysTree(TInputImage::Pointer img, TInputImage::Pointer img_sk, EdgeVector& tEdgeVector, Edge* trachea) ... OK" << std::endl; } AirwaysTree::~AirwaysTree() { } Node* AirwaysTree::GetRoot() const { return this->m_root; } std::string AirwaysTree::GetImageName() const { return (this->m_img_name); } std::string AirwaysTree::GetResultPath() const { return (this->m_result_path); } TInputImage::Pointer AirwaysTree::GetSegmentedImage() const { return this->m_img; } TInputImage::Pointer AirwaysTree::GetSkeletonImage() const { return this->m_skeleton; } const Node* AirwaysTree::GetNode(const Vec3 nodeCoords) const { return this->GetNode(nodeCoords); } Node* AirwaysTree::GetNodeById(unsigned int nId) { return this->m_root->GetNodeById(nId); } int AirwaysTree::GetDepthById(unsigned int nId) { return this->m_root->GetDepthById(nId); } unsigned int AirwaysTree::CountMarkedNodes(Node* current) const { if (current == NULL) current = this->m_root; Node* aux = NULL; bool found = current->FindMarked(aux); if (!found && !current->IsMarked()) return 0; if (aux != NULL && found) current = aux; unsigned int count = 1; vec_nodes::const_iterator it = current->GetChildren().begin(); for (; it != current->GetChildren().end(); ++it) count += this->CountMarkedNodes(*it); return count; } unsigned int AirwaysTree::GetWeight( ) const { if (this->m_root == NULL) return 0; return this->m_root->GetWeight(); } unsigned int AirwaysTree::GetHeight(Node* current) const { if (current == NULL) current = this->m_root; if (current->IsLeaf()) return 1; unsigned int max = 0; vec_nodes::const_iterator it = current->GetChildren().begin(); for (; it != current->GetChildren().end(); ++it) { unsigned int cMax = this->GetHeight(*it); if (cMax > max) max = cMax; } //rof if (current == this->m_root) return max; return ++max; } unsigned int AirwaysTree::GetLevels(Node* current, unsigned int cLevel) const { if (current == NULL) current = this->m_root; if (current->IsLeaf()) return current->GetLevel(); unsigned int maxLevel = cLevel; vec_nodes::const_iterator it = current->GetChildren().begin(); for (; it != current->GetChildren().end(); ++it) { unsigned int level = this->GetLevels(*it, maxLevel); if (level > maxLevel) maxLevel = level; } //rof return maxLevel; } unsigned int AirwaysTree::GetNumberOfLeafs( ) const { if(!this->m_root) return 0; return this->m_root->GetNumberOfLeafs( ); } const EdgeVector& AirwaysTree::GetEdges() const { return this->m_edges; } const vec_nodes& AirwaysTree::GetNodes() const { return this->m_nodes; } const Node* AirwaysTree::GetClosestBrachNodeToIndex(float point_x, float point_y, float point_z) const { float distance = 0; Node* closestNode = this->m_root->GetClosestBranchNodeToPoint(point_x, point_y, point_z, distance); return closestNode; } void AirwaysTree::GetBrancheNodesInfluencingPoint(float point_x, float point_y, float point_z, vec_nodes& vec_nodes_influence) { if(this->m_root) { std::cout << "AirwaysTree::GetBrancheNodesInfluencingPoint" << std::endl; this->m_root->GetBrancheNodesInfluencingPoint(point_x, point_y, point_z, vec_nodes_influence); } } AirwaysTree& AirwaysTree::GetTreeFromMarkedNodes(Node* currentNode, AirwaysTree* tree) { if (tree == NULL) { if (!this->m_root->IsMarked()) return *(new AirwaysTree()); currentNode = this->m_root; tree = new AirwaysTree(); Node* current = new Node(currentNode->GetCoords()); tree->SetRoot(current); vec_nodes::const_iterator it = currentNode->GetChildren().begin(); for (; it != currentNode->GetChildren().end(); ++it) this->GetTreeFromMarkedNodes(*it, tree); this->ImageReconstruction(tree->m_img); //this->ImageReconstruction(tree->m_skeleton); return *tree; } //fi if (currentNode->IsMarked()) { Edge* edge = new Edge(); *edge = *currentNode->GetEdge(); Node* target = new Node(currentNode->GetCoords()); edge->m_target = target; tree->Insert(edge); vec_nodes::const_iterator it = currentNode->GetChildren().begin(); for (; it != currentNode->GetChildren().end(); ++it) this->GetTreeFromMarkedNodes(*it, tree); } //fi return *(new AirwaysTree()); } AirwaysTree& AirwaysTree::GetSubTreeFromNode(Node* node, AirwaysTree* tree) { if (tree == NULL) { tree = new AirwaysTree(); Node* current = new Node(node->GetCoords()); tree->SetRoot(current); vec_nodes::const_iterator it = node->GetChildren().begin(); for (; it != node->GetChildren().end(); ++it) this->GetSubTreeFromNode(*it, tree); this->ImageReconstructionFromNode(tree->m_img, node); //this->ImageReconstructionFromNode(tree->m_skeleton, node, true); return *tree; } //fi Edge* edge = new Edge(); *edge = *node->GetEdge(); Node* target = new Node(node->GetCoords()); edge->m_target = target; tree->Insert(edge); vec_nodes::const_iterator it = node->GetChildren().begin(); for (; it != node->GetChildren().end(); ++it) this->GetSubTreeFromNode(*it, tree); return *(new AirwaysTree()); } AirwaysTree& AirwaysTree::GetSubTreeByLevels(const int& level, Node* node, AirwaysTree* tree) { if (tree == NULL) { node = this->m_root; tree = new AirwaysTree(); Node* current = new Node(node->GetCoords()); tree->SetRoot(current); if (node->GetLevel() <= level) { node->Mark(); vec_nodes::const_iterator it = node->GetChildren().begin(); for (; it != node->GetChildren().end(); ++it) this->GetSubTreeByLevels(level, *it, tree); } //fi if (node->GetLevel() == level) { DuplicatorType::Pointer duplicator = DuplicatorType::New(); duplicator->SetInputImage(this->m_img); duplicator->Update(); tree->m_img = duplicator->GetOutput(); duplicator->SetInputImage(this->m_skeleton); duplicator->Update(); tree->m_skeleton = duplicator->GetOutput(); } //if else { this->ImageReconstruction(tree->m_img); //this->ImageReconstruction(tree->m_skeleton, true); } //else this->UnMarkAll(); return *tree; } //fi if (node->GetLevel() <= level) { node->Mark(); Edge* edge = new Edge(); *edge = *node->GetEdge(); Node* target = new Node(node->GetCoords()); edge->m_target = target; tree->Insert(edge); vec_nodes::const_iterator it = node->GetChildren().begin(); for (; it != node->GetChildren().end(); ++it) this->GetSubTreeByLevels(level, *it, tree); if (node->GetChildren().size() == 1) { Node* child = *(node->GetChildren().begin()); node->MergeNodes(child); const Edge* edge = (child)->GetEdge(); //removing from nodeVector and edgeVector EdgeVector::iterator it2 = this->m_edges.begin(); for (; it2 != this->m_edges.end(); ++it2) if (edge == *it2) { this->m_edges.erase(it2); break; } //if vec_nodes::iterator it3 = this->m_nodes.begin(); for (; it3 != this->m_nodes.end(); ++it3) if (child == *it3) { this->m_nodes.erase(it3); break; } //if } //if } //if return *(new AirwaysTree()); } AirwaysTree& AirwaysTree::GetSubTreeByLength(const double& length, Node* node, AirwaysTree* tree, double cLenght) { if (tree == NULL) { node = this->m_root; tree = new AirwaysTree(); Node* current = new Node(node->GetCoords()); tree->SetRoot(current); node->Mark(); vec_nodes::const_iterator it = node->GetChildren().begin(); for (; it != node->GetChildren().end(); ++it) this->GetSubTreeByLength(length, *it, tree); this->ImageReconstruction(tree->m_img); //this->ImageReconstruction(tree->m_skeleton, true); this->UnMarkAll(); return *tree; } //fi cLenght += node->GetEdge()->m_length; if (cLenght <= length) { node->Mark(); Edge* edge = new Edge(); *edge = *node->GetEdge(); Node* target = new Node(node->GetCoords()); edge->m_target = target; tree->Insert(edge); vec_nodes::const_iterator it = node->GetChildren().begin(); for (; it != node->GetChildren().end(); ++it) this->GetSubTreeByLength(length, *it, tree, cLenght); if (node->GetChildren().size() == 1) { Node* child = *(node->GetChildren().begin()); node->MergeNodes(child); const Edge* edge = (child)->GetEdge(); //removing from nodeVector and edgeVector EdgeVector::iterator it2 = this->m_edges.begin(); for (; it2 != this->m_edges.end(); ++it2) if (edge == *it2) { this->m_edges.erase(it2); break; } //if vec_nodes::iterator it3 = this->m_nodes.begin(); for (; it3 != this->m_nodes.end(); ++it3) if (child == *it3) { this->m_nodes.erase(it3); break; } //if } //if } //if return *(new AirwaysTree()); } AirwaysTree& AirwaysTree::GetSubTreeByRadius(const double& radius, Node* node, AirwaysTree* tree, double cRadius) { if (tree == NULL) { node = this->m_root; tree = new AirwaysTree(); Node* current = new Node(node->GetCoords()); tree->SetRoot(current); node->Mark(); vec_nodes::const_iterator it = node->GetChildren().begin(); for (; it != node->GetChildren().end(); ++it) this->GetSubTreeByRadius(radius, *it, tree); this->ImageReconstruction(tree->m_img); //this->ImageReconstruction(tree->m_skeleton, true); this->UnMarkAll(); return *tree; } //fi cRadius += node->GetEdge()->m_aRadius; if (cRadius >= radius) { node->Mark(); Edge* edge = new Edge(); *edge = *node->GetEdge(); Node* target = new Node(node->GetCoords()); edge->m_target = target; tree->Insert(edge); vec_nodes::const_iterator it = node->GetChildren().begin(); for (; it != node->GetChildren().end(); ++it) this->GetSubTreeByRadius(radius, *it, tree, cRadius); if (node->GetChildren().size() == 1) { Node* child = *(node->GetChildren().begin()); node->MergeNodes(child); const Edge* edge = (child)->GetEdge(); //removing from nodeVector and edgeVector EdgeVector::iterator it2 = this->m_edges.begin(); for (; it2 != this->m_edges.end(); ++it2) if (edge == *it2) { this->m_edges.erase(it2); break; } //if vec_nodes::iterator it3 = this->m_nodes.begin(); for (; it3 != this->m_nodes.end(); ++it3) if (child == *it3) { this->m_nodes.erase(it3); break; } //if } //if } //if return *(new AirwaysTree()); } void AirwaysTree::MarkLevels(const int& level, Node* currentNode) { if (currentNode == NULL) currentNode = this->m_root; if (currentNode->GetLevel() <= level) { currentNode->Mark(); vec_nodes::const_iterator it = currentNode->GetChildren().begin(); for (; it != currentNode->GetChildren().end(); it++) this->MarkLevels(level, *it); } //if } bool AirwaysTree::IsEmpty() const { return this->m_root == NULL; } bool AirwaysTree::IsNodeInsidePath(unsigned int idNode_starting, unsigned int idNode_ending, unsigned int idNode_searched) { // Check if the starting point exist Node* node_starting = this->m_root->GetNodeById(idNode_starting); if(!node_starting) return false; // Check if the searched node exist in the subtree of the starting node Node* node_searched = node_starting->GetNodeById(idNode_searched); if(!node_searched) return false; // Check if the ending node exist in the subtree of the searched node if(!node_searched->HasNodeId(idNode_ending)) return false; // If all conditions were true then the node is in the path return true; } void AirwaysTree::SetRoot(Node* root) { this->m_root = root; this->m_root->SetLevel(0); this->m_nodes.push_back(this->m_root); } void AirwaysTree::SetImageName(const std::string& img_name) { this->m_img_name = img_name; } void AirwaysTree::SetResultPath(const std::string& folderPath) { this->m_result_path = folderPath; } bool AirwaysTree::Insert(Edge* edge) { if (this->m_root == NULL) return false; // Search if the source or target coordinates exist in the tree Node* source = this->GetNode(edge->m_source->GetCoords()); Node* target = this->GetNode(edge->m_target->GetCoords()); // If the source and the target coordinates do not exist then the // edge can not be added, also if both exist in the tree. if ( ( source == NULL && target == NULL ) || ( source != NULL && target != NULL) ) return false; else if (source == NULL && target != NULL) // If target was found { // Change the direction of the edge edge->m_target = edge->m_source; edge->m_source = target; } else edge->m_source = source; // Set the target and source nodes for the Edge edge->m_target->SetEdge(edge); edge->m_target->SetLevel(edge->m_source->GetLevel() + 1); edge->m_source->AddChild(edge->m_target); // Add the new child node this->m_nodes.push_back(edge->m_target); this->m_edges.push_back(edge); // Set the id node edge->m_target->SetId(this->m_nodes.size()); return true; } void AirwaysTree::UnMarkAll(Node* currentNode) { if (currentNode == NULL) currentNode = this->m_root; currentNode->UnMark(); vec_nodes::const_iterator it = currentNode->GetChildren().begin(); for (; it != currentNode->GetChildren().end(); ++it) this->UnMarkAll(*it); } void AirwaysTree::UpdateLevels(unsigned int levels) { this->m_root->UpdateLevels(levels); } void AirwaysTree::CompareTreesOrkiszMorales(AirwaysTree& treeB, unsigned int Q, unsigned int F, vec_nodes& commonA, vec_nodes& commonB, vec_nodes& nonCommonA, vec_nodes& nonCommonB, std::map< unsigned int, std::vector >& map_A_to_B, std::map< unsigned int, std::vector >& map_B_to_A, std::vector< std::pair< std::pair, std::pair > >& vector_pair_edges_A_to_B) { // Algorithm // The algorithm is recursive it is implemented the node class. The idea is to overlap the initial nodes of the subtrees // and find the best branch correspondence for the first level of the trees. // Hypothesis: It is supposed that the roots of the trees are common, so the algorithm does not run in the root nodes // 1. Translate one of the subtree so that the initial nodes overlap. // 2. While one of the trees has non-marked child // 2.1 Compare each child to all the branches is the other tree. // 2.2 Select the pair, child and branch in the other tree, that has the lowest distance function. // 2.3 Add the pair and the distance to the final result. // 2.4 Mark the nodes // 2.5 Find and mark the omitted nodes in the similar branch. If the selected branch has more that 2 nodes it means that intemediary nodes do not have correpondece. // 2.6 Run the process (First step) using the found pair of nodes. if( !this->IsEmpty() && !treeB.IsEmpty() ) { // ---------------------------- // ---- Pre-Matching steps ---- // Get the root nodes Node* root_A = this->m_root; Node* root_B = treeB.m_root; // Mark the roots root_A->Mark(); root_B->Mark(); // Add the root match map_A_to_B[root_A->GetId()].push_back(root_B); map_B_to_A[root_B->GetId()].push_back(root_A); // Add the root nodes match pair_nodes pair_edgeA(root_A, root_A); pair_nodes pair_edgeB(root_B, root_B); std::pair< pair_nodes, pair_nodes > pairRoorNodes_edge(pair_edgeA, pair_edgeB); vector_pair_edges_A_to_B.push_back(pairRoorNodes_edge); // ---------------------------- // ----- Run the comparison---- root_A->CompareSubTreesOrkiszMorales(root_B, Q, F, commonA, commonB, nonCommonA, nonCommonB, map_A_to_B, map_B_to_A, vector_pair_edges_A_to_B); } else std::cout << "Trees are empties." << std::endl; } void AirwaysTree::MarkPathFromNodeToNode(Node* node_begin, Node* node_end) { if(this->m_root) this->m_root->MarkPathFromNodeToNode(node_begin, node_end); } void AirwaysTree::CompareTrees(AirwaysTree& treeB) { // Compare all the "branches" (paths) in treeA with all branches in treeB Vector_Pair_PairNodes_Score vectorPairNodesScore = this->CompareAllBranches(treeB); std::cout << "Vector pairs size:" << vectorPairNodesScore.size() << std::endl; // Algorithm to find the comment branches (paths) // Until one of the trees is empty // 1. Find the pair, with at least one leaf in the pair, with the lowest score // 2. Compare the score of the father node of the leaf, or one of the leafs, with the correspondent pair leaf // If the score is lower that the score of the actual pair // - The compared leaf is not common. Mark the compared leaf, delete the compared leave and save the leaf as not common. // If the score is greater // - The leafs are common then mark both leafs as commons. Mark both leaves, delete them and save them as common leafs. // Variables //AirwaysTree* tree_copyA = this->GetCopy(); //AirwaysTree* tree_copyB = treeB.GetCopy(); //NodeVector nonCommonNodes_A; //NodeVector commonNodes_A; //NodeVector nonCommonNodes_B; //NodeVector commonNodes_B; std::map nonCommonNodes_A; std::map commonNodes_A; std::map nonCommonNodes_B; std::map commonNodes_B; // Until one of the trees is not empty while( this->GetWeight() > 1 && treeB.GetWeight() > 1 ) { // Print the weight of the trees std::cout << "Weight [A,B]: [" << this->GetWeight() << "," << treeB.GetWeight() << "]" << std::endl; std::cout << "Leafs [A,B]: [" << this->GetNumberOfLeafs() << "," << treeB.GetNumberOfLeafs() << "]" << std::endl; std::cout << "Vector pairs size:" << vectorPairNodesScore.size() << std::endl; // 1. Find the pair, with at least one leaf in the pair, with the lowest score Pair_PairNodes_Score pair_nonMarked = this->GetBestLeaf(vectorPairNodesScore); Node* node_actualA = pair_nonMarked.first.first; Node* node_actualB = pair_nonMarked.first.second; double score_actual = pair_nonMarked.second; // 2. Take the leaf (L) and his father (F), the other node is called (O). Compare the score of the father node (F) with the correspondent pair leaf (O). if(node_actualA->IsLeaf()) { //const Edge* edgeActual = node_actualA->GetEdge(); //Node* targetActual = edgeActual->GetTarget(); //const unsigned int id_father = targetActual->GetId(); //double score_fatherA_to_B = this->GetPairNodes_Score(vectorPairNodesScore, 0, node_actualB->GetId()); double score_fatherA_to_B = this->GetPairNodes_Score(vectorPairNodesScore, node_actualA->GetEdge()->GetTarget()->GetId(), node_actualB->GetId()); //double score_fatherA_to_B = pair_fatherA_to_B.second; // If the score is lower than the score of the actual pair if(score_fatherA_to_B < score_actual) { //- The compared leaf is not common. Mark the compared leaf, delete the compared leave and save the leaf as not common. node_actualA->Mark(); std::map::iterator it; it=nonCommonNodes_A.find(node_actualA->GetId()); if(it==nonCommonNodes_A.end()) nonCommonNodes_A[node_actualA->GetId()] = node_actualA; //nonCommonNodes_A.push_back(node_actualA); } // If the score is greater else { // - The leafs are common then mark both leafs as commons. Mark both leaves, delete them and save them as common leafs. node_actualA->Mark(); node_actualB->Mark(); std::map::iterator it; it=commonNodes_B.find(node_actualB->GetId()); if(it==commonNodes_B.end()) commonNodes_B[node_actualB->GetId()] = node_actualB; it=commonNodes_A.find(node_actualA->GetId()); if(it==commonNodes_A.end()) { std::cout << "CommonNode A:" << node_actualA->GetId() << std::endl; commonNodes_A[node_actualA->GetId()] = node_actualA; } //commonNodes_B.push_back(node_actualB); //commonNodes_A.push_back(node_actualA); } this->DeleteNodeById(node_actualA->GetId()); this->DeleteEntriesByIdNode(vectorPairNodesScore, 0, node_actualA->GetId()); } else { double score_fatherB_to_A = this->GetPairNodes_Score(vectorPairNodesScore, node_actualA->GetId(), node_actualB->GetEdge()->GetTarget()->GetId()); //double score_fatherB_to_A = pair_fatherB_to_A.second; // If the score is lower that the score of the actual pair if(score_fatherB_to_A < score_actual) { //- The compared leaf is not common. Mark the compared leaf, delete the compared leave and save the leaf as not common. node_actualB->Mark(); std::map::iterator it; it=nonCommonNodes_B.find(node_actualB->GetId()); if(it==nonCommonNodes_B.end()) nonCommonNodes_B[node_actualB->GetId()] = node_actualB; //nonCommonNodes_B.push_back(node_actualB); } // If the score is greater else { // - The leafs are common then mark both leafs as commons. Mark both leaves, delete them and save them as common leafs. node_actualA->Mark(); node_actualB->Mark(); //commonNodes_B.push_back(node_actualB); //commonNodes_A.push_back(node_actualA); std::map::iterator it; it=commonNodes_B.find(node_actualB->GetId()); if(it==commonNodes_B.end()) commonNodes_B[node_actualB->GetId()] = node_actualB; it=commonNodes_A.find(node_actualA->GetId()); if(it==commonNodes_A.end()) commonNodes_A[node_actualA->GetId()] = node_actualA; } treeB.DeleteNodeById(node_actualB->GetId()); this->DeleteEntriesByIdNode(vectorPairNodesScore, 1, node_actualB->GetId()); } } // Print the results std::cout << "Non-CommonNodes [A,B]" << nonCommonNodes_A.size() << ", " << nonCommonNodes_B.size() << std::endl; std::cout << "CommonNodes [A,B]" << commonNodes_A.size() << ", " << commonNodes_B.size() << std::endl; // Get the branches with the lowest difference /*bool first = true; double lowestValue = 0; Pair_Node_Node bestPairNodes; int iteration = 1; for(Vector_Pair_PairNodes_Score::iterator it = vectorPairNodesScore.begin(); it != vectorPairNodesScore.end(); ++it ) { if(first) { lowestValue = (*it).second; bestPairNodes = (*it).first; first = false; } else if( (*it).second < lowestValue ) { lowestValue = (*it).second; bestPairNodes = (*it).first; } } // Print the best pair of nodes if(vectorPairNodesScore.size() > 0) std::cout << "Best pair: Node A:" << (bestPairNodes).first->GetId() << ", Node B:" << (bestPairNodes).second->GetId() << std::endl; */ /*// AMP - This code was commented after a meeting with Leonardo Florez // We make the hypothesis that both roots are equal and // that the root has only one child. // The comparison of two branches implies the alignment // of the mother branches and then the comparison of the // daughters branches using intrinsic characteristics of // each branch and a distance function between both. if (this->IsEmpty() || treeB.IsEmpty()) { std::cout << "One or both airways are empty." << std::endl; return; } Edge actualRootEdge = this->m_root->GetEdge(); Edge comparedRootEdge = treeB.m_root->GetEdge(); // By the hypothesis, both root edges are similar. So we have to compared // the edged of the root edges. actualRootEdge.compareChildEdges(comparedRootEdge); */ } Pair_PairNodes_Score AirwaysTree::GetBestLeaf(Vector_Pair_PairNodes_Score vectorPairNodesScore) { // Variables Pair_PairNodes_Score pairNodesScore_final; bool first = true; for(Vector_Pair_PairNodes_Score::iterator it = vectorPairNodesScore.begin(); it != vectorPairNodesScore.end(); ++it) { // Check that one of the node is a leaf pair_nodes pair_actual = (*it).first; Node* a = pair_actual.first; Node* b = pair_actual.second; if( a->IsLeaf() || b->IsLeaf() ) { if(first) { first = false; pairNodesScore_final = (*it); } else if((*it).second < pairNodesScore_final.second) { pairNodesScore_final = (*it); } } } if(first) std::cout << "Best leaf not found" << std::endl; return pairNodesScore_final; } double AirwaysTree::GetPairNodes_Score(Vector_Pair_PairNodes_Score vectorPairNodesScore, const unsigned int idA, const unsigned int idB) { bool found = false; double score = -1; for(Vector_Pair_PairNodes_Score::iterator it = vectorPairNodesScore.begin(); it != vectorPairNodesScore.end(); ++it) { // Check that one of the node is a leaf pair_nodes pair_actual = (*it).first; Node* a = pair_actual.first; Node* b = pair_actual.second; if( a->GetId() == idA && b->GetId() == idB ) { found = true; score = (*it).second; } } if(!found) std::cout << "Pair of Ids not found: " << idA << ", " << idB << std::endl; return score; } bool AirwaysTree::DeleteNodeById(unsigned int nId) { bool deleted = false; if(m_root->GetId() == nId) { delete(m_root); m_root = NULL; return true; } return this->m_root->DeleteNodeById(nId); } unsigned int AirwaysTree::DeleteEntriesByIdNode(Vector_Pair_PairNodes_Score& vectorPairNodesScore, unsigned int component, unsigned int nId) { unsigned int pairs_deleted = 0; Vector_Pair_PairNodes_Score::iterator it = vectorPairNodesScore.begin(); while(it != vectorPairNodesScore.end()) { // Check that one of the node is a leaf pair_nodes pair_actual = (*it).first; unsigned int id_actual = -1; if(component == 0) id_actual = pair_actual.first->GetId(); else id_actual = pair_actual.second->GetId(); if( id_actual == nId) { it = vectorPairNodesScore.erase(it); ++pairs_deleted; } else ++it; } std::cout << "Pairs deleted: " << pairs_deleted << std::endl; return pairs_deleted; } AirwaysTree* AirwaysTree::GetCopy() { return NULL; } Vector_Pair_PairNodes_Score AirwaysTree::CompareAllBranches(AirwaysTree& treeB) { std::cout << "Compare all branches ..." << std::endl; // Variables int nodesA = this->m_nodes.size(); int nodesB = treeB.m_nodes.size(); Vector_Pair_PairNodes_Score vectorPairNodesScore; // For all the actual branches ( nodes different from the root) for(unsigned int idA = 2; idA <= nodesA; ++idA) { // Get the actual branch in A Edge* branchA = this->GetComposedEdge(idA); //Get the final actual node in A Node* node_actualA = this->GetNodeById(idA); std::cout << "IdA: " << idA << std::endl; // For all the branches in B tree for(unsigned int idB = 2; idB <= nodesB; ++idB) { // Get the actual branch in B Edge* branchB = treeB.GetComposedEdge(idB); //Get the final actual node in B Node* node_actualB = treeB.GetNodeById(idB); // Get the score from A to B and from B to A double scoreA2B = branchA->CompareWith(branchB); double scoreB2A = branchB->CompareWith(branchA); // Get the final score // Options: // A. Maximum score //double score = scoreB2A > scoreA2B ? scoreB2A : scoreA2B ; // B. Sum of scores double score = scoreB2A + scoreA2B; // Build the pair of nodes pair_nodes actualPairNodes(node_actualA, node_actualB); Pair_PairNodes_Score actualPairNodesScore(actualPairNodes, score); vectorPairNodesScore.push_back(actualPairNodesScore); //std::cout << "IdA: " << idA << ", IdB: " << idB << ", score: " << score << ", ... OK" << std::endl; delete(branchB); } delete(branchA); } std::cout << "Compare all branches ... OK" << std::endl; return vectorPairNodesScore; } Edge* AirwaysTree::GetComposedEdge(unsigned int idNode) { return this->m_root->GetComposedEdge(idNode); } AirwaysTree* AirwaysTree::GetSingleDetachedTreeNodeById(unsigned int nId) { AirwaysTree* tree_detached = NULL; Node* node_searched = this->GetNodeById(nId); if(node_searched) { Node* node_root_detached = node_searched->GetDetachedRootCopy(); tree_detached = new AirwaysTree(); tree_detached->m_root = node_root_detached; } else std::cout << "Node not found" << std::endl; return tree_detached; } void AirwaysTree::SubIsomorphism(AirwaysTree& treeB) { if (this->IsEmpty() || treeB.IsEmpty()) return; //Marking the root node this->m_root->Mark(); treeB.m_root->Mark(); //iterating children - first step vec_nodes::const_iterator it = this->m_root->GetChildren().begin(); for (; it != this->m_root->GetChildren().end(); ++it) { unsigned int totalCost = 0; Node* currentB = NULL; Node* currentA = *it; if (currentA->IsMarked()) continue; vec_nodes::const_iterator it2 = treeB.m_root->GetChildren().begin(); for (; it2 != treeB.m_root->GetChildren().end(); ++it2) { if ((*it2)->IsMarked()) continue; unsigned int currentCost = (*it)->GetCost(*it2); if (totalCost < currentCost) { currentB = *it2; totalCost = currentCost; } //if } //for if (currentB != NULL) if (*currentA == *currentB) this->GetSubTreeByDetachingNode(currentA).SubIsomorphism( treeB.GetSubTreeByDetachingNode(currentB)); } //for //end of first step //second step it = this->m_root->GetChildren().begin(); for (; it != this->m_root->GetChildren().end(); ++it) { if ((*it)->IsMarked()) continue; vec_nodes::const_iterator it2 = treeB.m_root->GetChildren().begin(); for (; it2 != treeB.m_root->GetChildren().end(); ++it2) { Node* currentB = *it2; Node* currentA = *it; if (*currentB > *currentA) continue; if (currentA->FindSimilarEdgeByAccumulation(currentB)) { AirwaysTree subTreeA = this->GetSubTreeByDetachingNode( currentA); AirwaysTree subTreeB = treeB.GetSubTreeByDetachingNode( currentB); subTreeB.UpdateLevels((*it2)->GetLevel()); subTreeA.SubIsomorphism(subTreeB); treeB.m_root->UpdateLevels(treeB.m_root->GetLevel()); currentA->Mark(); if (!(*it2)->MarkPath(currentB)) std::cout << "Error finding path" << std::endl; break; } //if } //for } //for vec_nodes::const_iterator it2 = treeB.m_root->GetChildren().begin(); for (; it2 != treeB.m_root->GetChildren().end(); ++it2) { if ((*it2)->IsMarked()) continue; it = this->m_root->GetChildren().begin(); for (; it != this->m_root->GetChildren().end(); ++it) { Node* currentB = *it2; Node* currentA = *it; if (*currentA > *currentB) continue; if (currentB->FindSimilarEdgeByAccumulation(currentA)) { AirwaysTree subTreeA = this->GetSubTreeByDetachingNode( currentA); AirwaysTree subTreeB = treeB.GetSubTreeByDetachingNode( currentB); subTreeA.UpdateLevels((*it)->GetLevel()); subTreeA.SubIsomorphism(subTreeB); this->m_root->UpdateLevels(this->m_root->GetLevel()); currentB->Mark(); if (!(*it)->MarkPath(currentA)) std::cout << "Error finding path" << std::endl; break; } //if } //for } //End of second step } bool AirwaysTree::Isomorphism(AirwaysTree& tree) { if ((this->GetWeight() != tree.GetWeight()) || (this->GetHeight() != tree.GetHeight())) return false; return this->m_root->CompareNodes(tree.m_root); } void AirwaysTree::ImageReconstructionFromNode(TInputImage::Pointer& result, Node* node, bool skeleton) { if (node == NULL) return; //Finding the center of the sphere const Edge* edge = node->GetEdge(); if (edge == NULL) return; //making a copy of the current image TInputImage::Pointer copy; DuplicatorType::Pointer duplicator = DuplicatorType::New(); if (skeleton) duplicator->SetInputImage(this->m_skeleton); else duplicator->SetInputImage(this->m_img); duplicator->Update(); copy = duplicator->GetOutput(); //First remove the node brothers -- the following code in a way does not // make sense but I'll just comment it if it is necessary /*Node* parent = edge->m_source; NodeVector::iterator pIt = parent->m_children.begin(); for (; pIt != parent->m_children.end(); ++pIt) if ((*pIt) != node) this->RemoveBranchFromImage(copy, node); //end of brother removal*/ pair_posVox_rad center; vec_pair_posVox_rad::const_iterator it = edge->m_vec_pair_posVox_rad.begin(); for (; it != edge->m_vec_pair_posVox_rad.end(); ++it) if (edge->m_source->GetCoords() == (*it).first) center = *it; //converting to index TInputImage::PointType point; point[0] = center.first[0]; point[1] = center.first[1]; point[2] = center.first[2]; TInputImage::IndexType indCenter; if (skeleton) this->m_skeleton->TransformPhysicalPointToIndex(point, indCenter); else this->m_img->TransformPhysicalPointToIndex(point, indCenter); //creating itk sphere SphereType::Pointer sphere = SphereType::New(); sphere->SetRadius(center.second * 4); SphereType::InputType sphereCenter; sphereCenter[0] = indCenter[0]; sphereCenter[1] = indCenter[1]; sphereCenter[2] = indCenter[2]; sphere->SetCenter(sphereCenter); //testing code // std::cout<<"center = "<< indCenter << std::endl; //std::cout << "Radio = " << center.second << std::endl; TInputImage::SizeType regionSize; regionSize[0] = 8 * center.second; regionSize[1] = 8 * center.second; regionSize[2] = 8 * center.second; //std::cout << "RegionSize = " << regionSize << std::endl; TInputImage::IndexType regionIndex; regionIndex[0] = indCenter[0] - center.second * 4; regionIndex[1] = indCenter[1] - center.second * 4; regionIndex[2] = indCenter[2] - center.second * 4; // std::cout << "regionIndex = " << regionIndex << std::endl; TInputImage::RegionType region; region.SetSize(regionSize); region.SetIndex(regionIndex); RegionIterator it2(copy, region); while (!it2.IsAtEnd()) { TInputImage::IndexType ind = it2.GetIndex(); SphereType::InputType point; point[0] = ind[0]; point[1] = ind[1]; point[2] = ind[2]; SphereType::OutputType output = sphere->Evaluate(point); if (output) it2.Set(0); ++it2; } /* * First region growing - Segmenting the wanted branch to be removed * Removing the branch from the image */ if (!ComputeSimpleRegionGrowing(copy, this->m_root->GetCoords())) return; SubtractImageFilterType::Pointer subtractFilter = SubtractImageFilterType::New(); if (skeleton) subtractFilter->SetInput1(this->m_skeleton); else subtractFilter->SetInput1(this->m_img); subtractFilter->SetInput2(copy); subtractFilter->Update(); TInputImage::Pointer diff = subtractFilter->GetOutput(); /* * Second region growing - Cleaning the resulting image */ Node* leaf = this->GetLeaf(node); if (ComputeSimpleRegionGrowing(diff, leaf->GetCoords())) result = diff; else std::cout << "problemas" << std::endl; //cin.ignore().get(); //Pause Command for Linux Terminal } void AirwaysTree::ImageReconstruction(TInputImage::Pointer& result, bool skeleton, Node* node) { if (node == NULL) { DuplicatorType::Pointer duplicator = DuplicatorType::New(); if (skeleton) duplicator->SetInputImage(this->m_skeleton); else duplicator->SetInputImage(this->m_img); duplicator->Update(); result = duplicator->GetOutput(); node = this->m_root; } //if if (!node->IsMarked()) { this->RemoveBranchFromImage(result, node); return; } vec_nodes::const_iterator it = node->GetChildren().begin(); for (; it != node->GetChildren().end(); ++it) this->ImageReconstruction(result, skeleton, *it); } void AirwaysTree::ImageReconstructionBySpheres(TInputImage::Pointer& result, Node* node, bool useMarks) { if (node == NULL) { node = this->m_root; DuplicatorType::Pointer duplicator = DuplicatorType::New(); duplicator->SetInputImage(m_img); duplicator->Update(); result = duplicator->GetOutput(); //Removing white pixels -- cleaning image TInputImage::RegionType lRegion = result->GetLargestPossibleRegion(); RegionIterator it(result, lRegion); while (!it.IsAtEnd()) { it.Set(0); ++it; } //while } //if if (node->IsMarked() || !useMarks) { this->CreateSpheres(result, node); vec_nodes::const_iterator it = node->GetChildren().begin(); for (; it != node->GetChildren().end(); ++it) this->ImageReconstructionBySpheres(result, *it); } //if } Node* AirwaysTree::GetNode(const Vec3 nodeCoords, Node* current) { if (current == NULL) current = this->m_root; if (current->GetCoords() == nodeCoords) return current; vec_nodes::const_iterator it = current->GetChildren().begin(); for (; it != current->GetChildren().end(); ++it) { Node* child = GetNode(nodeCoords, *it); if (child != NULL) return child; } //rof return NULL; } Node* AirwaysTree::GetLeaf(Node* current) { if (current == NULL) current = this->m_root; if (current->IsLeaf()) return current; vec_nodes::const_iterator it = current->GetChildren().begin(); Node* node = NULL; unsigned int maxHeight = 0; for (; it != current->GetChildren().end(); ++it) { unsigned int cHeight = this->GetHeight(*it); if (maxHeight <= cHeight) { maxHeight = cHeight; node = *it; } //if } //for if (node != NULL) return this->GetLeaf(node); return NULL; } void AirwaysTree::UpdateEdges(Node* node) { if (node == NULL) node = this->m_root; if (node->GetEdge() != NULL) { Edge* edge = node->GetEdge(); //edge->m_skInfoPairVector = this->GetSkeletonInfoFromEdge(edge->m_source->GetCoords(), edge->m_target->GetCoords()); edge->SetSkeletonPairVector( this->GetSkeletonInfoFromEdge(edge->m_source->GetCoords(), edge->m_target->GetCoords()) ); node->GetEdge()->UpdateEdgeInfo(); } vec_nodes::const_iterator it = node->GetChildren().begin(); for (; it != node->GetChildren().end(); ++it) this->UpdateEdges(*it); } AirwaysTree& AirwaysTree::GetSubTreeByDetachingNode(Node* node) { AirwaysTree* tree = new AirwaysTree(); tree->m_root = node; return *tree; } DiGraph_EdgePair AirwaysTree::AddBoostEdge(const pair_posVox_rad& source, const pair_posVox_rad& target, DiGraph& graph) { bool vFound[2] = { false, false }; DiGraph_VertexDescriptor vDescriptor[2]; //Remember that DiGraph_VertexIteratorPair, first = begin, second = end DiGraph_VertexIndexMap index = get(boost::vertex_index, graph); //Search the vertex in the graph for (DiGraph_VertexIteratorPair vPair = boost::vertices(graph); vPair.first != vPair.second && (!vFound[0] || !vFound[1]); ++vPair.first) { // Get the current information [vector, intensity] pair_posVox_rad current = graph[index[*vPair.first]]; // Check if current is equal to the source or target vertex if (current.first == source.first) { vDescriptor[0] = index[*vPair.first]; vFound[0] = true; } //if else if (current.first == target.first) { vDescriptor[1] = index[*vPair.first]; vFound[1] = true; } //if } //for // If one of the vertices is not in the graph, adds the new vertex // Add the vertices if they are not in the graph if (!vFound[0]) vDescriptor[0] = boost::add_vertex(source, graph); if (!vFound[1]) vDescriptor[1] = boost::add_vertex(target, graph); // Check if the edge exist in the graph // boost::edge returns the pair, with bool=true is the edge exists DiGraph_EdgePair edgeC1 = boost::edge(vDescriptor[0], vDescriptor[1],graph); DiGraph_EdgePair edgeC2 = boost::edge(vDescriptor[1], vDescriptor[0],graph); // If the edge does not exist, then add it if (!edgeC1.second && !edgeC2.second) { DiGraph_EdgePair nEdge = boost::add_edge(vDescriptor[0], vDescriptor[1], graph); return nEdge; } //if // If an edge has not been added then -> second = false // Remove the added vertices because the edge already exists. if (!vFound[0]) boost::remove_vertex(vDescriptor[0], graph); if (!vFound[1]) boost::remove_vertex(vDescriptor[1], graph); edgeC1.second = false; edgeC1.second = false; return edgeC1; } bool AirwaysTree::FindNeighborhood(DiGraph& graph, Vec3Queue& queue, Vec3List& used, const Vec3& end, ConstNeighborhoodIterator& iterator) { if (queue.empty()) return false; // Get the next pixel in the queue Vec3 current = queue.front(); // Put the pixel in the used list used.push_back(current); // Delete next pixel from the queu queue.pop(); //AMP//iterator.GoToBegin(); //AMP//while (!iterator.IsAtEnd()) //AMP//{ // AMP commented /*unsigned int centerIndex = iterator.GetCenterNeighborhoodIndex(); TInputImage::IndexType index = iterator.GetIndex(centerIndex); SKPairInfo src(Vec3(index[0], index[1], index[2]), iterator.GetPixel(iterator.GetCenterNeighborhoodIndex())); if (src.first != current) { ++iterator; continue; } //if */ //PMA commented // AMP // Set the current index to the actual pixel TInputImage::IndexType indexActual; indexActual[0] = current[0]; indexActual[1] = current[1]; indexActual[2] = current[2]; // Place the iterator in the actual index iterator.SetLocation(indexActual); // Create the pair [vector, intensity] for the actual index pair_posVox_rad src(current, iterator.GetPixel(iterator.GetCenterNeighborhoodIndex())); // PMA // Iterate over the neighbors for (unsigned int i = 0; i < iterator.Size(); i++) { //AMP//if (iterator.GetPixel(i) != 0 && i != centerIndex) // If the intensity is not zero and it's the center if (iterator.GetPixel(i) != 0 && i != iterator.GetCenterNeighborhoodIndex()) { // Get the index of the iterator TInputImage::IndexType ind = iterator.GetIndex(i); // Create the target pair [vector, intensity] for the target pair_posVox_rad target(Vec3(ind[0], ind[1], ind[2]), iterator.GetPixel(i)); // Add the edge to the graph bool added = AddBoostEdge(src, target, graph).second; // If it could not be added then it is because it already exist, then go to next neighboor if (!added) continue; // The edge was added. Stop the adding process if the target vertex was reached. if (target.first == end) return true; // If it the edge was added and it is not the target then add it to the queue, if and only if // it was not already used. if (std::find(used.begin(), used.end(), target.first)== used.end()) queue.push(target.first); }//if }//for //AMP//break; //AMP//} //while return false; } DiGraph AirwaysTree::GetGraphShortestPath(const DiGraph& graph, const Vec3& begin, const Vec3& end) { // Variables DiGraph ret; // Returning graph with the shortest path DiGraph_EdgeIterator ei, eo; // Initial and final iterators // Iterate over the edges of the graph boost::tie(ei, eo) = boost::edges(graph); for (; ei != eo; ++ei) { // Get the source of the actual edge pair_posVox_rad src = graph[boost::source(*ei, graph)]; // If the source corresponds to the begin pixel if (src.first == begin) { // Get the target of the actual edge pair_posVox_rad target = graph[boost::target(*ei, graph)]; // If the actual target corresponds to the end pixel if (target.first == end) { // Add the edge to the final path AddBoostEdge(src, target, ret); //AMP std::cout << "Add final target [src]-[ target]:[" << src.first << "]-[" << target.first << "], numVertices:" << boost::num_vertices(ret) << std::endl; //PMA // Return the path return ret; } // If the actual target does not correspond to the end pixel, then add it to the returning path // and run the shortest path with the target of the actual edge. ret = GetGraphShortestPath(graph, target.first, end); // If the path is empty then the iteration continues if (boost::num_vertices(ret) == 0) continue; // if not return ret + new edge // If the path was found then add the actual edge and return the path AddBoostEdge(src, target, ret); //AMP //std::cout << "Add found edge [src]-[ target]:[" << src.first << "]-[" << target.first << "], numVertices:" << boost::num_vertices(ret) << std::endl; //PMA return ret; }//fi } return ret; } vec_pair_posVox_rad AirwaysTree::GetGraphShortestPath_AMP(const DiGraph& graph, const Vec3& begin, const Vec3& end) { //std::cout << "SKPairInfoVector AirwaysTree::GetGraphShortestPath_AMP(const DiGraph& graph, const Vec3& begin, const Vec3& end)" << std::endl; // Variables vec_pair_posVox_rad path; DiGraph ret; // Returning graph with the shortest path DiGraph_EdgeIterator ei, eo; // Initial and final iterators // Iterate over the edges of the graph boost::tie(ei, eo) = boost::edges(graph); for (; ei != eo; ++ei) { // Get the source of the actual edge pair_posVox_rad src = graph[boost::source(*ei, graph)]; // If the source corresponds to the begin pixel if (src.first == begin) { // Get the target of the actual edge pair_posVox_rad target = graph[boost::target(*ei, graph)]; // If the actual target corresponds to the end pixel if (target.first == end) { // Add the edge to the final path AddBoostEdge(src, target, ret); path.push_back(target); path.push_back(src); //AMP //std::cout << "Add final target [src]-[ target]:[" << src.first << "]-[" << target.first << "], numVertices:" << boost::num_vertices(ret) << ", path_size:" << path.size() << std::endl; //PMA // Return the path //std::cout << "SKPairInfoVector AirwaysTree::GetGraphShortestPath_AMP(const DiGraph& graph, const Vec3& begin, const Vec3& end) ... FIRST ... OK" << std::endl; return path; } //std::cout << "Not yet in the target voxel" << std::endl; // If the actual target does not correspond to the end pixel, then add it to the returning path // and run the shortest path with the target of the actual edge. path = GetGraphShortestPath_AMP(graph, target.first, end); //std::cout << "Path found, path size:" << path.size() << std::endl; // If the path is empty then the iteration continues if (path.size() == 0) continue; // if not return ret + new edge // If the path was found then add the actual edge and return the path AddBoostEdge(src, target, ret); path.push_back(src); //AMP //std::cout << "Add found edge [src]-[ target]:[" << src.first << "]-[" << target.first << "], numVertices:" << boost::num_vertices(ret) << ", path_size:" << path.size() << std::endl; //PMA //std::cout << "SKPairInfoVector AirwaysTree::GetGraphShortestPath_AMP(const DiGraph& graph, const Vec3& begin, const Vec3& end) ... SECOND ... OK" << std::endl; return path; }//fi } //std::cout << "SKPairInfoVector AirwaysTree::GetGraphShortestPath_AMP(const DiGraph& graph, const Vec3& begin, const Vec3& end) ... END ... OK" << std::endl; return path; } vec_pair_posVox_rad AirwaysTree::GetSkeletonInfoFromEdge(const Vec3& source, const Vec3& target) { //converting to pixel TInputImage::PointType pointSource; pointSource[0] = source[0]; pointSource[1] = source[1]; pointSource[2] = source[2]; TInputImage::PointType pointTarget; pointTarget[0] = target[0]; pointTarget[1] = target[1]; pointTarget[2] = target[2]; TInputImage::IndexType indexSource; TInputImage::IndexType indexTarget; this->m_skeleton->TransformPhysicalPointToIndex(pointSource, indexSource); this->m_skeleton->TransformPhysicalPointToIndex(pointTarget, indexTarget); //end of conversion // AMP // Print the initial and final voxels to verify their positions //std::cout << "Begin: [" << indexSource[0] << "," << indexSource[1] << "," << indexSource[2] << "] -- " << this->m_skeleton->GetPixel(indexSource) << std::endl; //std::cout << "End: [" << indexTarget[0] << "," << indexTarget[1] << "," << indexTarget[2] << "] -- " << this->m_skeleton->GetPixel(indexTarget) << std::endl; //std::cout << "BeginVoxel: [" << pointSource[0] << "," << pointSource[1] << "," << pointSource[2] << "]"<< std::endl; //std::cout << "EndVoxel: [" << pointTarget[0] << "," << pointTarget[1] << "," << pointTarget[2] << "]" << std::endl; // PMA // Vec3 sourcePxl(indexSource[0], indexSource[1], indexSource[2]); Vec3 targetPxl(indexTarget[0], indexTarget[1], indexTarget[2]); // AMP // Commented /* // Compute the distance in each direction and add "21" in each one float dstX = beginPxl.EculideanDistance( Vec3(endPxl[0], beginPxl[1], beginPxl[2])) + 21; float dstY = beginPxl.EculideanDistance( Vec3(beginPxl[0], endPxl[1], beginPxl[2])) + 21; float dstZ = beginPxl.EculideanDistance( Vec3(beginPxl[0], beginPxl[1], endPxl[2])) + 21; //start point TInputImage::IndexType index; index[0] = beginPxl[0] < endPxl[0] ? beginPxl[0] : endPxl[0]; index[1] = beginPxl[1] < endPxl[1] ? beginPxl[1] : endPxl[1]; index[2] = beginPxl[2] < endPxl[2] ? beginPxl[2] : endPxl[2]; index[0] -= index[0] <= 10 ? 0 : 10; index[1] -= index[1] <= 10 ? 0 : 10; index[2] -= index[2] <= 10 ? 0 : 10; //size of region TInputImage::SizeType size; size[0] = ceil(dstX); size[1] = ceil(dstY); size[2] = ceil(dstZ); TInputImage::RegionType region; region.SetSize(size); region.SetIndex(index); //ConstNeighborhoodIterator iterator(radius, this->m_skeleton, region); // PMA // Commented */ TInputImage::SizeType radius; radius[0] = 1; radius[1] = 1; radius[2] = 1; ConstNeighborhoodIterator iterator(radius, this->m_skeleton, this->m_skeleton->GetLargestPossibleRegion()); DiGraph graph; Vec3Queue queue; Vec3List used; // Set the first pixel as starting pixel queue.push(sourcePxl); //FindNeighborhood(graph, queue, used, endPxl, iterator); // Add to the graph all the connected voxel until the ending pixel is found bool endFound = false; while (!queue.empty() && !endFound) endFound = FindNeighborhood(graph, queue, used, targetPxl, iterator); if(!endFound) std::cout << "***************** END NOT FOUND!!!!" << std::endl; else std::cout << "***************** END FOUND!!!! - Graph Vertices:" << boost::num_vertices(graph) << ", Graph Edges:" << boost::num_edges(graph) << std::endl; // Get the shortest path between the begin and end pixels //std::cout << "GetGraphShortestPath [from]-[to]:[" << sourcePxl << "]-[" << targetPxl << "]" << std::endl; //DiGraph result = GetGraphShortestPath(graph, sourcePxl, targetPxl); vec_pair_posVox_rad path = GetGraphShortestPath_AMP(graph, sourcePxl, targetPxl); //std::cout << "GetGraphShortestPath ... OK , numVertices:" << boost::num_vertices(result) << std::endl; //AMP bool beginPixelFound = false; bool endPixelFound = false; vec_pair_posVox_rad vector; for(vec_pair_posVox_rad::reverse_iterator it_path = path.rbegin(); it_path != path.rend(); ++it_path) { TInputImage::IndexType ind; ind[0] = (*it_path).first[0]; ind[1] = (*it_path).first[1]; ind[2] = (*it_path).first[2]; //std::cout << "["<< (*it_path).first << "], "; // To avoid precision problems if (indexSource == ind) { beginPixelFound = true; (*it_path).first = source; } else if (indexTarget == ind) { endPixelFound = true; (*it_path).first = target; } else { TInputImage::PointType pnt; this->m_skeleton->TransformIndexToPhysicalPoint(ind, pnt); (*it_path).first = Vec3(pnt[0], pnt[1], pnt[2]); } vector.push_back((*it_path)); } //vector = path; //PMA // Variables to iterate over the shortest path and save the results /*// AMP DiGraph_VertexIterator i, e; SKPairInfoVector vector; // Iterate over the shortest path and add each vertex in real coordinates boost::tie(i, e) = boost::vertices(result); std::cout << "Inserting ... [begin,end]: [" << begin << "], [" << end << "]" << std::endl; for (; i != e; ++i) //for (; e != i; --e) { // Get the actual vertex SKPairInfo vertex = result[*i]; //SKPairInfo vertex = result[*e]; std::cout << "["<< vertex.first << "], "; // Get the index (voxel position) of the actual vertex TInputImage::IndexType ind; ind[0] = vertex.first[0]; ind[1] = vertex.first[1]; ind[2] = vertex.first[2]; // To avoid precision problems if (indexBegin == ind) { beginPixelFound = true; vertex.first = begin; } else if (indexEnd == ind) { endPixelFound = true; vertex.first = end; } else { TInputImage::PointType pnt; this->m_skeleton->TransformIndexToPhysicalPoint(ind, pnt); vertex.first = Vec3(pnt[0], pnt[1], pnt[2]); } vector.push_back(vertex); } std::cout << "Inserting ... OK" << std::endl; *///AMP if(!beginPixelFound) std::cout << "Begin not found: "<< source << std::endl; if(!endPixelFound) std::cout << "End not found:" << target << std::endl; return vector; } bool AirwaysTree::ComputeSimpleRegionGrowing(TInputImage::Pointer& img, const Vec3 seedPtn) { TInputImage::PointType targetPtn; targetPtn[0] = seedPtn[0]; targetPtn[1] = seedPtn[1]; targetPtn[2] = seedPtn[2]; TInputImage::IndexType seed; img->TransformPhysicalPointToIndex(targetPtn, seed); if (img->GetPixel(seed) == 0) { //std::cout << "seed is 0" << std::endl; return false; } ConnectedFilterType::Pointer neighborhoodConnected = ConnectedFilterType::New(); neighborhoodConnected->SetLower(1); neighborhoodConnected->SetUpper(1); neighborhoodConnected->SetReplaceValue(1); neighborhoodConnected->SetSeed(seed); neighborhoodConnected->SetInput(img); neighborhoodConnected->Update(); img = neighborhoodConnected->GetOutput(); return true; } void AirwaysTree::RemoveBranchFromImage(TInputImage::Pointer& img, Node* node) { //typedef itk::ImageFileWriter WriterType; //Finding the center of the sphere const Edge* edge = node->GetEdge(); if (edge == NULL) return; pair_posVox_rad center; vec_pair_posVox_rad::const_iterator it = edge->m_vec_pair_posVox_rad.begin(); for (; it != edge->m_vec_pair_posVox_rad.end(); ++it) if (edge->m_source->GetCoords() == (*it).first) center = *it; //converting to index TInputImage::PointType point; point[0] = center.first[0]; point[1] = center.first[1]; point[2] = center.first[2]; TInputImage::IndexType indCenter; img->TransformPhysicalPointToIndex(point, indCenter); double radius = center.second; //creating itk sphere SphereType::Pointer sphere = SphereType::New(); SphereType::InputType sphereCenter; sphereCenter[0] = indCenter[0]; sphereCenter[1] = indCenter[1]; sphereCenter[2] = indCenter[2]; sphere->SetCenter(sphereCenter); unsigned int objCount = 0; unsigned int obj3Count = 0; // to assure 3 Connected obj //Number of connected components, children_size + parent unsigned int nCConnex = edge->m_source->GetNumberOfChildren() + 1; TInputImage::Pointer copy; //std::cout << "entró" << std::endl; while (objCount < nCConnex || obj3Count <= nCConnex) { if (objCount >= 3) obj3Count++; radius += 1.0; sphere->SetRadius(radius); //making a copy of the current image DuplicatorType::Pointer duplicator = DuplicatorType::New(); duplicator->SetInputImage(img); duplicator->Update(); copy = duplicator->GetOutput(); //testing code // std::cout<<"center = "<< indCenter << std::endl; //std::cout << "Radio = " << center.second << std::endl; TInputImage::SizeType regionSize; regionSize[0] = 4 * radius; regionSize[1] = 4 * radius; regionSize[2] = 4 * radius; //std::cout << "RegionSize = " << regionSize << std::endl; TInputImage::SizeType size = img->GetLargestPossibleRegion().GetSize(); TInputImage::IndexType regionIndex; regionIndex[0] = indCenter[0] - (radius * 2); if (regionIndex[0] < 0) regionIndex[0] = indCenter[0]; else if (regionIndex[0] > (unsigned int) size[0]) regionIndex[0] = size[0]; regionIndex[1] = indCenter[1] - (radius * 2); if (regionIndex[1] < 0) regionIndex[1] = indCenter[1]; else if (regionIndex[1] > (unsigned int) size[1]) regionIndex[1] = size[1]; regionIndex[2] = indCenter[2] - (radius * 2); if (regionIndex[2] < 0) regionIndex[2] = indCenter[2]; else if (regionIndex[2] > (unsigned int) size[2]) regionIndex[2] = size[2]; int diff[3]; diff[0] = size[0] - (regionSize[0] + regionIndex[0]); diff[1] = size[1] - (regionSize[1] + regionIndex[1]); diff[2] = size[2] - (regionSize[2] + regionIndex[2]); //std::cout << "(1) Region Index = " << regionIndex << std::endl; //std::cout << "(1) Region size = " << regionSize << std::endl; if (diff[0] < 0) regionSize[0] = size[0] - regionIndex[0]; if (diff[1] < 0) regionSize[1] = size[1] - regionIndex[1]; if (diff[2] < 0) regionSize[2] = size[2] - regionIndex[2]; // std::cout << "regionIndex = " << regionIndex << std::endl; //std::cout << "(2) Region Index = " << regionIndex << std::endl; //std::cout << "(2) Region size = " << regionSize << std::endl; TInputImage::RegionType region; region.SetSize(regionSize); region.SetIndex(regionIndex); RegionIterator it2(copy, region); while (!it2.IsAtEnd()) { TInputImage::IndexType ind = it2.GetIndex(); SphereType::InputType point; point[0] = ind[0]; point[1] = ind[1]; point[2] = ind[2]; SphereType::OutputType output = sphere->Evaluate(point); if (output) it2.Set(0); ++it2; } //while if (node->IsLeaf()) { TInputImage::PointType ptn; ptn[0] = node->GetCoords()[0]; ptn[1] = node->GetCoords()[1]; ptn[2] = node->GetCoords()[2]; TInputImage::IndexType tgt; img->TransformPhysicalPointToIndex(ptn, tgt); if (img->GetPixel(tgt) == 0) { std::cout << "It entered here!!!!" << std::endl; return; } } //if CastFilterType::Pointer castFilter = CastFilterType::New(); castFilter->SetInput(copy); castFilter->Update(); ConnectedComponentImageFilterType::Pointer connFilter = ConnectedComponentImageFilterType::New(); connFilter->SetFullyConnected(true); connFilter->SetInput(castFilter->GetOutput()); connFilter->Update(); objCount = connFilter->GetObjectCount(); //test /*WriterType::Pointer writer = WriterType::New(); writer->SetInput(copy); writer->SetFileName("output_antes.mhd"); writer->Update();*/ } //while //std::cout << "salio" << std::endl; /* * First region growing - Segmenting the wanted branch to be removed * Removing the branch from the image */ Node* leaf = this->GetLeaf(node); if (!ComputeSimpleRegionGrowing(copy, leaf->GetCoords())) return; SubtractImageFilterType::Pointer subtractFilter = SubtractImageFilterType::New(); subtractFilter->SetInput1(img); subtractFilter->SetInput2(copy); subtractFilter->Update(); TInputImage::Pointer diff = subtractFilter->GetOutput(); /* * Second region growing - Cleaning the resulting image */ if (ComputeSimpleRegionGrowing(diff, this->m_root->GetCoords())) img = diff; /*else std::cout << "problemas" << std::endl;*/ //cin.ignore().get(); //Pause Command for Linux Terminal } //Metodo obsoleto, ya no nos interesa la reconstruccion por esferas void AirwaysTree::CreateSpheres(TInputImage::Pointer& img, Node* node) { if (node->GetEdge() == NULL) return; const Edge* edge = node->GetEdge(); vec_pair_posVox_rad::const_iterator it = edge->m_vec_pair_posVox_rad.begin(); for (; it != edge->m_vec_pair_posVox_rad.end(); ++it) { //converting to index TInputImage::PointType point; point[0] = (*it).first[0]; point[1] = (*it).first[1]; point[2] = (*it).first[2]; TInputImage::IndexType indexPoint; img->TransformPhysicalPointToIndex(point, indexPoint); //creating itk sphere SphereType::Pointer sphere = SphereType::New(); sphere->SetRadius((*it).second); SphereType::InputType sphereCenter; sphereCenter[0] = indexPoint[0]; sphereCenter[1] = indexPoint[1]; sphereCenter[2] = indexPoint[2]; sphere->SetCenter(sphereCenter); //creating region TInputImage::SizeType regionSize; regionSize[0] = 4 * (*it).second; regionSize[1] = 4 * (*it).second; regionSize[2] = 4 * (*it).second; TInputImage::IndexType regionIndex; regionIndex[0] = indexPoint[0] - 2 * ceil((*it).second); regionIndex[1] = indexPoint[1] - 2 * ceil((*it).second); regionIndex[2] = indexPoint[2] - 2 * ceil((*it).second); TInputImage::RegionType region; region.SetSize(regionSize); region.SetIndex(regionIndex); RegionIterator it2(img, region); while (!it2.IsAtEnd()) { TInputImage::IndexType ind = it2.GetIndex(); SphereType::InputType point; point[0] = ind[0]; point[1] = ind[1]; point[2] = ind[2]; SphereType::OutputType output = sphere->Evaluate(point); if (output) it2.Set(1); ++it2; } //while } //for } void AirwaysTree::printUpToLevel(int level) { cout << "Printing up to level: " << level <m_root->printUpToLevel(level); cout << "Printing done" <m_root->printNodeAndChildrenIds( ); cout << "Printing nodes and children DONE" <= 2) { // Print header cout << "Level" << " " << "SonPositionX" << " " << "SonPositionY" << " " << "SonPositionZ" << " " "ParentVectorX" << " " << "ParentVectorY" << " " << "ParentVectorZ" << " " << "ChildVectorX" << " " << "ChildVectorY" << " " << "ChildVectorZ"<< " " << "Qr" << " " << "Qx" << " " << "Qy" " " << "Qz" " " << "Qtheta" << " " << "Wx" << " " << "Wy" << " " << "Wz" << " " << "EuclDistSonParent" << " " <<"EuclDistSonGrandson" << " " << "RadMeanSonParent" << " " << "RadMeanSonGrandson" <m_root->createQuaternionsUpToLevel(level, level); } else cout << "Quaternions must be created from level 2." <m_root->getStasticsBifurcations(p); cout << "Bifurcations:" << endl; for(int i = 0; i < 6; i++) { cout << i+1 << "->" << p[i] << endl; } cout << "Statistics bifurcations done " <SetRegions( region ); imagePointer->SetSpacing( spacing ); imagePointer->SetOrigin( origin ); imagePointer->Allocate(); //this->m_root->saveToImage(_imagePointer); vec_nodes nodes_children_root = this->m_root->GetChildren(); vec_nodes::const_iterator it_children = nodes_children_root.begin(); for( ; it_children != nodes_children_root.end(); ++it_children) { Vec3 coords_father = (*it_children)->GetEdge()->GetSource()->GetCoords(); Vec3 coords_child = (*it_children)->GetCoords(); drawLineInImage(coords_father, coords_child, imagePointer); } cout << "Writing ..." << endl; typedef itk::ImageFileWriter WriterType; WriterType::Pointer writer = WriterType::New(); writer->SetInput(imagePointer); writer->SetFileName(filename); writer->Update(); cout << "Writing ... done" << endl; } void AirwaysTree::drawLineInImage(Vec3 initVoxel, Vec3 endVoxel, TInputImage::Pointer imagePointer) { TInputImage::RegionType region = imagePointer->GetLargestPossibleRegion(); TInputImage::SpacingType spacing = imagePointer->GetSpacing(); TInputImage::PointType origin = imagePointer->GetOrigin(); TInputImage::IndexType init; init[0]=(initVoxel[0]-origin[0])/spacing[0]; init[1]=(initVoxel[1]-origin[1])/spacing[1]; init[2]=(initVoxel[2]-origin[2])/spacing[2]; TInputImage::IndexType end; end[0]=(endVoxel[0]-origin[0])/spacing[0]; end[1]=(endVoxel[1]-origin[1])/spacing[1]; end[2]=(endVoxel[2]-origin[2])/spacing[2]; TPixel pixel; pixel = 1; itk::LineIterator it(imagePointer, init, end); it.GoToBegin(); while (!it.IsAtEnd()) { it.Set(pixel); ++it; } } //To store the graph in a vtk void AirwaysTree::saveAirwayAsVTK(const std::string filename, bool common) { vtkSmartPointer colors = vtkSmartPointer::New(); colors->SetNumberOfComponents(3); colors->SetName("Colors"); //pointer of lines and points vtkSmartPointer lines = vtkSmartPointer::New(); vtkSmartPointer pts = vtkSmartPointer::New(); Vec3 root = this->m_root->GetCoords(); //UndirectedGraph srand(time(NULL)); unsigned int id = 1; CalculateVTKLinesFromEdges(this->m_root, 0, id, pts, lines, colors, common); vtkSmartPointer linesPolyData = vtkSmartPointer::New(); linesPolyData->SetPoints(pts); linesPolyData->SetLines(lines); linesPolyData->GetCellData()->SetScalars(colors); // Write the file vtkSmartPointer writer = vtkSmartPointer::New(); writer->SetFileName(filename.c_str()); #if VTK_MAJOR_VERSION <= 5 writer->SetInput(linesPolyData); #else writer->SetInputData(linesPolyData); #endif writer->Write(); } //To store the graph in a vtk void AirwaysTree::CalculateVTKLinesFromEdges(const Node* node, const unsigned int& parentId, unsigned int& cId, vtkSmartPointer& pts, vtkSmartPointer& lines, vtkSmartPointer& colors, bool common) { if (node == NULL) return; // Colors unsigned char red[3] = { 255, 0, 0 }; unsigned char green[3] = { 0, 255, 0 }; unsigned char blue[3] = { 0, 0, 255 }; unsigned char yellow[3] = { 255, 255, 0 }; const vec_nodes children = node->GetChildren(); for(vec_nodes::const_iterator it = children.begin(); it != children.end(); ++it) { if (!(*it)->IsMarked() && common) continue; const Edge* edge = (*it)->GetEdge(); //pts->InsertNextPoint(edge->GetSource()->GetCoords().GetVec3()); //pts->InsertNextPoint(edge->GetTarget()->GetCoords().GetVec3()); pts->InsertNextPoint(node->GetCoords().GetVec3()); pts->InsertNextPoint((*it)->GetCoords().GetVec3()); // Set color to be used int numColor = node->GetLevel() % 4; if(numColor == 0) colors->InsertNextTupleValue(green); else if(numColor == 1) colors->InsertNextTupleValue(red); else if(numColor == 2) colors->InsertNextTupleValue(blue); else colors->InsertNextTupleValue(yellow); vtkSmartPointer line = vtkSmartPointer::New(); line->GetPointIds()->SetId(0, parentId); line->GetPointIds()->SetId(1, cId++); lines->InsertNextCell(line); unsigned int newParent = cId++; CalculateVTKLinesFromEdges(*it, newParent, cId, pts, lines, colors, common); } //for } } /* namespace airways */ #endif