Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Cresson Remi
LSGRM
Commits
9493484b
Commit
9493484b
authored
Aug 24, 2016
by
remicres
Browse files
ENH: Fully modularized! Now require GRM Module
parent
bb65d2e0
Changes
19
Hide whitespace changes
Inline
Side-by-side
app/CMakeLists.txt
View file @
9493484b
...
...
@@ -2,4 +2,4 @@ cmake_minimum_required (VERSION 2.8)
OTB_CREATE_APPLICATION
(
NAME LSGRM
SOURCES otbLSGRM.cxx
LINK_LIBRARIES OTBCommon
)
LINK_LIBRARIES OTBCommon
OTBGRM
)
app/otbLSGRM.cxx
View file @
9493484b
...
...
@@ -49,48 +49,48 @@ private:
void
DoInit
()
{
SetName
(
"GenericRegionMerging"
);
SetDescription
(
"This application allows to use the Generic Region Merging library "
"(GRM) and provides currently 3 homogeneity criteria: Euclidean Distance, "
"Full Lambda Schedule and Baatz & Schape criterion."
);
AddParameter
(
ParameterType_InputImage
,
"in"
,
"Input Image"
);
AddParameter
(
ParameterType_OutputImage
,
"out"
,
"Ouput Label Image"
);
SetDefaultOutputPixelType
(
"out"
,
ImagePixelType_uint32
);
// AddParameter(ParameterType_Choice, "criterion", "Homogeneity criterion to use");
// AddChoice("criterion.bs", "Baatz & Schape");
// AddChoice("criterion.ed", "Euclidean Distance");
// AddChoice("criterion.fls", "Full Lambda Schedule");
AddParameter
(
ParameterType_Float
,
"threshold"
,
"Threshold for the criterion"
);
AddParameter
(
ParameterType_Int
,
"niter"
,
"Maximum number of iterations"
);
SetDefaultParameterInt
(
"niter"
,
75
);
MandatoryOff
(
"niter"
);
AddParameter
(
ParameterType_Int
,
"speed"
,
"Activate it to boost the segmentation speed"
);
SetDefaultParameterInt
(
"speed"
,
0
);
MandatoryOff
(
"speed"
);
// For Baatz & Schape
AddParameter
(
ParameterType_Float
,
"cw"
,
"Weight for the spectral homogeneity"
);
SetDefaultParameterFloat
(
"cw"
,
0.5
);
MandatoryOff
(
"cw"
);
AddParameter
(
ParameterType_Float
,
"sw"
,
"Weight for the spatial homogeneity"
);
SetDefaultParameterFloat
(
"sw"
,
0.5
);
MandatoryOff
(
"sw"
);
// For large scale
AddParameter
(
ParameterType_Directory
,
"tmpdir"
,
"temporary directory for tiles and graphs"
);
AddParameter
(
ParameterType_Choice
,
"tiling"
,
"Tiling layout for the large scale segmentation"
);
AddChoice
(
"tiling.auto"
,
"Automatic tiling layout"
);
AddChoice
(
"tiling.user"
,
"User tiling layout"
);
AddParameter
(
ParameterType_Int
,
"tiling.user.sizex"
,
"Tiles width"
);
AddParameter
(
ParameterType_Int
,
"tiling.user.sizey"
,
"Tiles height"
);
AddParameter
(
ParameterType_Int
,
"tiling.user.nfirstiter"
,
"Number of first iterations"
);
AddParameter
(
ParameterType_Int
,
"tiling.user.memory"
,
"Available memory"
);
AddChoice
(
"tiling.none"
,
"No tiling layout"
);
SetName
(
"GenericRegionMerging"
);
SetDescription
(
"This application allows to use the Generic Region Merging library "
"(GRM) and provides currently 3 homogeneity criteria: Euclidean Distance, "
"Full Lambda Schedule and Baatz & Schape criterion."
);
AddParameter
(
ParameterType_InputImage
,
"in"
,
"Input Image"
);
AddParameter
(
ParameterType_OutputImage
,
"out"
,
"Ouput Label Image"
);
SetDefaultOutputPixelType
(
"out"
,
ImagePixelType_uint32
);
// AddParameter(ParameterType_Choice, "criterion", "Homogeneity criterion to use");
// AddChoice("criterion.bs", "Baatz & Schape");
// AddChoice("criterion.ed", "Euclidean Distance");
// AddChoice("criterion.fls", "Full Lambda Schedule");
AddParameter
(
ParameterType_Float
,
"threshold"
,
"Threshold for the criterion"
);
AddParameter
(
ParameterType_Int
,
"niter"
,
"Maximum number of iterations"
);
SetDefaultParameterInt
(
"niter"
,
75
);
MandatoryOff
(
"niter"
);
AddParameter
(
ParameterType_Int
,
"speed"
,
"Activate it to boost the segmentation speed"
);
SetDefaultParameterInt
(
"speed"
,
0
);
MandatoryOff
(
"speed"
);
// For Baatz & Schape
AddParameter
(
ParameterType_Float
,
"cw"
,
"Weight for the spectral homogeneity"
);
SetDefaultParameterFloat
(
"cw"
,
0.5
);
MandatoryOff
(
"cw"
);
AddParameter
(
ParameterType_Float
,
"sw"
,
"Weight for the spatial homogeneity"
);
SetDefaultParameterFloat
(
"sw"
,
0.5
);
MandatoryOff
(
"sw"
);
// For large scale
AddParameter
(
ParameterType_Directory
,
"tmpdir"
,
"temporary directory for tiles and graphs"
);
AddParameter
(
ParameterType_Choice
,
"tiling"
,
"Tiling layout for the large scale segmentation"
);
AddChoice
(
"tiling.auto"
,
"Automatic tiling layout"
);
AddChoice
(
"tiling.user"
,
"User tiling layout"
);
AddParameter
(
ParameterType_Int
,
"tiling.user.sizex"
,
"Tiles width"
);
AddParameter
(
ParameterType_Int
,
"tiling.user.sizey"
,
"Tiles height"
);
AddParameter
(
ParameterType_Int
,
"tiling.user.nfirstiter"
,
"Number of first iterations"
);
AddParameter
(
ParameterType_Int
,
"tiling.user.memory"
,
"Available memory"
);
AddChoice
(
"tiling.none"
,
"No tiling layout"
);
}
void
DoUpdateParameters
()
...
...
@@ -167,16 +167,8 @@ private:
otbAppLogFATAL
(
"Unknow input tiling mode!"
);
}
// MPI configuration
#ifdef OTB_USE_MPI
if
(
myrank
==
0
)
std
::
cout
<<
"Number of MPI process : "
<<
nprocs
<<
std
::
endl
;
controller
.
SetNumberOfProcess
(
nprocs
);
controller
.
SetProcessRank
(
myrank
);
#endif
// Specific parameters
ls
rm
::
BaatzParam
params
;
g
rm
::
BaatzParam
params
;
params
.
m_SpectralWeight
=
GetParameterFloat
(
"cw"
);
params
.
m_ShapeWeight
=
GetParameterFloat
(
"sw"
);
controller
.
SetSpecificParameters
(
params
);
...
...
@@ -197,12 +189,26 @@ private:
labelImage
->
SetSpacing
(
inputImage
->
GetSpacing
());
SetParameterOutputImage
<
UInt32ImageType
>
(
"out"
,
labelImage
);
// Get temporary files list
m_TemporaryFilesList
=
controller
.
GetTemporaryFilesList
();
}
void
AfterExecuteAndWriteOutputs
()
{
// Delete temporary files
for
(
unsigned
int
i
=
0
;
i
<
m_TemporaryFilesList
.
size
()
;
i
++
)
{
if
(
remove
(
m_TemporaryFilesList
.
at
(
i
).
c_str
()
)
!=
0
)
{
otbAppLogWARNING
(
"Error deleting file "
<<
m_TemporaryFilesList
.
at
(
i
)
);
}
}
}
private:
std
::
vector
<
std
::
string
>
m_TemporaryFilesList
;
};
// app class
}
// end of namespace wrapper
}
// end of namespace otb
...
...
include/lpContour.cpp
deleted
100644 → 0
View file @
bb65d2e0
#include "lpContour.h"
namespace
lp
{
void
ContourOperations
::
MergeContour
(
Contour
&
mergedContour
,
BoundingBox
&
mergedBBox
,
Contour
&
contour1
,
Contour
&
contour2
,
BoundingBox
&
bbox1
,
BoundingBox
&
bbox2
,
const
CellIndex
cid1
,
const
CellIndex
cid2
,
const
std
::
size_t
gridSizeX
)
{
// First step consists of building the bounding box resulting from the fusion
// of the bounding boxes bbox1 and bbox2
mergedBBox
=
MergeBoundingBoxes
(
bbox1
,
bbox2
);
// Create the associate matrix indicating where the cells are located
// inside the bbox
std
::
vector
<
bool
>
cellMatrix
(
mergedBBox
.
m_W
*
mergedBBox
.
m_H
,
false
);
// Fill the cell matrix with the cells from both contours
{
CellLists
borderCells
;
// Fill with the cells of contour 1
GenerateBorderCells
(
borderCells
,
contour1
,
cid1
,
gridSizeX
);
for
(
auto
&
cell
:
borderCells
)
cellMatrix
[
GridToBBox
(
cell
,
mergedBBox
,
gridSizeX
)]
=
true
;
borderCells
.
clear
();
// Fill with the cells of contour 2
GenerateBorderCells
(
borderCells
,
contour2
,
cid2
,
gridSizeX
);
for
(
auto
&
cell
:
borderCells
)
cellMatrix
[
GridToBBox
(
cell
,
mergedBBox
,
gridSizeX
)]
=
true
;
}
// Create the new contour
CreateNewContour
(
mergedContour
,
GridToBBox
(
cid1
,
mergedBBox
,
gridSizeX
),
cellMatrix
,
mergedBBox
.
m_W
,
mergedBBox
.
m_H
);
}
void
ContourOperations
::
CreateNewContour
(
Contour
&
newContour
,
const
CellIndex
cidx
,
const
std
::
vector
<
bool
>&
cellMatrix
,
const
std
::
size_t
bboxWidth
,
const
std
::
size_t
bboxHeight
)
{
// The first move is always 1
Push1
(
newContour
);
// Previous move
short
prevMove
=
1
;
// Local pixel id
CellIndex
currIdx
=
cidx
;
// Table containing id neighbors
long
int
neighbors
[
8
];
for
(;;)
{
// Compute neighbor'ids
EIGHTNeighborhood
(
neighbors
,
currIdx
,
bboxWidth
,
bboxHeight
);
if
(
prevMove
==
1
)
{
if
(
neighbors
[
1
]
!=
-
1
&&
cellMatrix
[
neighbors
[
1
]])
{
Push0
(
newContour
);
currIdx
=
currIdx
+
1
-
bboxWidth
;
prevMove
=
0
;
}
else
if
(
neighbors
[
2
]
!=
-
1
&&
cellMatrix
[
neighbors
[
2
]])
{
Push1
(
newContour
);
currIdx
++
;
prevMove
=
1
;
}
else
{
Push2
(
newContour
);
prevMove
=
2
;
}
}
else
if
(
prevMove
==
2
)
{
if
(
neighbors
[
3
]
!=
-
1
&&
cellMatrix
[
neighbors
[
3
]])
{
Push1
(
newContour
);
currIdx
=
currIdx
+
bboxWidth
+
1
;
prevMove
=
1
;
}
else
if
(
neighbors
[
4
]
!=
-
1
&&
cellMatrix
[
neighbors
[
4
]])
{
Push2
(
newContour
);
currIdx
+=
bboxWidth
;
prevMove
=
2
;
}
else
{
Push3
(
newContour
);
prevMove
=
3
;
}
}
else
if
(
prevMove
==
3
)
{
if
(
neighbors
[
5
]
!=
-
1
&&
cellMatrix
[
neighbors
[
5
]])
{
Push2
(
newContour
);
currIdx
=
currIdx
-
1
+
bboxWidth
;
prevMove
=
2
;
}
else
if
(
neighbors
[
6
]
!=
-
1
&&
cellMatrix
[
neighbors
[
6
]])
{
Push3
(
newContour
);
currIdx
-=
1
;
prevMove
=
3
;
}
else
{
Push0
(
newContour
);
prevMove
=
0
;
}
}
else
{
assert
(
prevMove
==
0
);
if
(
neighbors
[
7
]
!=
-
1
&&
cellMatrix
[
neighbors
[
7
]])
{
Push3
(
newContour
);
currIdx
=
currIdx
-
bboxWidth
-
1
;
prevMove
=
3
;
}
else
if
(
neighbors
[
0
]
!=
-
1
&&
cellMatrix
[
neighbors
[
0
]])
{
Push0
(
newContour
);
currIdx
-=
bboxWidth
;
prevMove
=
0
;
}
else
{
if
(
currIdx
==
cidx
)
break
;
else
{
Push1
(
newContour
);
prevMove
=
1
;
}
}
}
}
}
void
ContourOperations
::
GenerateBorderCells
(
CellLists
&
borderCells
,
const
Contour
&
contour
,
const
CellIndex
startCellId
,
const
std
::
size_t
gridSizeX
)
{
// Add the first pixel to the border list
borderCells
.
insert
(
startCellId
);
if
(
contour
.
size
()
>
8
)
{
// Intialize the first move at prev
short
curr
,
prev
=
GetMove10
(
GetMove2
(
0
,
contour
));
// Declare the current pixel index
CellIndex
idx
=
startCellId
;
// Explore the contour
for
(
ContourIndex
cidx
=
1
;
cidx
<
contour
.
size
()
/
2
;
cidx
++
)
{
curr
=
GetMove10
(
GetMove2
(
cidx
,
contour
));
assert
(
curr
>=
0
&&
curr
<
4
);
if
(
curr
==
0
)
{
// Impossible case is prev = 2;
assert
(
prev
!=
2
);
//*
//*
if
(
prev
==
0
)
{
idx
-=
gridSizeX
;
borderCells
.
insert
(
idx
);
}
// *
// **
if
(
prev
==
1
)
{
idx
=
idx
+
1
-
gridSizeX
;
borderCells
.
insert
(
idx
);
}
}
else
if
(
curr
==
1
)
{
// Impossible case
assert
(
prev
!=
3
);
// **
if
(
prev
==
1
)
{
idx
++
;
borderCells
.
insert
(
idx
);
}
//*
//**
if
(
prev
==
2
)
{
idx
=
idx
+
1
+
gridSizeX
;
borderCells
.
insert
(
idx
);
}
}
else
if
(
curr
==
2
)
{
// Impossible case
assert
(
prev
!=
0
);
// *
// *
if
(
prev
==
2
)
{
idx
+=
gridSizeX
;
borderCells
.
insert
(
idx
);
}
// **
// *
if
(
prev
==
3
)
{
idx
=
idx
-
1
+
gridSizeX
;
borderCells
.
insert
(
idx
);
}
}
else
{
// Impossible case
assert
(
prev
!=
1
);
if
(
prev
==
0
)
{
idx
=
idx
-
1
-
gridSizeX
;
borderCells
.
insert
(
idx
);
}
if
(
prev
==
3
)
{
idx
--
;
borderCells
.
insert
(
idx
);
}
}
prev
=
curr
;
}
}
}
CellIndex
ContourOperations
::
BBoxToGrid
(
const
CellIndex
bboxId
,
const
BoundingBox
&
bbox
,
const
std
::
size_t
gridSizeX
)
{
CellIndex
bbX
=
bboxId
%
bbox
.
m_W
;
CellIndex
bbY
=
bboxId
/
bbox
.
m_W
;
CellIndex
gridX
=
bbox
.
m_UX
+
bbX
;
CellIndex
gridY
=
bbox
.
m_UY
+
bbY
;
CellIndex
gridId
=
gridY
*
gridSizeX
+
gridX
;
return
gridId
;
}
CellIndex
ContourOperations
::
GridToBBox
(
const
CellIndex
gridId
,
const
BoundingBox
&
bbox
,
const
std
::
size_t
gridSizeX
)
{
CellIndex
gridX
=
gridId
%
gridSizeX
;
CellIndex
gridY
=
gridId
/
gridSizeX
;
CellIndex
bbX
=
gridX
-
bbox
.
m_UX
;
CellIndex
bbY
=
gridY
-
bbox
.
m_UY
;
CellIndex
bbId
=
bbY
*
bbox
.
m_W
+
bbX
;
return
bbId
;
}
void
ContourOperations
::
EIGHTNeighborhood
(
long
int
*
neighborhood
,
const
CellIndex
id
,
const
std
::
size_t
width
,
const
std
::
size_t
height
)
{
const
unsigned
int
x
=
id
%
width
;
const
unsigned
int
y
=
id
/
width
;
/* top */
neighborhood
[
0
]
=
(
y
>
0
?
(
id
-
width
)
:
-
1
);
/* top right */
neighborhood
[
1
]
=
(
(
y
>
0
&&
x
<
(
width
-
1
)
)
?
(
id
-
width
+
1
)
:
-
1
);
/* right */
neighborhood
[
2
]
=
(
x
<
(
width
-
1
)
?
(
id
+
1
)
:
-
1
);
/* bottom right */
neighborhood
[
3
]
=
(
(
x
<
(
width
-
1
)
&&
y
<
(
height
-
1
)
)
?
(
id
+
1
+
width
)
:
-
1
);
/* bottom */
neighborhood
[
4
]
=
(
y
<
(
height
-
1
)
?
(
id
+
width
)
:
-
1
);
/* bottom left */
neighborhood
[
5
]
=
(
(
y
<
(
height
-
1
)
&&
x
>
0
)
?
(
id
+
width
-
1
)
:
-
1
);
/* left */
neighborhood
[
6
]
=
(
x
>
0
?
(
id
-
1
)
:
-
1
);
/* top left */
neighborhood
[
7
]
=
(
(
x
>
0
&&
y
>
0
)
?
(
id
-
width
-
1
)
:
-
1
);
}
BoundingBox
ContourOperations
::
MergeBoundingBoxes
(
const
BoundingBox
&
bb1
,
const
BoundingBox
&
bb2
)
{
std
::
size_t
min_ux
,
min_uy
,
max_xw
,
max_yh
;
BoundingBox
bb
;
min_ux
=
std
::
min
(
bb1
.
m_UX
,
bb2
.
m_UX
);
min_uy
=
std
::
min
(
bb1
.
m_UY
,
bb2
.
m_UY
);
max_xw
=
std
::
max
(
bb1
.
m_UX
+
bb1
.
m_W
,
bb2
.
m_UX
+
bb2
.
m_W
);
max_yh
=
std
::
max
(
bb1
.
m_UY
+
bb1
.
m_H
,
bb2
.
m_UY
+
bb2
.
m_H
);
bb
.
m_UX
=
min_ux
;
bb
.
m_UY
=
min_uy
;
bb
.
m_W
=
max_xw
-
min_ux
;
bb
.
m_H
=
max_yh
-
min_uy
;
return
bb
;
}
Move
ContourOperations
::
GetMove2
(
ContourIndex
idx
,
const
Contour
&
contour
)
{
return
Move
(
2
*
contour
[
2
*
idx
]
+
contour
[
idx
*
2
+
1
]);
}
short
ContourOperations
::
GetMove10
(
const
Move
&
m
)
{
return
(
m
[
0
]
*
2
+
m
[
1
]);
}
void
ContourOperations
::
Push0
(
Contour
&
contour
)
{
contour
.
push_back
(
0
);
contour
.
push_back
(
0
);
}
void
ContourOperations
::
Push1
(
Contour
&
contour
)
{
contour
.
push_back
(
1
);
contour
.
push_back
(
0
);
}
void
ContourOperations
::
Push2
(
Contour
&
contour
)
{
contour
.
push_back
(
0
);
contour
.
push_back
(
1
);
}
void
ContourOperations
::
Push3
(
Contour
&
contour
)
{
contour
.
push_back
(
1
);
contour
.
push_back
(
1
);
}
}
// end of namespace lp
include/lpContour.h
deleted
100644 → 0
View file @
bb65d2e0
#ifndef __LP_CONTOUR_H
#define __LP_CONTOUR_H
#include <cassert>
#include <iostream>
#include <bitset>
#include <vector>
#include <utility>
#include <unordered_set>
#include <unordered_map>
#include <boost/dynamic_bitset.hpp>
namespace
lp
{
/* Move along a contour: 4 possibles: top (0), right(1), bottom (2), left(3). */
using
Move
=
std
::
bitset
<
2
>
;
/* A contour is a list of moves represented by a pair of bits*/
using
Contour
=
boost
::
dynamic_bitset
<>
;
using
ContourIndex
=
boost
::
dynamic_bitset
<>::
size_type
;
/* Index of a cell in the grid */
using
CellIndex
=
std
::
size_t
;
/* List of cell indices */
using
CellLists
=
std
::
unordered_set
<
CellIndex
>
;
struct
BoundingBox
{
std
::
size_t
m_UX
;
std
::
size_t
m_UY
;
std
::
size_t
m_W
;
std
::
size_t
m_H
;
};
class
ContourOperations
{
public:
/* Methods to fill a contour. */
static
void
Push0
(
Contour
&
contour
);
// Push a move to the top.
static
void
Push1
(
Contour
&
contour
);
// Push a move to the right.
static
void
Push2
(
Contour
&
contour
);
// Push a move to the bottom.
static
void
Push3
(
Contour
&
contour
);
// Push a move to the left.
/* Methods to access to elements of a contour. */
static
Move
GetMove2
(
ContourIndex
idx
,
const
Contour
&
contour
);
// Retrieve a move
static
short
GetMove10
(
const
Move
&
m
);
// Transform the move into a 10 base number (0,1,2 or 3).
/* Main methods */
static
void
MergeContour
(
Contour
&
mergedContour
,
BoundingBox
&
mergedBoundingBox
,
Contour
&
contour1
,
Contour
&
contour2
,
BoundingBox
&
bbox1
,
BoundingBox
&
bbox2
,
const
CellIndex
cid1
,
const
CellIndex
cid2
,
const
std
::
size_t
gridSizeX
);
static
void
GenerateBorderCells
(
CellLists
&
borderCells
,
// From a contour, the smallest id of the cell
const
Contour
&
contour
,
// belonging to the shape and the size of the grid,
const
CellIndex
startCellId
,
// this method returns the ids of the border cells
const
std
::
size_t
gridSizeX
);
// of the shape.
static
void
CreateNewContour
(
Contour
&
newContour
,
const
CellIndex
startCellId
,
const
std
::
vector
<
bool
>&
cellMatrix
,
const
std
::
size_t
bboxWidth
,
const
std
::
size_t
bboxHeight
);
/* Utilities methods */
static
BoundingBox
MergeBoundingBoxes
(
const
BoundingBox
&
bb1
,
// Given 2 bounding boxes return the bounding
const
BoundingBox
&
bb2
);
// which is the union.
static
void
EIGHTNeighborhood
(
long
int
*
neighborhood
,
// return 8-neighbors of cell id.
const
CellIndex
id
,
const
std
::
size_t
width
,
const
std
::
size_t
height
);
static
CellIndex
BBoxToGrid
(
const
CellIndex
bboxId
,
const
BoundingBox
&
bbox
,
const
std
::
size_t
gridSizeX
);
static
CellIndex
GridToBBox
(
const
CellIndex
gridId
,
// Return the coordinates of the cell
const
BoundingBox
&
bbox
,
// in the bounding box reference.
const
std
::
size_t
gridSizeX
);
};
}
// end of namespace lp
#include "lpContour.cpp"
#endif
include/lsgrmController.h
View file @
9493484b
...
...
@@ -47,6 +47,7 @@ public: