泛洪填充(FloodFill)问题在图像处理中非常常用,它和连通图的概念相似。最近在YouTube看 Patrick Shyu (TechLead)的视频,他讲他在谷歌面试别人的时候,常会出一道泛洪填充的题。
1、泛洪填充——图像上色
这道题参考LeetCode733:
有一幅以二维整数数组表示的图画,每一个整数表示该图画的像素值大小,数值在 0 到 65535 之间。
给你一个坐标 (sr, sc) 表示图像渲染开始的像素值(行 ,列)和一个新的颜色值 newColor,让你重新上色这幅图像。为了完成上色工作,从初始坐标开始,记录初始坐标的上下左右四个方向上像素值与初始坐标相同的相连像素点,接着再记录这四个方向上符合条件的像素点与他们对应四个方向上像素值与初始坐标相同的相连像素点,……,重复该过程。将所有有记录的像素点的颜色值改为新的颜色值。
最后返回经过上色渲染后的图像。
示例 1:
输入: image = [[1,1,1],[1,1,0],[1,0,1]] sr = 1, sc = 1, newColor = 2
输出: [[2,2,2],[2,2,0],[2,0,1]] 解析: 在图像的正中间,(坐标(sr,sc)=(1,1)),
在路径上所有符合条件的像素点的颜色都被更改成2。 注意,右下角的像素没有更改为2, 因为它不是在上下左右四个方向上与初始点相连的像素点。这里是引用
先说结论:泛洪填充目前已知有三种解决方法,但是要注意边界条件,分别是:
- 深度优先遍历DFS:通过不断的遍历当前点的【上、下、左、右】点,相同则修改(连通),不断递归。DFS特点:速度快,但是对于图特别大的场景可能栈溢出。
- 广度优先遍历BSF:BFS通常与队列结合使用,本方法是将当前点加入队列,然后再将其【上、下、左、右】相邻点加入队尾。从队头弹出(poll-取值并删除)节点,如果与旧值相等则修改为新值,重复以上步骤,直到队列为空。BFS特点:对图很大的场景适用,但速度慢。
- 并查集:从(0, 0)位置开始依次遍历,这时就不需要同时兼顾上下左右四个方向了,只需要看看它右边和下面的像素点颜色是不是和我一样都为color,一样就合并。不一样就不管它,让它自己单独作为一个集合。最后渲染指定的一个集合即可。
以下是自己对DFS和BFS在本地实现的结果:
package floodFill;
import java.util.LinkedList;
import java.util.Queue;
public class FloodFill {
public static void main(String[] args){
int[][] image = new int[][]{
{
1,1,1},{
1,1,0},{
1,0,1}};
floodFill_DFS(image, 1, 1, 2);
for (int[] list: image){
for (int e: list){
System.out.print(e + " ");
}
System.out.println();
}
}
//速度慢,但支持的image更大
public static int[][] floodFill_BFS(int[][] image, int sr, int sc, int newColor) {
//BFS
Queue<int[]> queue = new LinkedList<int[]>();
queue.offer(new int[]{
sr, sc});
int curColor = image[sr][sc];
if (curColor == newColor)
return image;
while(!queue.isEmpty()){
int[] curXY = queue.poll();
int row = curXY[0];
int col = curXY[1];
if (image[row][col] == curColor){
image[row][col] = newColor;
if (row > 0)
queue.offer(new int[]{
row-1,col});
if (row < image.length-1)
queue.offer(new int[]{
row+1,col}<

本文介绍了图像处理中的泛洪填充算法,包括其在图像上色和腐烂橘子问题中的应用,并探讨了使用DFS和BFS两种方法的实现及特点。同时,提到了相关LeetCode题目,如01矩阵和地图分析问题,展示了泛洪填充在实际问题中的应用。
最低0.47元/天 解锁文章
1751

被折叠的 条评论
为什么被折叠?



