我正在寻找缩放和旋转不变模板匹配的方法。我已经尝试过一些,但是它们对我的示例而言效果不佳,或者使它们永远无法执行。
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



将这2张图像与OpenCV的模板匹配功能匹配后,我得到了结果继续。

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

例如我的简单蓝图:



和我的模板



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

编辑:

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模板匹配,但是,如果尝试过,问题出在哪里?

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

我们去了:cvpr.uni-muenster.de/teaching/ss08/seminarSS08/downloads/…(德语文章)和这一个jprr.org/index.php/jprr/article/viewFile/355/148

嘿,我想这不是很多人都能理解德语。而且,您仍然没有说出自己到底有什么问题。

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

#1 楼

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

因此,我的建议是:


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




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

这里有一些Matlab代码供您开始-我编写了查找特定blob距离轮廓并为模板进行计算的部分:

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


评论


$ \ begingroup $
我猜这不适用于非封闭形状吗?还是我只是跳过形状中的这些“孔”。
$ \ endgroup $
– Arndt Bieberstein
2012年12月12日上午9:10

$ \ begingroup $
@ArndtBieberstein,是的,它仅适用于封闭形状。我想应该有一些方法可以扩展它。
$ \ endgroup $
– Andrey Rubshtein
2012-12-12 14:36

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



$ \ begingroup $
@ArndtBieberstein,非常好!完成后,也许您可​​以与我们分享结果。
$ \ endgroup $
– Andrey Rubshtein
2012年12月12日15:35

$ \ begingroup $
当然,该代码不是很好,也不是很有效,但它确实有效。我将其附在我的问题下方。它是用C#编写的(我正在使用EmguCV)
$ \ endgroup $
– Arndt Bieberstein
2012-12-12 15:42

#2 楼

根据IIT Madras的Anurag Mittal教授的演讲,这是我所知道的基本思想。

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


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

关于该对象的文章位于:基于多阶段轮廓的可变形对象检测。 >
另一方面,我认为SIFT应该可以工作,因为角检测算法可以在您那里的模板特征上工作。

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

就像基于对数极的傅里叶-麦林(Fourier-Mellin)Transfroms一样:由于变换的采样方式,它们导致信息丢失。

评论


$ \ begingroup $
这种方法听起来很有前途!我无法打开您的链接,但我用谷歌搜索了您的方法。我不知道SIFT SIFT不是完全旋转不变的!很好的答案! +1
$ \ endgroup $
– Arndt Bieberstein
2012-12-10 8:14

$ \ begingroup $
我几乎没有找到有关倒角距离及其工作原理的信息,对于那些也在搜索此距离的人,请尝试此链接。
$ \ endgroup $
– Arndt Bieberstein
2012年12月12日15:06

$ \ begingroup $
@Naresh SIFT对于平面外的大旋转不是旋转不变的。不在同一平面上。
$ \ endgroup $
–a-Jays
15年4月22日在6:57



#3 楼

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

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

想起来就像使用FD从数据库中进行图像或音乐检索一样。关于此的许多白皮书。

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

,看看它们如何FD参数化苹果周边检测?就像您的门一样。

顺便说一句,我敢肯定,将整个原理图映射到极坐标不会帮助旋转不变性-您需要对每个门的质心进行处理,即确切地说,您的问题是从什么开始的。这就是为什么我认为您只想捕获门的候选对象,然后将其映射到极坐标以与FD门模板匹配的原因,就像上面链接的论文中所做的那样。如果您尝试这种方法,请告诉我。

#4 楼

也许您会发现我编写的该Matlab代码有用:坚固性比我发现的传统方法好。