Commit d5e27a59 authored by Pierre Lassalle's avatar Pierre Lassalle

Update

parent 64205ee9
GRM Library: Quick Start Tutorial
Requirements:
* Orfeo Toolbox library available here: http://orfeo-toolbox.org/otb/download.html
* Boost library
* CMake (version 2.8 minimum)
On Linux:
Step 1: copy the source code into your favorite directory. In the following we assume that
your path is PATH/grm/
Step 2: Go to PATH/grm/
Step 3: mkdir grm_build
Step 4: cd grm_build/
Step 5: Generate the Makefile:
cmake \
-DCMAKE_CXX_FLAGS:STRING=-std=c++11 \
-DOTB_DIR:PATH=/usr/lib/otb \
-DITK_DIR:PATH=/usr/lib/cmake/ITK-4.6 \
-DGDAL_CONFIG:FILEPATH=/usr/bin/gdal-config \
-DGDAL_INCLUDE_DIR:PATH=/usr/include/gdal \
-DGDAL_LIBRARY:FILEPATH=/usr/lib/libgdal.so \
../src/
Step 6: make
Step 7: cd Applications | ./BaatzSegmentation --help
3 region merging criteria have been already implemented, up to you to add a new one.
If you are a generous man then you can send me a message to propose your new criterion
at the following email address: lassallepierre34@gmail.com
For more explanation about this library, go to this site:
http://pierre33.github.io/
Enjoy !
......@@ -14,97 +14,52 @@
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
// Boost headers (mandatory)
#include <boost/program_options/cmdline.hpp>
#include <boost/program_options/parsers.hpp>
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/variables_map.hpp>
#include <iostream>
// Your algorithm header file
#include "baatz-algorithm.h"
namespace po = boost::program_options;
bool init_args(int argc, char ** argv, po::options_description& desc, po::variables_map& vm);
int main(int argc, char **argv)
{
po::options_description desc("Configuration of the Baatz & Schâpe region merging segmentation");
po::variables_map vm;
if(init_args(argc, argv, desc, vm))
if(argc < 7 || argc > 9)
{
typedef otb::VectorImage<float, 2> ImageType;
typedef BaatzAlgorithmRM<ImageType> SegmenterType;
BaatzParams params = {vm["cw"].as<float>(), vm["sw"].as<float>(), vm["sp"].as<float>()};
SegmenterType seg_;
seg_.SetInput(vm["input"].as<std::string>());
seg_.SetOutputRGB(vm["output_rgb"].as<std::string>());
seg_.SetParameters(params);
seg_.SetNumberOfIterations(vm["iter"].as<unsigned int>());
seg_.InitFromImage();
seg_.Segmentation();
seg_.WriteRGBOutputImage();
return 0;
}
else
std::cout << "############### Manual #############################\n\n\n"
<< "Usage " << argv[0] << "\n\n\n"
<< " -- [input image (tif, jpg, png) <mandatory>]\n"
<< " -- [output rgb image (tif, jpg, png) <mandatory>]\n"
<< " -- [output label image (tif) <mandatory>]\n"
<< " -- [spectral weight (value >= 0 and <= 1) <mandatory>]\n"
<< " -- [shape weight (value >= 0 and <= 1) <mandatory>]\n"
<< " -- [scale parameter (positive value) <mandatory>]\n"
<< " -- [number of iterations using the Local Mutual Best Fitting heuristic (70 by default) <optional>]\n"
<< " -- [activation of the Best Fitting heuristic (value = 0 (desactivated) or 1 (activated) \
- activated by default) <optional>]\n\n\n"
<< "################################################################\n";
return 1;
}
bool init_args(int argc, char ** argv, po::options_description& desc, po::variables_map& vm)
{
desc.add_options()
("help", "print mandatory arguments")
("input", po::value<std::string>(), "set input image file (mandatory)")
("output_rgb", po::value<std::string>(), "set output rgb image file (mandatory)")
("cw", po::value<float>(), "set the spectral weight (mandatory)")
("sw", po::value<float>(), "set the shape weight (mandatory)")
("sp", po::value<float>(), "set the scale parameter (mandatory)")
("iter", po::value<unsigned int>(), "set the number of iterations using LMBF\
(optional [value by default (70)])")
("bf", po::value<int>(), "activate the Best Fitting Heuristic \
[1: activated 0: desactivated] \
(optional [activated by default])");
po::store(po::parse_command_line(argc, argv, desc), vm);
po::notify(vm);
if (vm.count("help")) {
std::cout << desc << "\n";
return false;
}
if (!vm.count("input")) {
std::cout << "The input image file was not set (--input).\n";
std::cout << desc << "\n";
return false;
}
if (!vm.count("output_rgb")) {
std::cout << "The output rgb file was not set (--output_rgb).\n";
std::cout << desc << "\n";
return false;
}
if(!vm.count("cw")){
std::cout << "The spectral weight was not set (--cw).\n";
std::cout << desc << "\n";
return false;
}
if(!vm.count("sw")){
std::cout << "The shape weight was not set (--sw).\n";
std::cout << desc << "\n";
return false;
}
if(!vm.count("sp")){
std::cout << "The scale parameter was not set (--sp).\n";
std::cout << desc << "\n";
return false;
}
return true;
const std::string inputFileName = argv[1];
const std::string outputFileName = argv[2];
const std::string outputLabelFileName = argv[3];
const float cw = atof(argv[4]);
const float sw = atof(argv[5]);
const float sp = atof(argv[6]);
typedef otb::VectorImage<float, 2> ImageType;
typedef BaatzAlgorithmRM<ImageType> SegmenterType;
BaatzParams params = {cw, sw, sp};
SegmenterType seg_;
seg_.SetInput(inputFileName);
seg_.SetOutputRGB(outputFileName);
seg_.SetOutputLabel(outputLabelFileName);
seg_.SetParameters(params);
if(argc >= 8)
seg_.SetNumberOfIterations(static_cast<unsigned int>(atoi(argv[7])));
if(argc == 9)
seg_.SetBestFitting(atoi(argv[8]));
seg_.Run();
return 0;
}
......@@ -17,15 +17,12 @@
#=========================================================================
add_executable(EuclideanDistanceSegmentation EuclideanDistanceSegmentation.cxx)
target_link_libraries(EuclideanDistanceSegmentation
GRM
boost_program_options)
GRM)
add_executable(FLSASegmentation FLSASegmentation.cxx)
target_link_libraries(FLSASegmentation
GRM
boost_program_options)
GRM)
add_executable(BaatzSegmentation BaatzSegmentation.cxx)
target_link_libraries(BaatzSegmentation
GRM
boost_program_options)
GRM)
......@@ -14,77 +14,50 @@
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
// Boost headers (mandatory)
#include <boost/program_options/cmdline.hpp>
#include <boost/program_options/parsers.hpp>
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/variables_map.hpp>
#include <iostream>
// Your algorithm header file
#include "euc-dist-algorithm.h"
namespace po = boost::program_options;
bool init_args(int argc, char ** argv, po::options_description& desc, po::variables_map& vm);
int main(int argc, char **argv)
{
po::options_description desc("Configuration of the Euclidean distance region merging segmentation");
po::variables_map vm;
if(init_args(argc, argv, desc, vm))
if(argc < 6 || argc > 8)
{
typedef otb::VectorImage<float, 2> ImageType;
typedef EuclideanDistanceRM<ImageType> SegmenterType;
EucDistParams params = {vm["euc_thresh"].as<float>(), 0};
SegmenterType seg_;
seg_.SetInput(vm["input"].as<std::string>());
seg_.SetOutputRGB(vm["output_rgb"].as<std::string>());
seg_.SetParameters(params);
seg_.InitFromImage();
seg_.Segmentation();
seg_.WriteRGBOutputImage();
return 0;
}
else
std::cout << "############### Manual #############################\n\n\n"
<< "Usage " << argv[0] << "\n\n\n"
<< " -- [input image (tif, jpg, png) <mandatory>]\n"
<< " -- [output rgb image (tif, jpg, png) <mandatory>]\n"
<< " -- [output label image (tif) <mandatory>]\n"
<< " -- [maximum distance <mandatory>]\n"
<< " -- [minimum distance <mandatory>]\n"
<< " -- [number of iterations using the Local Mutual Best Fitting heuristic (70 by default) <optional>]\n"
<< " -- [activation of the Best Fitting heuristic (value = 0 (desactivated) or 1 (activated) \
- activated by default) <optional>]\n\n\n"
<< "################################################################\n";
return 1;
}
bool init_args(int argc, char ** argv, po::options_description& desc, po::variables_map& vm)
{
desc.add_options()
("help", "print mandatory arguments")
("input", po::value<std::string>(), "set input image file")
("output_rgb", po::value<std::string>(), "set output rgb image file")
("euc_thresh", po::value<float>(), "set the euclidean threshold");
po::store(po::parse_command_line(argc, argv, desc), vm);
po::notify(vm);
if (vm.count("help")) {
std::cout << desc << "\n";
return false;
}
if (!vm.count("input")) {
std::cout << "The input image file was not set (--input).\n";
std::cout << desc << "\n";
return false;
}
if (!vm.count("output_rgb")) {
std::cout << "The output rgb file was not set (--output_rgb).\n";
std::cout << desc << "\n";
return false;
}
if(!vm.count("euc_thresh")){
std::cout << "The Euclidean threshold was not set (--euc_thresh).\n";
std::cout << desc << "\n";
return false;
}
return true;
const std::string inputFileName = argv[1];
const std::string outputFileName = argv[2];
const std::string outputLabelFileName = argv[3];
const float max_dist = atof(argv[4]);
float min_dist = atof(argv[5]);
typedef otb::VectorImage<float, 2> ImageType;
typedef EuclideanDistanceRM<ImageType> SegmenterType;
EucDistParams params = {max_dist, min_dist};
SegmenterType seg_;
seg_.SetInput(inputFileName);
seg_.SetOutputRGB(outputFileName);
seg_.SetOutputLabel(outputLabelFileName);
seg_.SetParameters(params);
if(argc >= 7)
seg_.SetNumberOfIterations(static_cast<unsigned int>(atoi(argv[6])));
if(argc == 8)
seg_.SetBestFitting(atoi(argv[7]));
seg_.Run();
return 0;
}
......@@ -14,80 +14,48 @@
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
// Boost headers (mandatory)
#include <boost/program_options/cmdline.hpp>
#include <boost/program_options/parsers.hpp>
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/variables_map.hpp>
#include <iostream>
// Your algorithm header file
#include "fls-algorithm.h"
namespace po = boost::program_options;
bool init_args(int argc, char ** argv, po::options_description& desc, po::variables_map& vm);
int main(int argc, char **argv)
{
po::options_description desc("Configuration of the Full Lambda Schedule region merging segmentation");
po::variables_map vm;
if(init_args(argc, argv, desc, vm))
if(argc < 5 || argc > 7)
{
typedef otb::VectorImage<float, 2> ImageType;
typedef FLSAlgorithmRM<ImageType> SegmenterType;
FLSParams params = vm["thresh"].as<float>();
SegmenterType seg_;
seg_.SetInput(vm["input"].as<std::string>());
seg_.SetOutputRGB(vm["output_rgb"].as<std::string>());
seg_.SetParameters(params);
seg_.SetNumberOfIterations(vm["iter"].as<unsigned int>());
seg_.InitFromImage();
seg_.Segmentation();
seg_.WriteRGBOutputImage();
return 0;
}
else
std::cout << "############### Manual #############################\n\n\n"
<< "Usage " << argv[0] << "\n\n\n"
<< " -- [input image (tif, jpg, png) <mandatory>]\n"
<< " -- [output rgb image (tif, jpg, png) <mandatory>]\n"
<< " -- [output label image (tif) <mandatory>]\n"
<< " -- [lambda threshold <mandatory>]\n"
<< " -- [number of iterations using the Local Mutual Best Fitting heuristic (70 by default) <optional>]\n"
<< " -- [activation of the Best Fitting heuristic (value = 0 (desactivated) or 1 (activated) \
- activated by default) <optional>]\n\n\n"
<< "################################################################\n";
return 1;
}
}
bool init_args(int argc, char ** argv, po::options_description& desc, po::variables_map& vm)
{
desc.add_options()
("help", "print arguments")
("input", po::value<std::string>(), "set input image file (mandatory)")
("output_rgb", po::value<std::string>(), "set output rgb image file (mandatory)")
("thresh", po::value<float>(), "set the threshold (mandatory)")
("iter", po::value<unsigned int>(), "set the number of iterations using LMBF (optional)")
("bf", po::value<int>(), "activate the Best Fitting Heuristic");
const std::string inputFileName = argv[1];
const std::string outputFileName = argv[2];
const std::string outputLabelFileName = argv[3];
float lambda = atof(argv[4]);
po::store(po::parse_command_line(argc, argv, desc), vm);
po::notify(vm);
typedef otb::VectorImage<float, 2> ImageType;
typedef FLSAlgorithmRM<ImageType> SegmenterType;
if (vm.count("help")) {
std::cout << desc << "\n";
return false;
}
FLSParams params = lambda;
SegmenterType seg_;
seg_.SetInput(inputFileName);
seg_.SetOutputRGB(outputFileName);
seg_.SetOutputLabel(outputLabelFileName);
seg_.SetParameters(params);
if (!vm.count("input")) {
std::cout << "The input image file was not set (--input).\n";
std::cout << desc << "\n";
return false;
}
if(argc >= 6)
seg_.SetNumberOfIterations(static_cast<unsigned int>(atoi(argv[5])));
if(argc == 7)
seg_.SetBestFitting(atoi(argv[6]));
if (!vm.count("output_rgb")) {
std::cout << "The output rgb file was not set (--output_rgb).\n";
std::cout << desc << "\n";
return false;
}
if(!vm.count("thresh")){
std::cout << "The threshold was not set (--thresh).\n";
std::cout << desc << "\n";
return false;
}
seg_.Run();
return true;
return 0;
}
......@@ -150,10 +150,9 @@ BaatzAlgorithmRM<TInputImage>::Segmentation()
while(prev_merged && step < this->m_NumberOfIterations)
{
//std::cout << "." << std::flush;
std::cout << "." << std::flush;
prev_merged = false;
++step;
std::cout << step << std::endl;
this->m_RMHandler.UpdateMergingCosts(this->m_RegionList, cost_func);
......@@ -184,8 +183,7 @@ BaatzAlgorithmRM<TInputImage>::Segmentation()
{
while(prev_merged)
{
//std::cout << "." << std::flush;
std::cout << "Best Fitting" << std::endl;
std::cout << "." << std::flush;
prev_merged = false;
this->m_RMHandler.UpdateMergingCosts(this->m_RegionList, cost_func);
......@@ -222,8 +220,6 @@ BaatzAlgorithmRM<TInputImage>::Segmentation()
this->m_RMHandler.RemoveExpiredVertices(this->m_RegionList);
}
}
std::cout << "\n";
std::cout << "\n";
}
......
......@@ -433,131 +433,196 @@ namespace shpenc
direction = 3;
}
bool ShapeEncoder::IsInternalPixel(unsigned int curr_idx, std::vector<short>& bbox_array,
unsigned int bbox_size_x, unsigned int bbox_size_y)
bool ShapeEncoder::GetCollisionAtNorth(unsigned int idx,
const std::vector<short>& bbox_array,
unsigned int bbox_cols,
unsigned int bbox_rows)
{
const unsigned int bbox_len = bbox_size_x * bbox_size_y;
long int tmp_idx;
// Check if a pixel is at the top
tmp_idx = (long int)curr_idx - (long int)bbox_size_x;
while(tmp_idx >= 0)
assert(idx >= 0 && idx < bbox_cols * bbox_rows);
long int tmp_idx = idx - bbox_cols;
if(bbox_array[tmp_idx] == 1)
return true;
while(tmp_idx > 0)
{
if(bbox_array[tmp_idx] == 1)
break;
else
tmp_idx -= bbox_size_x;
return true;
tmp_idx -= bbox_cols;
}
if(tmp_idx < 0)
return false;
return false;
}
// Check if a pixel is at the top right
tmp_idx = curr_idx - bbox_size_x + 1;
while( (tmp_idx >= 0) && ((tmp_idx % bbox_size_x) > 0))
bool ShapeEncoder::GetCollisionAtNorthEast(unsigned int idx,
const std::vector<short>& bbox_array,
unsigned int bbox_cols,
unsigned int bbox_rows)
{
assert(idx >= 0 && idx < bbox_cols * bbox_rows);
long int tmp_idx = idx - bbox_cols + 1;
if(bbox_array[tmp_idx] == 1)
return true;
while(tmp_idx > 0 && (tmp_idx % bbox_cols) != 0)
{
if(bbox_array[tmp_idx] == 1)
break;
else
{
tmp_idx++;
tmp_idx -= bbox_size_x;
}
return true;
tmp_idx = tmp_idx - bbox_cols + 1;
}
return false;
}
if( (tmp_idx < 0) || ((tmp_idx % bbox_size_x) == 0))
return false;
bool ShapeEncoder::GetCollisionAtEast(unsigned int idx,
const std::vector<short>& bbox_array,
unsigned int bbox_cols,
unsigned int bbox_rows)
{
assert(idx >= 0 && idx < bbox_cols * bbox_rows);
long int tmp_idx = idx + 1;
// Check if a pixel is at the right
tmp_idx = curr_idx + 1;
while((tmp_idx % bbox_size_x) > 0)
if(bbox_array[tmp_idx] == 1)
return true;
while((tmp_idx % bbox_cols) != 0)
{
if(bbox_array[tmp_idx] == 1)
break;
else
tmp_idx++;
return true;
++tmp_idx;
}
return false;
}
if((tmp_idx % bbox_size_x) == 0)
return false;
bool ShapeEncoder::GetCollisionAtSouthEast(unsigned int idx,
const std::vector<short>& bbox_array,
unsigned int bbox_cols,
unsigned int bbox_rows)
{
assert(idx >= 0 && idx < bbox_cols * bbox_rows);
long int tmp_idx = idx + 1 + bbox_cols;
if(bbox_array[tmp_idx] == 1)
return true;
// Check if a pixel is at the bottom right
tmp_idx = curr_idx + bbox_size_x + 1;
while( (tmp_idx < bbox_len) && ((tmp_idx % bbox_size_x) > 0))
while(tmp_idx < (bbox_cols * bbox_rows) &&
(tmp_idx % bbox_cols) != 0)
{
if(bbox_array[tmp_idx] == 1)
break;
else
{
tmp_idx++;
tmp_idx += bbox_size_x;
}
return true;
tmp_idx = tmp_idx + 1 + bbox_cols;
}
return false;
}
if( (tmp_idx >= bbox_len) || ((tmp_idx % bbox_size_x) == 0))
return false;
bool ShapeEncoder::GetCollisionAtSouth(unsigned int idx,
const std::vector<short>& bbox_array,
unsigned int bbox_cols,
unsigned int bbox_rows)
{
assert(idx >= 0 && idx < bbox_cols * bbox_rows);
long int tmp_idx = idx + bbox_cols;
// Check if a pixel is at the bottom
tmp_idx = curr_idx + bbox_size_x;
while(tmp_idx < bbox_len)
if(bbox_array[tmp_idx] == 1)
return true;
while(tmp_idx < (bbox_cols * bbox_rows))
{
if(bbox_array[tmp_idx] == 1)
break;
else
tmp_idx += bbox_size_x;
return true;
tmp_idx += bbox_cols;
}
return false;
}
if(tmp_idx >= bbox_len)
return false;
bool ShapeEncoder::GetCollisionAtSouthWest(unsigned int idx,
const std::vector<short>& bbox_array,
unsigned int bbox_cols,
unsigned int bbox_rows)
{
assert(idx >= 0 && idx < bbox_cols * bbox_rows);
long int tmp_idx = idx + bbox_cols - 1;
if(bbox_array[tmp_idx] == 1)
return true;
// Check if a pixel is at the bottom left
tmp_idx = curr_idx + bbox_size_x - 1;
while((tmp_idx < bbox_len) && ((tmp_idx % bbox_size_x) < (bbox_size_x - 1)))
while(tmp_idx < (bbox_cols * bbox_rows) &&
(tmp_idx % bbox_cols) != bbox_cols - 1)
{
if(bbox_array[tmp_idx] == 1)
break;
else
{
tmp_idx--;
tmp_idx += bbox_size_x;
}
return true;
tmp_idx = tmp_idx + bbox_cols - 1;
}
return false;
}
if((tmp_idx >= bbox_len) || ((tmp_idx % bbox_size_x) == (bbox_size_x - 1)))
return false;
bool ShapeEncoder::GetCollisionAtWest(unsigned int idx,
const std::vector<short>& bbox_array,
unsigned int bbox_cols,
unsigned int bbox_rows)
{
assert(idx >= 0 && idx < bbox_cols * bbox_rows);
long int tmp_idx = idx - 1;
if(bbox_array[tmp_idx] == 1)
return true;
// Check if the pixel is at the left
tmp_idx = curr_idx - 1;
while((tmp_idx % bbox_size_x) < (bbox_size_x - 1))
while((tmp_idx % bbox_cols) != bbox_cols - 1)
{
if(bbox_array[tmp_idx] == 1)
break;
else
tmp_idx--;
return true;
tmp_idx -= 1;
}
return false;
}
if(((tmp_idx % bbox_size_x) == (bbox_size_x - 1)))
return false;
bool ShapeEncoder::GetCollisionAtNorthWest(unsigned int idx,
const std::vector<short>& bbox_array,
unsigned int bbox_cols,
unsigned int bbox_rows)
{
assert(idx >= 0 && idx < bbox_cols * bbox_rows);
long int tmp_idx = idx - bbox_cols - 1;
if(bbox_array[tmp_idx] == 1)
return true;
// Check if the pixel is at the top left
tmp_idx = curr_idx - 1 - bbox_size_x;
while((tmp_idx >= 0) && (tmp_idx % bbox_size_x) < (bbox_size_x - 1))
while(tmp_idx > 0 && (tmp_idx % bbox_cols) != bbox_cols - 1)
{
if(bbox_array[tmp_idx] == 1)
break;
else
{
tmp_idx--;
tmp_idx -= bbox_size_x;
}
return true;
tmp_idx = tmp_idx - bbox_cols - 1;