不规则形状比较

时间:2012-02-06 14:56:38

标签: matlab edge image-comparison

我正试图为一些行为心理学研究提出一个评分系统。

我要求人们在图形输入板上画一封信然后追踪它。我想评估这种痕迹的准确性。所以,你绘制任何字母('a'),然后你再做一次,然后我根据它与你第一次绘画时的相似程度得分。图纸存储为像素位置。

准确性被评估为与原始信件的接近程度。该方法不需要允许缩放,旋转或位置改变。从概念上讲,它就像是两条线之间的区域,只有线条非常不规则,所以积分(据我所知)不会起作用。

我在MATLAB写作,但任何概念上的帮助都会受到赞赏。我已经尝试对绘制的所有像素之间的最小距离进行求和,但这样可以得到良好(低)的分数,以获得良好的单点。

之前必须这样做,但我的搜索没有运气。任何帮助非常感谢!

---部分解决方案使用@Bill建议的方法。不起作用,因为bwdist渐变太陡。而不是Bill显示的漂亮的第二张图片,它看起来更像是原版。

%% Letter to image 
im = zeros(1080,1920,3); % The screen (possible pixel locations) 
% A small square a bit like the letter 'a', a couple of pixels wide. 
pixthick = 5; 
im(450:450+pixthick,[900:1100],:) = 1; 
im(550:550+pixthick,[900:1100],:) = 1; 
im([450:550],900:900+pixthick,:) = 1; 
im([450:570],1100:1100+pixthick,:) = 1;
subplot(2,1,1); imagesc(im); %% atransbw = bwdist(im(:,:,1)<0.5); subplot(2,1,2); 
imagesc(atransbw);

5 个答案:

答案 0 :(得分:3)

形状上下文是基于形状的“极坐标图”的强大特征描述符。 Wikipedia page是深入的,但here是另一个包含其他信息的页面(以及对该技术的良好直观解释),以及MATLAB demo code。匹配字母是该方法的原始应用程序之一,我链接到的演示代码不需要您将跟踪向量转换为图像。

更简单的方法可能是“图像差异”,定义为两个字母的异或。这需要将跟踪向量转换为二进制图像。类似的东西:

x = xor(im1,im2);
d = sum(x(:)) / sum(im1(:)); %# normalize to the first image

最后,如果您的跟踪向量具有相同的点数,或者可以通过采样进行,则Procrustes Analysis可能很有用。 Procrustes分析的想法是在两组点之间找到最小二乘最优线性变换(旋转,平移和缩放)。两个点集之间的拟合优度由“Procrustes统计量”或其他度量(如点的均方根偏差)给出。

%# Whatever makes sense;
%# procrustes needs N x 2 matrices with (x,y) coords for N points.
coords1 = [x1 y1];
coords2 = [x2 y2];

%# This sampling may be too naive.
n = max( size(coords1,1), size(coords2,1) );
coords1 = coords1(1:n,:);
coords2 = coords2(1:n,:);

%# d is sum-of-squares error
%# z is transformed coords2
%# tr is the linear transformation
[ d, z, tr ] = procrustes( coords1, coords2 );

%# RMS deviation of points may be better than SSE.
n = size(coords1,1);
rmsd = sqrt((sum((coords1(:) - z(:)).^2) / n));

答案 1 :(得分:2)

有什么可以帮到你的是distance transform,在MATLAB中用bwdist实现。即使它们不匹配,这种奖励线也很接近。

a_img_1 = imread('a.jpg');
imagesc(a_img_1);

enter image description here

a_img_1_dist_transform = bwdist( a(:, :, 1) < 250 );
imagesc(a_img_1_dist_transform);

enter image description here

您可以对第二张图像执行相同操作,并总结距离变换图像中像素值的差异,如:

score = sum( abs( a_img_1_dist_transform(:) - a_img_2_dist_transform(:) ) )

(请注意,这将为较少的相似图像和v.v提供更高的分数。)

为了帮助防止您提到的“良好(低分)到良好放置的单点”的问题,您可以尝试其他距离度量,例如像素值之间的平方距离。

答案 2 :(得分:1)

您可能希望找到一个与某些误差标准匹配的仿射变换,例如均方误差。这样,您将对翻译和缩放保持不变。或者如果你想惩罚翻译,你也可以增加翻译费用。 (如果您提供有关哪些功能类似或类似的更多信息,这将有助于我们帮助您

现在,有效的实施是另一回事。也许你应该看一下图像注册。我确信已经做了很多次。

答案 3 :(得分:1)

这是我最终的,过于复杂的解决方案,它基本上使用Bill Cheatham的方法。谢谢你的帮助!

% pixLet is the 2D vector contain locations where drawing occurred. First convert it to an image. 

im = zeros(1000,1000); % This is the image
for pix = 2:size(pixLet,1)
    y1 = pixLet(pix-1,2); x1 = pixLet(pix-1,1);
    y2 = pixLet(pix,2); x2 = pixLet(pix,1);
    xyd = round(pdist([x1 y1; x2 y2])*2);
    xs = round(linspace(x1,x2,xyd));
    ys = round(linspace(y1,y2,xyd));
    for linepix = 1:length(xs)
        im(ys(linepix),xs(linepix)) = 1;
    end
end

% Blur the image
blur = fspecial('gaussian',[sz sz],reach);
gausIm = conv2(im,blur,'same');

% I made a function of the above to do this for both the template and the trace.
score = sum(sum(abs(gausIm1-gausIm2)));

答案 4 :(得分:0)

我实际上建议使用更高级别的解决方案。找到一种返回某种置信度的OCR机器学习算法。或者,如果您没有信心,请测试输出文本与实际文本之间的距离 这就像一个观察手写并试图理解它的人。信心越高,结果越好。