Commit a77b7b5f authored by Pierre Lassalle's avatar Pierre Lassalle

OTB friendly version

parent 3f558e48
#include <iostream>
#include <otbImage.h>
#include <otbImageFileReader.h>
#include <otbVectorImage.h>
#include <otbImageFileReader.h>
#include <otbImageFileWriter.h>
#include "lsrmBaatzSegmenter.h"
int main(int argc, char *argv[])
......@@ -20,26 +21,45 @@ int main(int argc, char *argv[])
}
lsrm::BaatzParam params;
const char * input_image = argv[1];
const char * clustered_image = argv[2];
const char * label_image = argv[3];
const char * inFileName = argv[1];
const char * clusterFileName = argv[2];
const char * labelFileName = argv[3];
params.m_SpectralWeight = atof(argv[4]);
params.m_ShapeWeight = atof(argv[5]);
float sqrt_scale = atof(argv[6]);
const float scale = sqrt_scale * sqrt_scale;
typedef float PixelType;
typedef otb::VectorImage<PixelType, 2> ImageType;
typedef lsrm::BaatzSegmenter<ImageType> SegmenterType;
typedef unsigned long int LabelPixelType;
typedef unsigned char ClusterPixelType;
typedef otb::VectorImage<PixelType, 2> InputImageType;
typedef otb::Image<LabelPixelType, 2> LabelImageType;
typedef otb::VectorImage<ClusterPixelType, 2> ClusterImageType;
typedef otb::ImageFileReader<InputImageType> InputImageReaderType;
typedef otb::ImageFileWriter<LabelImageType> LabelImageWriterType;
typedef otb::ImageFileWriter<ClusterImageType> ClusterImageWriterType;
typedef lsrm::BaatzSegmenter<InputImageType> SegmenterType;
auto imgReader = InputImageReaderType::New();
imgReader->SetFileName(inFileName);
imgReader->Update();
SegmenterType segmenter;
segmenter.SetParam(params);
segmenter.SetThreshold(scale);
segmenter.SetInputFileName(input_image);
segmenter.SetClusteredImageFileName(clustered_image);
segmenter.SetLabelImageFileName(label_image);
segmenter.RunSegmentation();
segmenter.SetInput(imgReader->GetOutput());
segmenter.Update();
auto labelWriter = LabelImageWriterType::New();
labelWriter->SetFileName(labelFileName);
labelWriter->SetInput(segmenter.GetLabeledClusteredOutput());
labelWriter->Update();
auto clusterWriter = ClusterImageWriterType::New();
clusterWriter->SetFileName(clusterFileName);
clusterWriter->SetInput(segmenter.GetClusteredImageOutput());
clusterWriter->Update();
return 0;
}
......@@ -50,3 +70,5 @@ int main(int argc, char *argv[])
#ifndef __LSRM_BAATZ_SEGMENTER_H
#define __LSRM_BAATZ_SEGMENTER_H
#include "lsrmSegmenter.h"
#include "lsrmGraphToOtbImage.h"
/*
* Tutorial : Implementation of the Baatz & Schape criterion
*
......@@ -88,7 +87,7 @@ namespace lsrm
BaatzSegmenter();
void RunSegmentation();
void Update();
float ComputeMergingCost(NodePointerType n1, NodePointerType n2);
void UpdateSpecificAttributes(NodePointerType n1, NodePointerType n2);
void InitFromImage();
......
......@@ -17,19 +17,14 @@ namespace lsrm
void
BaatzSegmenter<TImage>::InitFromImage()
{
typedef otb::ImageFileReader<TImage> ImageReaderType;
typedef itk::ImageRegionIterator<TImage> ImageIterator;
typename ImageReaderType::Pointer reader = ImageReaderType::New();
reader->SetFileName(this->m_InputFileName);
reader->Update();
this->m_ImageWidth = reader->GetOutput()->GetLargestPossibleRegion().GetSize()[0];
this->m_ImageHeight = reader->GetOutput()->GetLargestPossibleRegion().GetSize()[1];
this->m_NumberOfComponentsPerPixel = reader->GetOutput()->GetNumberOfComponentsPerPixel();
this->m_ImageWidth = this->m_InputImage->GetLargestPossibleRegion().GetSize()[0];
this->m_ImageHeight =this->m_InputImage->GetLargestPossibleRegion().GetSize()[1];
this->m_NumberOfComponentsPerPixel = this->m_InputImage->GetNumberOfComponentsPerPixel();
std::size_t idx = 0;
ImageIterator it(reader->GetOutput(), reader->GetOutput()->GetLargestPossibleRegion());
ImageIterator it(this->m_InputImage, this->m_InputImage->GetLargestPossibleRegion());
for(it.GoToBegin(); !it.IsAtEnd(); ++it)
{
this->m_Graph.m_Nodes[idx]->m_Means.reserve(this->m_NumberOfComponentsPerPixel);
......@@ -112,34 +107,34 @@ namespace lsrm
template<class TImage>
void
BaatzSegmenter<TImage>::RunSegmentation()
BaatzSegmenter<TImage>::Update()
{
GraphOperatorType::InitNodes(this->m_Graph, *this, this->m_InputFileName, FOUR);
bool prev_merged =
GraphOperatorType::PerfomAllIterationsWithLMBFAndConstThreshold(this->m_Graph, *this,
this->m_Threshold, this->m_NumberOfIterations,
this->m_ImageWidth, this->m_ImageHeight);
if(prev_merged && this->m_DoBFSegmentation)
GraphOperatorType::InitNodes(this->m_InputImage, this->m_Graph, *this, FOUR);
bool prev_merged = false;
if(this->m_NumberOfIterations > 0)
{
prev_merged =
GraphOperatorType::PerfomAllIterationsWithBFAndConstThreshold(this->m_Graph, *this,
this->m_Threshold, this->m_NumberOfIterations,
this->m_ImageWidth, this->m_ImageHeight);
}
GraphOperatorType::PerfomAllIterationsWithLMBFAndConstThreshold(this->m_Graph, *this,
this->m_Threshold, this->m_NumberOfIterations,
this->m_ImageWidth, this->m_ImageHeight);
if(!this->m_ClusteredImageFileName.empty())
IOType::WriteOutputRGBImage(this->m_Graph,
this->m_ImageWidth,
this->m_ImageHeight,
this->m_ClusteredImageFileName);
if(!this->m_LabelImageFileName.empty())
IOType::WriteLabelImage(this->m_Graph,
this->m_ImageWidth,
this->m_ImageHeight,
this->m_LabelImageFileName);
if(prev_merged && this->m_DoBFSegmentation)
{
prev_merged =
GraphOperatorType::PerfomAllIterationsWithBFAndConstThreshold(this->m_Graph, *this,
this->m_Threshold, this->m_NumberOfIterations,
this->m_ImageWidth, this->m_ImageHeight);
}
}
else
{
assert(this->m_DoBFSegmentation == true);
prev_merged =
GraphOperatorType::PerfomAllIterationsWithBFAndConstThreshold(this->m_Graph, *this,
this->m_Threshold, this->m_NumberOfIterations,
this->m_ImageWidth, this->m_ImageHeight);
}
}
} // end of namespace lsrm
......
......@@ -18,6 +18,7 @@ namespace lsrm
/* Some convenient typedefs */
typedef TSegmenter SegmenterType;
typedef typename SegmenterType::ImageType ImageType;
typedef typename SegmenterType::GraphType GraphType;
typedef typename GraphType::NodeType NodeType;
typedef typename GraphType::EdgeType EdgeType;
......@@ -40,9 +41,9 @@ namespace lsrm
* const unsigned int height: height of the input image
* CONNECTIVITY mask : mask of the neighborhood (4X4 or 8X8)
*/
static void InitNodes(GraphType& graph,
static void InitNodes(ImageType * inputImg,
GraphType& graph,
SegmenterType& seg,
const std::string& inputFileName,
CONNECTIVITY mask);
/*
......
......@@ -5,22 +5,16 @@
namespace lsrm
{
template<class TSegmenter>
void GraphOperations<TSegmenter>::InitNodes(GraphType& graph,
void GraphOperations<TSegmenter>::InitNodes(ImageType * inputImg,
GraphType& graph,
SegmenterType& seg,
const std::string& inputFileName,
CONNECTIVITY mask)
{
unsigned int width, height;
{
typedef typename TSegmenter::ImageType ImageType;
typedef otb::ImageFileReader<ImageType> ReaderType;
typename ReaderType::Pointer reader = ReaderType::New();
reader->SetFileName(inputFileName);
reader->UpdateOutputInformation();
width = reader->GetOutput()->GetLargestPossibleRegion().GetSize()[0];
height = reader->GetOutput()->GetLargestPossibleRegion().GetSize()[1];
width = inputImg->GetLargestPossibleRegion().GetSize()[0];
height = inputImg->GetLargestPossibleRegion().GetSize()[1];
}
const long unsigned int num_nodes = width * height;
......@@ -430,17 +424,25 @@ namespace lsrm
const unsigned int height)
{
bool merged = true;
unsigned int maxNumberOfIterations;
if(numberOfIterations < 1)
maxNumberOfIterations = 75;
else
maxNumberOfIterations = numberOfIterations;
unsigned int iterations = 0;
while(merged &&
iterations < numberOfIterations &&
iterations < maxNumberOfIterations &&
graph.m_Nodes.size() > 1)
{
std::cout << "." << std::flush;
++iterations;
merged = PerfomOneIterationWithBF(graph, seg, threshold,
width, height);
}
std::cout << std::endl;
if(graph.m_Nodes.size() < 2)
return false;
......@@ -457,3 +459,6 @@ namespace lsrm
#ifndef __LSRM_GRAPH_TO_OTBIMAGE_H
#define __LSRM_GRAPH_TO_OTBIMAGE_H
#include <itkRGBPixel.h>
#include <itkImageRegion.h>
#include <otbImage.h>
#include <otbVectorImage.h>
#include <otbImageFileReader.h>
......@@ -22,38 +23,19 @@ namespace lsrm
typedef typename GraphType::NodeType NodeType;
typedef std::vector< boost::shared_ptr<NodeType> > NodeList;
typedef typename NodeList::const_iterator NodeConstIterator;
typedef unsigned long int LabelPixelType;
typedef otb::Image<LabelPixelType, 2> LabelImageType;
typedef unsigned char ClusterPixelType;
typedef otb::VectorImage<ClusterPixelType, 2> ClusteredImageType;
/*
* Given a graph of nodes and the size of the image, it returns
* a raster image where to every pixel of a region is assigned
* the same unique label value.
*
* @params
* const GraphType& graph : graph of nodes
* const unsigned int width : width of the output labeled image.
* const unsigned int height : height of the output labeled image.
* const std::string& outputFileName : filename of the output image.
*/
static void WriteLabelImage(const GraphType& graph,
const unsigned int width,
const unsigned int height,
const std::string& outputFileName);
LabelImageType::Pointer GetLabelImage(const GraphType& graph,
const unsigned int width,
const unsigned int height);
/*
* Given a graph of nodes and the size of the image, it returns
* a raster image where to every pixel of a region is assigned
* the same rgb color.
*
* @params
* const GraphType& graph : graph of nodes
* const unsigned int width : width of the output rgb image.
* const unsigned int height : height of the output rgb image.
* const std::string& outputFileName : filename of the output image.
*/
static void WriteOutputRGBImage(const GraphType& graph,
const unsigned int width,
const unsigned int height,
const std::string& outputFileName);
ClusteredImageType::Pointer GetClusteredOutput(const GraphType& graph,
const unsigned int width,
const unsigned int height);
};
} // end of namespace lsrm
......
......@@ -5,15 +5,11 @@
namespace lsrm
{
template<class TGraph>
void GraphToOtbImage<TGraph>::WriteLabelImage(const GraphType& graph,
const unsigned int width,
const unsigned int height,
const std::string& outputFileName)
typename GraphToOtbImage<TGraph>::LabelImageType::Pointer
GraphToOtbImage<TGraph>::GetLabelImage(const GraphType& graph,
const unsigned int width,
const unsigned int height)
{
typedef long unsigned int LabelPixelType;
typedef otb::Image<LabelPixelType, 2> LabelImageType;
LabelImageType::IndexType index;
LabelImageType::SizeType size;
LabelImageType::RegionType region;
......@@ -41,51 +37,31 @@ namespace lsrm
++label;
}
typedef otb::ImageFileWriter<LabelImageType> LabelWriterType;
LabelWriterType::Pointer label_writer = LabelWriterType::New();
label_writer->SetInput(label_img);
label_writer->SetFileName(outputFileName);
label_writer->Update();
return label_img;
}
template<class TGraph>
void GraphToOtbImage<TGraph>::WriteOutputRGBImage(const GraphType& graph,
const unsigned int width,
const unsigned int height,
const std::string& outputFileName)
typename GraphToOtbImage<TGraph>::ClusteredImageType::Pointer
GraphToOtbImage<TGraph>::GetClusteredOutput(const GraphType& graph,
const unsigned int width,
const unsigned int height)
{
typedef unsigned char RGBPixelType;
typedef otb::VectorImage<RGBPixelType, 2> RGBImageType;
typename RGBImageType::PixelType pixelValue;
RGBImageType::IndexType index;
RGBImageType::SizeType size;
RGBImageType::RegionType region;
ClusteredImageType::IndexType index;
ClusteredImageType::SizeType size;
ClusteredImageType::RegionType region;
index[0] = 0; index[1] = 0;
size[0] = width; size[1] = height;
region.SetIndex(index);
region.SetSize(size);
RGBImageType::Pointer rgb_img = RGBImageType::New();
rgb_img->SetRegions(region);
rgb_img->SetNumberOfComponentsPerPixel(3);
rgb_img->Allocate();
pixelValue.Reserve(3);
pixelValue[0] = 0;
pixelValue[1] = 0;
pixelValue[2] = 0;
ClusteredImageType::Pointer clusterImg = ClusteredImageType::New();
clusterImg->SetRegions(region);
clusterImg->SetNumberOfComponentsPerPixel(3);
clusterImg->Allocate();
for(unsigned int y = 0; y < height; ++y)
{
for(unsigned int x = 0; x < width; ++x)
{
index[0] = x;
index[1] = y;
rgb_img->SetPixel(index, pixelValue);
}
}
ClusteredImageType::PixelType pixelValue;
pixelValue.Reserve(3);
srand(time(NULL));
unsigned char c1, c2, c3;
......@@ -101,16 +77,11 @@ namespace lsrm
pixelValue[0] = c1;
pixelValue[1] = c2;
pixelValue[2] = c3;
rgb_img->SetPixel(index, pixelValue);
clusterImg->SetPixel(index, pixelValue);
}
}
typedef otb::ImageFileWriter<RGBImageType> RGBWriterType;
RGBWriterType::Pointer rgb_writer = RGBWriterType::New();
rgb_writer->SetInput(rgb_img);
rgb_writer->SetFileName(outputFileName);
rgb_writer->Update();
return clusterImg;
}
} // end of namespace lsrm
#endif
......@@ -3,6 +3,7 @@
#include "macro-generator.h"
#include "lsrmGraph.h"
#include "lsrmGraphOperations.h"
#include "lsrmGraphToOtbImage.h"
namespace lsrm
{
......@@ -21,6 +22,9 @@ namespace lsrm
typedef typename GraphType::EdgeType EdgeType;
typedef GraphOperations<Self> GraphOperatorType;
typedef typename GraphOperatorType::NodePointerType NodePointerType;
typedef GraphToOtbImage<GraphType> IOType;
typedef typename IOType::LabelImageType LabelImageType;
typedef typename IOType::ClusteredImageType ClusteredImageType;
/* Default constructor and destructor */
......@@ -30,7 +34,7 @@ namespace lsrm
/*
* This method performs the region merging segmentation.
*/
virtual void RunSegmentation() = 0;
virtual void Update() = 0;
/* methods to overload */
......@@ -66,17 +70,30 @@ namespace lsrm
* const std::string& inputFileName : input image path
*/
virtual void InitFromImage() = 0;
/* Return the label image */
inline typename LabelImageType::Pointer GetLabeledClusteredOutput()
{
IOType io;
auto labelImg = io.GetLabelImage(this->m_Graph, this->m_ImageWidth, this->m_ImageHeight);
return labelImg;
}
inline typename ClusteredImageType::Pointer GetClusteredImageOutput()
{
IOType io;
auto clusteredImg = io.GetClusteredOutput(this->m_Graph, this->m_ImageWidth, this->m_ImageHeight);
return clusteredImg;
}
/* Set methods */
SetMacro(bool, DoBFSegmentation);
SetMacro(unsigned int, NumberOfIterations);
SetMacro(float, Threshold);
SetMacro(ParamType, Param);
SetMacro(std::string, InputFileName);
SetMacro(std::string, ClusteredImageFileName);
SetMacro(std::string, LabelImageFileName);
SetMacro(std::string, ContourImageFileName);
inline void SetInput(TImage * in){ m_InputImage = in;}
protected:
/* Activate the Best Fitting heuristic */
......@@ -98,10 +115,9 @@ namespace lsrm
unsigned int m_ImageWidth; // Number of columns
unsigned int m_ImageHeight; // NUmber of rows
unsigned int m_NumberOfComponentsPerPixel; // Number of spectral bands
std::string m_InputFileName;
std::string m_ClusteredImageFileName;
std::string m_LabelImageFileName;
std::string m_ContourImageFileName;
/* Pointer to the input image to segment */
TImage * m_InputImage;
};
} // end of namespace lsrm
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment