如何使用matlab检测图像中的多个符号实例

时间:2016-08-22 06:46:23

标签: matlab image-processing

我尝试使用this answer中提供的代码,使用与FFT匹配的模板检测符号(通过fft2

但是,代码只检测一个符号,但它没有检测到所有相似的符号。

代码已从链接的帖子改编而来,如下所示。

template=im2bw(imread(http://www.clipartkid.com/images/543/floor-plan-symb-aT0MYg-clipart.png)); 
background=im2bw(imread(http://www.the-house-plans-guide.com/images/blueprints/draw-floor-plan-step-6.png));

bx = size(background, 2); 
by = size(background, 1);
tx = size(template, 2); % used for bbox placement
ty = size(template, 1);
pos=[];
%// Change - Compute the cross power spectrum
Ga = fft2(background);
Gb = fft2(template, by, bx);
c = real(ifft2((Ga.*conj(Gb))./abs(Ga.*conj(Gb))));

%% find peak correlation
[max_c, imax]   = max(abs(c(:)));
[ypeak, xpeak] = find(c == max(c(:))); % Added to make code work
if ~isempty(ypeak) || ~isempty(xpeak)
 pos=position;

plot(xpeak,ypeak,'x','LineWidth',1,'Color','g');
rectangle('position',position,'edgecolor','b','linewidth',1, 'LineStyle', '-  ');
end

我如何使用上面的代码来检测多个符号,而不只是一个?

1 个答案:

答案 0 :(得分:1)

Amitay的评估是正确的。顺便说一句,您所采用的代码来自以下帖子:Matlab Template Matching Using FFT

该代码仅用于检测您指定的模板中的一个匹配项。如果您希望检测多个模板,您可以尝试各种方法,各自有其优点和缺点:

  1. 使用全局阈值,并且从交叉功率谱中,超过此阈值的任何值都认为存在匹配。
  2. 找出交叉功率谱中最大的相似度,并且距离此最大值有一定距离的任何内容都将被视为存在匹配。也许百分之一的距离,或一个标准偏差可能有效。
  3. 尝试对交叉功率谱中的唯一值进行直方图,并找出与模板明显不相关的值与相关值之间存在明显分离的点。我不会在这里为你实现这个,因为它要求我们查看你的图像然后通过检查直方图来找到阈值,所以我不会为你做那个。相反,你可以尝试前两种情况,看看它在哪里。
  4. 如果它们出现,你将不得不循环多个匹配,所以你需要遍历在图像中绘制矩形的代码。

    案例#1

    第一种情况非常简单。您所要做的就是修改find语句,以便不是搜索具有最大值的位置,而只需找到超过阈值的位置。

    因此:

    %% find peak correlation
    thresh = 0.1; % For example
    [ypeak, xpeak] = find(c >= thresh);
    

    案例#2

    这与第一种情况非常相似,但不是找到超过阈值的值,而是确定最大相似度值(已经完成),以及高于(1 - x)*max_val x的任何值的阈值是介于0和1之间的值,表示您希望远离最大值的百分比被视为匹配。因此,如果您希望距离最大值x = 0.05最多5%,那么阈值现在变为0.95*max_val。类似地,对于标准偏差,只需使用std函数找到它是什么,并确保将其转换为单个向量,以便您可以计算整个图像的值,然后阈值变为max_val - std_val其中std_val是相似度值的标准差。

    因此,对百分比比较做这样的事情:

    %% find peak correlation
    x = 0.05; % For example
    [max_c, imax] = max(abs(c(:)));
    [ypeak, xpeak] = find(c >= (1-x)*max_c);
    

    ...并为标准偏差比较执行此操作:

    std_dev = std(abs(c(:)));
    [max_c, imax] = max(abs(c(:)));
    [ypeak, xpeak] = find(c >= (max_c - std_dev));
    

    一旦你最终建立了这个,你会发现有多个匹配。现在,它是在图像顶部绘制所有检测到的模板的点。使用您“借用”代码的帖子,可以修改绘制检测到的模板的代码以绘制多个模板。

    你可以在下面这样做:

    %% display best matches
    tx = size(template, 2);
    ty = size(template, 1);
    hFig = figure;
    hAx  = axes;
    imshow(background, 'Parent', hAx);
    hold on;
    
    for ii = 1 : numel(xpeak)
        position = [xpeak(ii), ypeak(ii), tx, ty]; % Draw match on figure
        imrect(hAx, position);
    end