比例和旋转不变模板匹配


12

我正在寻找缩放和旋转不变模板匹配的方法。我已经尝试过一些,但是对于我的示例来说,它们并没有那么好用,或者永远无法执行。SIFT和SURF特征检测完全失败。我还尝试实现Log-Polar模板匹配功能,但我从未完成(不知道确切的操作方法)。

在这些文章中(第一个是德语)

http://cvpr.uni-muenster.de/teaching/ss08/seminarSS08/downloads/Wentker-Vortrag.pdf

http://www.jprr.org/index.php/jprr/article/viewFile/355/148

我了解了该方法。绘制极坐标是可行的,但我不知道它是否正确。图片看起来像这样。

source_log_polar.png http://www.shareimages.com/images/pics/0/0/3/62394-pZSfl5WenZysnpyVnKg-source_log_polar.png

template_log_polar.png

在用OpenCV的模板匹配功能匹配这两个图像后,我得到了结果

match_log_polar.png

现在我不继续了。

我的模板始终是构建蓝图和蓝图本身的简单符号。这些符号的大小和方向可以不同。

例如我的简单蓝图:

在此处输入图片说明

还有我的模板

在此处输入图片说明

在此示例中,只有一个模板,但是在蓝图中,它应该找到所有出现的位置,甚至包括具有大小和/或方向的出现位置。

有谁有办法解决这个问题?

编辑:

对Andrey的方法的补充。径向轮廓的距离捕获算法。(使用EmguCV)

private float[] getRadialProfile( Image<Gray, byte> image, Point center, int resolution )
 {

 var roi = image.ROI;

 if ( !roi.Contains( center ) )
  {
   return null;
  }

 var steps = resolution;
 var degreeSteps = 360 / (double)resolution;
 var data = image.Data;
 var peak = 0.0f;
 var bottom = double.MaxValue;
 var bottomIndex = 0;
 var width = roi.Width;
 var height = roi.Height;
 var minX = roi.X;
 var minY = roi.Y;

 float[] distances = new float[resolution];
 for ( var i = 0; i < steps; i++ )
  {
   var degree = i * degreeSteps;
   var radial = degree * Math.PI / 180.0;
   var dy = Math.Sin( radial );
   var dx = Math.Cos( radial );

   var x = (double)center.X;
   var y = (double)center.Y;

   while ( true )
    {
    x += dx;
    y += dy;
    if ( x >= minX + width || y >= minY + height || x <= minX || y <= minY )
     {
      x = -1;
      y = -1;
      break;
     }
    var pixel = data[(int)y, (int)x, 0];
    if ( pixel == 0 )
     {
      break;
     }
    }

    float distance = 0.0f;
    if ( x != -1 && y != -1 )
    {
      distance = (float)Math.Sqrt( Math.Pow( (center.X - x), 2 ) + Math.Pow( (center.Y - y), 2 ) );
    }

    distances[i] = distance;
    if ( distance > peak )
    {
      peak = distance;
    }
    if ( distance < bottom )
    {
      bottom = distance;
      bottomIndex = i;
    }
   }

    // Scale invariance. Divide by peak
   for ( var i = 0; i < distances.Length; i++ )
   {
     distances[i] /= peak;
   }

    // rotation invariance, shift to lowest value
   for ( var i = 0; i < bottomIndex; i++ )
   {
     distances.ShiftLeft(); // Just rotates the array nothing special
   }

   return distances;
}

欢迎来到dsp.SE。我们将尽力为您提供帮助,但是提供更准确的信息将非常有用。SIFT和SURF“完全失败”是什么意思?他们检测/匹配了什么?另外,我个人不了解Log-Polar模板匹配,但是,如果尝试过,问题出在哪里?
penelope

SIFT和SURF特征检测未在模板图像中找到任何特征。看来模板的信息太少了(只是那小小的弓和一条线)。对于Log-Polar匹配,我找到了描述的论文,但没有确切的数学描述。我将其搜索并添加。
Arndt Bieberstein


嘿,我想这不是很多人都能理解德语。:D但是,对于其他所有事情:您可以编辑自己的帖子以在适当的位置添加任何新信息,而不必在评论中添加。而且,您仍然没有说出您确实有什么问题。
penelope

3
“德语文章”的作者有英文文章-www-cs.engr.ccny.cuny.edu/~wolberg/pub/icip00.pdf(感谢Google)
SergV 2012年

Answers:


6

我认为您可以轻松得多地解决问题。考虑到您正在处理蓝图,您不必担心边缘连接性,噪声以及SIFT和SURF可以容纳的许多其他问题。您的模板是带有特定边缘形状的空心形状。

因此,我的建议是:

  • 围绕周边走一圈,找到围绕模板中心的边缘距离的分布图。这是模板的径向轮廓。除以最大距离,即可成比例不变。旋转矢量,以使最小距离为第一距离,成为旋转不变的。(如果您的模板没有主导距离,则可以稍后更改第2步)

在此处输入图片说明

  • 查找图像中的斑点。计算第(1)部分所述的径向轮廓,并通过归一化相关性比较两个向量。如果您的模板没有主导距离,则相关将变为归一化互相关,并选择最大值。那些通过某个阈值的人被视为比赛。

这是一些Matlab代码,供您开始-我编写了查找特定斑点的距离轮廓并为模板计算出来的部分:

function Doors
    im = imread('http://i.stack.imgur.com/Tf8EV.png');
    im = im(:,:,1);
    template = imread('http://i.stack.imgur.com/PlP4i.png');
    template = template(:,:,1);

    blobs = regionprops(template>0,'Area','Image');
    largestBlob = GetLargestBlob(blobs);
    [prof,edgeImage] = GetBlobRadialProfile(largestBlob);

    figure;
    subplot(1,2,1);plot(prof); title('Radial profile')
    subplot(1,2,2);imshow(edgeImage); title('Template');

end

function [prof,edgeImage] = GetBlobRadialProfile(blob)
    paddedImage = padarray( blob.Image,[8 8]);
    erodedImage = imerode(paddedImage,strel('disk',1));
    edgeImage = xor(erodedImage,paddedImage);

    c = regionprops(paddedImage,'Centroid');
    cx  = c.Centroid(1);
    cy  = c.Centroid(2);

    [y,x] = find(edgeImage);
    rad = (x(:)-cx).^2 + (y(:)-cy).^2;
    [~,minIndex] = min(rad);
    contour = bwtraceboundary(edgeImage, [y(minIndex), x(minIndex)],'N');
    prof = (contour(:,2)-cx).^2 + (contour(:,1)-cy).^2;
    prof = prof./max(prof);
end

function largestBlob = GetLargestBlob(blobs)    
    area = [blobs.Area];
    [~,index] = max(area);
    largestBlob = blobs(index);
end

我猜这不适用于非封闭形状吗?还是我只是跳过形状中的这些“孔”。
Arndt Bieberstein

@ArndtBieberstein,是的,它仅适用于封闭形状。我想应该有一些方法可以扩展它。
Andrey Rubshtein 2012年

由于OpenCV不包含bwtraceboundary函数,所以我编写了自己的函数,只是“跳过”了孔并填充了零。这是一个小例子,结果现在看起来如何。每个模板5个图。红点是起点。样地
Arndt Bieberstein

@ArndtBieberstein,非常好!完成后,也许您可​​以与我们分享结果。
Andrey Rubshtein 2012年

当然,该代码虽然不那么出色或性能出色,但确实有效。我将其附在我的问题下方。它是用C#语言编写的(我使用的是EmguCV)
Arndt Bieberstein

3

以下是IIT Madras教授Anurag Mittal教授的演讲,这是我所知道的基本知识。

这个想法是基于形状的对象检测,但是显然也可以扩展到其他地方。

  1. 使用Berkeley边缘检测器计算edgels。
  2. 连接获得的边缘。“全局对象边界检测”。
  3. 使用倒角距离或Houstoff距离进行形状匹配。

有关此问题的论文,可参见:基于多阶段轮廓的可变形物体检测。

另一方面,我认为SIFT应该可以工作,因为拐角检测算法可以在您那里的模板特征上工作。

注意:SIFT并不是完全旋转不变的。它无法应对大于60度的旋转。因此,形成多个模板是一个好主意。

就像基于对数极点的傅里叶-麦林(Fourier-Mellin)变换一样:由于变换是如何进行采样的,因此它们会导致信息丢失。


这种方法听起来真的很有希望!我无法打开您的链接,但是我用谷歌搜索了您的方法。我不知道SIFT SIFT不是完全旋转不变的!很好的答案!+1
Arndt Bieberstein

1
我几乎没有发现关于倒角距离什么,它是如何工作的,对于那些谁也搜索出该试试这个链接。
Arndt Bieberstein

@Naresh SIFT不是旋转不变的大旋转平面的。不在同一平面上。
2015年

1

我没有考虑太多,但是我敢肯定,使用经典的傅里叶描述符(FD)可以拥有一个健壮的解决方案,而不会遇到很多麻烦。我认为您的问题可能是一个很好的选择。不要以为您有黑线图就可以进行边缘检测。只需开始光栅扫描,直到碰到任何像素,然后执行以下操作:

只需将您的房间周长视为一维信号即可,其中信号幅度是距对象质心的正常距离,以一定的稳定速率进行采样。因此,为门做一个简单的FD模型。然后,使用某种凸过滤器扫描每个房间的参数,以查找上升沿,峰值和下降沿,从而设置要捕获的“信号”的开始/停止窗口。对捕获的“信号”执行FFT或类似的FD算法,并与FD模板进行比较。模板比较步骤可能是与阈值进行触发的简单关联。由于只有您的门具有圆形边缘,这应该是一个非常容易的FD匹配问题。

可以将其视为使用FD从数据库中进行图像或音乐检索的方式。关于此的许多白皮书。

这是有关使用FD近似形状的很好的教程: 我怀疑您会需要它,但您也可以首先将图像转换为极坐标框架来处理旋转,如本文中所建议的: 使用基于形状的图像检索通用傅里叶描述符

看看他们如何FD参数化苹果周边检测?像您的门一样的想法。

顺便说一句,我很确定将整个原理图映射到极坐标不会帮助旋转不变性-您将需要对每个门的质心进行此操作,这正是您要解决的问题。这就是为什么我认为您只想捕获门的候选对象,然后将它们映射到极坐标以与FD门模板匹配的原因,就像上面链接的论文中所做的那样。

让我知道如何尝试这种方法。


0

也许您会发现我编写的该Matlab代码很有用: 分形马赛克

它在艺术应用程序中实现了论文“使用对数-极性变换进行稳健的图像配准”(pdf),该应用程序比我发现的传统方法需要更强的鲁棒性。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.