有两种方法可以解决这个问题,具体取决于您的偏好。
方法 #1 - 使用bwareaopen
实现此目的的一种廉价方法是反转图像,使对象像素为白色而不是黑色,然后对图像执行形态闭合并移除那些低于一定数量的区域。关闭会将不连接的区域连接在一起,并利用连接“结构”会生成一个面积较大的区域,您可以按每个区域的面积进行阈值并消除那些低于一定数量的区域。
然后您可以通过简单地使用反转图像和封闭结果执行逻辑AND 来取回原始图像,然后重新反转此中间结果。这样做的效果是我们只保留属于原始图像的像素,因为关闭操作人为地创建了对象像素。具体来说,结构的附近区域的连接将创建新的对象像素,因此执行AND 将确保那些与原始像素不同的像素被删除。由于这是在与原始结果相反的情况下执行的,因此重新反转可让您回到对象像素的原始域,即黑色而不是白色。
类似这样的:
%// Read in image from StackOverflow
im = imread('http://i.stack.imgur.com/A7iT7.png');
%// Invert image
im = ~im;
%// Define 50 x 50 structuring element and close the image
se = strel('square', 50);
out = imclose(im, se);
%// Remove regions whose areas fall below 10000 pixels
out = bwareaopen(out, 10000);
%// Remove out extraneous closing areas by ANDing with inverted image
%// then reinvert to bring back to original label scheme
out = ~(im & out);
%// Show the image
imshow(out);
我们得到这张图片:
注意事项
- 函数
imclose 将使用strel 定义的结构元素为您执行形态闭合。我使用了一个 50 x 50 的正方形来确保我们有足够大的窗口来将相邻的对象像素连接在一起。
- 函数
bwareaopen 接收二值图像并去除像素面积低于一定数量的区域。关闭后,您将有两个连接区域 - 图像的顶部带有结构,底部带有文本。通过实验,10000 像素去除了底部区域。
方法 #2 - 使用regionprops
与方法 #1 相关,执行此操作且与阈值无关的另一种方法是遵循您的原始想法。进行闭合操作,然后评估每个连接区域的面积并选择面积最大的区域。我建议在这种情况下使用regionprops,这是一个专门用于分析不同图像区域特征的函数。输出将是N 元素的结构,其中N 是图像中发现的唯一和连接对象的总数,每个结构都包含您要在图像中测量的属性字段。在您的情况下,指定 'Area' 和 'PixelIdxList' 属性,其中包含每个区域的区域和列主要像素位置。
您将找到总体上的最大区域并使用相应的像素位置并设置一个输出映射,您可以将其与 AND 进行逻辑运算。
类似这样的:
%// Read in image from StackOverflow
im = imread('http://i.stack.imgur.com/A7iT7.png');
%// Invert image
im = ~im;
%// Define 50 x 50 structuring element and close the image
se = strel('square', 50);
out = imclose(im, se);
s = regionprops(out, 'Area', 'PixelIdxList'); %// Apply regionprops
%// Find the region with the max area
[~,id] = max([s.Area]);
%// Create an output mask with the largest area
%// Make logical
out = false(size(im));
%// Set pixels from largest area
out(s(id).PixelIdxList) = true;
%// Rest of the logic from before
%// Remove out extraneous closing areas by ANDing with inverted image
%// then reinvert to bring back to original label scheme
out = ~(im & out);
%// Show the image
imshow(out);
您应该得到与第一种方法完全相同的结果。