4

我是 MATLAB 新手,我正在尝试在 matlab 中使用这个算法来实现洪水填充,我不知道我做错了什么可能是我没有正确使用递归函数,但我仍然没有出什么问题,这段代码让我的 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);

我是我的 200 x 200 的矩阵图像我想要我的黑色(0)到灰色(127),任何帮助将不胜感激

4

4 回答 4

5

您可能正在达到 Matlab 的递归限制。我的计算机没有崩溃,但会生成此错误:

达到最大递归限制 500。使用 set(0,'RecursionLimit',N) 更改限制。请注意,超出可用堆栈空间可能会使 MATLAB 和/或您的计算机崩溃。

解决这个问题的方法是重写 floodFill 使其不使用递归。维基百科上有一些替代算法

另外:aardvarkk 的回答对 Matlab 的列主索引很重要。您可以通过交换所有 x 和 y 变量来修复您的函数。

于 2013-01-09T15:35:05.103 回答
3

我认为这有两个问题:

a)您似乎image正在按顺序索引矩阵(x,y)。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;
于 2013-01-09T15:30:19.273 回答
2
    %(假设您的图像已加载到 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.util 中导入一个更容易。

这没有做任何边界检查(所以如果洪水击中边缘就会失败......简单的解决方法是在你的图像周围放置一个边框,或者在索引 img 之前只检查 x 和 y 范围。

于 2014-05-02T23:30:58.630 回答
1

对@Jason 的回答进行了一些修复 - 我添加了边界检查,即填充颜色与初始颜色不同(否则为无限递归)并返回结果的保护。工作但很慢。

function img = flood(x,y,img,value)
    % http://stackoverflow.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
于 2014-05-21T15:50:00.953 回答