MATLAB использует пользовательскую функцию с pdist
У меня есть пользовательская функция для расчета веса между двумя пикселями (которые представляют узлы на графике) изображения
function [weight] = getWeight(a,b,img, r, L)
ac = num2cell(a);
bc = num2cell(b);
imgint1 = img(sub2ind(size(img),ac{:}));
imgint2 = img(sub2ind(size(img),bc{:}));
weight = (sum((a - b) .^ 2) + (r^2/L) * abs(imgint2 - imgint1)) / (2*r^2);
где a = [x1 y1]
а также b = [x2 y2]
координаты, которые представляют пиксели изображения, img
это серое изображение и r
а также L
являются постоянными. Внутри функции imgint1
а также imgint2
серые интенсивности пикселей на a
а также b
,
Мне нужно рассчитать вес среди множества точек изображения.
Вместо двух вложенных циклов я хочу использовать функцию pdist, потому что она ПУТЬ БЫСТРО!
Например, пусть nodes
набор координат пикселей
nodes =
1 1
1 2
2 1
2 2
А также img = [ 128 254; 0 255]
, r = 3
, L = 255
Чтобы получить эти веса, я использую промежуточную функцию.
function [weight] = fxIntermediate(a,b, img, r, L)
weight = bsxfun(@(a,b) getWeight(a,b,img,r,L), a, b);
Для того, чтобы наконец получить весь набор весов
distNodes = pdist(nodes,@(XI,XJ) fxIntermediate(XI,XJ,img,r,L));
Но это всегда дает мне ошибку
Error using pdist (line 373)
Error evaluating distance function '@(XI,XJ)fxIntermediate(XI,XJ,img,r,L)'.
Error in obtenerMatriz (line 27)
distNodes = pdist(nodes,@(XI,XJ) fxIntermediate(XI,XJ,img,r,L));
Caused by:
Error using bsxfun
Invalid output dimensions.
РЕДАКТИРОВАТЬ 1
Это короткий пример моего кода, который должен работать, но я получил ошибку, упомянутую выше. Если вы скопируете / вставите код в MATLAB и запустите код, вы увидите ошибку
function [adjacencyMatrix] = problem
img = [123, 229; 0, 45]; % 2x2 Image as example
nodes = [1 1; 1 2; 2 2]; % I want to calculate distance function getWeight()
% between pixels img(1,1), img(1,2), img(2,2)
r = 3; % r is a constant, doesn't matter its meaning
L = 255; % L is a constant, doesn't matter its meaning
distNodes = pdist(nodes,@(XI,XJ) fxIntermediate(XI,XJ,img,r,L));
adjacencyMatrix = squareform(distNodes );
end
function [weight] = fxIntermediate(a,b, img, r, L)
weight = bsxfun(@(a,b) getWeight(a,b,img,r,L), a, b);
end
function [weight] = getWeight(a,b,img, r, L)
ac = num2cell(a);
bc = num2cell(b);
imgint1 = img(sub2ind(size(img),ac{:}));
imgint2 = img(sub2ind(size(img),bc{:}));
weight = (sum((a - b) .^ 2) + (r^2/L) * abs(imgint2 - imgint1)) / (2*r^2);
end
Моя цель - получить матрицу смежности, которая представляет расстояние между пикселями. Для приведенного выше примера желаемая матрица смежности имеет вид:
adjacencyMatrix =
0 0.2634 0.2641
0.2634 0 0.4163
0.2641 0.4163 0
1 ответ
Проблема в том, что вы не соответствуете ожиданиям для функции, которая будет использоваться с pdist
ни те, что для функции, которая будет использоваться с bsxfun
,
- из документации pdist
:
Функция расстояния должна иметь форму
d2 = distfun(XI,XJ)
принимая в качестве аргументов вектор XI 1 на n, соответствующий одной строке X, и матрицу XJ m2-на-n, соответствующую нескольким строкам X. distfun должен принимать матрицу XJ с произвольным числом строк. distfun должен возвращать вектор m2 на 1 расстояний d2, k-й элемент которых является расстоянием между XI и XJ(k,:).
Однако с помощью bsxfun
в fxIntermediate
эта функция всегда возвращает матрицу значений, размер которых больше размеров двух входных данных.
- из документации bsxfun
:
Бинарная поэлементная функция вида C = fun(A,B) принимает массивы A и B произвольного, но одинакового размера и возвращает выходные данные того же размера. Каждый элемент в выходном массиве C является результатом операции только с соответствующими элементами A и B. fun также должен поддерживать скалярное расширение, так что если A или B является скаляром, C является результатом применения скаляра к каждому элементу в другом входном массиве.
Тем не менее, ваш getWeight
кажется, всегда возвращает скаляр.
Я не понимаю вашу проблему достаточно хорошо, чтобы исправить это. Более того, я думаю, что если скорость - это то, что вам нужно, кормление pdist
с ручкой функции не путь. pdist
не выполняет магию; это только быстро, потому что его встроенные функции расстояния реализованы эффективно. Кроме того, вы используете анонимные функции для обработки и преобразования в и из массивов ячеек, которые замедляют процесс. Я думаю, что вы должны опубликовать новый вопрос, где вы начнете с описания того, что вы пытаетесь вычислить, включите некоторый код, который выполняет работу, даже если он неэффективен, и спросите, как его улучшить.