Many image processing libraries like OpenCV, Intel Performance Primitives or Octave have a useful function called "remap", that takes an image, an array with X coordinates and an array with Y coordinates, and returns an image that "transforms" the image by that geometric mapping. Or, as the IPP documentation puts it: "Pixel remapping is performed using pxMap
and pyMap
buffers to look-up the coordinates of the source image pixel that is written to the target destination image pixel:
dst_pixel[i, j] = src_pixel[pxMap[i, j], pyMap[i, j]]
The closest thing in Mathematica that I'm aware of is ImageTransformation
, but that takes a function, not an array. Using arrays can often save a lot of time (for example, you can apply the same mapping-array to multiple image, and arithmetic operations on arrays are very fast).
The best I've come up with so far is to combine ImageTransformation
and ListInterpolation
to convert the arrays to functions:
img = ExampleData[{"TestImage", "Lena"}];
mapX = Table[i + j, {i, 500}, {j, 500}];
mapY = Table[i - j, {i, 500}, {j, 500}];
(Imagine some time-consuming operation here. I know that passing i + j, i - j
as a function to ImageTransformation
is probably much faster in this simple case, but that's not the point.)
{xFn, yFn} =
ListInterpolation[#, {{0, 1}, {0, 1}}, InterpolationOrder -> 1] & /@ {mapX, mapY};
Timing[ImageTransformation[img, {xFn @@ #, yFn @@ #} &, {500, 500},
PlotRange -> {{0, 1}, {0, 1}}, DataRange -> Full]]
This works, but is extremely slow (4.7 s on my PC).
The second idea I had was to use ListInterpolation
on the image directly (in this case, only on the red channel):
redFn = ListInterpolation[ImageData[img][[All, All, 1]],
InterpolationOrder -> 1];
Timing[Image[redFn[mapY, mapX]]]
This takes 1.7 s for one color channel, so it's even slower for 3 channels.
For comparison: The IPP's remap function usually takes a few milliseconds.
ImageTransformation
whatListPlot
is toPlot
: Does the same thing, but with an array of data instead of a function to generate the data. $\endgroup$