Matlab 两个输入之间的不规则形状比较

Matlab 两个输入之间的不规则形状比较,matlab,image-comparison,Matlab,Image Comparison,我想为一些行为心理学研究建立一个评分系统 我让人们画一封信,然后在它上面画一条线,都是在图形板上。我想评估一下这个痕迹的准确性。所以,你画任何一个字母('a'),然后你再画一次,然后我根据它与你第一次画它的相似程度给它打分。图形存储为像素位置 准确度评估为与原始信函的接近程度。该方法不需要考虑缩放、旋转或位置变化。从概念上讲,它就像两条直线之间的区域,只有直线是高度不规则的,所以积分(据我所知)不起作用 我是用MATLAB写的,但任何概念上的帮助都将不胜感激。我已经尝试将绘制的所有像素之间的最小

我想为一些行为心理学研究建立一个评分系统

我让人们画一封信,然后在它上面画一条线,都是在图形板上。我想评估一下这个痕迹的准确性。所以,你画任何一个字母('a'),然后你再画一次,然后我根据它与你第一次画它的相似程度给它打分。图形存储为像素位置

准确度评估为与原始信函的接近程度。该方法不需要考虑缩放、旋转或位置变化。从概念上讲,它就像两条直线之间的区域,只有直线是高度不规则的,所以积分(据我所知)不起作用

我是用MATLAB写的,但任何概念上的帮助都将不胜感激。我已经尝试将绘制的所有像素之间的最小距离求和,但这会给位置良好的单点提供良好(较低)的分数

这肯定是以前做过的,但我的搜索没有任何运气

---使用下面@Bill建议的方法进行部分解决。不起作用,因为bwdist坡度太陡。比尔展示的不是第二张漂亮的照片,它看起来更像原作

%% 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);
%%字母到图像
im=零(10801920,3);%屏幕(可能的像素位置)
%一个有点像字母“A”的小正方形,几个像素宽。
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;
子批次(2,1,1);imagesc(im);%%atransbw=bwdist(im(:,:,1)可以帮助您的是a,在MATLAB中实现为。这会奖励线接近,即使它们不匹配

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

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


有助于防止您提到的“好(低)分到好(低)分”的问题,您可以尝试其他距离度量,例如像素值之间的平方距离。

您可能希望找到一个仿射变换,该变换将与某些误差标准相匹配,例如均方误差。这样,您将对平移和缩放保持不变。或者,如果您想惩罚平移,您可以增加平移的成本离子也可以(它会帮助我们帮助你,如果你提供更多的信息关于什么样的特征考虑类似或其他)
现在,高效的实现是另一个问题。也许你应该研究一下图像注册。我相信这已经做了很多次了。

我实际上会建议一个更高级的解决方案。找到一个OCR机器学习算法,返回某种信心。或者,如果你没有信心,测试两者之间的距离输出文本和实际值。

这就像是一个人观察笔迹并试图理解它。可信度越高,结果越好。

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

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

score = sum( abs( a_img_1_dist_transform(:) - a_img_2_dist_transform(:) ) )
x = xor(im1,im2);
d = sum(x(:)) / sum(im1(:)); %# normalize to the first image
最后,如果轨迹向量具有相同数量的点,或者可以通过采样进行调整,则Procrustes分析可能会很有用。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));

这是我最后一个过于复杂的解决方案,它基本上使用了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)));

您已经描述的方法有什么问题?(最短距离的总和)一个点可以得到很高的分数,因为只有一个值可以找到最短距离。例如,想象一个圆心上的点-最短距离之和很小,这意味着分数很高,而实际上这是一条很差的轨迹。好的,我会尝试实现它-谢谢!我唯一的问题是这个解决方案很简单考虑到“图像”仅存储为矢量,这可能会很昂贵。抱歉,我想我不是很清楚-图像比较可能不是最好的标记。不过,这可能会起作用,我会在会议后稍后再试。干杯!(尝试投票,但我的代表还不高)你的意思是它们存储为矢量图像,而不是光栅文件吗?在这种情况下,是的,我肯定有比这个答案更好的方法。甚至不是图像-它只是笔接触图形平板电脑的像素位置的二维矢量。@dgmp88-根据平板电脑的大小将其转换为图像没有问题。我同意d开始使用这个基本的想法,但是修改了…我的解决方案作为一个单独的答案发布,平移和缩放不变性并不重要。从概念上讲,某种计算原始和轨迹之间面积的方法是完美的。就像你在绘画中使用桶填充工具时看到的那样,对于原始和轨迹所在的每个地方跟踪彼此偏离,这将是完美的。我将研究仿射变换和图像注册,干杯!OCR解决方案似乎真的很高级。我相信它会起作用,但我希望有一个更简单的解决方案,因为我只是使用像素位置集合来定义字母。但是,是的,我最终可能不得不这么做:)。好主意,谢谢!但有一个问题是我不希望procrustes和形状上下文允许的各种变换的不变性-太小/太大/旋转算作错误。你可以使用
procrustes(X,Y,'sc
% 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)));