Сравнение неправильной формы между двумя входными данными

Я пытаюсь придумать систему оценки для некоторых исследований в области поведенческой психологии.

Я прошу людей нарисовать букву, а затем обвести ее, как на графическом планшете. Я хочу оценить точность этой трассировки. Итак, вы рисуете любую букву («а»), затем делаете это снова, затем я оцениваю ее в зависимости от того, насколько она была похожа на первую, когда вы ее нарисовали. Рисунки хранятся в виде пиксельных местоположений.

Точность оценивается как близость к исходному письму. Этот метод не требует изменения масштаба, поворота или положения. Концептуально это похоже на область между двумя линиями, только линии очень неправильные, поэтому интегралы (насколько мне известно) не работают.

Я пишу в 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);

person dgmp88    schedule 06.02.2012    source источник
comment
в чем проблема с методом, который вы уже описали? (сумма кратчайших расстояний)   -  person Ali    schedule 06.02.2012
comment
Одна точка может иметь очень высокую оценку, так как есть только одно значение, для которого можно найти кратчайшее расстояние. Например. представьте себе точку в центре круга - сумма кратчайших расстояний будет небольшой, что означает хороший результат, когда на самом деле это довольно плохой след.   -  person dgmp88    schedule 06.02.2012


Ответы (5)


Вам может помочь преобразование расстояния, реализованное в MATLAB как bwdist. Это вознаграждает близкие линии, даже если они не совпадают.

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

введите здесь описание изображения

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

введите здесь описание изображения

Вы можете сделать то же самое со вторым изображением и суммировать разницу в значениях пикселей в изображениях с преобразованием расстояния, например:

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

(Обратите внимание, что это даст более высокие баллы менее похожим изображениям и v.v.)

Чтобы помочь предотвратить проблемы, о которых вы говорите как о «хороших (низких) оценках для хорошо расположенных одиночных точек», вы можете поэкспериментировать с другими мерами расстояния, такими как квадрат расстояния между значениями пикселей.

person Bill Cheatham    schedule 06.02.2012
comment
Хорошо, я попробую реализовать это - спасибо! Моя единственная проблема с этим решением заключается в том, что оно довольно дорогое, учитывая, что «изображения» хранятся только в виде векторов. Извините, я думаю, что я не был так ясен - сравнение изображений может быть не лучшим тегом. Тем не менее, это может сработать, я попробую через мгновение после встречи. Ваше здоровье! (пытался проголосовать, но моя репутация еще не высока) - person dgmp88; 06.02.2012
comment
Вы имеете в виду, что они хранятся в виде векторных изображений, а не растровых файлов? В этом случае да, я уверен, что будут лучшие способы, чем этот ответ. - person Bill Cheatham; 06.02.2012
comment
Даже не изображения — это просто двухмерный вектор расположения пикселей, где перо коснулось графического планшета. - person dgmp88; 06.02.2012
comment
@ dgmp88 - нет проблем преобразовать это в изображение, учитывая размер планшета. - person Andrey Rubshtein; 06.02.2012
comment
В итоге я использовал эту основную идею, но изменил... Мое решение опубликовано как отдельный ответ - person dgmp88; 09.02.2012

Контексты форм — это мощный дескриптор функций, основанный на «полярных гистограммах» фигур. страница Википедии содержит подробную информацию, но вот — еще одна страница с дополнительной информацией (и хорошим наглядным объяснением техники), а также демонстрационный код MATLAB. Сопоставление букв было одним из первых применений этого метода, и демонстрационный код, на который я ссылаюсь, не требует преобразования векторов трассировки в изображения.

Более упрощенным методом может быть «различие изображений», определяемое как исключающее ИЛИ двух букв. Это потребует преобразования векторов трассировки в бинарные изображения. Что-то типа:

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

Наконец, если ваши векторы трасс имеют одинаковое количество точек или могут быть получены с помощью выборки, анализ Прокруста может быть полезен. Идея прокрустова анализа состоит в том, чтобы найти оптимальное линейное преобразование методом наименьших квадратов (вращение, перемещение и масштабирование) между двумя наборами точек. Качество соответствия между двумя наборами точек определяется «статистикой Прокруста» или другими мерами, такими как среднеквадратичное отклонение точек.

%# 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));
person reve_etrange    schedule 06.02.2012
comment
Хорошие идеи, спасибо! Однако одна проблема заключается в том, что я не хочу, чтобы инвариантность к различным преобразованиям, которые допускают прокрусты и контексты формы, - слишком маленький/большой/повернутый счет за ошибки. - person dgmp88; 07.02.2012
comment
Вы можете использовать procrustes(X,Y,'scaling',false) для отключения компонента масштабирования. Вы также можете напрямую использовать RMSD или SSE точек... - person reve_etrange; 07.02.2012
comment
спасибо, я проверю это и сравню с другой версией решения, предложенного Биллом Читэмом, над которым я сейчас работаю. - person dgmp88; 07.02.2012

Вы можете захотеть найти аффинное преобразование, которое будет соответствовать некоторому критерию ошибки, например, среднеквадратической ошибке. Таким образом, вы будете инвариантны к переводу и масштабированию. Или, если вы хотите оштрафовать перевод, вы также можете добавить стоимость перевода. (Мы могли бы помочь вам, если бы вы предоставили больше информации о том, какие функции вы считаете похожими или нет)

Теперь другое дело — эффективная реализация. Возможно, вам следует изучить регистрацию изображений. Я уверен, что это было сделано много раз.

person Memming    schedule 06.02.2012
comment
Инвариантность к переводу и масштабированию не важна. Концептуально, какой-то способ вычислить площадь между оригиналом и трассой был бы идеальным. Что-то вроде того, что вы видите, если вы используете инструмент заливки ведра в краске, для каждого места, где оригинал и трассировка отклоняются друг от друга, было бы идеально. Я рассмотрю аффинные преобразования и регистрацию изображений, ура! - person dgmp88; 06.02.2012

Это мое окончательное, слишком сложное решение, которое в основном использует метод Билла Читама. Спасибо за помощь!

% 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)));
person dgmp88    schedule 09.02.2012

На самом деле я бы предложил гораздо более высокоуровневое решение. Найдите алгоритм машинного обучения OCR, который возвращает какую-то уверенность. Или, если вы не уверены, проверьте расстояние между выходным текстом и фактическим.
Это похоже на человека, который наблюдает за почерком и пытается его понять. Чем выше уверенность, тем лучше результат.

person Andrey Rubshtein    schedule 06.02.2012
comment
Решение OCR кажется действительно высоким уровнем. Я уверен, что это сработает, но я надеюсь на более простое решение, поскольку я просто использую наборы местоположений пикселей для определения букв. Но да, мне, возможно, придется сделать это в конце :). - person dgmp88; 06.02.2012