如何调整fminunc的初始步骤?

时间:2012-01-22 05:26:30

标签: matlab

我需要通过平移和旋转将两个图像转换为另一个图像。为此,我有这样的功能:

function [differences] = cost_function(transformation)

disp(transformation);

offset_x = transformation(1); % one of the images will be shifted by these many
offset_y = transformation(2); % pixels in either direction
angle    = transformation(3); % and rotated by this much

% snip:
%   * transform the second image
%   * otsu treshold both
%   * xor the results
%   * count pixels that xored

然后我试着找到它的最小值!

best_transform = fminunc(@cost_function, [0 0 0]);

然而,求解器日志显示了一个非常大的问题:

  1.0e-007 *
    0.1490         0         0
  1.0e-007 *
         0    0.1490         0
  1.0e-007 *
         0         0    0.1490
         0         0         1
    0.0000         0    1.0000
         0    0.0000    1.0000
         0         0    1.0000
         0         0    0.3333
    0.0000         0    0.3333

求解器试图在每个维度上微微移动以找到最佳线条,但显然将图像移动0.1490像素确实没有太大作用,而将其移动0.1490弧度自然会做到。然而,我不知道0.1490实际来自哪里。

The documentation似乎没有给出建议。如何增加求解器的初始步骤?

2 个答案:

答案 0 :(得分:2)

fminunc旨在找到一个连续函数的最小值,正如您所指出的那样,这不是您的情况,因为更改像素数量会使图像移动无穷小的数量导致无结果。

您可以通过以愚弄 fminunc的方式正确扩展目标函数来解决此问题,使其相信您的功能确实是连续的。要实现这一点,只需将偏移参数乘以一个相当大的标量,例如:

offset_x = transformation(1)*1000; 
offset_y = transformation(2)*1000; 
angle    = transformation(3); 

并用同一组标量划分你的最终解决方案,以获得移动的像素数。

通常,即使您的问题没有出现不连续性问题,在非线性优化问题中正确缩放变量也是至关重要的。

答案 1 :(得分:0)

我目前有这个kludge:

best_score_so_far = 9999999999;
best_so_far = [0 0 0];
optimset('display', 'off', 'MaxIter', 100);
for dist = 1:1:10
    for angle = 0:2*pi/4/dist:2*pi
        x = cos(angle)*dist;
        y = sin(angle)*dist;
        disp([dist angle x y]); %heh
        [best, cost] = fminunc(@(angle)cost_function([x,y,angle]), 0);
        if(cost < best_score_so_far)
            best_score_so_far = cost;
            best_so_far = best;
        end
    end
end

......但是它很丑陋,超级慢,而且是一个kludge。