# \[Images.jl\] Projective Transform based on Matrix

**URL:** https://discourse.julialang.org/t/images-jl-projective-transform-based-on-matrix/108559
**Category:** Signal and Image Processing
**Tags:** images, image-processing, juliaimages
**Created:** [January 9, 2024, 12:19pm UTC](https://discourse.julialang.org/t/images-jl-projective-transform-based-on-matrix/108559 "2024-01-09T12:19:03Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![lgmendes](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lgmendes/32/34577_2.png) [@lgmendes](https://discourse.julialang.org/u/lgmendes)
#### Post date: [January 9, 2024, 12:19pm UTC](https://discourse.julialang.org/t/images-jl-projective-transform-based-on-matrix/108559/1 "2024-01-09T12:19:03Z")

</div>

How I can apply an Projective Transform (or an Affine) to a image based on a transform matrix ?

In phyton I can do this using:

```julia
tform = transform.ProjectiveTransform(matrix=matrix)

```

An example in Python (from Documentation):

```julia
from skimage import data

from skimage import transform

from skimage import img_as_float

from skimage import transform

img= img_as_float([data.chelsea])

# Define the transformation matrix
matrix = [[1.0060923472904499, 6.8872896368778122e-002, -4.7977514755983762e+001], [-8.4231722023165673e-002, 9.8715396636307107e-001, 6.7039265228088230e+000], [1.7669387251995766e-015, -3.0176300815504264e-015, 9.9999999999999978e-001]];

# Create the projective transform

tform = transform.ProjectiveTransform(matrix=matrix)

tf_img = transform.warp(img, tform.inverse)

fig, ax = plt.subplots()

ax.imshow(tf_img)

ax.set_title('Projective transformation')

plt.show()

```

---

<div class="post-metadata">

### Author: ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)
#### Post date: [January 9, 2024, 4:25pm UTC](https://discourse.julialang.org/t/images-jl-projective-transform-based-on-matrix/108559/2 "2024-01-09T16:25:28Z")

</div>

It looks like a nice API for this is an outstanding feature requests in ImageTransformations.jl. The core functionality is there as `warp`, but it takes some doing to make it work currently.

> <https://github.com/JuliaImages/ImageTransformations.jl/issues/140>
>
> It's better to have \`Projective\` transformation to \`ImageTransformations.jl\`.
> 
> …
> \`\`\`julia
> \# Definition of projective transformation
> """
> Projective transformation.
> """
> struct Projective \<: Transformation
> H::SArray{Tuple{3,3},Float64,2,9}
> end
> """
> Definition of projective transformation.
> """
> function (p::Projective)(x)
> x\_ = SA\[x\[1\],x\[2\],1.0\]
> x′\_1, x′\_2, x′\_3 = p.H\*x\_
> return SA\[x′\_1/x′\_3, x′\_2/x′\_3\]
> end
> """
> Inverse of projective transformation.
> """
> function Base.inv(p::Projective)
> Projective(inv(p.H))
> end
> \`\`\`
> 
> Discussions in Slack:
> https://julialang.slack.com/archives/CB1R90P8R/p1626929588093000
> https://julialang.slack.com/archives/CB1R90P8R/p1626983453103200
> 
> \>\>I feel the right place to add this is in CoordinateTransformations.jl
> 
> \>Or we could 1) first introduce a high-level API in ImageTransformations.jl with this Projective as internal type, and then 2) migrate it to upstream CoordinateTransformations, and finally 3) use the upstream version.
> 
> (The quoted words are by @johnnychen94)

---

<div class="post-metadata">

### Author: ![JohnnyChen94](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/johnnychen94/32/29979_2.png) [@JohnnyChen94](https://discourse.julialang.org/u/JohnnyChen94)
#### Post date: [January 15, 2024, 6:43am UTC](https://discourse.julialang.org/t/images-jl-projective-transform-based-on-matrix/108559/3 "2024-01-15T06:43:18Z")

</div>

[Swirl effect using warp operation · ImageTransformations](https://juliaimages.org/ImageTransformations.jl/stable/examples/operations/swirl/#Swirl-effect-using-warp-operation) might be a good example to start with.

Simply put, you need a coordinate map function `f` that receives `SVector{N}` and outputs `SVector{N]`, just like the `swirl_map` function in the above example.

* * *

As @mbauman said, wrapping this into a function would be a good feature for ImageTransformations. I’m happy to see and merge a PR, but I don’t have time to do the devs myself.
