timholy / AffineTransforms.jl

Computational geometry with affine transformations
Other
20 stars 6 forks source link

Add support for non-scalar indexing #8

Closed mbauman closed 8 years ago

mbauman commented 8 years ago

With these minor adjustments, I'm able to write my rotate-and-crop function that I proposed in timholy/Images.jl#397 as:

function rotate_and_crop{T}(A::AbstractMatrix{T}, θ, region=(1:size(A, 1), 1:size(A, 2)), fill=zero(T))
    etp = extrapolate(interpolate(A, BSpline(Linear()), OnGrid()), fill)
    R = TransformedArray(etp, tformrotate(θ))
    Base.unsafe_getindex(R, region[1], region[2])
end
# While the above will work for images, it may iterate through them inefficiently depending on the storage order
rotate_and_crop(A::Image, θ, region) = shareproperties(A, rotate_and_crop(A.data, θ, region))

Amazingly, your much more general, higher level framework has performance on par with my specialized rotate function. Very nice work here!

timholy commented 8 years ago

Thanks!

Theoretically, the fastest version should be this one, which is quite hard to read but basically does this:

for j = 1:N
    # precompute the terms that come from the 2nd column of the affine transform matrix
    for i = imin(j):imax(j)   # skip almost all the pixels that will give NaN
        # stuff involving the 1st column of the affine transform matrix
        dest[i,j] = #stuff
    end
end

In three dimensions (which is what I usually care about), the savings from hoisting the computations for the 2nd and 3rd columns are quite substantial.

mbauman commented 8 years ago

Ah, that makes sense. I did see that, but in my use-case I needed to restrict the image down to about 10% of its original area… so I figured it'd be fastest to just do it by indexing into just the small section I need. I didn't test it, though.

timholy commented 8 years ago

Surely if you only need 10% of the area, it will indeed be faster to compute just for that region.