【问题标题】:Removing unwanted characters in an organic molecule diagram去除有机分子图中不需要的字符
【发布时间】:2015-07-11 10:50:53
【问题描述】:

我有这张图片:

我想删除图像中不构成有机分子结构的所有部分。所以在这个特定的图像中,我想删除Process Aline below it。我尝试使用bwlabel 来获取连接的组件,但结构本身并没有形成一个单独的组件。因此,无法通过该方法移除。知道如何解决这个问题吗?

【问题讨论】:

  • 这个问题可能听起来很愚蠢,但是你想要的部分和你不想要的部分有什么区别呢?两者都是行和字符。也许检测垂直间隙(使用行总和)并在那里分割?也许使用 imero 连接两个黑色区域,然后用 bwlabel 分割?

标签: matlab image-processing computer-vision image-segmentation


【解决方案1】:

有两种方法可以解决这个问题,具体取决于您的偏好。

方法 #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);

我们得到这张图片:

注意事项

  1. 函数imclose 将使用strel 定义的结构元素为您执行形态闭合。我使用了一个 50 x 50 的正方形来确保我们有足够大的窗口来将相邻的对象像素连接在一起。
  2. 函数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);

您应该得到与第一种方法完全相同的结果。

【讨论】:

  • 非常感谢。我还有一个问题。通过 bwareapen,您正在删除像素区域低于 1000 的区域。有什么方法可以在关闭操作后找到每个区域的像素区域。这个是因为在大多数情况下我只需要最大的连接区域,所以如果我能得到每个连接区域的像素区域,我可以只取面积最大的区域
  • 啊,是的,你可以。给我一点修改我的答案。老实说,你的想法是我正在考虑的另一个想法,但我想尽快给你一个答案。
  • 事实上我尝试在closing 操作之后使用bwlabel 来获取连接的组件。使用第一个连接的组件然后我通过执行逻辑AND 得到我的原始图像。它恰好给出了正确的结果。但我不认为每次第一个组件都会是面积最大的组件。这就是为什么我想获得每个区域的面积
  • regionprops 与 Area 和 PixelIdxList 属性一起使用。
  • @Noober - 完成。看看吧。
【解决方案2】:

假设图像标题在空间上与“实际图像”分离得足够远:

通过模糊图像来构造 blob,找到连接的组件,取上/更大的一个(或其他一些取决于您的数据的启发式方法)。所以,在使用连通分量算法之前,先进行预处理:

  1. 高斯/中值滤波器(如果需要)和边缘检测。
  2. 二值化
  3. 形态学运算(腐蚀、膨胀)
  4. 使用启发式(大小/形状/位置)提取 Blob。

while 4. 是连接组件的替代品(这不是强制性的)。您可以在关键字blob extractiontext extraction 下搜索其他方法。这是您“在一般情况下”会做什么的粗略概述。哪些步骤能带来最佳解决方案取决于您的数据,因此您必须进行一些试验。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-06
    • 2017-11-23
    • 1970-01-01
    • 2013-05-14
    相关资源
    最近更新 更多