MATLAB递归4向Flood_Fill算法填充异常问题求助
MATLAB 4向递归Flood Fill算法问题修复方案
问题描述
我有一项作业任务,需要用MATLAB实现4向递归Flood_Fill算法,填充两个重叠圆的区域,通过鼠标选取填充起点并编写了对应函数,但运行时遇到三个问题:
- 角落像素无法被填充
- 递归返回后程序会“遗忘”已绘制的像素,进而陷入无限循环
- 即使添加
x_prev、y_prev参数记录上一位置,返回时仍会出现像素变回旧颜色的情况
8向算法效果较好,但需要将圆边框设为至少2像素才能避免重叠,尝试过扩大搜索区域等方法都没解决。我对MATLAB不太熟悉,求解决这个递归填充的问题。
以下是我编写的两段函数代码:
第一段代码
function [] = Flood_Fill(M,x,y,new_color,old_color,border_color) if(x < 0 || y < 0 || x >= 60 || y >= 60 || M(x,y) ~= old_color) % M is a 60x60 array return else M(x,y) = new_color; pause(0.16); image(M'); Flood_Fill(M,x+1,y,new_color,old_color,border_color); Flood_Fill(M,x-1,y,new_color,old_color,border_color); Flood_Fill(M,x,y+1,new_color,old_color,border_color); Flood_Fill(M,x,y-1,new_color,old_color,border_color); end disp("looped"); end
第二段代码
function M = Zadacha_4_Fill_Recursion(M,x,y,new_color,old_color,border_color,x_prev,y_prev) if(x < 0 || y < 0 || x >= 60 || y >= 60 || M(x,y) ~= old_color ) fprintf("return cond: x = %d, y = %d\n", x,y); if(M(x,y) ~= border_color) fprintf("erase_not: x = %d, y = %d | x_prev = %d, y_prev = %d\n", x,y,x_prev,y_prev); M(x_prev,y_prev) = new_color; x_prev = x; y_prev = y; end pause(1.2); image(M'); return else M(x,y) = new_color; x_prev = x; y_prev = y; pause(0.3); image(M'); fprintf("normal: x = %d, y = %d | x_prev = %d, y_prev = %d\n", x,y,x_prev,y_prev); Zadacha_4_Fill_Recursion(M,x+1,y,new_color,old_color,border_color,x_prev,y_prev); Zadacha_4_Fill_Recursion(M,x-1,y,new_color,old_color,border_color,x_prev,y_prev); Zadacha_4_Fill_Recursion(M,x,y+1,new_color,old_color,border_color,x_prev,y_prev); Zadacha_4_Fill_Recursion(M,x,y-1,new_color,old_color,border_color,x_prev,y_prev); end %disp("looped"); end
问题根源与修复方案
1. 核心问题:MATLAB参数传递机制
MATLAB函数默认是值传递,不是引用传递。你第一段代码里的M没有作为返回值输出,递归调用中修改的M不会同步到上层调用的数组——这就是递归返回后像素变回旧颜色、程序重复处理同一像素导致无限循环的根本原因。
2. 边界判断错误
MATLAB数组索引从1开始,不是0!你代码里的x < 0 || y < 0会把合法的(1,1)附近像素误判为越界,导致角落像素无法填充,正确的边界判断应该是x < 1 || y < 1 || x > 60 || y > 60。
3. x_prev/y_prev参数冗余
这个参数完全没必要,只要保证每次递归调用时传递并接收更新后的M,就能避免重复处理同一像素。
修复后的4向递归Flood Fill代码
function M = Flood_Fill(M, x, y, new_color, old_color) % 修正边界判断:适配MATLAB从1开始的索引规则 if x < 1 || y < 1 || x > size(M,1) || y > size(M,2) return; end % 仅当前像素为旧颜色时才填充,自动跳过边框(边框颜色≠旧颜色) if M(x,y) ~= old_color return; end % 修改当前像素颜色 M(x,y) = new_color; pause(0.16); image(M'); drawnow; % 强制刷新图像,避免显示滞后 % 递归处理四个方向,接收返回值更新当前M M = Flood_Fill(M, x+1, y, new_color, old_color); M = Flood_Fill(M, x-1, y, new_color, old_color); M = Flood_Fill(M, x, y+1, new_color, old_color); M = Flood_Fill(M, x, y-1, new_color, old_color); end
使用说明
- 调用时传入初始
M数组、鼠标选取的起点(x,y)、新颜色、旧颜色(即填充区域的初始颜色)即可,无需单独传递边框颜色(边框颜色与旧颜色不同时会被自动跳过)。 - 如果你的
M不是固定60x60,size(M,1)和size(M,2)会自动适配数组尺寸,通用性更强。
这样修改后,三个问题都能解决:边界判断修正后角落像素可正常填充,值传递问题通过返回更新后的数组解决,不会再出现像素“遗忘”和无限循环的情况。
内容的提问来源于stack exchange,提问作者Alex_Stankov
相关产品推荐
相关产品推荐

