2

我已将图像文件读入 MATLAB,我试图将其拉伸到一个方向,但数量可变(正弦曲线)。这会在图像上产生手风琴效果。我玩弄了imresize,但是它只会线性调整图像的大小。我希望每个图像行的“拉伸”量有所不同。我试图用以下代码传达这一点:

periods = 10; % Number of "stretch" cycles
sz = size(original_image,2)/periods;
s = 0;
x = 0;
for index = 1:periods
    B = original_image(:,round(s+1:s+sz));
    if mod(index,2) == 0
        amp = 1.5;
    else
        amp = 0.75;
    end
    xi = size(B,2)*amp;
    new_image(:,x+1:x+xi) = imresize(B, [size(B,1) size(B,2)*amp]);
    s = s + sz;
    x = x+xi;
end

您可以看到图像的各个部分被拉伸、压缩、拉伸等等,就像手风琴一样。但是,每个部分都有一个统一的拉伸量,而我希望它随着您沿着图像移动而增加然后减少。

我还查看了 MATLAB 的将正弦变换应用于棋盘的示例,这似乎非常适用于我的问题,但是我一直在尝试,但我无法让它为我的图像产生所需的结果。任何帮助深表感谢。


更新:

谢谢你的答案#1。我无法让它为我工作,但也意识到它会导致数据丢失,因为代码只要求原始图像中的某些行,而其他行将被忽略。

在进一步实验之后,我开发了下面的代码。我以棋盘格为例。虽然很整洁,但它确实完成了工作。但是,在使用实际的高分辨率图像尝试脚本时,它非常慢,最终由于内存不足而失败。我相信这是因为循环中使用了过多的“imresize”命令。

I = checkerboard(10,50);
I = imrotate(I,90);
[X Y] = size(I);
k = 4; % Number of "cycles"
k = k*2;
x = 1;
y = 2;
z = 2;
F = [];
i = 1;
t = 0;
s = 0;

for j = 1:k/2
    t = t + 1;
    for inc = round(s+1):round(Y/k*t)
        Yi = i + 1;
        F(:,(x:y)) = imresize(I(:,(inc:inc)),[X Yi]);
        x = y + 1;
        y = x + z;
        z = z + 1;
        i = i + 1;
    end
    y = y - 2;
    z = z - 4;
    for inc = round(Y/k*t+1):round(Y/k*(t+1))
        Yi = i - 1;
        F(:,(x:y)) = imresize(I(:,(inc:inc)),[X Yi]);
        x = y + 1;
        y = x + z;
        z = z - 1;
        i = i - 1;
    end
    y = y + 2;
    z = z + 4;

    s = Y/k*(t+1);
    t = t + 1;
end
Fn = imresize(F, [X Y]);
imshow(Fn);

有谁知道实现这一目标的更简单方法?如果你运行上面的代码,你可以看到我想要达到的效果。不幸的是,我上面的方法也不允许我调整“拉伸”的幅度,只能调整“周期”的数量或频率。对此的帮助也将不胜感激。非常感谢!

4

1 回答 1

1

这是我将如何处理它:

  1. 确定最终图像 F 中每个点的坐标如何映射到大小为 (M,N) 的初始图像 I

    由于您只想水平拉伸,给定最终图像中的一个点 (xF,yF),该点将是初始图像中的 (xI,yI),其中 xI 和 yI 可以按如下方式获得:

    yI = yF;
    xI = xF + L sin(xF K);

    笔记:

    • 这些方程不能保证 xI 保持在 [1:N] 范围内,因此需要添加裁剪
    • K 控制您想要在手风琴效果中产生多少皱纹。例如,如果你只想要一个皱纹,K 将是 2*pi/N
    • L 控制要应用多少拉伸
  2. 然后简单地用你在 1 中的变换从图像 I 中表达你的图像 F。

综上所述,下面的代码创建了一个示例图像 I 并生成图像 F,如下所示:

  % Generate a sample input image
  N=500;
  xF=1:N;
  I=(1:4)'*xF/N*50;

  % Set the parameters for your accordion transform
  K=2*pi/N;
  L=100;

  % Apply the transform
  F=I(:, round(min(N*ones(1,N), max(ones(1,N), (xF + L*sin(xF*K))))) );

  % Display the input and output images side by side
  image(I);
  figure;
  image(F);

如果你运行这个确切的代码,你会得到:

在此处输入图像描述

如您所见,右侧的最终图像拉伸了左侧图像的中心部分,为您提供了带有皱纹的手风琴效果。

您可以摆弄 K 和 L 并调整公式以获得您想要的确切效果,但请注意通过以矩阵形式表示变换,MATLAB 如何在几分之一秒内执行代码。如果你有一个收获,那就是你应该尽可能远离 for 循环和复杂的处理。

玩得开心!

于 2013-03-08T02:39:17.007 回答