使用matlab进行洪水填充
Posted
技术标签:
【中文标题】使用matlab进行洪水填充【英文标题】:Flood Fill using matlab 【发布时间】:2013-01-09 15:00:17 【问题描述】:我是 MATLAB 新手,我正在尝试在 matlab 中使用 algorithm 实现洪水填充,我不知道我做错了什么可能是我没有正确使用递归函数,但我仍然没有出错,这段代码让我的matlab关闭 我正在使用以下代码,我从早上开始尝试对其进行调试,但未能找到问题
function [ colored_Image ] = floodFill( image, target_Loc_x, target_Loc_y, targetColor, replacementColor )
colored_Image = image;
if (target_Loc_x >= 1) && (target_Loc_x <= size(image,1)) && (target_Loc_y >= 1) && (target_Loc_y <= size(image,2))
if image(target_Loc_x,target_Loc_y) == targetColor
colored_Image(target_Loc_x,target_Loc_y) = replacementColor;
colored_Image = floodFill(colored_Image,target_Loc_x ,target_Loc_y + 1, targetColor, replacementColor);
colored_Image = floodFill(colored_Image,target_Loc_x + 1,target_Loc_y, targetColor, replacementColor);
colored_Image = floodFill(colored_Image,target_Loc_x,target_Loc_y - 1, targetColor, replacementColor);
colored_Image = floodFill(colored_Image,target_Loc_x - 1,target_Loc_y, targetColor, replacementColor);
end
end
end
使用
调用这个函数image = floodFill(im,1,1,0,127);
imshow(image);
im 是我的 200 x 200 的矩阵图像我想要我的黑色(0)到灰色(127),任何帮助将不胜感激
【问题讨论】:
【参考方案1】:您可能正在达到 Matlab 的递归限制。我的电脑没有崩溃,但产生了这个错误:
达到最大递归限制 500。使用 set(0,'RecursionLimit',N) 更改限制。请注意,超出您的可用堆栈 space 可能会使 MATLAB 和/或您的计算机崩溃。
解决这个问题的方法是重写floodFill,使其不使用递归。还有一些alternative algorithms on Wikipedia。
另外:aardvarkk's answer 对 Matlab 的 column-major 索引提出了重要的一点。您可以通过交换所有 x 和 y 变量来修复您的函数。
【讨论】:
【参考方案2】:我认为这有两个问题:
a) 您似乎按照(x,y)
的顺序索引image
矩阵。 MATLAB 矩阵按列顺序排列,因此您必须(不直观地)按(y,x)
的顺序对它们进行索引。所以这行:
image(target_Loc_x,target_Loc_y)
应该是:
image(target_Loc_y,target_Loc_x)
在彩色图像中设置值时也是如此。另请注意,size(image,1)
将给出y
方向的大小,而不是x
!
b) 您正在使用递归函数来执行非常简单的操作。它很快就达到了 MATLAB 的递归限制。在 200x200 图像中,您将拥有 40,000 深度的调用堆栈,而 MATLAB 默认情况下只允许递归限制为 500。为什么不尝试这样的事情呢:
colored_image = image;
colored_image(colored_image == targetColor) = replacementColor;
【讨论】:
最后的代码 sn-p 不适用于洪水填充。它将使用目标颜色更改所有像素,而不仅仅是连接的像素。 @shoelzer 好点。无论如何,我误解了原始代码 sn-p 来填充整个图像,但你是对的 - 只有当你选择的第一个像素是目标颜色时,它才会真正做任何事情。【参考方案3】: %(假设您的图像已加载到 img 并且您正在填充“值”) 函数洪水(x,y,img,值) %MATLAB 没有友好队列?使用java 导入 java.util.LinkedList q = 链表(); %洪水填充图像 初始 = img(y,x); q.add([y, x]); 而 q.size() > 0 pt = q.removeLast(); y = pt(1); x = pt(2); if (img(y+1, x) == 初始) img(y+1,x) = 值; q.add([y+1, x]); 结尾 如果(img(y-1,x)==初始) img(y-1,x) = 值; q.add([y-1, x]); 结尾 if (img(y, x+1) == 初始) img(y,x+1) = 值; q.add([y, x+1]); 结尾 如果(img(y,x-1)==初始) img(y,x-1) = 值; q.add([y, x-1]); 结尾 结尾 结尾因为 matlab 的递归限制非常低,所以我从来没有使用递归调用来填充洪水。另外,因为它似乎没有合适的队列(如果我错了,请纠正我)从 java 中导入一个更容易。
这没有做任何边界检查(所以如果洪水击中边缘就会失败......简单的解决方法是在你的图像周围放置一个边框,或者在索引 img 之前只检查 x 和 y。
【讨论】:
【参考方案4】:对@Jason 的回答进行了一些修复——我添加了边界检查,即填充颜色与初始颜色不同(否则为无限递归)并返回结果。工作,但很慢。
function img = flood(x,y,img,value)
% http://***.com/questions/14238083/flood-fill-using-matlab
import java.util.LinkedList
q = LinkedList();
initial = img(y,x);
dims = size(img);
if (value == initial)
error('cant flood fill as initial==value');
end
q.add([y, x]);
while q.size() > 0
pt = q.removeLast();
y = pt(1);
x = pt(2);
if (y < dims(1) && img(y+1, x) == initial) % step down
img(y+1,x) = value;
q.add([y+1, x]);
end
if (y > 1 && img(y-1, x) == initial) % step up
img(y-1,x) = value;
q.add([y-1, x]);
end
if (x < dims(2) && img(y, x+1) == initial) % step right
img(y,x+1) = value;
q.add([y, x+1]);
end
if (x > 1 && img(y, x-1) == initial) % step left
img(y,x-1) = value;
q.add([y, x-1]);
end
end
end
【讨论】:
我已经合并了来自匿名评论者的错误修复。谢谢以上是关于使用matlab进行洪水填充的主要内容,如果未能解决你的问题,请参考以下文章