我想在图像中检测边缘(具有子像素精度),如下所示:
分辨率约为600 X 1000。
我遇到了Mark Ransom here的评论,其中提到了垂直边缘的边缘检测算法。我还没有遇到任何问题。在我的情况下是否有用(因为边缘不是严格的直线)?但它始终是一个垂直边缘。我希望它至少精确到像素的1/100。我还希望能够访问这些子像素坐标值。
我曾尝试过Agustin Trujillo-Pino的"Accurate subpixel edge location"。但这并没有给我一个持续的优势。
还有其他可用的算法吗?我将使用MATLAB。
我附上了算法必须处理的另一个类似图像:
任何意见都将受到赞赏。
谢谢。
编辑:
我想知道我是否可以这样做: 在MATLAB中应用Canny / Sobel并获取此图像的边缘(请注意,它不是连续的线)。然后,以某种方式插入此Sobel边缘并获得子像素中的坐标。有可能吗?
答案 0 :(得分:4)
一种简单的方法是垂直投影图像,并使用适当的函数拟合投影轮廓。
这是一个尝试,atan
形状:
% Load image
Img = double(imread('bQsu5.png'));
% Project
x = 1:size(Img,2);
y = mean(Img,1);
% Fit
f = fit(x', y', 'a+b*atan((x0-x)/w)', 'Startpoint', [150 50 10 150])
% Display
figure
hold on
plot(x, y);
plot(f);
legend('Projected profile', 'atan fit');
结果:
我的第一张图片得到x_0 = 149.6像素。
但是,我怀疑你能用这些图像实现1/100像素的亚像素精度,原因如下:
正如您在个人资料中看到的那样,您的白人已经饱和(灰度等级为255)。当您剪切真实的atan
个人资料时,拟合是有偏见的。如果您可以控制实验,我建议您再次使用较小的曝光时间再次进行实验。
转换的点数不多,因此关于转换的位置信息并不多。通常,您的分辨率将是atan
宽度的平方根(或您喜欢的任何形状)。在这种情况下,这将子像素分辨率限制为像素的1/5。
最后,你的边缘不是严格垂直的,它们略微标题。如果您选择使用此投影方法,为了提高精度,您应该在投影前寻找纠正此倾斜的方法。但这并不会使你的准确度提高几个数量级。
最佳,
答案 1 :(得分:1)
您的图片存在问题。在像素级,似乎有四个隔行扫描子图像(奇数和偶数行和列)。看看这个zoomed area close to the edge。
为了避免这种伪影,我只是采用图像的偶数行和列,并计算子像素边缘。最后,我使用函数clsq寻找最合适的直线,其函数为this page:
%load image
url='http://i.stack.imgur.com/bQsu5.png';
image = imread(url);
imageEvenEven = image(1:2:end,1:2:end);
imshow(imageEvenEven, 'InitialMagnification', 'fit');
% subpixel detection
threshold = 25;
edges = subpixelEdges(imageEvenEven, threshold);
visEdges(edges);
% compute fit line
A = [ones(size(edges.x)) edges.x edges.y];
[c n] = clsq(A,2);
y = [1,200];
x = -(n(2)*y+c) / n(1);
hold on;
plot(x,y,'g');
执行此代码时,您可以看到最适合所有边缘点的绿线。该线由等式c + n(1)* x + n(2)* y = 0
给出考虑到当仅拍摄偶数行和列时,此图像已缩放1/2,因此必须缩放右坐标。
此外,您可以尝试使用其他树子图像(imageEvenOdd,imageOddEven和imageOddOdd)并组合四条直线以获得最佳解决方案。