Как заставить ImageTransformation создать анаморфную версию изображения - PullRequest
9 голосов
/ 23 ноября 2011

Я экспериментирую с функцией ImageTransformation, чтобы попытаться сделать анаморфные версии изображений, но пока с ограниченным прогрессом.Я стремлюсь к результатам, которые вы получаете, используя изображение, отраженное в цилиндрическом зеркале, где изображение изгибается вокруг центрального зеркала примерно на 270 градусов.В статье в википедии есть несколько интересных примеров (и я позаимствовал у них череп Гольбейна).

i = Import["../Desktop/Holbein_Skull.jpg"];

wikipedia holbein skull

i = ImageResize[i, 120]
f[x_, y_] := {(2 (y - 0.3) Cos [1.5 x]), (2 (y - 0.3) Sin [1.5 x])};
ImageTransformation[i, f[#[[1]], #[[2]]] &, Padding -> White] 

wikipedia holbein skull

Но я не могу убедить Mathematica показать мне все изображение или правильно согнуть его.Анаморфное изображение должно обернуться вокруг зеркала, помещенного «внутри» центра изображения, но это не так.Я нашел подходящие значения для констант, поместив их в манипуляции (и уменьшив разрешение :).Я использую формулу:

x1 = a(y + b) cos(kx)
y1 = a(y + b) sin(kx)

Любая помощь, дающая лучший результат, будет принята с благодарностью!

1 Ответ

14 голосов
/ 23 ноября 2011

В ImageTransformation[f,img] функция f такова, что точка {x,y} на полученном изображении соответствует f[{x,y}] в img.Поскольку результирующее изображение в основном представляет собой полярное преобразование img, f должно быть обратным полярным преобразованием, чтобы вы могли сделать что-то вроде

anamorphic[img_, angle_: 270 Degree] :=
  Module[{dim = ImageDimensions[img], rInner = 1, rOuter},
    rOuter = rInner (1 + angle dim[[2]]/dim[[1]]);
    ImageTransformation[img,
      Function[{pt}, {ArcTan[-#2, #1] & @@ pt, Norm[pt]}],
      DataRange -> {{-angle/2, angle/2}, {rInner, rOuter}},
      PlotRange -> {{-rOuter, rOuter}, {-rOuter, rOuter}},
      Padding -> White
    ]
  ]

Результирующее изображение будет выглядеть примерно так*

anamorphic plot

Обратите внимание, что вы можете получить аналогичный результат с ParametricPlot и TextureCoordinateFunction, например

anamorphic2[img_Image, angle_: 270 Degree] := 
  Module[{rInner = 1,rOuter},
    rOuter = rInner (1 + angle #2/#1 & @@ ImageDimensions[img]);
    ParametricPlot[{r Sin[t], -r Cos[t]}, {t, -angle/2, angle/2}, 
      {r, rInner, rOuter}, 
      TextureCoordinateFunction -> ({#3, #4} &),
      PlotStyle -> {Opacity[1], Texture[img]},
      Mesh -> None, Axes -> False,
      BoundaryStyle -> None,
      Frame -> False
    ]
  ]
anamorphic2[ExampleData[{"TestImage", "Lena"}]]

Редактировать

В ответ на вопрос Mr.Wizard, если у вас нет доступа к ImageTransformation или Texture, вы можете преобразовать данные изображения вручную, выполнив что-то вроде

anamorph3[img_, angle_: 270 Degree, imgWidth_: 512] :=
 Module[{data, f, matrix, dim, rOuter, rInner = 1.},
  dim = ImageDimensions[img];
  rOuter = rInner (1 + angle #2/#1 & @@ dim);
  data = Table[
      ListInterpolation[#[[All, All, i]], 
        {{rOuter, rInner}, {-angle/2, angle/2}}], {i, 3}] &@ImageData[img];
  f[i_, j_] := If[Abs[j] <= angle/2 && rInner <= i <= rOuter, 
    Through[data[i, j]], {1., 1., 1.}];
  Image@Table[f[Sqrt[i^2 + j^2], ArcTan[i, -j]], 
   {i, -rOuter, rOuter, 2 rOuter/(imgWidth - 1)},
   {j, -rOuter, rOuter, 2 rOuter/(imgWidth - 1)}]]

Обратите внимание, что это предполагаету img есть три канала.Если в изображении меньше или больше каналов, вам нужно адаптировать код.

...