Skip to content

Instantly share code, notes, and snippets.

@empet
Last active April 2, 2024 09:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save empet/b2447da03d99358fbf90cf2b039a6672 to your computer and use it in GitHub Desktop.
Save empet/b2447da03d99358fbf90cf2b039a6672 to your computer and use it in GitHub Desktop.
Image Warping Through a Complex Function
using Images, ImageTransformations, CoordinateTransformations, Interpolations
import StaticArrays: @SMatrix, @SVector, SVector
mutable struct ImageRectangle{T<:Real}
img::Union{Matrix{RGB{T}}, Matrix{Gray{T}}}
inprectangle::NamedTuple
outrectangle::NamedTuple
end
function check_rectangle(a, b, c, d)
(a<b && c<d) || error("[$a $b] or [$c,$d] is not an interval")
end
function ImageRectangle(img::Union{Matrix{RGB{T}}, Matrix{Gray{T}}},
inprectangle::NamedTuple,
outrectangle::NamedTuple) where T <:Real
length(inprectangle) == 4 && length(outrectangle) == 4 ||
error("the named tuples must have length 4")
check_rectangle(values(inprectangle)...)
check_rectangle(values(outrectangle)...)
return ImageRectangle{T}(img, inprectangle, outrectangle)
end
struct ComplexTransformation{T<:Function} <:Transformation
f::T
end
function (cplxtform::ComplexTransformation)(x::SVector{2, T}) where T<:Real
w = cplxtform.f(x[1]+im*x[2])
@SVector [real(w), imag(w)]
end
struct ModTransformation <:Transformation
m::Int
n::Int
end
function (modtform::ModTransformation)(x::SVector{2,T}) where T<:Real
@SVector [Base.mod(x[1], modtform.m), Base.mod(x[2], modtform.n)]
end
function outpix2coord(obj::ImageRectangle)
"""
Affine transformation from output pixels to the corresponding output cartesian coords
"""
m, n = size(obj.img)
A, B, C, D = values(obj.outrectangle)
Mout = @SMatrix [0 (B-A)/(n-1); -(D-C)/(m-1) 0]
vout = @SVector [(A*n-B)/(n-1), (D*m-C)/(m-1)]
return AffineMap(Mout, vout)
end
function inpcoord2pix(obj::ImageRectangle)
"""
Affine transformation from input cartesian coords to corresponding (approx)pixels
"""
m, n = size(obj.img)
a, b, c, d =values(obj.inprectangle)
Minp = @SMatrix [0 -(m-1)/(d-c); (n-1)/(b-a) 0]
vinp = @SVector [(d*m-c)/(d-c), (b-a*n)/(b-a)]
return AffineMap(Minp, vinp)
end
function get_invtform(obj::ImageRectangle, invf::T) where T <: Function
affine_right = outpix2coord(obj)
affine_left = inpcoord2pix(obj)
icplxtform = ComplexTransformation(invf) #inverse of the complex transformation
affine_left ∘ icplxtform ∘ affine_right
end
function complexwarped(obj::ImageRectangle, invf::T; fillvalue=1, method=BSpline(Linear())) where T<: Function
m, n = size(obj.img)
invtform = get_invtform(obj, invf)
warp(obj.img, invtform, (1:m, 1:n); fillvalue=fillvalue, method=method)
end
function complexwarped(obj::ImageRectangle, invf::T, transf::Transformation; fillvalue=1, method=BSpline(Linear())) where T<: Function
m, n = size(obj.img)
invtform = get_invtform(obj, invf)
warp(obj.img, transf ∘ invtform, (1:m, 1:n); fillvalue=fillvalue, method=method)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment