FloodFill算法实现及填充改进
来源:互联网 发布:js trim函数在哪里 编辑:程序博客网 时间:2024/06/06 02:17
+ From wikipedia
Flood fill, also called seed fill, is an algorithm that determines the area connected to a given node in a multi-dimensional array. It is used in the "bucket" fill tool of paint programs to determine which parts of a bitmap to fill with color
+ the algorithms
The flood fill algorithm takes three parameters: a start node, a target color, and a replacement color. The algorithm looks for all nodes in the array which are connected to the start node by a path of the target color, and changes them to the replacement color. There are many ways in which the flood-fill algorithm can be structured, but they all make use of a queue or stack data structure, explicitly or implicitly.
从上面的算法介绍可知,凡是会搜索的同学就能很轻易地掌握floodfill。因为floodfill算法从大体而言可以细分为两种算法思想,一种是DFS,一种是BFS。以下讲介绍两大种常用的算法,并简单分析其中用到的dfs和bfs。
1. per-pixel fill (点点填充)
recursive flood-fill with 4 directions recursive flood-fill with 8 directions
这两个有一个小区别,就是8方向的算法是在4方向的算法的基础上添加了四个方向(左上、左下、右上、右下),因此造成的结果是8方向的算法有可能会“leak through sloped edges of 1 pixel thick”。至于其它方面则是完全一样,下面所有的算法都是基于4方向的。
用dfs的搜索思想(递归)写的代码:
Flood-fill (node, target-color, replacement-color):
1. If the color of node is not equal to target-color, return.
2. Set the color of node to replacement-color.
3. Perform Flood-fill (one step to the west of node, target-color, replacement-color).
Perform Flood-fill (one step to the east of node, target-color, replacement-color).
Perform Flood-fill (one step to the north of node, target-color, replacement-color).
Perform Flood-fill (one step to the south of node, target-color, replacement-color).
4. Return.
用bfs的搜索思想(队列)写的代码:
Flood-fill (node, target-color, replacement-color):
1. Set Q to the empty queue.
2. If the color of node is not equal to target-color, return.
3. Add node to the end of Q.
4. While "Q" is not empty:
5. Set "n" equal to the first element of "Q"
6. If the color of n is equal to target-color, set the color of n to replacement-color.
7. Remove first element from "Q"
8. If the color of the node to the west of n is target-color, set the color of that node to replacement-color, add that node to the end of Q.
9. If the color of the node to the east of n is target-color, set the color of that node to replacement-color, add that node to the end of Q.
10. If the color of the node to the north of n is target-color, set the color of that node to replacement-color, add that node to the end of Q.
11. If the color of the node to the south of n is target-color, set the color of that node to replacement-color, add that node to the end of Q.
12. Return.
以上两种小算法的问题在于,如果填充的面积较大的话,程序很容易爆掉。究其原因,就是搜索的深度过大或队列的长度不够造成的。因此为了减少搜索深度或进队列的元素个数,可以用线方式代替点方式。而这样做还有一个好处就是填充速度的提高。
2. scanline fill (扫描线填充)
//stack friendly and fast floodfill algorithm(递归深搜的写法)
void floodFillScanline(int x, int y, int newColor, int oldColor)
{
if(oldColor == newColor) return;
if(screenBuffer[x][y] != oldColor) return;
int y1;
//draw current scanline from start position to the top
y1 = y;
while(y1 < h && screenBuffer[x][y1] == oldColor)
{
screenBuffer[x][y1] = newColor;
y1++;
}
//draw current scanline from start position to the bottom
y1 = y - 1;
while(y1 >= 0 && screenBuffer[x][y1] == oldColor)
{
screenBuffer[x][y1] = newColor;
y1--;
}
//test for new scanlines to the left
y1 = y;
while(y1 < h && screenBuffer[x][y1] == newColor)
{
if(x > 0 && screenBuffer[x - 1][y1] == oldColor)
{
floodFillScanline(x - 1, y1, newColor, oldColor);
}
y1++;
}
y1 = y - 1;
while(y1 >= 0 && screenBuffer[x][y1] == newColor)
{
if(x > 0 && screenBuffer[x - 1][y1] == oldColor)
{
floodFillScanline(x - 1, y1, newColor, oldColor);
}
y1--;
}
//test for new scanlines to the right
y1 = y;
while(y1 < h && screenBuffer[x][y1] == newColor)
{
if(x < w - 1 && screenBuffer[x + 1][y1] == oldColor)
{
floodFillScanline(x + 1, y1, newColor, oldColor);
}
y1++;
}
y1 = y - 1;
while(y1 >= 0 && screenBuffer[x][y1] == newColor)
{
if(x < w - 1 && screenBuffer[x + 1][y1] == oldColor)
{
floodFillScanline(x + 1, y1, newColor, oldColor);
}
y1--;
}
}
//The scanline floodfill algorithm using our own stack routines, faster(广搜队列的写法)
void floodFillScanlineStack(int x, int y, int newColor, int oldColor)
{
if(oldColor == newColor) return;
emptyStack();
int y1;
bool spanLeft, spanRight;
if(!push(x, y)) return;
while(pop(x, y))
{
y1 = y;
while(y1 >= 0 && screenBuffer[x][y1] == oldColor) y1--;
y1++;
spanLeft = spanRight = 0;
while(y1 < h && screenBuffer[x][y1] == oldColor )
{
screenBuffer[x][y1] = newColor;
if(!spanLeft && x > 0 && screenBuffer[x - 1][y1] == oldColor)
{
if(!push(x - 1, y1)) return;
spanLeft = 1;
}
else if(spanLeft && x > 0 && screenBuffer[x - 1][y1] != oldColor)
{
spanLeft = 0;
}//写这一部分是防止因为同一列上有断开的段而造成的可能的“没填充”
if(!spanRight && x < w - 1 && screenBuffer[x + 1][y1] == oldColor)
{
if(!push(x + 1, y1)) return;
spanRight = 1;
}
else if(spanRight && x < w - 1 && screenBuffer[x + 1][y1] != oldColor)
{
spanRight = 0;
} //写这一部分是防止因为同一列上有断开的段而造成的可能的“没填充”
y1++;
}
}
}
以上两个小算法填充的方向都是纵向填充,你也可以修改成横向填充。
- FloodFill算法实现及填充改进
- FloodFill填充算法
- OpenCV实现FloodFill泛洪填充算法的代码及相关函数详解
- Opencv实现曼水填充算法-floodFill函数
- FloodFill(洪水填充 )算法
- 图像填充算法--洪水填充FloodFill
- FloodFill(漫水填充)算法
- OpenCV 漫水填充算法(Floodfill)
- opencv2-第五章-floodFill漫水填充算法
- 水漫金山:OpenCV漫水填充算法(Floodfill)
- 水漫金山:OpenCV漫水填充算法(Floodfill)
- 區域生長(floodFill) —— 漫水填充算法
- 11基于opencv的漫水填充算法floodFill()
- 改进的种子填充算法
- KMP算法及改进KMP算法实现
- floodfill算法
- floodfill算法
- floodfill算法
- 环境搭建
- Layout的重要属性
- D3D的D3DPRESENT_PARAMETERS参数介绍
- 指向多维数组的指针
- 关于表格冻结行和列的方法
- FloodFill算法实现及填充改进
- 有状态会话Bean与无状态会话Bean
- ubuntu下minicom和USB转串口(转)
- C语言实现一元多项式的加减运算
- qsort()应用大全
- java 常用系统参数System.getProperty()列表
- 选夫婿1
- 使用base64编码图片音频资源
- android:screenOrientation&&configchanges