使用matlab进行洪水填充

时间:2013-01-09 15:00:18

标签: matlab flood-fill

我是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);

我是200×200的矩阵图像我希望我的黑色(0)变成灰色(127),任何帮助都会感激不尽

4 个答案:

答案 0 :(得分:5)

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

  

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

解决这个问题的方法是重写floodFill,这样它就不会使用递归。有一些alternative algorithms on Wikipedia

另外:aardvarkk's answer对Matlab的column-major索引提出了重要观点。您可以通过交换所有x和y变量来修复函数。

答案 1 :(得分: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;

答案 2 :(得分:2)

    %(assume your image is loaded into img and you are filling with 'value')

function flood(x,y,img,value)

    %MATLAB doesnt have a friendly queue ? use java   
    import java.util.LinkedList
    q = LinkedList();

    %flood fill image 
    initial = img(y,x);

    q.add([y, x]);

    while q.size() > 0

        pt = q.removeLast();
        y = pt(1);
        x = pt(2);

        if (img(y+1, x) == initial) 
            img(y+1,x) = value;
            q.add([y+1, x]); 
        end
        if (img(y-1, x) == initial) 
            img(y-1,x) = value;
            q.add([y-1, x]); 
        end
        if (img(y, x+1) == initial) 
            img(y,x+1) = value;
            q.add([y, x+1]); 
        end
        if (img(y, x-1) == initial) 
            img(y,x-1) = value;
            q.add([y, x-1]); 
        end
    end
end

因为matlab的递​​归限制非常低,所以我从来没有使用递归调用填充洪水。此外,因为它似乎没有一个正确的队列(请纠正我,如果我错了),更容易从java导入一个。

这不会进行任何边界检查(因此如果洪水击中边缘会失败...简单的解决方法是在图像上放置一个边框,或者只是在索引img之前检查x和y。

答案 3 :(得分: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