用于光纤对准的傅里叶变换

时间:2016-03-04 15:21:35

标签: matlab image-processing fft

我正在开发一个应用程序,用于从图像中确定光纤网络的对齐程度。我已经阅读了几篇关于这个问题的论文,他们基本上都是这样做的:

  1. 查找图像的2D离散傅里叶变换(DFT = F(u,v))(灰色,范围0-255)
  2. 查找傅里叶谱(FS = abs(F(u,v)))和功率谱(PS = FS^2
  3. 将光谱转换为极坐标并将其划分为1º间隔。
  4. 计算每个区间(FI)的数字平均线强度(theta),即相对于水平轴形成“θ”度的所有强度(像素)的平均值
  5. 将FI(theta)转换为笛卡尔坐标

    Cxy(theta) = [FI*cos(theta), FI*sin(theta)]

  6. 查找矩阵lambda1

  7. 的特征值(lambda2Cxy'*Cxy
  8. 查找对齐索引为alpha = 1 - lamda2/lambda1
  9. 我已经在MATLAB中实现了这个(下面的代码),但是我不确定它是否正常,因为第3点和第4点对我来说并不是很清楚(我得到的结果与论文相似,但是并非在所有情况下)。例如,在第3点,“频谱”是指FS或PS?。在第4点,这个平均值应该如何完成?考虑所有像素? (即使对角线上有更多像素)。

    rgb = imread('network.tif');%513x513 pixels
    im = rgb2gray(rgb);
    im = imrotate(im,-90);%since FFT space is rotated 90º
    FT = fft2(im) ;
    FS = abs(FT); %Fourier spectrum
    PS = FS.^2; % Power spectrum
    FS = fftshift(FS);
    PS = fftshift(PS);
    
    xoffset = (513-1)/2;
    yoffset = (513-1)/2;
    
    % Avoid low frequency points
    x1 = 5;
    y1 = 0;
    
    % Maximum high frequency pixels
    x2 = 255;
    y2 = 0;
    
    for theta = 0:pi/180:pi
        % Transposed rotation matrix
        Rt = [cos(theta) sin(theta); 
             -sin(theta) cos(theta)]; 
    
        % Find radial lines necessary for improfile
        xy1_rot = Rt * [x1; y1] + [xoffset; yoffset]; 
        xy2_rot = Rt * [x2; y2] + [xoffset; yoffset];
    
        plot([xy1_rot(1) xy2_rot(1)], ...
             [xy1_rot(2) xy2_rot(2)], ...
             'linestyle','none', ...
             'marker','o', ...
             'color','k');
    
         prof = improfile(F,[xy1_rot(1) xy2_rot(1)],[xy1_rot(2) xy2_rot(2)]);
         i = i + 1;
         FI(i) = sum(prof(:))/length(prof);
         Cxy(i,:) = [FI(i)*cos(theta), FI(i)*sin(theta)];
    end
    
    C = Cxy'*Cxy;
    [V,D] = eig(C)
    lambda2 = D(1,1);
    lambda1 = D(2,2);
    
    alpha = 1 - lambda2/lambda1
    

    A) original image, B) plot of log(P+1), C) polar plot of FI 图:A)原始图像,B)log(P + 1),C)FI的极坐标图。

    我主要担心的是,当我选择完全对齐的人工图像(附图)时,我得到alpha = 0.91,它应该是1。 任何帮助将不胜感激。

    PD:中间图中的那些黑点只是improfile使用的点。

1 个答案:

答案 0 :(得分:2)

我相信这里有一些潜在的错误来源会导致您无法获得完美的alpha值。

离散傅立叶变换

你有离散的成像数据迫使你进行离散的傅里叶变换,这不可避免地(取决于输入数据的分辨率)有一些准确性问题。

分组与一线采样

您完成分箱的方式是您实际绘制一条线(按特定角度旋转)并使用improfile沿该线采样图像。使用improfile执行沿该行的数据插值,引入另一个潜在的错误来源。默认值是最近邻插值,在下面显示的示例中可以导致多个"配置文件"所有人都拿起相同的点。

enter image description here

当技术上你想要那些峰只出现在一条完美的垂直线上时,这是一个离开1度的旋转。很明显,傅立叶频谱的这种插值如何导致围绕“正确”的传播。答案。

数据欠采样

与傅里叶域中的奈奎斯特采样类似,空间域中的采样也有一些要求。

想象一下你想要使用45度宽度而不是1度的宽度。您的方法仍然会沿着细线进行采样,并使用该样本来表示45度的值或数据。显然,这是对数据的严重欠采样,您可以想象结果不会非常准确。

越来越多的问题是你从图像中心得到的距离越远,因为这个" bin"是一个非常形状的楔形,你用它来近似它。

潜在解决方案

不同的分级方法是确定图像中所有像素中心的极坐标(r,theta)。然后将theta组件分成1度的箱子。然后将落入该bin的所有值相加。

这有几个好处:

  • 它删除了我们所讨论的欠采样,并从整个"馅饼楔中抽取样本"无论采样角度如何。
  • 确保每个像素属于一个且只有一个角度bin

我在下面的代码中使用了一些错误的水平线数据实现了这种替代方法,并且能够实现0.988的alpha值,鉴于数据的离散性,我说这是非常好的。

% Draw a bunch of horizontal lines
data = zeros(101);
data([5:5:end],:) = 1;

fourier = fftshift(fft2(data));

FS = abs(fourier);
PS = FS.^2;

center = fliplr(size(FS)) / 2;

[xx,yy] = meshgrid(1:size(FS,2), 1:size(FS, 1));

coords = [xx(:), yy(:)];

% De-mean coordinates to center at the middle of the image
coords = bsxfun(@minus, coords, center);

[theta, R] = cart2pol(coords(:,1), coords(:,2));

% Convert to degrees and round them to the nearest degree
degrees = mod(round(rad2deg(theta)), 360);

degreeRange = 0:359;

% Band pass to ignore high and low frequency components;
lowfreq = 5;
highfreq = size(FS,1)/2;

% Now average everything with the same degrees (sum over PS and average by the number of pixels)
for k = degreeRange
    ps_integral(k+1) = mean(PS(degrees == k & R > lowfreq & R < highfreq));
    fs_integral(k+1) = mean(FS(degrees == k & R > lowfreq & R < highfreq));
end

thetas = deg2rad(degreeRange);

Cxy = [ps_integral.*cos(thetas);
       ps_integral.*sin(thetas)]';

C = Cxy' * Cxy;
[V,D] = eig(C);

lambda2 = D(1,1);
lambda1 = D(2,2);

alpha = 1 - lambda2/lambda1;