简体   繁体   English

Matlab:二进制图像打开到最小矩形大小

[英]Matlab: binary image open to minimum rectangle size

I have a binary image: 我有一个二进制图像:

在此输入图像描述

and I'm trying to see if a 100x150 rectangle will fit in any blank space on the map. 我试图看看100x150矩形是否适合地图上的任何空白区域。 I tried creating a rectangular strel & then eroding & dilating the picture to get rid of any areas smaller than needed: 我尝试创建一个矩形strel然后侵蚀和扩大图片,以摆脱任何小于所需的区域:

se = strel('rectangle',[150, 100]);
BW = imerode(BW,se);
BW = imdilate(BW,se);

Unfortunately, it finds a hole prematurely 不幸的是,它过早地发现了一个洞

在此输入图像描述

which is only 80x150. 这只是80x150。 I think the erosion is failing since it's against the wall & only needs half the width, but don't know how to fix it. 我认为侵蚀是失败的,因为它靠墙而且只需要宽度的一半,但不知道如何修复它。

Also, if I'm headed down the wrong path, please feel free to set me straight. 而且,如果我走错了路,请随意让我直截了当。 Ultimately, I just need to find the upper-left corner of the a blank space at least as big as 100x150. 最后,我只需要找到一个空白区域的左上角至少大到100x150。

The approach below works quite well and runs fairly quickly. 以下方法运行良好,运行速度相当快。 It has a few nested loops but you can probably further optimize the performance, I mainly just wanted to get it working for you. 它有一些嵌套循环,但你可以进一步优化性能,我主要是想让它适合你。 Keep in mind though that if you comment out the fprintf() and the plotting command, that will speed things up. 请记住,如果你注释掉fprintf()和绘图命令,那将会加快速度。

I downloaded your image from your Stack post but I believe that my downloaded version has a different size (398x398) than the raw data you are working with, so keep that in mind when viewing my results below. 我从您的Stack帖子下载了您的图片,但我相信我下载的版本与您使用的原始数据的大小不同(398x398),因此在查看下面的结果时请记住这一点。

As indicated in the code, you supply the width (w) and height (h), the algorithm then returns all of the (col, row) positions where the rectangle can fit. 如代码中所示,您提供宽度(w)和高度(h),然后算法返回矩形可以适合的所有(col,row)位置。

Side Note: I believe this provides a solution to a 2D version of the Bin packing problem , but I'm not sure about that, you can check out the link above if thats of interest to you. 附注: 我相信这提供了二维包装问题的2D版本的解决方案,但我不确定,您可以查看上面的链接,如果你感兴趣的话。

Either way, its a great example of computational problem where an exhaustive search can be a carried out rather quickly. 无论哪种方式,它都是计算问题的一个很好的例子,其中穷举搜索可以相当快地执行。

To verify the results, I added simple plotting of the rectangles. 为了验证结果,我添加了矩形的简单绘图。 Keep in mind that if the rectangle fits in more than one position, a plot of the multiple rectangles begins to look rather jumbled as they are drawn repeatedly on top of one another (with offsets). 请记住,如果矩形适合多个位置,多个矩形的图形开始看起来相当混乱,因为它们被重复绘制在彼此之上(具有偏移)。

As an example case where only a single rectangle is found, I use: w = 29; h = 102; 作为仅找到一个矩形的示例情况,我使用: w = 29; h = 102; w = 29; h = 102; and then the result shows that the only position where this particular rectangle can fit, has the upper left corner = (row = 295, col = 368) (this rectangle size will likely only work for my downloaded version of your data): 然后结果显示该特定矩形可以适合的唯一位置,左上角= (row = 295, col = 368) (此矩形大小可能仅适用于我下载的数据版本):

在此输入图像描述

In summary, I first I load the data and then convert to a binary map (0's and 1's): 总之,我首先加载数据,然后转换为二进制映射(0和1):

% Note: '0' = black; '1' = white
data = round(im2double(rgb2gray(imread(filepath))));
figure(1);imshow(data); set(gcf,'Color',[1 1 1]);
hold on;

Input the search width and height: 输入搜索宽度和高度:

w = 29;
h = 102;

sze = size(data);
numRows = sze(1);
numCols = sze(2);

Next we just do a search to see what will fit at each row and col position: 接下来我们只是搜索一下,看看每个行和col位置的适合度:

for col = 1:numCols - w - 1
    for row = 1:numRows - h - 1
        doesFit = fitshere(data, row,col, w, h);
        if (doesFit == 1)
            fprintf('row = %d; col = %d \n',row,col);
            colX = [col col+w col+w col col];
            colY = [row row row+h row+h row];
            line(colX,colY,'Color','r','linewidth',2);
        end
    end
end

hold off;

You will need the following function to check if a given rectangle can fit in the array: 您将需要以下函数来检查给定的矩形是否适合数组:

function [val] = fitshere(data, row, col, w, h)
val = 1;
for i = col:col + w
    for j = row:row + h
        if (data(j,i) == 0) % if this is true, we are in the black!
            val = 0;
            return;
        end
    end
end
return;

If your interested in knowing if your rectangle will fit at all (say either width X height or height X width ), you can simply repeat the search after swapping the width and height. 如果您有兴趣知道矩形是否适合(例如width X heightheight X width ),您可以在交换宽度和高度后重复搜索。

Hope this helps. 希望这可以帮助。

lets do this with some matlab idioms 让我们用一些matlab习语来做这件事

M=binaryImage;
sz=size(M);
nrows = 100;
ncols = 150 ;

colsum = cumsum(M,1);
cols_are_good = colsum(nrows+1:end,:)-colsum(1:end-nrows+1,:)==0; 
    %  nrows empty rows below this point. in this column
rows_are_also_good = cols_are_good(:,ncols+1:end)-cols_are_good(:,1:end+1-ncols)==0;

and Bob's your uncle, that last variable contains 1 in all places that have nrows below them clear and each of those has ncols to the side 鲍勃是你的叔叔,最后一个变量在所有地方都有1个,它们下方有明显的颜色,每个都有ncols到一边

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM