Сплайн MATLAB: оценка по оси Y

См. иллюстрацию на этом графике: before . Две красные кривые интерполируются с использованием функции сплайна дважды. Теперь мне нужно найти сдвиг по горизонтали, который совместит синие точки с двумя красными кривыми. Результат должен выглядеть так: after .

Можно ли найти координаты x, которые принадлежат некоторым заданным координатам y для сплайна? Тогда это можно было бы решить очень просто.

Изменить: простое изменение осей x и y не помогает, потому что сплайн не дает красивой кривой для одной из двух кривых.

Edit2: я забыл упомянуть, что время важно. Я ищу очень быстрое решение.


person Derk    schedule 25.10.2012    source источник
comment
Вы уже задавали этот вопрос: stackoverflow.com/questions/12857108/   -  person nibot    schedule 26.10.2012


Ответы (1)


Пусть xBlue и yBlue будут координатами синих точек (векторы размером n на 1), а yRedFun будет функцией аппроксимации сплайна, поэтому yRedFun(x) вернет интерполированную красную линию в точке x. Например. yRedFun может быть дескриптором анонимной функции @(x) ppval(pp,x) . Возможно, вам потребуется немного экстраполировать красную линию, чтобы yRedFun определялся для всех xBlue .

Теперь мы можем определить функцию минимизации:

cost = @(deltaX) norm( yBlue - arrayfun(yRedFun, xBlue + deltaX) )

Его минимум можно найти с помощью deltaX = fminsearch(cost, 0) или deltaX = fzero(cost, 0).

Хотя это может быть слишком общий подход, если высокая производительность не требуется, все должно быть в порядке. Кроме того, поскольку соответствие между синим и красным, вероятно, неточное, метод формализует норму, которую вы пытаетесь минимизировать.


Если требуется производительность, можно использовать следующий алгоритм:

function deltaX = findDeltaX(xBlue, yBlue, yRedFun, precision)
    deltaX = 0;         % total delta
    deltaDeltaX = Inf;  % delta at each iteration
    yRedFunDer = fnder(yRedFun);

    while(abs(deltaDeltaX) > precision)
        xRed = xBlue + deltaX;
        yRed = fnval(yRedFun, xRed);
        yRedDer = fnval(yRedFunDer, xRed);

        deltaDeltaX = yRedDer \ (yRed - yBlue);

        deltaX = deltaX + deltaDeltaX;
    end
end

Точки с низкой производной могут снизить точность. На первой итерации вы можете выбрать N точек с наивысшей производной и отбросить все остальные. Это также повысит производительность.

[~, k] = sort(abs(yRedDer), 'descend');  
k = k(1:N);  
yRedDer = yRedDer(k);
xBlue = xBlue(k);  
yBlue = yBlue(k);  
person VBel    schedule 26.10.2012
comment
Спасибо за ответ, однако в данном случае нужна высокая производительность :). Цель состоит в том, чтобы сделать это примерно за 1 мс. - person Derk; 26.10.2012
comment
Еще раз спасибо, но эта строка fnder(yRedFun) выдает ошибку??? Ошибка при использовании ==> fn2fm в 62 Ввод не является функцией Ошибка в ==> fnder в 33, если ~isstruct(f), f = fn2fm(f); конец - person Derk; 26.10.2012
comment
Попробуйте использовать вывод вашего сплайна как yRedFun, а не, как я сказал в начале, как @(x) ppval(pp,x) (т.е. используйте сам pp или как-то так, как выглядит описание вашего сплайна). - person VBel; 27.10.2012