Skip to content

Commit 43880fc

Browse files
authored
Merge pull request #116 from JuliaImages/jc/alphacard
add two democards: "image difference view" and "alpha compositing"
2 parents b665795 + 43e3a4d commit 43880fc

File tree

3 files changed

+148
-0
lines changed

3 files changed

+148
-0
lines changed

Project.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ ImageShow = "4e3cecfd-b093-5904-9786-8bbb286a6a31"
2020
Images = "916415d5-f1e6-5110-898d-aaa5f9f070e0"
2121
MappedArrays = "dbb5928d-eab1-5f90-85c2-b9b0edb7c900"
2222
MosaicViews = "e94cdb99-869f-56ef-bcf0-1ae2bcbe0389"
23+
OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881"
2324
PaddedViews = "5432bcbf-9aad-5242-b902-cca2824c8663"
2425
SimpleTraits = "699a6c99-e7fa-54fc-8d76-47d257e15c1d"
2526
TestImages = "5e47fb64-e119-507b-a336-dd2b206d9990"
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
# ---
2+
# title: Alpha Compositing
3+
# cover: assets/alpha_compositing.png
4+
# ---
5+
6+
# This demonstration shows how [alpha compositing](https://en.wikipedia.org/wiki/Alpha_compositing)
7+
# can be done in 10 lines of code using
8+
# [OffsetArrays](https://github.com/JuliaArrays/OffsetArrays.jl) and
9+
# [PaddedViews](https://github.com/JuliaArrays/PaddedViews.jl)
10+
11+
using Images, MosaicViews
12+
using OffsetArrays, PaddedViews # provide `OffsetArray` and `paddedviews`
13+
14+
# ## 1. basic offset and pad operation
15+
16+
# Assume that we have two objects with transparent color and we want to place them on a canvas
17+
# with partially overlapping.
18+
19+
red_patch = fill(RGBA(1., 0., 0., 1), 24, 24)
20+
green_patch = fill(RGBA(0., 1., 0., 1), 32, 32)
21+
mosaicview(red_patch, green_patch; npad=20, nrow=1, fillvalue=colorant"white")
22+
23+
# Assume the canvas axes starts from `(1, 1)`, here we keep the red patch unshifted,
24+
# and shift the green patch 6 pixels downward and 16 pixels rightward, and then
25+
# pad them to a common axes
26+
green_o = OffsetArray(green_patch, 6, 16)
27+
r, g = paddedviews(Gray(0.2), red_patch, green_o)
28+
mosaicview(r, g; npad=20, nrow=1, fillvalue=colorant"white")
29+
30+
# Note that their axes and sizes are changed after shifting and padding:
31+
32+
## Regardless of implementaion details, `Base.OneTo(32)` is mostly equivalent to `1:32`
33+
println("before shifting -- size: ", size(green_patch), " axes: ", axes(green_patch))
34+
println("after shifting -- size: ", size(green_o), " axes: ", axes(green_o))
35+
println("after padding -- size: ", size(g), " axes: ", axes(g))
36+
37+
# Axes are preserved after padding, which means you can easily get original image from
38+
# padded results using
39+
40+
r[axes(red_patch)...]
41+
g[axes(green_o)...]
42+
#md nothing #hide
43+
44+
# As described [here](https://en.wikipedia.org/wiki/Alpha_compositing), there are several compositing
45+
# methods:
46+
47+
## add operation
48+
out_add = r .+ g
49+
50+
## clear operation
51+
out_clear = copy(r)
52+
out_clear[axes(green_o)...] .= colorant"black"
53+
54+
## multiply operation
55+
out_mul = copy(r)
56+
## channel-wise multiplication
57+
channelview(out_mul)[:, axes(green_o)...] .*= channelview(green_o)
58+
59+
## overlap operation
60+
out_over = copy(r)
61+
out_over[axes(green_o)...] .= green_o
62+
63+
## display the results of these operation
64+
mosaicview(out_add, out_clear, out_mul, out_over;
65+
npad=20, nrow=1, fillvalue=colorant"white")
66+
67+
# ## 2. build the three-primary color panel
68+
69+
# Now, let's use the same trick to build something more meaningful.
70+
# First we create three circles with colors red, green and blue
71+
72+
using ImageDraw
73+
function make_circle(sz, c::T) where T
74+
## fill with transparent color to avoid black region
75+
fillvalue = ARGB(c)
76+
img = fill(ARGB{eltype(T)}(0., 0., 0., 0.), sz...)
77+
origin = sz 2
78+
r = sz 4
79+
draw!(img, Ellipse(origin..., r...), fillvalue)
80+
img
81+
end
82+
83+
## create three circles with color red, green and blue
84+
red_c = make_circle((256, 256), ARGB(1., 0., 0., 1.))
85+
green_c = make_circle((256, 256), ARGB(0., 1., 0., 1.))
86+
blue_c = make_circle((256, 256), ARGB(0., 0., 1., 1.))
87+
88+
mosaicview(red_c, green_c, blue_c; nrow=1)
89+
90+
# Then, shift these circles to appropriate positions, pad them to common axes, and finally composite
91+
# using the add operation:
92+
93+
r = size(red_c, 1) ÷ 8
94+
red_o = OffsetArray(red_c, r, r)
95+
green_o = OffsetArray(green_c, -r, 0)
96+
blue_o = OffsetArray(blue_c, r, -r)
97+
98+
color_panel = sum(paddedviews(zero(eltype(red_o)), red_o, green_o, blue_o))
99+
color_panel = color_panel[axes(red_c)...] # crop empty region
100+
101+
# --- save covers --- #src
102+
using FileIO #src
103+
save("assets/alpha_compositing.png", color_panel) #src
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# ---
2+
# title: Image Difference View
3+
# cover: assets/image_diffview.png
4+
# ---
5+
6+
# This demonstration shows some common tricks in image comparision -- difference view
7+
8+
# People with MATLAB experiences would miss the function
9+
# [`imshowpair`](https://www.mathworks.com/help/images/ref/imshowpair.html), but in JuliaImages
10+
# it is not that indispensable.
11+
12+
using Images, MosaicViews
13+
using TestImages
14+
15+
img = float.(testimage("cameraman"))
16+
## rotate img by 4 degrees and keep axes unchanged
17+
img_r = imrotate(img, -pi/45, axes(img))
18+
nothing #hide #md
19+
20+
# `mosaicview` is a convenience tool to show multiple images, especially useful when they have
21+
# different sizes and colors.
22+
23+
mosaicview(img, img_r; nrow=1, npad=20, fillvalue=colorant"white")
24+
25+
# In some cases, when the differences of two images are relative insignificant, a plain
26+
# substraction can help amplify the difference.
27+
plain_diffview = @. img - img_r
28+
nothing #hide #md
29+
30+
# For gray images, a fancy trick is to fill each image into different RGB channels
31+
# and make a RGB view
32+
RGB_diffview = colorview(RGB, channelview(img), channelview(img_r), fill(0., size(img)))
33+
nothing #hide #md
34+
35+
# or convert the RGB view back to Gray image after that
36+
Gray_diffview = Gray.(RGB_diffview)
37+
38+
mosaicview(plain_diffview, RGB_diffview, Gray_diffview;
39+
nrow=1, npad=20, fillvalue=colorant"white")
40+
41+
42+
# --- save covers --- #src
43+
using FileIO #src
44+
save("assets/image_diffview.png", RGB_diffview) #src

0 commit comments

Comments
 (0)