diff --git a/include/lsgrmController.h b/include/lsgrmController.h index afaba38389be0be222023eb92da2b992f1367f44..5da2eb68079292c37a9878259ca93422930b5212 100644 --- a/include/lsgrmController.h +++ b/include/lsgrmController.h @@ -49,13 +49,12 @@ public: typename LabelImageType::Pointer GetLabeledClusteredOutput(); itkGetMacro(Margin, unsigned int); - itkGetMacro(TemporaryFilesList, std::vector<std::string>); - itkGetMacro(CleanTemporaryDirectory, bool); - itkSetMacro(CleanTemporaryDirectory, bool); + itkGetMacro(CleanTemporaryFiles, bool); + itkSetMacro(CleanTemporaryFiles, bool); - itkGetMacro(TemporaryDirectory, std::string); - itkSetMacro(TemporaryDirectory, std::string); + itkGetMacro(TemporaryFilesPrefix, std::string); + itkSetMacro(TemporaryFilesPrefix, std::string); itkGetMacro(Threshold, float); itkSetMacro(Threshold, float); @@ -94,8 +93,8 @@ private: long unsigned int GetMaximumNumberOfNodesInMemory(); /* Parameters given by the user */ - std::string m_TemporaryDirectory; // Directory used to store intermediate files during the process. - bool m_CleanTemporaryDirectory; // Clean the temporary directory. + std::string m_TemporaryFilesPrefix; // Path used to store intermediate files during the process. + bool m_CleanTemporaryFiles; // Clean temporary files ImageType * m_InputImage; // Input image /* Segmentation parameters */ @@ -117,7 +116,6 @@ private: LSGRMTilingMode m_TilingMode; // tiling mode (none/user/auto) unsigned int m_Margin; // stability margin related to m_NumberOfFirstIterations std::vector<ProcessingTile> m_Tiles; // list of tiles - std::vector<std::string> m_TemporaryFilesList; // list of temporary files typename LabelImageType::Pointer m_LabelImage; // output label image }; } // end of namespace lsgrm diff --git a/include/lsgrmController.txx b/include/lsgrmController.txx index 052911bf3be7065d4c986afb8dea591b5967ce4a..ec776b6c8eaa63b5fabae45925891e8c1b68f957 100644 --- a/include/lsgrmController.txx +++ b/include/lsgrmController.txx @@ -14,7 +14,7 @@ Controller<TSegmenter>::Controller() m_TileWidth = 0; m_NbTilesX = 0; m_NbTilesY = 0; - m_CleanTemporaryDirectory = true; + m_CleanTemporaryFiles = true; m_Threshold = 75; m_Memory = 0; } @@ -53,8 +53,8 @@ void Controller<TSegmenter>::RunSegmentation() "\n\tTiling layout: " << m_NbTilesX << " x " << m_NbTilesY << std::endl; // Compute the splitting scheme - SplitOTBImage<ImageType>(m_InputImage, m_TileWidth, m_TileHeight, m_Margin, - m_NbTilesX, m_NbTilesY, m_Tiles); + m_Tiles = SplitOTBImage<ImageType>(m_InputImage, m_TileWidth, m_TileHeight, m_Margin, + m_NbTilesX, m_NbTilesY, m_TemporaryFilesPrefix); // Boolean indicating if there are remaining fusions bool isFusion = false; @@ -72,9 +72,7 @@ void Controller<TSegmenter>::RunSegmentation() m_NbTilesY, m_TileWidth, m_TileHeight, - m_TemporaryDirectory, isFusion); - // long long unsigned int accumulatedMemory = 19373051714; // Update the given number of iterations numberOfIterationsRemaining -= m_NumberOfFirstIterations; @@ -96,7 +94,6 @@ void Controller<TSegmenter>::RunSegmentation() m_Threshold, numberOfIterationsForPartialSegmentations, m_Tiles, - m_TemporaryDirectory, m_NbTilesX, m_NbTilesY, m_InputImage->GetLargestPossibleRegion().GetSize()[0], @@ -127,7 +124,6 @@ void Controller<TSegmenter>::RunSegmentation() m_SpecificParameters, m_Threshold, m_Tiles, - m_TemporaryDirectory, m_NbTilesX, m_NbTilesY, m_InputImage->GetLargestPossibleRegion().GetSize()[0], @@ -176,7 +172,7 @@ unsigned int Controller<TSegmenter>::GetNodeMemory() lsrm::GraphOperations<TSegmenter>::InitNodes(onePixelImage,segmenter,FOUR); unsigned int memory = segmenter.GetGraphMemory() / (n*n); - itkWarningMacro(<<"Size of a node is " << memory); + itkDebugMacro(<<"Size of a node is " << memory); return memory; } @@ -198,7 +194,8 @@ long unsigned int Controller<TSegmenter>::GetMaximumNumberOfNodesInMemory() } template<class TSegmenter> -void Controller<TSegmenter>::ComputeMaximumStabilityMargin(unsigned int width, +void +Controller<TSegmenter>::ComputeMaximumStabilityMargin(unsigned int width, unsigned int height, unsigned int &niter, unsigned int &margin) { itkDebugMacro(<< "Computing maximum stability margin"); @@ -331,7 +328,7 @@ void Controller<TSegmenter>::GetAutomaticConfiguration() long long unsigned int memoryUsed = GetNodeMemory(); memoryUsed *= static_cast<long long unsigned int>(m_TileHeight + 2*m_Margin); memoryUsed *= static_cast<long long unsigned int>(m_TileWidth + 2*m_Margin); - itkWarningMacro(<< "An amount of " << memoryUsed/(1024.0*1024.0) << " Mbytes of RAM will be used for regular tiles of size " + itkDebugMacro(<< "An amount of " << memoryUsed/(1024.0*1024.0) << " Mbytes of RAM will be used for regular tiles of size " << (m_TileWidth + 2*m_Margin) << "x" << (m_TileHeight + 2*m_Margin) ); } diff --git a/include/lsgrmGraphOperations.h b/include/lsgrmGraphOperations.h index ae7c6ad78f061e305bba66db88197c8d1ae4f5ef..b2e52e9077c9f773f321f57ae750295f741e89d9 100644 --- a/include/lsgrmGraphOperations.h +++ b/include/lsgrmGraphOperations.h @@ -16,6 +16,12 @@ struct ProcessingTile long int tileNeighbors[8]; // tile Neighbors at (top, top right, right, bottom right, bottom, bottom left, left, top left) long int margin[4]; // Is there a margin at top, left, bottom or right otb::VectorImage<double>::RegionType region; // The image region + + // Temporary files + std::string nodeFileName; + std::string edgeFileName; + std::string nodeMarginFileName; + std::string edgeMarginFileName; }; // Read an image region @@ -30,7 +36,6 @@ MergeAllGraphsAndAchieveSegmentation( const typename TSegmenter::ParameterType& params, const float& threshold, std::vector<ProcessingTile>& tiles, - const std::string& tmpDir, const unsigned int nbTilesX, const unsigned int nbTilesY, const unsigned int imageWidth, @@ -50,7 +55,6 @@ long long unsigned int RunFirstPartialSegmentation( const unsigned int nbTilesY, const unsigned int tileWidth, const unsigned int tileHeight, - const std::string& tmpDir, bool& isFusion); template<class TSegmenter> @@ -59,7 +63,6 @@ long long unsigned int RunPartialSegmentation( const float& threshold, const unsigned int niter, std::vector<ProcessingTile>& tiles, - const std::string& tmpDir, const unsigned int nbTilesX, const unsigned int nbTilesY, const unsigned int imageWidth, @@ -101,9 +104,13 @@ void BuildBorderPixelMap(typename TSegmenter::GraphType& graph, std::vector<typename TSegmenter::NodePointerType> >& borderPixelMap, const unsigned int imageWidth); +template<class TSegmenter> +void InsertNodesFromTile(typename TSegmenter::GraphType& graph, + ProcessingTile& tile, bool margin = true); + template<class TSegmenter> void AddStabilityMargin(typename TSegmenter::GraphType& graph, - const std::string& tmpDir, + std::vector<ProcessingTile>& tiles, const unsigned int row, const unsigned int col, const unsigned int nbTilesX, @@ -134,18 +141,19 @@ void DetectBorderNodes(typename TSegmenter::GraphType& graph, const unsigned int imageHeight); template<class TSegmenter> -void ReadGraph(typename TSegmenter::GraphType& graph, +void ReadGraph(TSegmenter& segmenter, const std::string& nodesPath, const std::string& edgesPath); template<class TSegmenter> -void WriteGraph(typename TSegmenter::GraphType& graph, - const std::string& tmpDir, - const unsigned int row, - const unsigned int col); +void ReadGraph(typename TSegmenter::GraphType& graph, + const std::string& nodesPath, + const std::string& edgesPath); template<class TSegmenter> -long long unsigned int GetGraphMemory(TSegmenter segmenter); +void WriteGraph(typename TSegmenter::GraphType& graph, + const std::string& nodesFile, + const std::string& edgesFile); template<class TSegmenter> void RemoveUnstableSegments(typename TSegmenter::GraphType& graph, diff --git a/include/lsgrmGraphOperations.txx b/include/lsgrmGraphOperations.txx index d37e5aa16fa415de38738a469b717bf6a7f10606..c7edae657b9ffc19ff49f4bd4a9e9dd736b7fce6 100644 --- a/include/lsgrmGraphOperations.txx +++ b/include/lsgrmGraphOperations.txx @@ -27,7 +27,6 @@ MergeAllGraphsAndAchieveSegmentation( const typename TSegmenter::ParameterType& params, const float& threshold, std::vector<ProcessingTile>& tiles, - const std::string& tmpDir, const unsigned int nbTilesX, const unsigned int nbTilesY, const unsigned int imageWidth, @@ -36,16 +35,16 @@ MergeAllGraphsAndAchieveSegmentation( unsigned int numberOfIterations) { - // TODO parallelize this ... + std::cout << "--- Graph aggregation...\n" << std::endl; + + // TODO parallelize this ? #ifdef OTB_USE_MPI if (otb::MPIConfig::Instance()->GetMyRank() != 0) return; #endif TSegmenter segmenter; - std::string nodesPath, edgesPath; - std::cout << "--- Graph aggregation...\n" << std::endl; std::cout << "Reading graphs" << std::endl; @@ -55,16 +54,7 @@ MergeAllGraphsAndAchieveSegmentation( { std::cout << "\tImporting graph of tile " << (row*nbTilesX + col) << " / " << (nbTilesX*nbTilesY) << std::endl; - typename TSegmenter::GraphType graph; - - // Load the graph - nodesPath = tmpDir + "tile_nodes_" + std::to_string(row) + "_" + std::to_string(col) + ".bin"; - edgesPath = tmpDir + "tile_edges_" + std::to_string(row) + "_" + std::to_string(col) + ".bin"; - ReadGraph<TSegmenter>(graph, nodesPath, edgesPath); - - segmenter.m_Graph.m_Nodes.insert(segmenter.m_Graph.m_Nodes.end(), - graph.m_Nodes.begin(), - graph.m_Nodes.end()); + InsertNodesFromTile<TSegmenter>(segmenter.m_Graph, tiles[row*nbTilesX + col], false); } } @@ -95,7 +85,6 @@ MergeAllGraphsAndAchieveSegmentation( } } - std::cout << "Achieve segmentation process" ; // Segmentation of the graph @@ -121,7 +110,6 @@ long long unsigned int RunPartialSegmentation(const typename TSegmenter::Paramet const float& threshold, const unsigned int niter, std::vector<ProcessingTile>& tiles, - const std::string& tmpDir, const unsigned int nbTilesX, const unsigned int nbTilesY, const unsigned int imageWidth, @@ -130,7 +118,6 @@ long long unsigned int RunPartialSegmentation(const typename TSegmenter::Paramet bool& isFusion) { long long unsigned int accumulatedMemory = 0; - std::string nodesPath, edgesPath; isFusion = false; const unsigned int numberOfNeighborLayers = static_cast<unsigned int>(pow(2, niter + 1) - 2); @@ -143,28 +130,27 @@ long long unsigned int RunPartialSegmentation(const typename TSegmenter::Paramet { if (MyTurn(row*nbTilesX + col)) { + // Get the current tile + ProcessingTile currentTile = tiles[row*nbTilesX + col]; + TSegmenter segmenter; std::cout << "Processing tile " << row << ", " << col << std::endl; std::cout << "\tLoad graph..." << std::endl; // Load the graph - nodesPath = tmpDir + "tile_nodes_" + std::to_string(row) + "_" + std::to_string(col) + ".bin"; - edgesPath = tmpDir + "tile_edges_" + std::to_string(row) + "_" + std::to_string(col) + ".bin"; - ReadGraph<TSegmenter>(segmenter.m_Graph, nodesPath, edgesPath); - + ReadGraph<TSegmenter>(segmenter.m_Graph, currentTile.nodeFileName, currentTile.edgeFileName); // Add stability margin to the graph { std::cout << "\tAdd stability margin..." << std::endl; - AddStabilityMargin<TSegmenter>(segmenter.m_Graph, tmpDir, + AddStabilityMargin<TSegmenter>(segmenter.m_Graph, tiles, row, col, nbTilesX, nbTilesY); - std::unordered_map<long unsigned int, std::vector<typename TSegmenter::NodePointerType> > borderPixelMap; std::cout << "\tBuild border pixel map..." << std::endl; - BuildBorderPixelMap<TSegmenter>(segmenter.m_Graph, tiles[row*nbTilesX + col], row, col, + BuildBorderPixelMap<TSegmenter>(segmenter.m_Graph, currentTile, row, col, nbTilesX, nbTilesY, borderPixelMap, imageWidth); std::cout << "\tRemove duplicated nodes..." << std::endl; @@ -176,7 +162,7 @@ long long unsigned int RunPartialSegmentation(const typename TSegmenter::Paramet imageHeight); std::cout << "\tRemove useless.." << std::endl; - RemoveUselessNodes<TSegmenter>(tiles[row*nbTilesX + col], segmenter.m_Graph, + RemoveUselessNodes<TSegmenter>(currentTile, segmenter.m_Graph, row, col, nbTilesX, nbTilesY, imageWidth, numberOfNeighborLayers); } @@ -198,15 +184,15 @@ long long unsigned int RunPartialSegmentation(const typename TSegmenter::Paramet // Remove unstable segments std::cout << "\tRemove unstable segments..." << std::endl; - RemoveUnstableSegments<TSegmenter>(segmenter.m_Graph, tiles[row*nbTilesX + col], imageWidth); + RemoveUnstableSegments<TSegmenter>(segmenter.m_Graph, currentTile, imageWidth); // Retrieve the amount of memory to store this graph std::cout << "\tGet graph memory..." << std::endl; - accumulatedMemory += GetGraphMemory<TSegmenter>(segmenter); + accumulatedMemory += segmenter.GetGraphMemory(); - // Write graph to temporay directory (warning specific to Baatz & Schape !!!) + // Write graph to temporay directory std::cout << "\tWrite graph..." << std::endl; - WriteGraph<TSegmenter>(segmenter.m_Graph, tmpDir, row, col); + WriteGraph<TSegmenter>(segmenter.m_Graph, currentTile.nodeFileName, currentTile.edgeFileName); } } } @@ -224,32 +210,24 @@ long long unsigned int RunPartialSegmentation(const typename TSegmenter::Paramet { if (MyTurn(row*nbTilesX + col)) { - // std::cout << "*" << std::flush; - typename TSegmenter::GraphType graph; + // Get current tile + ProcessingTile currentTile = tiles[row*nbTilesX + col]; // Load the graph - nodesPath = tmpDir + "tile_nodes_" + std::to_string(row) + "_" + std::to_string(col) + ".bin"; - edgesPath = tmpDir + "tile_edges_" + std::to_string(row) + "_" + std::to_string(col) + ".bin"; - ReadGraph<TSegmenter>(graph, nodesPath, edgesPath); + typename TSegmenter::GraphType graph; + ReadGraph<TSegmenter>(graph, currentTile.nodeFileName, currentTile.edgeFileName); // Extract stability margin for all borders different from 0 imageWidth-1 et imageHeight - // and write them to the stability margin { std::unordered_map<typename TSegmenter::NodePointerType, unsigned int> borderNodeMap; - DetectBorderNodes<TSegmenter>(graph, tiles[row*nbTilesX + col], + DetectBorderNodes<TSegmenter>(graph, currentTile, borderNodeMap, imageWidth, imageHeight); - ExtractStabilityMargin<TSegmenter>(borderNodeMap, numberOfNeighborLayers); - std::string nodesPath = tmpDir + "tile_nodes_margin_" + - std::to_string(row) + "_" + std::to_string(col) + ".bin"; - std::string edgesPath = tmpDir + "tile_edges_margin_" + - std::to_string(row) + "_" + std::to_string(col) + ".bin"; - - - WriteStabilityMargin<TSegmenter>(borderNodeMap, nodesPath, edgesPath); + WriteStabilityMargin<TSegmenter>(borderNodeMap, currentTile.nodeMarginFileName, currentTile.edgeMarginFileName); } std::cout << "Process finished on tile " << (row*nbTilesX + col) << std::endl; } @@ -529,156 +507,79 @@ void BuildBorderPixelMap(typename TSegmenter::GraphType& graph, } } +template<class TSegmenter> +void InsertNodesFromTile(typename TSegmenter::GraphType& graph, + ProcessingTile& tile, bool margin = true) +{ + typename TSegmenter::GraphType subgraph; + if (margin) + { + ReadGraph<TSegmenter>(subgraph, tile.nodeMarginFileName, tile.edgeMarginFileName); + } + else + { + ReadGraph<TSegmenter>(subgraph, tile.nodeFileName, tile.edgeFileName); + } + + graph.m_Nodes.insert(graph.m_Nodes.end(), subgraph.m_Nodes.begin(), subgraph.m_Nodes.end()); + +} + template<class TSegmenter> void AddStabilityMargin(typename TSegmenter::GraphType& graph, - const std::string& tmpDir, + std::vector<ProcessingTile>& tiles, const unsigned int row, const unsigned int col, const unsigned int nbTilesX, const unsigned int nbTilesY) { - std::string nodesPath; - std::string edgesPath; - unsigned int rowNeigh; - unsigned int colNeigh; // Margin to retrieve at top if(row > 0) { - colNeigh = col; - rowNeigh = row-1; - - nodesPath = tmpDir + "tile_nodes_margin_" + - std::to_string(rowNeigh) + "_" + std::to_string(colNeigh) + ".bin"; - - edgesPath = tmpDir + "tile_edges_margin_" + - std::to_string(rowNeigh) + "_" + std::to_string(colNeigh) + ".bin"; - - typename TSegmenter::GraphType subgraph; - ReadGraph<TSegmenter>(subgraph, nodesPath, edgesPath); - graph.m_Nodes.insert(graph.m_Nodes.end(), subgraph.m_Nodes.begin(), subgraph.m_Nodes.end()); + InsertNodesFromTile<TSegmenter>(graph, tiles[(row-1) * nbTilesX + col]); } // Margin to retrieve at right if(col < nbTilesX - 1) { - colNeigh = col + 1; - rowNeigh = row; - - nodesPath = tmpDir + "tile_nodes_margin_" + - std::to_string(rowNeigh) + "_" + std::to_string(colNeigh) + ".bin"; - - edgesPath = tmpDir + "tile_edges_margin_" + - std::to_string(rowNeigh) + "_" + std::to_string(colNeigh) + ".bin"; - - typename TSegmenter::GraphType subgraph; - ReadGraph<TSegmenter>(subgraph, nodesPath, edgesPath); - - graph.m_Nodes.insert(graph.m_Nodes.end(), subgraph.m_Nodes.begin(), subgraph.m_Nodes.end()); - + InsertNodesFromTile<TSegmenter>(graph, tiles[row * nbTilesX + (col+1)]); } // Margin to retrieve at bottom if(row < nbTilesY - 1) { - colNeigh = col; - rowNeigh = row + 1; - - nodesPath = tmpDir + "tile_nodes_margin_" + - std::to_string(rowNeigh) + "_" + std::to_string(colNeigh) + ".bin"; - - edgesPath = tmpDir + "tile_edges_margin_" + - std::to_string(rowNeigh) + "_" + std::to_string(colNeigh) + ".bin"; - - typename TSegmenter::GraphType subgraph; - ReadGraph<TSegmenter>(subgraph, nodesPath, edgesPath); - graph.m_Nodes.insert(graph.m_Nodes.end(), subgraph.m_Nodes.begin(), subgraph.m_Nodes.end()); - + InsertNodesFromTile<TSegmenter>(graph, tiles[(row+1) * nbTilesX + col]); } // Margin to retrieve at left if(col > 0) { - colNeigh = col-1; - rowNeigh = row; - - nodesPath = tmpDir + "tile_nodes_margin_" + - std::to_string(rowNeigh) + "_" + std::to_string(colNeigh) + ".bin"; - - edgesPath = tmpDir + "tile_edges_margin_" + - std::to_string(rowNeigh) + "_" + std::to_string(colNeigh) + ".bin"; - - typename TSegmenter::GraphType subgraph; - ReadGraph<TSegmenter>(subgraph, nodesPath, edgesPath); - graph.m_Nodes.insert(graph.m_Nodes.end(), subgraph.m_Nodes.begin(), subgraph.m_Nodes.end()); + InsertNodesFromTile<TSegmenter>(graph, tiles[row * nbTilesX + (col-1)]); } // Margin to retrieve at top right if(row > 0 && col < nbTilesX - 1) { - colNeigh = col+1; - rowNeigh = row-1; - - nodesPath = tmpDir + "tile_nodes_margin_" + - std::to_string(rowNeigh) + "_" + std::to_string(colNeigh) + ".bin"; - - edgesPath = tmpDir + "tile_edges_margin_" + - std::to_string(rowNeigh) + "_" + std::to_string(colNeigh) + ".bin"; - - typename TSegmenter::GraphType subgraph; - ReadGraph<TSegmenter>(subgraph, nodesPath, edgesPath); - graph.m_Nodes.insert(graph.m_Nodes.end(), subgraph.m_Nodes.begin(), subgraph.m_Nodes.end()); + InsertNodesFromTile<TSegmenter>(graph, tiles[(row-1) * nbTilesX + (col+1)]); } // Margin to retrieve at bottom right if(row < nbTilesY - 1 && col < nbTilesX - 1) { - colNeigh = col+1; - rowNeigh = row+1; - - nodesPath = tmpDir + "tile_nodes_margin_" + - std::to_string(rowNeigh) + "_" + std::to_string(colNeigh) + ".bin"; - - edgesPath = tmpDir + "tile_edges_margin_" + - std::to_string(rowNeigh) + "_" + std::to_string(colNeigh) + ".bin"; - - typename TSegmenter::GraphType subgraph; - ReadGraph<TSegmenter>(subgraph, nodesPath, edgesPath); - graph.m_Nodes.insert(graph.m_Nodes.end(), subgraph.m_Nodes.begin(), subgraph.m_Nodes.end()); + InsertNodesFromTile<TSegmenter>(graph, tiles[ (row+1) * nbTilesX + (col+1)]); } // Margin to retrieve at bottom left if(row < nbTilesY - 1 && col > 0) { - colNeigh = col-1; - rowNeigh = row+1; - - nodesPath = tmpDir + "tile_nodes_margin_" + - std::to_string(rowNeigh) + "_" + std::to_string(colNeigh) + ".bin"; - - edgesPath = tmpDir + "tile_edges_margin_" + - std::to_string(rowNeigh) + "_" + std::to_string(colNeigh) + ".bin"; - - typename TSegmenter::GraphType subgraph; - ReadGraph<TSegmenter>(subgraph, nodesPath, edgesPath); - graph.m_Nodes.insert(graph.m_Nodes.end(), subgraph.m_Nodes.begin(), subgraph.m_Nodes.end()); + InsertNodesFromTile<TSegmenter>(graph, tiles[ (row+1) * nbTilesX + (col-1)]); } // Margin to retrieve at top left if(row > 0 && col > 0) { - colNeigh = col-1; - rowNeigh = row-1; - - nodesPath = tmpDir + "tile_nodes_margin_" + - std::to_string(rowNeigh) + "_" + std::to_string(colNeigh) + ".bin"; - - edgesPath = tmpDir + "tile_edges_margin_" + - std::to_string(rowNeigh) + "_" + std::to_string(colNeigh) + ".bin"; - - typename TSegmenter::GraphType subgraph; - ReadGraph<TSegmenter>(subgraph, nodesPath, edgesPath); - graph.m_Nodes.insert(graph.m_Nodes.end(), subgraph.m_Nodes.begin(), subgraph.m_Nodes.end()); + InsertNodesFromTile<TSegmenter>(graph, tiles[ (row-1) * nbTilesX + (col-1)]); } } @@ -694,7 +595,6 @@ long long unsigned int RunFirstPartialSegmentation( const unsigned int nbTilesY, const unsigned int tileWidth, const unsigned int tileHeight, - const std::string& tmpDir, bool& isFusion) { @@ -717,6 +617,7 @@ long long unsigned int RunFirstPartialSegmentation( { // Reading images ProcessingTile currentTile = tiles[row*nbTilesX + col]; + std::cout << "Processing tile " << (row*nbTilesX + col) << " / " << (nbTilesX*nbTilesY) << " (" << col << ", " << row << ")" << " start: [" << currentTile.region.GetIndex()[0] << ", " << currentTile.region.GetIndex()[1] << @@ -740,7 +641,7 @@ long long unsigned int RunFirstPartialSegmentation( // Rescale the graph to be in the reference of the image std::cout << "\tRescaling graph..." << std::endl; RescaleGraph<TSegmenter>(segmenter.m_Graph, - tiles[row*nbTilesX + col], + currentTile, row, col, tileWidth, @@ -749,15 +650,15 @@ long long unsigned int RunFirstPartialSegmentation( // Remove unstable segments std::cout << "\tRemoving unstable segments..." << std::endl; - RemoveUnstableSegments<TSegmenter>(segmenter.m_Graph, tiles[row*nbTilesX + col], imageWidth); + RemoveUnstableSegments<TSegmenter>(segmenter.m_Graph, currentTile, imageWidth); // Retrieve the amount of memory to store this graph std::cout << "\tRetrieving graph memory..." << std::endl; - accumulatedMemory += GetGraphMemory<TSegmenter>(segmenter); + accumulatedMemory += segmenter.GetGraphMemory(); - // Write graph to temporay directory (warning specific to Baatz & Schape !!!) - std::cout << "\tWriting graph..." << std::endl; - WriteGraph<TSegmenter>(segmenter.m_Graph, tmpDir, row, col); + // Write graph to temporay directory + std::cout << "\tWriting graph..." << currentTile.nodeFileName << " et " << currentTile.edgeFileName << std::endl; + WriteGraph<TSegmenter>(segmenter.m_Graph, currentTile.nodeFileName, currentTile.edgeFileName); // Extract stability margin for all borders different from 0 imageWidth-1 et imageHeight -1 // and write them to the stability margin @@ -765,19 +666,12 @@ long long unsigned int RunFirstPartialSegmentation( { std::unordered_map<typename TSegmenter::NodePointerType, unsigned int> borderNodeMap; - DetectBorderNodes<TSegmenter>(segmenter.m_Graph, tiles[row*nbTilesX + col], + DetectBorderNodes<TSegmenter>(segmenter.m_Graph, currentTile, borderNodeMap, imageWidth, imageHeight); - ExtractStabilityMargin<TSegmenter>(borderNodeMap, numberOfNeighborLayers); - std::string nodesPath = tmpDir + "tile_nodes_margin_" + - std::to_string(row) + "_" + std::to_string(col) + ".bin"; - std::string edgesPath = tmpDir + "tile_edges_margin_" + - std::to_string(row) + "_" + std::to_string(col) + ".bin"; - - - WriteStabilityMargin<TSegmenter>(borderNodeMap, nodesPath, edgesPath); + WriteStabilityMargin<TSegmenter>(borderNodeMap, currentTile.nodeMarginFileName, currentTile.edgeMarginFileName); } } } // for each col @@ -889,96 +783,34 @@ void DetectBorderNodes(typename TSegmenter::GraphType& graph, } } -// Specific to Baatz & Schape (sorry it has to be fast) + +// Generic template<class TSegmenter> -void ReadGraph(typename TSegmenter::GraphType& graph, +void ReadGraph(TSegmenter& segmenter, const std::string& nodesPath, const std::string& edgesPath) { FILE * nodeStream = fopen(nodesPath.c_str(), "r"); assert(nodeStream != NULL); - std::unordered_map<long unsigned int, typename TSegmenter::NodePointerType> nodeMap; - - // Read the size of the graph - { - std::size_t graphSize; - fread(&graphSize, sizeof(graphSize), 1, nodeStream); - graph.m_Nodes.reserve(graphSize); - - // Creation of the nodes - for(std::size_t i = 0; i < graphSize; i++) - { - typename TSegmenter::NodePointerType node(new typename TSegmenter::NodeType()); - - node->m_Valid = true; - node->m_Expired = false; - node->m_IsMerged = true; // force to compute costs for the first iteration - - fread(&(node->m_Id), sizeof(node->m_Id), 1, nodeStream); - fread(&(node->m_Perimeter), sizeof(node->m_Perimeter), 1, nodeStream); - fread(&(node->m_Area), sizeof(node->m_Area), 1, nodeStream); - fread(&(node->m_Bbox.m_UX), sizeof(node->m_Bbox.m_UX), 1, nodeStream); - fread(&(node->m_Bbox.m_UY), sizeof(node->m_Bbox.m_UY), 1, nodeStream); - fread(&(node->m_Bbox.m_W), sizeof(node->m_Bbox.m_W), 1, nodeStream); - fread(&(node->m_Bbox.m_H), sizeof(node->m_Bbox.m_H), 1, nodeStream); - - std::size_t bands; - fread(&(bands), sizeof(bands), 1, nodeStream); - node->m_Means.assign(bands, 0); - node->m_SquareMeans.assign(bands, 0); - node->m_SpectralSum.assign(bands, 0); - node->m_Std.assign(bands, 0); - - for(unsigned int b = 0; b < bands; b++) - { - fread(&(node->m_Means[b]), sizeof(node->m_Means[b]), 1, nodeStream); - fread(&(node->m_SquareMeans[b]), sizeof(node->m_SquareMeans[b]), 1, nodeStream); - fread(&(node->m_SpectralSum[b]), sizeof(node->m_SpectralSum[b]), 1, nodeStream); - fread(&(node->m_Std[b]), sizeof(node->m_Std[b]), 1, nodeStream); - } - - { - std::size_t contourSize; - fread(&(contourSize), sizeof(contourSize), 1, nodeStream); - short moves[contourSize]; - fread(&moves, sizeof(short), contourSize, nodeStream); - for(unsigned int b = 0; b < contourSize; b++) - { - node->m_Contour.push_back(moves[b]); - } - } - nodeMap[node->m_Id] = node; - graph.m_Nodes.push_back(node); - } - } - fclose(nodeStream); - - // Build edges with nodeMap FILE * edgeStream = fopen(edgesPath.c_str(), "r"); assert(edgeStream != NULL); - for(auto& node: graph.m_Nodes) - { - long unsigned int nodeId; - fread(&(nodeId), sizeof(nodeId), 1, edgeStream); - assert(nodeId == node->m_Id); - - std::size_t edgeSize; - fread(&(edgeSize), sizeof(edgeSize), 1, edgeStream); - node->m_Edges.reserve(edgeSize); - for(unsigned int b = 0; b < edgeSize; b++) - { - long unsigned int targetId; - unsigned int boundary; - fread(&(targetId), sizeof(targetId), 1, edgeStream); - fread(&(boundary), sizeof(boundary), 1, edgeStream); - node->m_Edges.push_back(typename TSegmenter::EdgeType(nodeMap[targetId], 0, boundary)); - } - } + segmenter.ReadGraph(nodeStream, edgeStream); + fclose(nodeStream); fclose(edgeStream); } +template<class TSegmenter> +void ReadGraph(typename TSegmenter::GraphType& graph, + const std::string& nodesPath, + const std::string& edgesPath) +{ + TSegmenter segmenter; + ReadGraph<TSegmenter>(segmenter, nodesPath, edgesPath); + graph = segmenter.m_Graph; +} + // Write stability margin template<class TSegmenter> void WriteStabilityMargin(std::unordered_map< @@ -992,52 +824,19 @@ void WriteStabilityMargin(std::unordered_map< FILE * edgeStream = fopen(edgesPath.c_str(), "wb"); assert(edgeStream != NULL); - // Write size of the graph - { - // Write number of nodes - std::size_t size = stabilityMargin.size(); - fwrite(&size, sizeof(size), 1, nodeStream); - } + // Write number of nodes + std::size_t size = stabilityMargin.size(); + fwrite(&size, sizeof(size), 1, nodeStream); + TSegmenter seg; for(auto& kv : stabilityMargin) { auto node = kv.first; - - fwrite(&(node->m_Id), sizeof(node->m_Id), 1, nodeStream); - fwrite(&(node->m_Perimeter), sizeof(node->m_Perimeter), 1, nodeStream); - fwrite(&(node->m_Area), sizeof(node->m_Area), 1, nodeStream); - fwrite(&(node->m_Bbox.m_UX), sizeof(node->m_Bbox.m_UX), 1, nodeStream); - fwrite(&(node->m_Bbox.m_UY), sizeof(node->m_Bbox.m_UY), 1, nodeStream); - fwrite(&(node->m_Bbox.m_W), sizeof(node->m_Bbox.m_W), 1, nodeStream); - fwrite(&(node->m_Bbox.m_H), sizeof(node->m_Bbox.m_H), 1, nodeStream); - - std::size_t bands = node->m_Means.size(); - fwrite(&(bands), sizeof(bands), 1, nodeStream); - - for(unsigned int b = 0; b < node->m_Means.size(); b++) - { - fwrite(&(node->m_Means[b]), sizeof(node->m_Means[b]), 1, nodeStream); - fwrite(&(node->m_SquareMeans[b]), sizeof(node->m_SquareMeans[b]), 1, nodeStream); - fwrite(&(node->m_SpectralSum[b]), sizeof(node->m_SpectralSum[b]), 1, nodeStream); - fwrite(&(node->m_Std[b]), sizeof(node->m_Std[b]), 1, nodeStream); - } - - { - std::size_t contourSize = node->m_Contour.size(); - fwrite(&(contourSize), sizeof(contourSize), 1, nodeStream); - short moves[contourSize]; - for(unsigned int b = 0; b < contourSize; b++) - { - moves[b] = node->m_Contour[b]; - } - fwrite(moves, sizeof(short), contourSize, nodeStream); - } + seg.WriteNode(node, nodeStream); // Write only edges pointing to nodes which are in the stability margin. - fwrite(&(node->m_Id), sizeof(node->m_Id), 1, edgeStream); std::size_t edgeSize = node->m_Edges.size(); - for(auto& edg : node->m_Edges) { if(stabilityMargin.find(edg.GetRegion()) == stabilityMargin.end()) @@ -1048,8 +847,7 @@ void WriteStabilityMargin(std::unordered_map< { if(stabilityMargin.find(edg.GetRegion()) != stabilityMargin.end()) { - fwrite(&(edg.GetRegion()->m_Id), sizeof(edg.GetRegion()->m_Id), 1, edgeStream); - fwrite(&(edg.m_Boundary), sizeof(edg.m_Boundary), 1, edgeStream); + seg.WriteEdge(edg, edgeStream); } } } @@ -1058,65 +856,26 @@ void WriteStabilityMargin(std::unordered_map< fclose(edgeStream); } -// Specific to Baatz & Schape (sorry it has to be fast) +// Write the graph template<class TSegmenter> void WriteGraph(typename TSegmenter::GraphType& graph, - const std::string& tmpDir, - const unsigned int row, - const unsigned int col) + const std::string& nodeFile, + const std::string& edgeFile) { - // One file for the nodes - std::string nodeFile = tmpDir + "tile_nodes_" + - std::to_string(row) + "_" + std::to_string(col) + ".bin"; - // One file for the edges - std::string edgeFile = tmpDir + "tile_edges_" + - std::to_string(row) + "_" + std::to_string(col) + ".bin"; FILE * nodeStream = fopen(nodeFile.c_str(), "wb"); assert(nodeStream != NULL); FILE * edgeStream = fopen(edgeFile.c_str(), "wb"); assert(edgeStream != NULL); - // Write size of the graph - { - // Write number of nodes - std::size_t size = graph.m_Nodes.size(); - fwrite(&size, sizeof(size), 1, nodeStream); - } - + // Write number of nodes + std::size_t size = graph.m_Nodes.size(); + fwrite(&size, sizeof(size), 1, nodeStream); + TSegmenter seg; for(auto& node : graph.m_Nodes) { - - fwrite(&(node->m_Id), sizeof(node->m_Id), 1, nodeStream); - fwrite(&(node->m_Perimeter), sizeof(node->m_Perimeter), 1, nodeStream); - fwrite(&(node->m_Area), sizeof(node->m_Area), 1, nodeStream); - fwrite(&(node->m_Bbox.m_UX), sizeof(node->m_Bbox.m_UX), 1, nodeStream); - fwrite(&(node->m_Bbox.m_UY), sizeof(node->m_Bbox.m_UY), 1, nodeStream); - fwrite(&(node->m_Bbox.m_W), sizeof(node->m_Bbox.m_W), 1, nodeStream); - fwrite(&(node->m_Bbox.m_H), sizeof(node->m_Bbox.m_H), 1, nodeStream); - - std::size_t bands = node->m_Means.size(); - fwrite(&(bands), sizeof(bands), 1, nodeStream); - - for(unsigned int b = 0; b < node->m_Means.size(); b++) - { - fwrite(&(node->m_Means[b]), sizeof(node->m_Means[b]), 1, nodeStream); - fwrite(&(node->m_SquareMeans[b]), sizeof(node->m_SquareMeans[b]), 1, nodeStream); - fwrite(&(node->m_SpectralSum[b]), sizeof(node->m_SpectralSum[b]), 1, nodeStream); - fwrite(&(node->m_Std[b]), sizeof(node->m_Std[b]), 1, nodeStream); - } - - { - std::size_t contourSize = node->m_Contour.size(); - fwrite(&(contourSize), sizeof(contourSize), 1, nodeStream); - short moves[contourSize]; - for(unsigned int b = 0; b < contourSize; b++) - { - moves[b] = node->m_Contour[b]; - } - fwrite(moves, sizeof(short), contourSize, nodeStream); - } + seg.WriteNode(node, nodeStream); // Write edges fwrite(&(node->m_Id), sizeof(node->m_Id), 1, edgeStream); @@ -1124,8 +883,7 @@ void WriteGraph(typename TSegmenter::GraphType& graph, fwrite(&(edgeSize), sizeof(edgeSize), 1, edgeStream); for(auto& edg : node->m_Edges) { - fwrite(&(edg.GetRegion()->m_Id), sizeof(edg.GetRegion()->m_Id), 1, edgeStream); - fwrite(&(edg.m_Boundary), sizeof(edg.m_Boundary), 1, edgeStream); + seg.WriteEdge(edg, edgeStream); } } @@ -1133,29 +891,6 @@ void WriteGraph(typename TSegmenter::GraphType& graph, fclose(edgeStream); } -template<class TSegmenter> -long long unsigned int GetGraphMemory(TSegmenter segmenter) -{ -// TSegmenter::GraphType graph = segmenter.graph; -// long long unsigned int memory = 0; -// long unsigned int numberOfMoves = 0; -// -// // Amount of memory needed to store the nodes -// memory += graph.m_Nodes.size() * (sizeof(*graph.m_Nodes.begin()) + sizeof(graph.m_Nodes.begin()) + 4 * sizeof(float)); -// -// for(auto& node : graph.m_Nodes) -// { -// memory += node->m_Edges.size() * (sizeof(*node->m_Edges.begin()) + sizeof(node->m_Edges.begin())); -// numberOfMoves += node->m_Contour.size(); -// } -// -// memory += std::ceil(numberOfMoves / 4); -// -// return memory; - - return segmenter.GetGraphMemory(); -} - template<class TSegmenter> void RemoveUnstableSegments(typename TSegmenter::GraphType& graph, ProcessingTile& tile, @@ -1236,29 +971,13 @@ void RescaleGraph(typename TSegmenter::GraphType& graph, unsigned int rowNodeTile, colNodeTile; unsigned int rowNodeImg, colNodeImg; -// unsigned int currTileWidth = tile.columns[1] - tile.columns[0] + 1; -// currTileWidth += tile.margin[1]; -// currTileWidth += tile.margin[3]; -// unsigned int diffHeightMargin = tile.margin[0]; -// unsigned int diffWidthMargin = tile.margin[3]; - for(auto& node : graph.m_Nodes) { - -// // Row of the start pixel of the node -// rowNodeTile = node->m_Id / currTileWidth; -// // Col of the start pixel of the node -// colNodeTile = node->m_Id % currTileWidth; -// -// // Row of the start pixel of the node in the image -// rowNodeImg = rowTile * tileHeight + rowNodeTile - diffHeightMargin; -// // Col of the start pixel of the node in the image -// colNodeImg = colTile * tileWidth + colNodeTile - diffWidthMargin; -// -// node->m_Id = rowNodeImg * imageWidth + colNodeImg; - + // Start pixel index of the node (in the tile) rowNodeTile = node->m_Id / tile.region.GetSize()[0]; colNodeTile = node->m_Id % tile.region.GetSize()[0]; + + // Start pixel index of the node (in the image) rowNodeImg = rowTile * tileHeight + rowNodeTile - tile.margin[0]; colNodeImg = colTile * tileWidth + colNodeTile - tile.margin[3]; node->m_Id = rowNodeImg * imageWidth + colNodeImg;