An error occurred while loading the file. Please try again.
-
Pierre Lassalle authoredd8ebd795
#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)
{
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
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]])
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
{
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)
{
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
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;
}
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
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]);
351352353354355356357358359360361362363364365366367368369370371372373374375376377378
}
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