在 Matlab 中从图像中提取对象

Extract object from image in Matlab

我目前正在学习使用 Matlab 进行图像处理。我要做的是在下图中找到所有字母 a 并删除所有其余字母。

首先,我将图像转换为二进制图像。然后我尝试使用中值滤波器去除噪声。 tha a 的一些边框中有一些空白,我通过打开图像来填充这些空白。 但后来我陷入困境,我在互联网上发现了一些东西(我不完全理解),我可以用它们 select 所有 a 的差距。

接下来我该做什么?

我的代码如下:

text = imread('http://i.stack.imgur.com/N4nCm.png');
text = mat2gray(text);

% find threshold and chance to binary image
border = graythresh(text);
textbw = im2bw(text, border);
imshow(textbw);

% remove noise with median filter
textfilt = medfilt2(textbw);

% remove small holes in the border of the a
se = strel('disk', 4);
texter = imopen(textfilt, se);

% find holes
s = regionprops(texter, 'BoundingBox');
bb = round(reshape([s.BoundingBox], 4, []).');

% show original image with holes
imshow(textbw);

for idx = 1 : numel(s)
    rectangle('Position', bb(idx,:), 'edgecolor', 'red');
end

这是一个很好解决的问题。这是您可以使用的一种方法,但我承认它绝不是完美的,而且可能不那么健壮。希望它能给你一些想法...

我所做的基本上是使用中值过滤器过滤图像(就像您所做的那样)并使用 bwareaopen 删除小元素。然后我调用 regionprops 得到一堆属性,其中最重要的是 areaeccentricity。这个想法是所有字母 "a" 都应该有一些相似的偏心率,因此一旦我们知道一个字母的偏心率,我们就可以找到其他具有大致相同的字母。您可以使用使字母从其他字母中脱颖而出的其他属性来使代码更健壮;例如 MajorAxisLength/MinorAxisLength 的比率。我会把那部分留给你:)

所以在这种情况下,最简单的选择字母的方法是 select 面积最大的对象,也就是位于你的中心的大 a图片。一旦我们有了它的偏心率,我们就可以应用一些阈值和 select 只有那些使用 regionprops 找到的具有相似偏心率的对象。之前应用的中值滤波器和对 bwareaopen 的调用在这里很重要,因为右侧 4 个框中的噪声类型如果不删除它们会使事情变得复杂,因为一些随机点可能有偏心类似于我们亲爱的信 "a".

话虽这么说,这里是注释代码。请注意,我将 text 变量的名称更改为 textIm,因为 text 是一个 Matlab 函数。

clc
clear
close all

textIm = imread('http://i.stack.imgur.com/N4nCm.png');


%// find threshold and change to binary image
border = graythresh(textIm);

%// =========== NEW \ ===========
%// NOTICE the use of ~im2bw(...)
textbw = ~im2bw(textIm, border);

%// remove noise with median filter

%// =========== NEW \ ===========
textfilt = medfilt2(textbw,[7 7]);
textfilt = bwareaopen(textfilt,8);

%// =========== NEW \ ===========
%// Use an absurdely large line structuring element oriented at 25 degrees
%// to make the a's stand out

se = strel('line', 20 ,25);
textfilt = imclose(textfilt, se);

%// Get a couple properties. Note the "Eccentricity"
S = regionprops(textfilt, 'Area','Eccentricity','Centroid','BoundingBox');

All_areas = vertcat(S.Area);

%// Find the largest element (i.e. the big a). We will use it to get its
%// eccentricity and fetch other a's.

[MaxArea, MaxAreaIdx] = (max(All_areas(:)));

%// Get eccentricity of largest letter.
RefEcc = S(MaxAreaIdx).Eccentricity

这里大"a"的偏心率为0.6654。偏心率为0表示圆,偏心率为1表示直线

%// Just concatenate everything. Easier to work with.
All_Ecc = vertcat(S.Eccentricity);
All_Centroids = vertcat(S.Centroid);
All_BB = vertcat(S.BoundingBox)

%// Find elements that have the approximate eccentricity of the large a
%// found earlier. You can be more/less stringent and add more conditions here.

PotA = find(All_Ecc > RefEcc*.8 & All_Ecc < RefEcc*1.2)

%// Display output with centroids and bounding boxes.
imshow(textIm)
hold on

scatter(All_Centroids(PotA,1),All_Centroids(PotA,2),60,'r','filled');

for k = 1:numel(PotA)

rectangle('Position',All_BB(PotA(k),:),'EdgeColor','y','LineWidth',2)
end

然后输出,质心为红点,边界框为黄色矩形:

太有趣了!希望我能以某种方式提供帮助。您可能需要为其他字母调整代码,或者如果图像中有其他圆形对象,但我想这是一个开始。