Skip to content

PerspectiveMap question on Stackoverflow #32

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
timholy opened this issue Aug 20, 2017 · 9 comments
Open

PerspectiveMap question on Stackoverflow #32

timholy opened this issue Aug 20, 2017 · 9 comments

Comments

@timholy
Copy link
Member

timholy commented Aug 20, 2017

https://stackoverflow.com/questions/45772848/perspective-warp-an-image-in-julia

I haven't dug into this here, but the core issue seems to be how to define a perspective transformation that takes a 2d input and returns a 2d output.

@Evizero
Copy link

Evizero commented Aug 20, 2017

Just from looking at it, I think that issue just concerns ImageTransformations. The fix to me looks to be two fold (without checking)

1.) use the new warp (change is tagged thanks to you)
2.) make sure to specify the output indices, because by default that performs inv to see where pixel end up (see https://github.com/JuliaImages/ImageTransformations.jl/blob/master/src/warp.jl#L82)

@timholy
Copy link
Member Author

timholy commented Aug 20, 2017

It's more than that:

julia> using CoordinateTransformations, ImageTransformations, Interpolations, Colors, ColorVectorSpace, TestImages

julia> img = testimage("light");

julia> M = [1 0 0; 0 1 0; -1/5 0 1]   # a 3x3 perspective transformation matrix
3×3 Array{Float64,2}:
  1.0  0.0  0.0
  0.0  1.0  0.0
 -0.2  0.0  1.0

julia> tform = PerspectiveMap()  inv(LinearMap(M))
(CoordinateTransformations.PerspectiveMap()  LinearMap([1.0 0.0 0.0; 0.0 1.0 0.0; 0.2 0.0 1.0]))

julia> warp(img, tform, indices(img))
ERROR: DimensionMismatch("matrix A has dimensions (3,3), vector B has length 2")
Stacktrace:
 [1] generic_matvecmul!(::Array{Float64,1}, ::Char, ::Array{Float64,2}, ::SVector{2,Int64}) at ./linalg/matmul.jl:407
 [2] warp!(::Array{ColorTypes.RGB{FixedPointNumbers.Normed{UInt8,8}},2}, ::Interpolations.FilledExtrapolation{ColorTypes.RGB{FixedPointNumbers.Normed{UInt8,8}},2,Interpolations.BSplineInterpolation{ColorTypes.RGB{FixedPointNumbers.Normed{UInt8,8}},2,Array{ColorTypes.RGB{FixedPointNumbers.Normed{UInt8,8}},2},Interpolations.BSpline{Interpolations.Linear},Interpolations.OnGrid,0},Interpolations.BSpline{Interpolations.Linear},Interpolations.OnGrid,ColorTypes.RGB{FixedPointNumbers.Normed{UInt8,8}}}, ::CoordinateTransformations.ComposedTransformation{CoordinateTransformations.PerspectiveMap,CoordinateTransformations.LinearMap{Array{Float64,2}}}) at /home/tim/.julia/v0.6/ImageTransformations/src/warp.jl:89
 [3] warp(::Array{ColorTypes.RGB{FixedPointNumbers.Normed{UInt8,8}},2}, ::CoordinateTransformations.ComposedTransformation{CoordinateTransformations.PerspectiveMap,CoordinateTransformations.LinearMap{Array{Float64,2}}}, ::Tuple{Base.OneTo{Int64},Base.OneTo{Int64}}) at /home/tim/.julia/v0.6/ImageTransformations/src/warp.jl:96

julia> using StaticArrays

julia> tform(@SVector([1,1]))
ERROR: DimensionMismatch("matrix A has dimensions (3,3), vector B has length 2")
Stacktrace:
 [1] generic_matvecmul!(::Array{Float64,1}, ::Char, ::Array{Float64,2}, ::SVector{2,Int64}) at ./linalg/matmul.jl:407
 [2] (::CoordinateTransformations.ComposedTransformation{CoordinateTransformations.PerspectiveMap,CoordinateTransformations.LinearMap{Array{Float64,2}}})(::SVector{2,Int64}) at /home/tim/.julia/v0.6/CoordinateTransformations/src/core.jl:37

@timholy
Copy link
Member Author

timholy commented Aug 20, 2017

Perhaps what we need is a type that essentially appends 1 to the SVector? EDIT: this might make PerspectiveMap invertible, unlike my push solution below.

@timholy
Copy link
Member Author

timholy commented Aug 20, 2017

Aha, I didn't know about push. Here's a complete example (EDIT: slightly more polished on SO):

julia> using Images, TestImages, StaticArrays, CoordinateTransformations

julia> M = @SMatrix [1 0 0; 0 1 0; -1/1000 0 1]   # a 3x3 perspective transformation matrix
3×3 StaticArrays.SArray{Tuple{3,3},Float64,2,9}:
  1.0    0.0  0.0
  0.0    1.0  0.0
 -0.001  0.0  1.0

julia> tform = PerspectiveMap()  inv(LinearMap(M))
(CoordinateTransformations.PerspectiveMap()  LinearMap([1.0 0.0 0.0; -0.0 1.0 0.0; 0.001 -0.0 1.0]))

julia> tform2(x) = tform(push(x, 1))
tform2 (generic function with 1 method)

julia> img = testimage("lighthouse");

julia> imgw = warp(img, tform2, indices(img));

I can post that to the SO post, but it occurs to me that we should put this somewhere in docs. How much of that should go here versus in JuliaImages?

@IshitaTakeshi
Copy link

Seems @timholy's tform2 assumes depth=1 but I'd like to specify depth per pixel. Do you have a future plan to add the functionality like it?

@c42f
Copy link
Member

c42f commented Dec 10, 2018

@IshitaTakeshi I don't think we will do this, because you can get the same effect by permuting the axes with a LinearMap before passing to PerspectiveMap.

@c42f
Copy link
Member

c42f commented Dec 10, 2018

We could possibly consider adding more options to the cameramap convenience function to add this permutation for you.

@IshitaTakeshi
Copy link

Thanks for the answer

@yakir12
Copy link
Member

yakir12 commented Sep 11, 2020

Just posting a link to my trials and tribulations (don't worry, it has a good ending, kind of) on Discourse concerning this issue:
https://discourse.julialang.org/t/help-converting-a-transformation-matrix

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants