Commit 3f558e48 authored by Pierre Lassalle's avatar Pierre Lassalle
Browse files

More efficient GRM

Showing with 153 additions and 2029 deletions
+153 -2029
......@@ -27,6 +27,15 @@ ELSE(OTB_FOUND)
"Cannot build OTB project without OTB. Please set OTB_DIR.")
ENDIF(OTB_FOUND)
#Activate c++11
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
if(COMPILER_SUPPORTS_CXX11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fpermissive -Wall -Wmaybe-uninitialized")
else()
message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
endif()
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/Code)
add_subdirectory(Code)
......
......@@ -16,7 +16,6 @@
#=========================================================================
add_library(OTBGRM
lsrmContourOperations.cpp
lsrmNeighborhood.cpp)
target_link_libraries(OTBGRM OTBCommon OTBIO)
......@@ -51,7 +51,6 @@ namespace lsrm
float
BaatzSegmenter<TImage>::ComputeMergingCost(NodePointerType n1, NodePointerType n2)
{
const std::size_t bands = n1->m_Means.size();
const unsigned int a1 = n1->m_Area, a2 = n2->m_Area, a_sum = a1 + a2;
float spect_cost = 0.0f;
......@@ -77,7 +76,7 @@ namespace lsrm
const unsigned int boundary = (GraphOperatorType::FindEdge(n1, n2))->m_Boundary;
const float p3 = p1 + p2 - 2 * static_cast<float>(boundary);
const BoundingBox merged_bbox = ContourOperations::MergeBoundingBoxes(n1->m_Bbox, n2->m_Bbox);
const BoundingBox merged_bbox = MergeBoundingBoxes(n1->m_Bbox, n2->m_Bbox);
const float bb1_perimeter = static_cast<float>(2*n1->m_Bbox.m_W + 2*n1->m_Bbox.m_H);
const float bb2_perimeter = static_cast<float>(2*n2->m_Bbox.m_W + 2*n2->m_Bbox.m_H);
const float mbb_perimeter = static_cast<float>(2 * merged_bbox.m_W + 2 * merged_bbox.m_H);
......@@ -141,11 +140,6 @@ namespace lsrm
this->m_ImageWidth,
this->m_ImageHeight,
this->m_LabelImageFileName);
if(!this->m_ContourImageFileName.empty())
IOType::WriteContourImage(this->m_Graph,
this->m_InputFileName,
this->m_LabelImageFileName);
}
} // end of namespace lsrm
......
#include "lsrmContourOperations.h"
namespace lsrm
{
BoundingBox
ContourOperations::MergeBoundingBoxes(const BoundingBox& bb1,
const BoundingBox& bb2)
{
long unsigned int 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;
}
long unsigned int
ContourOperations::ToBoundingBoxCoordinates(const long unsigned int id,
const BoundingBox& bb,
const unsigned int width)
{
long unsigned int img_x = id % width;
long unsigned int img_y = id / width;
long unsigned int bb_x = img_x - bb.m_UX;
long unsigned int bb_y = img_y - bb.m_UY;
return (bb_y * bb.m_W + bb_x);
}
typename ContourOperations::PixelList
ContourOperations::GenerateBorderPixels(long unsigned int id,
const Contour& contour,
const unsigned int width)
{
PixelList pixels;
pixels.push_back(id);
short curr_move, prev_move;
if(contour.size() > 4)
{
for(ContourConstIterator m = contour.begin()+1; m != contour.end(); m++)
{
curr_move = (*m)[0] + 2*(*m)[1];
prev_move = (*(m-1))[0] + 2*(*(m-1))[1];
if(curr_move == 0)
{
if(prev_move == 0)
{
id-=width;
pixels.push_back(id);
}
else if(prev_move == 1) // 1
{
id++;
pixels.push_back(id);
id-=width;
pixels.push_back(id);
}
}
else if(curr_move == 1)
{
if(prev_move == 1)
{
id++;
pixels.push_back(id);
}
else if(prev_move == 2)
{
id+=width;
pixels.push_back(id);
id++;
pixels.push_back(id);
}
}
else if(curr_move == 2)
{
if(prev_move == 3)
{
id--;
pixels.push_back(id);
id+=width;
pixels.push_back(id);
}
else if(prev_move == 2)
{
id+=width;
pixels.push_back(id);
}
}
else if(curr_move == 3)
{
if(prev_move==0)
{
id-=width;
pixels.push_back(id);
id--;
pixels.push_back(id);
}
else if(prev_move == 3)
{
id--;
pixels.push_back(id);
}
}
}
// Remove duplicated pixels
std::sort(pixels.begin(), pixels.end());
PixelIterator it = std::unique(pixels.begin(), pixels.end());
pixels.resize(std::distance(pixels.begin(), it));
}
return pixels;
}
bool
ContourOperations::GetCollisionAtNorth(const long unsigned int idx,
const short * grid,
const unsigned int grid_width)
{
long int tmp_idx = idx - grid_width;
if(grid[tmp_idx] > 0)
return true;
while(tmp_idx > 0)
{
if(grid[tmp_idx] > 0)
return true;
tmp_idx -= grid_width;
}
return false;
}
bool
ContourOperations::GetCollisionAtNorthEast(const long unsigned int idx,
const short * grid,
const unsigned int grid_width)
{
long int tmp_idx = idx - grid_width + 1;
if(grid[tmp_idx] > 0)
return true;
while(tmp_idx > 0 && (tmp_idx % grid_width) != 0)
{
if(grid[tmp_idx] > 0)
return true;
tmp_idx = tmp_idx - grid_width + 1;
}
return false;
}
bool
ContourOperations::GetCollisionAtEast(const long unsigned int idx,
const short * grid,
const unsigned int grid_width)
{
long int tmp_idx = idx + 1;
if(grid[tmp_idx] > 0)
return true;
while((tmp_idx % grid_width) != 0)
{
if(grid[tmp_idx] > 0)
return true;
++tmp_idx;
}
return false;
}
bool
ContourOperations::GetCollisionAtSouthEast(const long unsigned int idx,
const short * grid,
const unsigned int grid_width,
const unsigned int grid_height)
{
long int tmp_idx = idx + 1 + grid_width;
if(grid[tmp_idx] > 0)
return true;
while(tmp_idx < (grid_width * grid_height) &&
(tmp_idx % grid_width) != 0)
{
if(grid[tmp_idx] > 0)
return true;
tmp_idx = tmp_idx + 1 + grid_width;
}
return false;
}
bool
ContourOperations::GetCollisionAtSouth(const long unsigned int idx,
const short * grid,
const unsigned int grid_width,
const unsigned int grid_height)
{
long int tmp_idx = idx + grid_width;
if(grid[tmp_idx] > 0)
return true;
while(tmp_idx < (grid_width * grid_height))
{
if(grid[tmp_idx] > 0)
return true;
tmp_idx += grid_width;
}
return false;
}
bool
ContourOperations::GetCollisionAtSouthWest(const long unsigned int idx,
const short * grid,
const unsigned int grid_width,
const unsigned int grid_height)
{
long int tmp_idx = idx + grid_width - 1;
if(grid[tmp_idx] > 0)
return true;
while(tmp_idx < (grid_width * grid_height) &&
(tmp_idx % grid_width) != grid_width - 1)
{
if(grid[tmp_idx] > 0)
return true;
tmp_idx = tmp_idx + grid_width - 1;
}
return false;
}
bool
ContourOperations::GetCollisionAtWest(const long unsigned int idx,
const short * grid,
const unsigned int grid_width)
{
long int tmp_idx = idx - 1;
if(grid[tmp_idx] > 0)
return true;
while((tmp_idx % grid_width) != grid_width - 1)
{
if(grid[tmp_idx] > 0)
return true;
tmp_idx -= 1;
}
return false;
}
bool
ContourOperations::GetCollisionAtNorthWest(const long unsigned int idx,
const short * grid,
const unsigned int grid_width)
{
long int tmp_idx = idx - grid_width - 1;
if(grid[tmp_idx] > 0)
return true;
while(tmp_idx > 0 && (tmp_idx % grid_width) != grid_width - 1)
{
if(grid[tmp_idx] > 0)
return true;
tmp_idx = tmp_idx - grid_width - 1;
}
return false;
}
bool
ContourOperations::IsInternalPixel(const long unsigned int idx,
const short * grid,
const unsigned int grid_width,
const unsigned int grid_height)
{
if(!GetCollisionAtNorth(idx, grid, grid_width))
return false;
if(!GetCollisionAtNorthEast(idx, grid, grid_width))
return false;
if(!GetCollisionAtEast(idx, grid, grid_width))
return false;
if(!GetCollisionAtSouthEast(idx, grid, grid_width, grid_height))
return false;
if(!GetCollisionAtSouth(idx, grid, grid_width, grid_height))
return false;
if(!GetCollisionAtSouthWest(idx, grid, grid_width, grid_height))
return false;
if(!GetCollisionAtWest(idx, grid, grid_width))
return false;
if(!GetCollisionAtNorthWest(idx, grid, grid_width))
return false;
return true;
}
void
ContourOperations::UpdateSight(short * sight, const short direction)
{
sight[0] = (direction + 3) % 4; // look at the left
sight[1] = direction; // look in front
sight[2] = (direction + 1) % 4; // look at the right
sight[3] = (direction + 2) % 4; // look behind
}
void
ContourOperations::EncodeContourForTopPixel(long unsigned int& curr_mat_id,
short& direction,
short& pos,
Contour& curr_contour,
const unsigned int grid_width)
{
if(pos == 1)
{
if(direction==0)
pos = 4;
else if(direction == 1)
{
pos = 1;
curr_contour.push_back(0);
}
}
else if(pos == 2)
{
pos = 4;
curr_contour.push_back(2);
curr_contour.push_back(3);
curr_contour.push_back(0);
}
else if(pos == 3)
{
pos = 4;
curr_contour.push_back(3);
curr_contour.push_back(0);
}
else if(pos == 4)
curr_contour.push_back(0);
curr_mat_id -= grid_width;
direction = 0;
}
void
ContourOperations::EncodeContourForRightPixel(long unsigned int& curr_mat_id,
short& direction,
short& pos,
Contour& curr_contour)
{
if(pos == 1)
curr_contour.push_back(1);
else if(pos == 2)
{
if(direction == 1)
pos = 1;
else if(direction == 2)
curr_contour.push_back(1);
}
else if(pos == 3)
{
pos = 1;
curr_contour.push_back(3);
curr_contour.push_back(0);
curr_contour.push_back(1);
}
else if(pos == 4)
{
pos = 1;
curr_contour.push_back(0);
curr_contour.push_back(1);
}
curr_mat_id++;
direction = 1;
}
void
ContourOperations::EncodeContourForBottomPixel(long unsigned int& curr_mat_id,
short& direction,
short& pos,
Contour& curr_contour,
const unsigned int grid_width)
{
if(pos == 1)
{
pos = 2;
curr_contour.push_back(1);
curr_contour.push_back(2);
}
else if(pos == 2)
curr_contour.push_back(2);
else if(pos == 3)
{
if(direction == 2)
pos = 2;
else if(direction == 3)
curr_contour.push_back(2);
}
else if(pos == 4)
{
pos = 2;
curr_contour.push_back(0);
curr_contour.push_back(1);
curr_contour.push_back(2);
}
curr_mat_id += grid_width;
direction = 2;
}
void
ContourOperations::EncodeContourForLeftPixel(long unsigned int& curr_mat_id,
short& direction,
short& pos,
Contour& curr_contour)
{
if(pos == 1)
{
pos = 3;
curr_contour.push_back(1);
curr_contour.push_back(2);
curr_contour.push_back(3);
}
else if(pos == 2)
{
pos = 3;
curr_contour.push_back(2);
curr_contour.push_back(3);
}
else if(pos == 3)
curr_contour.push_back(3);
else if(pos == 4)
{
if(direction == 3)
pos = 3;
else if(direction == 0)
{
pos = 4;
curr_contour.push_back(3);
}
}
curr_mat_id --;
direction = 3;
}
Contour
ContourOperations::CreateContourFromBorderPixels(const long unsigned int id,
const BoundingBox& bbox,
const short * grid,
const unsigned int width)
{
/* Location on one of the 4 corners of a pixel */
short direction, pos;
/* Field of view */
short sight[4];
long unsigned int start_mat_id = ToBoundingBoxCoordinates(id, bbox, width);
long unsigned int curr_mat_id = start_mat_id;
/* New contour */
Contour curr_contour;
// Build the first move
long int neighbors[4];
FOURNeighborhood(neighbors, curr_mat_id, bbox.m_W, bbox.m_H);
// Only 2 cases: neighbor at the right or at the bottom
if(grid[neighbors[1]] > 0) // right
{
pos = 1; // top left corner of the pixel
curr_mat_id++; // go to the pixel at the right
direction = 1; // direction is along the right
curr_contour.push_back(1); // Add the move to the right
}
else if(grid[neighbors[2]] > 0) // bottom
{
pos = 2; // top right corner of the pixel
curr_mat_id += bbox.m_W; // go to the pixel at the bottom
direction = 2; // direction is along the bottom
curr_contour.push_back(1); // add move to the right
curr_contour.push_back(2); // add move to the bottom
}
// Keep going this same reasonning until we reach the start pixel (start_mat_id)
while(curr_mat_id != start_mat_id)
{
UpdateSight(sight, direction);
FOURNeighborhood(neighbors, curr_mat_id, bbox.m_W, bbox.m_H);
// All the cases are possible: top, right, bottom, left
for(short d=0; d<4; d++)
{
if(neighbors[sight[d]] > -1)
{
if(grid[neighbors[sight[d]]] > 0)
{
if(sight[d] == 0)
{
EncodeContourForTopPixel(curr_mat_id, direction, pos, curr_contour, bbox.m_W);
break;
}
else if(sight[d] == 1)
{
EncodeContourForRightPixel(curr_mat_id, direction, pos, curr_contour);
break;
}
else if(sight[d] == 2)
{
EncodeContourForBottomPixel(curr_mat_id, direction, pos, curr_contour, bbox.m_W);
break;
}
else if(sight[d] == 3)
{
EncodeContourForLeftPixel(curr_mat_id, direction, pos, curr_contour);
break;
}
}
}
}
// It is possible to reach the start pixel whithout finishing to encode the whole contour.
// 00111
// 11100
// In this case the direction value is always 3, the position value is always 3
// We have to check if there is a neighbor at left of the current direction
if(curr_mat_id == start_mat_id)
{
if(pos == 3 && direction == 3)
{
UpdateSight(sight, direction);
FOURNeighborhood(neighbors, curr_mat_id, bbox.m_W, bbox.m_H);
if(neighbors[sight[0]] > -1)
{
if(grid[neighbors[sight[0]]] == 1)
{
pos = 3;
direction = 2;
curr_contour.push_back(2);
curr_mat_id += bbox.m_W;
}
}
}
}
}
// We reach the start pixel but maybe we did not encode the whole contour
if(pos == 3)
{
curr_contour.push_back(3);
curr_contour.push_back(0);
}
else if(pos == 4)
curr_contour.push_back(0);
return curr_contour;
}
Contour
ContourOperations::MergeContours(const long unsigned int start_id1,
const long unsigned int start_id2,
const Contour& c1,
const Contour& c2,
const BoundingBox& bb,
const unsigned int width,
const unsigned int height)
{
/* Grid with the dimension of the bounding box initialized to 0 */
short matrix_bbox[bb.m_W * bb.m_H];
memset(matrix_bbox, 0, bb.m_W * bb.m_H * sizeof(short));
/* Generate the border pixels wrt to c1 and c2 */
PixelList pixels1 = GenerateBorderPixels(start_id1, c1, width);
{
PixelList pixels2 = GenerateBorderPixels(start_id2, c2, width);
pixels1.insert(pixels1.end(), pixels2.begin(), pixels2.end());
}
/* Each case of the grid where a pixel is located is set to 1 */
for(PixelConstIterator pit = pixels1.begin(); pit != pixels1.end(); ++pit)
matrix_bbox[ToBoundingBoxCoordinates(*pit, bb, width)] = 1;
/* Remove internal pixels */
long unsigned int bb_id;
bool is_internal;
long int neighbors[8];
for(long unsigned int y = 1; y < bb.m_H - 1; ++y)
{
for(long unsigned int x = 1; x < bb.m_W - 1; ++x)
{
bb_id = y*bb.m_W + x;
is_internal = true;
if(matrix_bbox[bb_id] > 0)
{
EIGHTNeighborhood(neighbors, bb_id, bb.m_W, bb.m_H);
for(short j = 0; j < 8; ++j)
{
if(matrix_bbox[neighbors[j]] < 1)
{
is_internal = false;
break;
}
}
if(is_internal)
matrix_bbox[bb_id] = 2;
}
}
}
for(long unsigned int i = 0; i < bb.m_H * bb.m_W; ++i)
{
if(matrix_bbox[i] > 1)
matrix_bbox[i] = 0;
}
/* Create a new contour */
return CreateContourFromBorderPixels(start_id1, bb, matrix_bbox, width);
}
long unsigned int
ContourOperations::ToImageCoordinates(const long unsigned int id,
const BoundingBox& bbox,
const unsigned int width)
{
long unsigned int bbox_y = id / bbox.m_W;
long unsigned int bbox_x = id % bbox.m_W;
long unsigned int img_x = bbox.m_UX + bbox_x;
long unsigned int img_y = bbox.m_UY + bbox_y;
return (img_y * width + img_x);
}
typename ContourOperations::PixelList
ContourOperations::GeneratePixels(long unsigned int id,
const Contour& contour,
const BoundingBox& bbox,
const unsigned int width)
{
// Generate the bounding box grid
short matrix_bbox[bbox.m_W * bbox.m_H];
memset(matrix_bbox, 0, bbox.m_W * bbox.m_H * sizeof(short));
PixelList pixels;
/* Each case of the grid where a pixel is located is set to 1 */
{
// Generate the border pixels
PixelList border_pixels = GenerateBorderPixels(id, contour, width);
for(PixelConstIterator pit = border_pixels.begin();
pit != border_pixels.end(); ++pit)
matrix_bbox[ToBoundingBoxCoordinates(*pit, bbox, width)] = 1;
pixels.insert(pixels.end(), border_pixels.begin(), border_pixels.end());
}
/* For each case of the grid we determine if it is inside or outside
of the region */
long unsigned int bb_id;
for(long unsigned int y = 1; y < bbox.m_H - 1; ++y)
{
for(long unsigned int x = 1; x < bbox.m_W - 1; ++x)
{
bb_id = y*bbox.m_W + x;
if(matrix_bbox[bb_id] < 1)
{
if(IsInternalPixel(bb_id, matrix_bbox, bbox.m_W, bbox.m_H))
{
matrix_bbox[bb_id] = 1;
pixels.push_back(ToImageCoordinates(bb_id, bbox, width));
}
}
}
}
return pixels;
}
} // end of namespace lsrm
#ifndef __LSRM_CONTOUR_OPERATIONS_H
#define __LSRM_CONTOUR_OPERATIONS_H
#include "lsrmDataStructures.h"
#include "lsrmNeighborhood.h"
#include <cstring>
#include <algorithm>
namespace lsrm
{
class ContourOperations
{
public:
/* Some convenient typedefs */
typedef std::vector<long unsigned int> PixelList;
typedef typename PixelList::iterator PixelIterator;
typedef typename PixelList::const_iterator PixelConstIterator;
/*
* Given two rectangular bounding boxes,
* it returns the bounding box which is
* the union of both bounding boxes.
*
* @params
* const BoundingBox& bb1 : reference to the first bounding box
* const BoundingBox& bb2 : reference to the second bounding box
* @return the union of bb1 and bb2.
*/
static BoundingBox MergeBoundingBoxes(const BoundingBox& bb1,
const BoundingBox& bb2);
/*
* Given the coordinates of the pixel in the current image, the
* bounding box containing it and the width of the image, it returns
* the coordinates of the pixel in the referential of the bounding box.
*
* @params
* const long unsigned int id : coordinates of the pixel in the image
* referential.
* const BoundingBox& bb : bounding box containing the pixel
* const unsigned int width : width of the image
* @return the coordinates of the pixel in the bounding box referential.
*/
static long unsigned int ToBoundingBoxCoordinates(const long unsigned int id,
const BoundingBox& bb,
const unsigned int width);
/*
* Given the contour, the first pixel coordinates
* and the width of the current image,
* it returns the list of the border pixels.
*
* @params
* const long unsigned int id : coordinates of the first pixel.
* const Contour& contour : reference to the contour.
* const unsigned int width : width of the current image.
*/
static PixelList GenerateBorderPixels(long unsigned int id,
const Contour& contour,
const unsigned int width);
/*
* Return true if it exists a pixel in the grid at the north
* of the current pixel.
*
* @params
* const long unsigned int idx : coordinates of the current pixel
* const short * grid : grid
* const unsigned int grid_width : width of the grid
*/
static bool GetCollisionAtNorth(const long unsigned int idx,
const short * grid,
const unsigned int grid_width);
/*
* Return true if it exists a pixel in the grid at the north East
* of the current pixel.
*
* @params
* const long unsigned int idx : coordinates of the current pixel
* const short * grid : grid
* const unsigned int grid_width : width of the grid
*/
static bool GetCollisionAtNorthEast(const long unsigned int idx,
const short * grid,
const unsigned int grid_width);
/*
* Return true if it exists a pixel in the grid at the East
* of the current pixel.
*
* @params
* const long unsigned int idx : coordinates of the current pixel
* const short * grid : grid
* const unsigned int grid_width : width of the grid
*/
static bool GetCollisionAtEast(const long unsigned int idx,
const short * grid,
const unsigned int grid_width);
/*
* Return true if it exists a pixel in the grid at the South East
* of the current pixel.
*
* @params
* const long unsigned int idx : coordinates of the current pixel
* const short * grid : grid
* const unsigned int grid_width : width of the grid
* const unsigned int grid_height : height of the grid
*/
static bool GetCollisionAtSouthEast(const long unsigned int idx,
const short * grid,
const unsigned int grid_width,
const unsigned int grid_height);
/*
* Return true if it exists a pixel in the grid at the South
* of the current pixel.
*
* @params
* const long unsigned int idx : coordinates of the current pixel
* const short * grid : grid
* const unsigned int grid_width : width of the grid
* const unsigned int grid_height : height of the grid
*/
static bool GetCollisionAtSouth(const long unsigned int idx,
const short * grid,
const unsigned int grid_width,
const unsigned int grid_height);
/*
* Return true if it exists a pixel in the grid at the South West
* of the current pixel.
*
* @params
* const long unsigned int idx : coordinates of the current pixel
* const short * grid : grid
* const unsigned int grid_width : width of the grid
* const unsigned int grid_height : height of the grid
*/
static bool GetCollisionAtSouthWest(const long unsigned int idx,
const short * grid,
const unsigned int grid_width,
const unsigned int grid_height);
/*
* Return true if it exists a pixel in the grid at the West
* of the current pixel.
*
* @params
* const long unsigned int idx : coordinates of the current pixel
* const short * grid : grid
* const unsigned int grid_width : width of the grid
*/
static bool GetCollisionAtWest(const long unsigned int idx,
const short * grid,
const unsigned int grid_width);
/*
* Return true if it exists a pixel in the grid at the North West
* of the current pixel.
*
* @params
* const long unsigned int idx : coordinates of the current pixel
* const short * grid : grid
* const unsigned int grid_width : width of the grid
*/
static bool GetCollisionAtNorthWest(const long unsigned int idx,
const short * grid,
const unsigned int grid_width);
/*
* Return true if the pixel located at the coordinates idx
* is an internal pixel, i.e, in each direction there is a pixel.
*
* @params
* const long unsigned int idx : coordinates of the current pixel
* const short * grid : grid
* const unsigned int grid_width : width of the grid
* const unsigned int grid_height : height of the grid
*/
static bool IsInternalPixel(const long unsigned int idx,
const short * grid,
const unsigned int grid_width,
const unsigned int grid_height);
/*
* Given the direction of the front, it returns the field of view
*
* @params
* short * sight : former field of view.
* const short direction : new front direction.
*/
static void UpdateSight(short * sight, const short direction);
/*
* Create a contour element when we move toward the top, right, bottom
* or left wrt to the current pixel.
*
* @params
* long unsigned int& curr_mat_id : pixel coordinates
* short& direction : toward the direction we look
* short& pos : location on the pixel
* Contour& curr_contour : new contour to be created
* const unsigned int grid_width : width of the grid
*/
static void EncodeContourForTopPixel(long unsigned int& curr_mat_id,
short& direction,
short& pos,
Contour& curr_contour,
const unsigned int grid_width);
static void EncodeContourForRightPixel(long unsigned int& curr_mat_id,
short& direction,
short& pos,
Contour& curr_contour);
static void EncodeContourForBottomPixel(long unsigned int& curr_mat_id,
short& direction,
short& pos,
Contour& curr_contour,
const unsigned int grid_width);
static void EncodeContourForLeftPixel(long unsigned int& curr_mat_id,
short& direction,
short& pos,
Contour& curr_contour);
/*
* Given the coordinates of the first pixel, the bounding box, the grid
* with the location of the border pixels and the dimension of the referential
* image, it returns a new contour
*
* @params
* const long unsigned int idx : coordinates of the current pixel.
* const BoundingBox& bbox : reference to the bounding box
* const short * grid : grid
* const unsigned int width : width of the current image.
* cont unsigned int height : height of the current image.
*/
static Contour CreateContourFromBorderPixels(const long unsigned int id,
const BoundingBox& bbox,
const short * grid,
const unsigned int width);
/*
* Given two contours, the coordinates of their first pixels
* and the bounding box wrapping both contours, it returns the
* new contour by merging c1 and c2.
*
* @params
* const long unsigned int start_id1 : coordinates of the first
* pixel of the first contour
* const long unsigned int start_id2 : coordinates of the first
* pixel of the second contour
* const Contour& c1 : reference to the first contour
* const Contour& c2 : reference to the second contour
* const BoundingBox& bb : reference to the bounding box wrapping c1 and c2
* const unsigned int width : width of the current image
* const unsigned int height : height of the current image
*/
static Contour MergeContours(const long unsigned int start_id1,
const long unsigned int start_id2,
const Contour& c1,
const Contour& c2,
const BoundingBox& bb,
const unsigned int width,
const unsigned int height);
/*
* Given the coordinates of the pixel within its bounding box, it
* returns the coordinates of this pixel in the current image.
*
* @params
* const long unsigned int id : coordinates of the pixel within the bounding box
* const BoundingBox& bbox : reference to the bounding box
* const unsigned int width : width of the image
* @return the coordinates of the pixel in the image.
*/
static long unsigned int ToImageCoordinates(const long unsigned int id,
const BoundingBox& bbox,
const unsigned int width);
/*
* Given the contour, the first pixel coordinates
* and the width of the current image,
* it returns the list of the pixels within the area
* delineated by the contour.
*
* @params
* const long unsigned int id : coordinates of the first pixel.
* const Contour& contour : reference to the contour.
* const unsigned int width : width of the current image.
*/
static PixelList GeneratePixels(long unsigned int id,
const Contour& contour,
const BoundingBox& bbox,
const unsigned int width);
};
} // end of namespace lsrm
#endif
#ifndef __LSRM_DATA_STRUCTURES_H
#define __LSRM_DATA_STRUCTURES_H
#include <stdexcept>
#include <bitset>
#include <vector>
namespace lsrm
{
typedef std::bitset<2> ContourElem;
typedef std::vector<ContourElem> Contour;
typedef typename Contour::iterator ContourIterator;
typedef typename Contour::const_iterator ContourConstIterator;
struct BoundingBox
{
......@@ -25,6 +22,25 @@ namespace lsrm
unsigned int m_H;
};
BoundingBox MergeBoundingBoxes(const BoundingBox& bb1,
const BoundingBox& bb2)
{
long unsigned int 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;
}
} // end of namespace lsrm
#endif
#ifndef __LSRM_GRAPH_H
#define __LSRM_GRAPH_H
#include <boost/shared_ptr.hpp>
#include "lsrmDataStructures.h"
namespace lsrm
{
struct BaseNode
{
BaseNode(){}
virtual ~BaseNode() {}
/* Node already merged. */
bool m_Valid;
/* Node has to be removed from the graph. */
bool m_Expired;
/* Does the node merge at the previous iteration */
bool m_IsMerged;
/* Perimeter of the region */
unsigned int m_Perimeter;
......@@ -35,39 +33,47 @@ namespace lsrm
*/
BoundingBox m_Bbox;
/*
Contour of the region
*/
Contour m_Contour;
/* List of pixels contained in the regions */
std::vector<unsigned long int> m_Pixels;
};
template<class DerivedNode>
struct Node : BaseNode
{
struct Edge
struct NeighborType
{
/* Boundary length between two adjacent regions.*/
typedef std::weak_ptr<DerivedNode> WeakDerived;
typedef std::shared_ptr<DerivedNode> SharedDerived;
WeakDerived m_Target;
float m_Cost;
unsigned int m_Boundary;
bool m_CostUpdated;
NeighborType(WeakDerived ptr, double w, unsigned int c) :
m_Target(ptr), m_Cost(w), m_Boundary(c), m_CostUpdated(false) {}
/* Fusion cost (similarity measure) with the target node. */
float m_Cost;
/* Pointer to a neighboring node. */
boost::shared_ptr<DerivedNode> m_Target;
inline SharedDerived GetRegion()
{
SharedDerived ptr(m_Target.lock());
if(!ptr)
throw std::runtime_error("lss_GenericLMBFRegionMergingHandler.h - NeighborType::GetRegion - Region pointer is not valid");
return ptr;
}
};
Node(){};
virtual ~Node() {}
std::vector<Edge> m_Edges;
template<class DerivedNode>
struct Node : BaseNode
{
typedef NeighborType<DerivedNode> CRPTNeighborType;
std::vector<CRPTNeighborType> m_Edges;
};
template<class TNode>
struct Graph
{
typedef TNode NodeType;
typedef typename NodeType::Edge EdgeType;
typedef boost::shared_ptr<NodeType> NodePointerType;
typedef std::shared_ptr<NodeType> NodePointerType;
typedef typename NodeType::CRPTNeighborType EdgeType;
typedef std::vector<NodePointerType> NodeListType;
typedef typename NodeListType::iterator NodeIteratorType;
typedef typename NodeListType::const_iterator NodeConstIteratorType;
......@@ -75,7 +81,7 @@ namespace lsrm
typedef typename EdgeListType::iterator EdgeIteratorType;
typedef typename EdgeListType::const_iterator EdgeConstIteratorType;
std::vector< boost::shared_ptr<TNode> > m_Nodes;
std::vector< NodePointerType > m_Nodes;
};
} // end of namespace lsrm
......
......@@ -2,7 +2,6 @@
#define __LSRM_GRAPH_OPERATIONS_H
#include "lsrmGraph.h"
#include "lsrmNeighborhood.h"
#include "lsrmContourOperations.h"
#include <iostream>
#include <cassert>
#include <limits>
......@@ -30,59 +29,6 @@ namespace lsrm
typedef typename GraphType::EdgeIteratorType EdgeIterator;
typedef typename GraphType::EdgeConstIteratorType EdgeConstIterator;
/* Some static constants */
static const long long unsigned int NodeSize = sizeof(NodeType) + sizeof(NodePointerType);
static const long long unsigned int EdgeSize = sizeof(EdgeType);
/* Functors (former than lambda expression...
but it can accept all compiler' versions) */
struct EdgeEqualTo
{
explicit EdgeEqualTo(NodePointerType t_) : m_T(t_)
{assert(m_T != NULL);}
bool operator()(const EdgeType& e)
{
return e.m_Target == m_T;
}
NodePointerType m_T;
};
struct IsExpired
{
IsExpired () {}
bool operator()(NodePointerType n) const
{
return n->m_Expired;
}
};
struct IsInSet
{
explicit IsInSet(std::set<long unsigned int>& ur) : m_UsedRegions(ur)
{
}
bool operator()(const EdgeType& e)
{
if(m_UsedRegions.find(e.m_Target->m_Id) == m_UsedRegions.end())
return true;
else
return false;
}
std::set<long unsigned int>& m_UsedRegions;
};
struct NodePtrComparator : public std::unary_function<NodePointerType, bool>
{
NodePointerType nn;
explicit NodePtrComparator(NodePointerType n) : nn(n){}
bool operator()(NodePointerType v) { return v == nn;}
};
/*
* Given the size of the input image and the mask of the
......@@ -282,110 +228,6 @@ namespace lsrm
const unsigned int numberOfIterations,
const unsigned int width,
const unsigned int height);
/*
*
*/
static void LargeScaleInitNodes(GraphType& graph,
SegmenterType& seg,
const unsigned int tileWidth,
const unsigned int tileHeight,
const unsigned int nbTilesX,
const unsigned int nbTilesY,
const unsigned int tileId,
const unsigned int margin,
const unsigned int imageWidth,
const unsigned int imageHeight,
CONNECTIVITY mask);
/*
*
*/
static bool IsOnTileBorder(const unsigned int pixelRow,
const unsigned int pixelCol,
const unsigned int lowerRow,
const unsigned int upperRow,
const unsigned int lowerCol,
const unsigned int upperCol,
const unsigned int imageWidth,
const unsigned int imageHeight);
static bool IsOnTileBorderAndAdjacentTileBorder(const unsigned int pixelRow,
const unsigned int pixelCol,
const unsigned int lowerRow,
const unsigned int upperRow,
const unsigned int lowerCol,
const unsigned int upperCol,
const unsigned int imageWidth,
const unsigned int imageHeight);
/*
*
*/
static bool IsBboxStrictlyInsideTile(NodePointerType n,
const unsigned int lowerRow,
const unsigned int upperRow,
const unsigned int lowerCol,
const unsigned int upperCol);
/*
*
*/
static bool IsBboxInsideTile(NodePointerType n,
const unsigned int lowerRow,
const unsigned int upperRow,
const unsigned int lowerCol,
const unsigned int upperCol);
/*
*
*/
static void RemoveEdgesToUnstableRegion(NodePointerType r);
/*
*
*/
static void RemoveUnstableRegions(GraphType& graph,
unsigned int lowerRow,
unsigned int upperRow,
unsigned int lowerCol,
unsigned int upperCol,
unsigned int imageWidth);
/*
*
*/
static void AddNeighboringLayer(NodePointerType n,
GraphType& g,
std::set<long unsigned int>& bset);
/*
*
*/
static void BuildStabilityMargins(const GraphType& graph,
GraphType& subgraph,
const unsigned int lowerRow,
const unsigned int upperRow,
const unsigned int lowerCol,
const unsigned int upperCol,
const unsigned int imageWidth,
const unsigned int imageHeight);
/*
*
*/
static void MergeGraphs(GraphType& graph,
const unsigned int lowerRow,
const unsigned int upperRow,
const unsigned int lowerCol,
const unsigned int upperCol,
const unsigned int imageWidth,
const unsigned int imageHeight,
bool useless);
/*
*
*/
static long long unsigned int GetMemorySpace(const GraphType& graph);
};
} // end of namespace lsrm
......
This diff is collapsed.
......@@ -6,7 +6,6 @@
#include <otbImageFileReader.h>
#include <otbImageFileWriter.h>
#include "lsrmGraph.h"
#include "lsrmContourOperations.h"
#include <string>
#include <stdlib.h>
#include <time.h>
......@@ -54,13 +53,7 @@ namespace lsrm
static void WriteOutputRGBImage(const GraphType& graph,
const unsigned int width,
const unsigned int height,
const std::string& outputFileName);
static void WriteContourImage(const GraphType& graph,
const std::string& inputFileName,
const std::string& outputFileName);
const std::string& outputFileName);
};
} // end of namespace lsrm
......
......@@ -29,19 +29,13 @@ namespace lsrm
// Start at 1 (value 0 can be used for invalid pixels)
long unsigned int label = 1;
for(NodeConstIterator nit = graph.m_Nodes.begin();
nit != graph.m_Nodes.end(); ++nit)
for(auto& region : graph.m_Nodes)
{
ContourOperations::PixelList pixels = ContourOperations::GeneratePixels((*nit)->m_Id,
(*nit)->m_Contour,
(*nit)->m_Bbox,
width);
for (ContourOperations::PixelConstIterator pit = pixels.begin();
pit != pixels.end(); ++pit)
for (auto& pix: region->m_Pixels)
{
index[0] = (*pit) % width;
index[1] = (*pit) / width;
index[0] = pix % width;
index[1] = pix / width;
label_img->SetPixel(index, label);
}
++label;
......@@ -95,21 +89,15 @@ namespace lsrm
srand(time(NULL));
unsigned char c1, c2, c3;
for(NodeConstIterator nit = graph.m_Nodes.begin();
nit != graph.m_Nodes.end(); ++nit)
for(auto& region : graph.m_Nodes)
{
ContourOperations::PixelList pixels = ContourOperations::GeneratePixels((*nit)->m_Id,
(*nit)->m_Contour,
(*nit)->m_Bbox,
width);
c1 = rand() % 256;
c2 = rand() % 256;
c3 = rand() % 256;
for (ContourOperations::PixelConstIterator pit = pixels.begin();
pit != pixels.end(); ++pit)
for (auto& pix : region->m_Pixels)
{
index[0] = (*pit) % width;
index[1] = (*pit) / width;
index[0] = pix % width;
index[1] = pix / width;
pixelValue[0] = c1;
pixelValue[1] = c2;
pixelValue[2] = c3;
......@@ -123,50 +111,6 @@ namespace lsrm
rgb_writer->SetFileName(outputFileName);
rgb_writer->Update();
}
template<class TGraph>
void GraphToOtbImage<TGraph>::WriteContourImage(const GraphType& graph,
const std::string& inputFileName,
const std::string& outputFileName)
{
typedef unsigned char RGBPixelType;
typedef otb::VectorImage<RGBPixelType, 2> RGBImageType;
typedef typename RGBImageType::IndexType RGBIndexType;
typedef otb::ImageFileReader<RGBImageType> RGBImageReaderType;
typedef otb::ImageFileWriter<RGBImageType> RGBImageWriterType;
RGBImageReaderType::Pointer rgb_reader = RGBImageReaderType::New();
rgb_reader->SetFileName(inputFileName);
rgb_reader->Update();
RGBImageType::Pointer rgb_img = rgb_reader->GetOutput();
RGBIndexType index;
const unsigned int width = rgb_img->GetLargestPossibleRegion().GetSize()[0];
for(NodeConstIterator nit = graph.m_Nodes.begin();
nit != graph.m_Nodes.end(); ++nit)
{
ContourOperations::PixelList pixels = ContourOperations::GenerateBorderPixels((*nit)->m_Id,
(*nit)->m_Contour,
width);
for (ContourOperations::PixelConstIterator pit = pixels.begin();
pit != pixels.end(); ++pit)
{
index[0] = (*pit) % width;
index[1] = (*pit) / width;
typename RGBImageType::PixelType rgb_pix = rgb_img->GetPixel(index);
for(unsigned int b=0; b<rgb_img->GetNumberOfComponentsPerPixel(); b++)
rgb_pix[b] = 0;
rgb_img->SetPixel(index, rgb_pix);
}
}
RGBImageWriterType::Pointer rgb_writer = RGBImageWriterType::New();
rgb_writer->SetFileName(outputFileName);
rgb_writer->SetInput(rgb_img);
rgb_writer->Update();
}
} // end of namespace lsrm
#endif
Supports Markdown
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