Skip to content

Commit 5cc52e8

Browse files
authored
Merge pull request #131 from JuliaImages/jc/docs
add documentation page
2 parents c73b48e + 9a623a8 commit 5cc52e8

File tree

12 files changed

+285
-4
lines changed

12 files changed

+285
-4
lines changed

.github/workflows/UnitTest.yml

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ on:
77
branches:
88
- master
99
pull_request:
10-
schedule:
11-
- cron: '20 00 1 * *'
1210

1311
jobs:
1412
test:
@@ -17,14 +15,24 @@ jobs:
1715
fail-fast: false
1816
matrix:
1917
julia-version: ['1.0', '1', 'nightly']
20-
os: [ubuntu-latest, windows-latest, macOS-latest]
18+
os: [ubuntu-latest]
19+
arch: [x64]
20+
include:
21+
- os: windows-latest
22+
julia-version: '1'
23+
arch: x64
24+
- os: macOS-latest
25+
julia-version: '1'
26+
arch: x64
27+
2128

2229
steps:
2330
- uses: actions/checkout@v2
2431
- name: "Set up Julia"
2532
uses: julia-actions/setup-julia@v1
2633
with:
2734
version: ${{ matrix.julia-version }}
35+
arch: ${{ matrix.arch }}
2836

2937
- name: Cache artifacts
3038
uses: actions/cache@v1

.github/workflows/docs.yml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
name: Documentation
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches:
7+
- 'master'
8+
- 'release-'
9+
tags: '*'
10+
release:
11+
types: published
12+
13+
jobs:
14+
build:
15+
runs-on: ${{ matrix.os }}
16+
strategy:
17+
matrix:
18+
julia-version: [1]
19+
os: [ubuntu-latest]
20+
steps:
21+
- uses: actions/checkout@v2
22+
- uses: julia-actions/setup-julia@latest
23+
with:
24+
version: ${{ matrix.julia-version }}
25+
- name: Cache artifacts
26+
uses: actions/cache@v1
27+
env:
28+
cache-name: cache-artifacts
29+
with:
30+
path: ~/.julia/artifacts
31+
key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }}
32+
restore-keys: |
33+
${{ runner.os }}-test-${{ env.cache-name }}-
34+
${{ runner.os }}-test-
35+
${{ runner.os }}-
36+
- name: Install dependencies
37+
run: julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()'
38+
- name: Build and deploy
39+
env:
40+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
41+
run: julia --project=docs/ docs/make.jl

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
*.jl.cov
22
*.jl.*.cov
33
*.jl.mem
4-
/Manifest.toml
4+
Manifest.toml

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
[![][action-img]][action-url]
44
[![][pkgeval-img]][pkgeval-url]
55
[![][codecov-img]][codecov-url]
6+
[![][docs-stable-img]][docs-stable-url]
7+
[![][docs-dev-img]][docs-dev-url]
68

79
This package provides support for image resizing, image rotation, and
810
other spatial transformations of arrays.
@@ -15,3 +17,7 @@ other spatial transformations of arrays.
1517
[action-url]: https://github.com/JuliaImages/ImageTransformations.jl/actions
1618
[codecov-img]: https://codecov.io/github/JuliaImages/ImageTransformations.jl/coverage.svg?branch=master
1719
[codecov-url]: https://codecov.io/github/JuliaImages/ImageTransformations.jl?branch=master
20+
[docs-stable-img]: https://img.shields.io/badge/docs-stable-blue.svg
21+
[docs-stable-url]: https://JuliaImages.github.io/ImageTransformations.jl/stable
22+
[docs-dev-img]: https://img.shields.io/badge/docs-dev-blue.svg
23+
[docs-dev-url]: https://JuliaImages.github.io/ImageTransformations.jl/latest

docs/Project.toml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
[deps]
2+
CoordinateTransformations = "150eb455-5306-5404-9cee-2592286d6298"
3+
DemoCards = "311a05b2-6137-4a5a-b473-18580a3d38b5"
4+
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
5+
FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549"
6+
ImageBase = "c817782e-172a-44cc-b673-b171935fbb9e"
7+
ImageCore = "a09fc81d-aa75-5fe9-8630-4744c3626534"
8+
ImageIO = "82e4d734-157c-48bb-816b-45c225c6df19"
9+
ImageMagick = "6218d12a-5da1-5696-b52f-db25d2ecc6d1"
10+
ImageShow = "4e3cecfd-b093-5904-9786-8bbb286a6a31"
11+
ImageTransformations = "02fcd773-0e25-5acc-982a-7f6622650795"
12+
Interpolations = "a98d9a8b-a2ab-59e6-89dd-64a1c18fca59"
13+
OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881"
14+
Rotations = "6038ab10-8711-5258-84ad-4b1120ba62dc"
15+
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
16+
TestImages = "5e47fb64-e119-507b-a336-dd2b206d9990"
17+
18+
[compat]
19+
DemoCards = "0.4"
20+
Documenter = "0.27"

docs/examples/config.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"theme": "grid"
3+
}

docs/examples/operations/swirl.jl

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# ---
2+
# cover: assets/swirl.gif
3+
# title: Swirl effect using warp operation
4+
# ---
5+
6+
# In this example, we illustrate how to construct a custom warping map
7+
# and pass it to `warp`. This swirl example comes from
8+
# [the Princeton Computer Graphics course for Image Warping (Fall 2000)](https://www.cs.princeton.edu/courses/archive/fall00/cs426/lectures/warp/warp.pdf)
9+
# and [scikit-image swirl example](https://scikit-image.org/docs/dev/auto_examples/transform/plot_swirl.html).
10+
11+
using ImageTransformations
12+
using OffsetArrays, StaticArrays
13+
using ImageShow, TestImages
14+
using LinearAlgebra
15+
16+
img = imresize(testimage("cameraman"), (256, 256));
17+
18+
# As we've illustrated in [image warping](@ref index_image_warping), a warp operation
19+
# consists of two operations: backward coordinate map `ϕ` and intensity estimator.
20+
# To implement swirl operation, we need to customize the coordinate map `ϕ`.
21+
# A valid coordinate map `q = ϕ(p)` follows the following interface:
22+
#
23+
# ```julia
24+
# # SVector comes from StaticArrays
25+
# ϕ(::SVector{N})::SVector{N} where N
26+
# ```
27+
#
28+
# A cartesian position `(x, y)` can be transfered to/from polar coordinate `(ρ, θ)`
29+
# using formula:
30+
#
31+
# ```julia
32+
# # Cartesian to Polar
33+
# ρ = norm(y-y0, x-x0)
34+
# θ = atan(y/x)
35+
#
36+
# # Polar to Cartesian
37+
# y = y0 + ρ*sin(θ)
38+
# x = x0 + ρ*cos(θ)
39+
# ```
40+
#
41+
# For given input index `p`, a swirl operation enforces more rotations in its polar coordinate using
42+
# `θ̃ = θ + ϕ + s*exp(-ρ/r)`, and returns the cartesian index (x̃, ỹ) from the warped polor coordinate
43+
# (ρ, θ̃). (Here we use the formula from [scikit-image swirl example](https://scikit-image.org/docs/dev/auto_examples/transform/plot_swirl.html)
44+
# to build our version.)
45+
46+
function swirl(rotation, strength, radius)
47+
x0 = OffsetArrays.center(img)
48+
r = log(2)*radius/5
49+
50+
function swirl_map(x::SVector{N}) where N
51+
xd = x .- x0
52+
ρ = norm(xd)
53+
θ = atan(reverse(xd)...)
54+
55+
## Note that `x == x0 .+ ρ .* reverse(sincos(θ))`
56+
## swirl adds more rotations to θ based on the distance to center point
57+
θ̃ = θ + rotation + strength * exp(-ρ/r)
58+
59+
SVector{N}(x0 .+ ρ .* reverse(sincos(θ̃)))
60+
end
61+
62+
warp(img, swirl_map, axes(img))
63+
end
64+
65+
# Now let's see how radius argument affects the result
66+
67+
preview = ImageShow.gif([swirl(0, 10, radius) for radius in 10:10:150]; fps=5)
68+
69+
using FileIO #src
70+
save("assets/swirl.gif", preview; fps=5) #src

docs/make.jl

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using Documenter, DemoCards
2+
using ImageBase, ImageTransformations, ImageShow
3+
using TestImages
4+
using CoordinateTransformations, Interpolations, Rotations
5+
6+
# this is used to trigger artifact download and IO backend precompilation
7+
testimage.(["cameraman", "lighthouse"])
8+
9+
examples, postprocess_cb, examples_assets = makedemos("examples")
10+
format = Documenter.HTML(edit_link = "master",
11+
prettyurls = get(ENV, "CI", nothing) == "true",
12+
assets = [examples_assets,])
13+
14+
makedocs(modules = [ImageTransformations, ImageBase],
15+
format = format,
16+
sitename = "ImageTransformations",
17+
pages = [
18+
"index.md",
19+
examples,
20+
"reference.md"])
21+
22+
postprocess_cb()
23+
24+
deploydocs(repo = "github.com/JuliaImages/ImageTransformations.jl.git")

docs/src/assets/warp_resize.png

107 KB
Loading

docs/src/index.md

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# ImageTransformations.jl
2+
3+
```@setup overview
4+
using ImageShow
5+
```
6+
7+
This package provides support for image resizing, image rotation, and
8+
other spatial transformations of arrays.
9+
10+
## Overview
11+
12+
ImageTransformations.jl consists of two sets of API: the low level warping operations, and the high-level operations that built on top of it.
13+
14+
- Low-level warping API:
15+
- `warp`: backward-mode warping
16+
- `WarpedView`: the lazy view version of `warp`
17+
- `InvWarpedView`: the inverse of `WarpedView`
18+
- high-level spatial operations:
19+
- `imresize`: aspect adjustment
20+
- `restrict`: a much more efficient version of `imresize` that two-folds/down-samples image to approximate 1/2 size. (This is now provided by ImageBase.)
21+
- `imrotate`: rotation
22+
23+
For detailed usage of these functions, please refer to [function references](@ref package_references) and [examples](@ref Examples). The following section explains
24+
the core concept image warping so that you can get a clear understanding about
25+
this package while using it.
26+
27+
## [Image warping](@id index_image_warping)
28+
29+
!!! info
30+
This is just a very simple explaination on the internal of ImageTransformations. For more information about image warping, you can take a look at [the Princeton Computer Graphics course for Image Warping (Fall 2000)](https://www.cs.princeton.edu/courses/archive/fall00/cs426/lectures/warp/warp.pdf)
31+
32+
Most image spatial transformation operations (e.g., rotation, resizing, translation) fall into the category of warping operation. Mathematically, for given input image `X`, a (backward-mode) warping operation `f` consists of two functions: coordination map `ϕ` and intensity estimator `τ`.
33+
34+
```math
35+
Y_{i,j} = f(X)_{i, j} = τ(X, ϕ(i, j))
36+
```
37+
38+
Take the following resizing operation as an example, for every pixel position `p` in output image `Y`, we 1) use the backward coordinate map `ϕ` to get its corresponding pixel position `q` in original image `X`. Since `q` may not be on grid, we need to 2) estimate the value of `X` on position `q` using function `τ`, and finally 3) assign `X[q]` back to `Y[p]`. In Julia words, it is
39+
40+
```julia
41+
for p in CartesianIndexes(Y)
42+
q = ϕ(p) # backward coordinate map
43+
v = τ(X, q) # estimate the value
44+
Y[p] = v # assign value back
45+
end
46+
```
47+
48+
As you may have notice, we use backward coordinate map because this is the simplest way to iterate every pixel of the output image. This is why it is called backward-mode warping. In some literature, it is also called reverse warping.
49+
50+
![warp resize demo](assets/warp_resize.png)
51+
52+
In ImageTransformations, the `warp`-based operation uses Interpolations as our intensity estimator `τ`:
53+
54+
```@example overview
55+
using Interpolations, ImageCore, TestImages
56+
using ImageTransformations
57+
58+
X = imresize(testimage("cameraman"), (64, 64)) # use small image as an example
59+
60+
sz = (128, 128)
61+
Y = similar(X, sz...)
62+
63+
# intensity estimator using interpolation
64+
itp = interpolate(X, BSpline(Linear())) # bilinear interpolation
65+
τ(q) = itp(q...)
66+
67+
# A linear coordinate map that satisfies:
68+
# - `ϕ(1, 1) == (1, 1)`
69+
# - `ϕ(128, 128) == (64, 64)`
70+
K = (size(X) .- (1, 1))./(sz .- (1, 1))
71+
b = (1, 1) .- K
72+
ϕ(p) = @. K*p + b
73+
74+
for p in CartesianIndices(Y)
75+
q = ϕ(p.I)
76+
Y[p] = τ(q)
77+
end
78+
79+
mosaic(X, Y; nrow=1)
80+
```
81+
82+
This is the internal of ImageTransformations. For common usage of ImageTransformations, you should use either the low-level API `warp` or
83+
high-level API `imresize` and others.

0 commit comments

Comments
 (0)