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;
}
#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门模板匹配的原因,就像上面链接的论文中所做的那样。如果您尝试这种方法,请告诉我。
评论
欢迎来到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)