我目前正在研究一种算法,在某些时候我必须经历一个图像并对具有相同属性的像素进行分组。我从最左上角的像素开始,我使用递归:从输入像素我可以获得邻近像素的高度,如果第一个具有相同的属性,那么我通过将此像素作为输入像素调用相同的函数。
以下是一些代码(请记住,这仍在进行中)。 基本呼叫者:
// R.A.G.
for( std::vector<Cell*>::iterator iterCell = cellVec.begin();
iterCell != cellVec.end(); ++iterCell )
{
Cell* mother = (*iterCell);
if( mother->visited != true )
{
mother->visited = true;
}
CheckNeighbors( mother );
}
递归函数:
void
CheckNeighbors( Cell* mother )
{
Cell* cell = nullptr;
// Get the neighbours for the cell.
// 5 6 7
// 4 c 0
// 3 2 1
if( (cell=CheckCell( 1, 0, mother )) != mother )
{
mother = cell;
CheckNeighbors( mother );
}
if( (cell=CheckCell( 1, 1, mother )) != mother )
{
mother = cell;
CheckNeighbors( mother );
}
if( (cell=CheckCell( 0, 1, mother )) != mother )
{
mother = cell;
CheckNeighbors( mother );
}
if( (cell=CheckCell( -1, 1, mother )) != mother )
{
mother = cell;
CheckNeighbors( mother );
}
if( (cell=CheckCell( -1, 0, mother )) != mother )
{
mother = cell;
CheckNeighbors( mother );
}
if( (cell=CheckCell( -1, -1, mother )) != mother )
{
mother = cell;
CheckNeighbors( mother );
}
if( (cell=CheckCell( 0, -1, mother )) != mother )
{
mother = cell;
CheckNeighbors( mother );
}
if( (cell=CheckCell( 1, -1, mother )) != mother )
{
mother = cell;
CheckNeighbors( mother );
}
}
我如何检查细胞:
Cell*
CheckCell( int x, int y, Cell* cell )
{
// Here a cell is one pixel, but it depends on the size of the window we choose.
// So for an image of 640*480, windowSize = 1, w = 640, h = 480
x += cell->window.x()/windowSize;
y += cell->window.y()/windowSize;
// The cell at (x, y) coordinates is not in the map
if( x < 0 || x >= w || y < 0 || y >= h ) return cell;
// Get the neighbor cell in (x, y)
// NB: cellVec has been filled up earlier and contains all the cells
Cell* neighbor = cellVec.at( (y*w) + x );
// The neighbor cell has already been visited
if( neighbor->visited ) return cell;
// The neighbor cell is of the same class as the mother cell
if( neighbor->cClass != cell->cClass ) return cell;
// Set the region number for the neighbor
neighbor->visited = true;
return neighbor;
}
所以这是我的问题:我确信这可以改善,但我想知道如何。 我应该使用其他递归的东西吗? 如何改进这种递归? 我读了关于尾调用优化的this article,但由于我无法丢弃调用者的状态,因此无法应用。但是我还有其他技巧吗?
感谢您的回答,我希望我已经足够明确了。
注意:如果我的图像是单色的,大小为640 * 480,单元格大小为2 * 2像素,我有153765个调用。当然还有1 * 1单元大小的段错误。我知道我可以增加堆栈的大小,但我更愿意找到另一种解决方案。
答案 0 :(得分:2)
您正在做的是Flood fill,实施为Depth First Search。
要改进它,你可以:
答案 1 :(得分:1)
使用迭代方法会更快,因为您已经读取了向量中的所有元素,并且可以线性地运行它。这是更加缓存友好的,你摆脱了所有抵消的东西
// Copy all elements starting from the selected cell pointed to by the iterator, if
// they are equal to the cell
void checkAllCells(vector<Cell*> input, vector<Cell*>::iterator it; vector<Cell*> output)
{
auto localIt = it;
while( localIt != input.end())
{
if ((*localIt)->class == (*it)->class)
{
output.pushback(*it);
}
}
}
请注意,您不需要像visited
等那样进行簿记,因为从第一个元素开始,您将找到所有其他相同的元素。如果你接着第二个元素,你知道,你已经在考虑前面的元素了