Skip to content

Commit

Permalink
rework example page using DemoCards
Browse files Browse the repository at this point in the history
  • Loading branch information
johnnychen94 committed Nov 4, 2021
1 parent 41d8ffb commit e847f1b
Show file tree
Hide file tree
Showing 17 changed files with 454 additions and 394 deletions.
12 changes: 12 additions & 0 deletions docs/Project.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[deps]
DemoCards = "311a05b2-6137-4a5a-b473-18580a3d38b5"
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
ImageContrastAdjustment = "f332f351-ec65-5f6a-b3d1-319c6670881a"
ImageIO = "82e4d734-157c-48bb-816b-45c225c6df19"
ImageMagick = "6218d12a-5da1-5696-b52f-db25d2ecc6d1"
ImagePhaseCongruency = "10e51d30-6ba1-539a-b97e-c69c597142c4"
Images = "916415d5-f1e6-5110-898d-aaa5f9f070e0"

[compat]
Documenter = "0.27"
DemoCards = "0.4"
11 changes: 11 additions & 0 deletions docs/examples/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"theme": "grid",
"order": [
"phase_congruency",
"test_images",
"misc"
],
"properties": {
"notebook": "false"
}
}
54 changes: 54 additions & 0 deletions docs/examples/misc/perfft2.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# ---
# title: Fourier transform of Moisan periodic image component
# id: demo_perfft2
# cover: assets/perfft2.png
# author: Peter Kovesi
# date: 2018-10-26
# ---

# The function `perfft2()` implements Moisan's "Periodic plus Smooth Image
# Decomposition" which decomposes an image into two components
#
# img = p + s
#
# where `s` is the 'smooth' component with mean 0 and `p` is the 'periodic' component
# which has no sharp discontinuities when one moves cyclically across the image
# boundaries.
#
# This decomposition is very useful when one wants to obtain an FFT of an image
# with minimal artifacts introduced from the boundary discontinuities. The image
# `p` gathers most of the image information but avoids periodization artifacts.
#
# Reference:
# L. Moisan, "Periodic plus Smooth Image Decomposition", Journal of
# Mathematical Imaging and Vision, vol 39:2, pp. 161-179, 2011.

using Images
using FFTW
using ImagePhaseCongruency
using ImageContrastAdjustment
using TestImages

img = Float64.(Gray.(testimage("lena")))

IMG = fft(img) # 'Standard' fft
(P, S, p, s) = perfft2(img) # 'Periodic' fft

mosaic(
adjust_histogram(Gray.(p), LinearStretching()),
adjust_histogram(s, LinearStretching()),
## Note the vertical and horizontal cross in
## the spectrum induced by the non-periodic edges.
adjust_histogram(log.(abs.(fftshift(IMG)) .+ 1), LinearStretching()),
## Note the clean spectrum because p is periodic.
adjust_histogram(log.(abs.(fftshift(P)) .+ 1), LinearStretching());
nrow=2, rowmajor=true
)
# Top 1) left: periodic component 2) right: smooth component
#
# Bottom 3) left: spectrum of standard FFT 4) right: spectrum of periodic component

# save cover image #src
isdir("assets") || mkdir("assets") #src
cover = Gray.(adjust_histogram(log.(abs.(fftshift(P)) .+ 1), LinearStretching())) #src
save(joinpath("assets", "perfft2.png"), cover) #src
30 changes: 30 additions & 0 deletions docs/examples/phase_congruency/phasecong3.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# ---
# title: Log-Gabor filters v3
# id: demo_phasecong3
# cover: assets/phasecong3.png
# author: Peter Kovesi
# date: 2018-10-26
# ---

# Use of the function `phasecong3()` allows corner points to be detected as well. These
# corner points are a subset of the edge image and, unlike other corner detectors, their
# location is precise and stable over different scales.

using TestImages
using Images
using ImagePhaseCongruency

img = restrict(testimage("mandril_gray"))
(edges, corners) = phasecong3(img)

mosaic(
img,
adjust_histogram(Gray.(edges), LinearStretching()),
adjust_histogram(corners, LinearStretching()),
nrow=1
)
# Images from top to right: 1) original image 2) edges 3) corners

# save cover image #src
isdir("assets") || mkdir("assets") #src
save(joinpath("assets", "phasecong3.png"), adjust_histogram(Gray.(edges), LinearStretching())) #src
35 changes: 35 additions & 0 deletions docs/examples/phase_congruency/phasecongmono.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# ---
# title: Monogenic filters
# id: demo_phasecongmono
# cover: assets/phasecongmono.png
# author: Peter Kovesi
# date: 2018-10-26
# ---

# Phase congruency marks all classes of features from steps to lines and is a dimensionless
# quantity that ranges from 0 to 1. This allows fixed thresholds to be used over wide
# classes of images.

using TestImages
using Images
using ImagePhaseCongruency

img = restrict(testimage("mandril_gray"))

(pc, or, ft, T) = phasecongmono(img)
nonmax = Images.thin_edges(pc, or)

mosaic(
img,
adjust_histogram(pc, LinearStretching()),
nonmax,
hysthresh(nonmax, 0.1, 0.2);
nrow=2, rowmajor=true
)

# Images: 1) top left: original image 2) top right: phase congruency 3) bottom left:
# non-maximal suppression 4) bottom right: Hystersis thresholded

# save cover image #src
isdir("assets") || mkdir("assets") #src
save(joinpath("assets", "phasecongmono.png"), adjust_histogram(Gray.(pc), LinearStretching())) #src
30 changes: 30 additions & 0 deletions docs/examples/phase_congruency/phasesymmetry.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# ---
# title: Symmetric monogenic filters
# id: demo_phasesymmono
# cover: assets/phasesymmono.gif
# author: Peter Kovesi
# date: 2018-10-26
# ---

# Phase symmetry responds well to line like features and circular objects. The number of
# filter scales will affect the scale of features that are marked. Phase symmetry marks
# features independently of contrast (a bright circle is not more symmetric than a grey
# circle) and is a dimensionless quantity between 0 and 1. However this may not be what one
# desires in which case the symmetry energy may be of greater interest.

using TestImages
using Images
using ImagePhaseCongruency

img = Gray.(testimage("blobs"))
## Detect regions of bright symmetry (polarity = 1)
phase_bright, = phasesymmono(img; nscale=5, polarity=1)

## Detect regions of dark symmetry (polarity = -1)
phase_dark, = phasesymmono(img; nscale=5, polarity=-1)

mosaic(img, phase_bright, phase_dark; nrow=1)

# save cover image #src
isdir("assets") || mkdir("assets") #src
save(joinpath("assets", "phasesymmono.gif"), Images.gif([phase_bright, phase_dark]); fps=1) #src
33 changes: 33 additions & 0 deletions docs/examples/phase_congruency/ppdenoise.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# ---
# title: Denoise
# id: demo_ppdenoise
# cover: assets/ppdenoise.png
# author: Peter Kovesi
# date: 2018-10-26
# ---

using TestImages
using Images
using ImageContrastAdjustment
using ImagePhaseCongruency
using Random #hide
Random.seed!(1234) #hide

## Values in the range 0 to 1
img = centered(Gray.(restrict(testimage("lighthouse"))))[-127:128, -127:128]

## Add noise with standard deviation of 0.25
img .+= 0.25 * randn(size(img))

cleanimg = ppdenoise(img; nscale=6, norient=6, mult=2.5, minwavelength=2, sigmaonf=0.55, dthetaonsigma=1.0, k=3, softness=1.0)

mosaic(
adjust_histogram(img, LinearStretching()),
adjust_histogram(cleanimg, LinearStretching());
nrow=1
)

# save cover image #src
isdir("assets") || mkdir("assets") #src
cover = adjust_histogram(Gray.(cleanimg), LinearStretching()) #src
save(joinpath("assets", "ppdenoise.png"), cover) #src
42 changes: 42 additions & 0 deletions docs/examples/phase_congruency/ppdrc.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# ---
# title: Dynamic Range Compression
# id: demo_ppdrc
# cover: assets/ppdrc.png
# author: Peter Kovesi
# date: 2018-10-26
# ---

# An example using the 16 bit M51 image. Phase preserving dynamic range compression allows
# the scale of analysis to be controlled. Here we process the image at wavelengths up to 50
# pixels and up to 200 pixels. Longer wavelengths allow larger structures to be seen. Small
# wavelengths allow fine structures to be seen. Note the image size is (510, 320).

using TestImages
using Images
using ImageContrastAdjustment
using ImagePhaseCongruency

img = float64.(testimage("m51"))

## Histogram equalization for reference (with a very large number of bins!)
img_histeq = histeq(img, 100_000)

## Phase presserving dynamic range compression at cutoff wavelengths of 50 and
## 200 pixels. Note we scale the image because its raw values are between 0 and
## 1, see the help information for ppdrc() for details.
scale = 1e4
img_ppdrc1 = ppdrc(img*scale, 50)
img_ppdrc2 = ppdrc(img*scale, 200)

mosaic(
adjust_histogram(img, LinearStretching()),
adjust_histogram(img_histeq, LinearStretching()),
adjust_histogram(img_ppdrc1, LinearStretching()),
adjust_histogram(img_ppdrc2, LinearStretching()),
nrow=1
)

# save cover image #src
isdir("assets") || mkdir("assets") #src
cropped_cover = adjust_histogram(centered(img_ppdrc1)[-128:127, -128:127], LinearStretching()) #src
save(joinpath("assets", "ppdrc.png"), cropped_cover) #src
27 changes: 27 additions & 0 deletions docs/examples/phase_congruency/quantizephase.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# ---
# title: Phase Quantization
# id: demo_quantizephase
# cover: assets/quantizephase.gif
# author: Peter Kovesi
# date: 2018-10-26
# ---

# Phase values in an image are important. However, despite this, phase can be quantized
# very heavily with little perceptual loss. It can be quantized to a few as four levels, or
# even three. Quantizing to two levels still gives an image that can be interpreted.

using TestImages
using Images
using ImagePhaseCongruency

img = Float64.(restrict(testimage("mandril_gray")))

results = map((8, 4, 3, 2)) do nlevels
out = quantizephase(img, nlevels)
clamp01!(Gray.(out))
end
mosaic(results; nrow=1)

# save cover image #src
isdir("assets") || mkdir("assets") #src
save(joinpath("assets", "quantizephase.gif"), Images.gif([results...]); fps=1) #src
32 changes: 32 additions & 0 deletions docs/examples/phase_congruency/swapphase.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# ---
# title: Amplitude swapping
# id: demo_swapphase
# cover: assets/swapphase.gif
# author: Peter Kovesi
# date: 2018-10-26
# ---

# A demonstration of the importance of phase information in images. Given two
# images`swapphase()` takes their Fourier transforms and constructs two new, synthetic,
# images formed from the swapped phase and amplitude imformation. In general it is the
# phase information that dominates. However, for textures where the amplitude spectra can
# be concentrated in a limited set of locations, the reverse can apply.

# See [Oppenheim and Lim's paper "The importance of phase in signals". Proceedings of the
# IEEE. Volume: 69 , Issue: 5 , May 1981](https://ieeexplore.ieee.org/document/1456290)

using TestImages
using Images
using ImagePhaseCongruency

img1 = centered(Float64.(Gray.(restrict(testimage("lighthouse")))))[-127:128, -127:128]
img2 = restrict(Float64.(testimage("mandril_gray")))[1:256, 1:256]

(newimg1, newimg2) = swapphase(img1, img2)

mosaic(Gray.(img1), newimg1, img2, newimg2; nrow=2)
# Bottom 1) left: phase of lighthouse, amplitude of Mandrill 2) right: amplitude of lighthouse, phase of Mandrill

# save cover image #src
isdir("assets") || mkdir("assets") #src
save(joinpath("assets", "swapphase.gif"), Images.gif([img1, newimg1]); fps=1) #src
19 changes: 19 additions & 0 deletions docs/examples/test_images/circsine.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# ---
# title: circsine
# id: demo_circsine
# cover: assets/circsine.png
# author: Peter Kovesi
# date: 2018-10-26
# ---

using Images
using ImagePhaseCongruency

## Circular features at a phase congruent angle of pi/4 and
## an amplitude decay exponent of 1.5
img = circsine(offset = pi/4, ampexponent = -1.5)
adjust_histogram(Gray.(img), LinearStretching())

# save cover image #src
isdir("assets") || mkdir("assets") #src
save(joinpath("assets", "circsine.png"), adjust_histogram(Gray.(img), LinearStretching())) #src
25 changes: 25 additions & 0 deletions docs/examples/test_images/noiseonf.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# ---
# title: noiseonf
# id: demo_noiseonf
# cover: assets/noiseonf.png
# author: Peter Kovesi
# date: 2018-10-26
# ---

using Images
using ImageContrastAdjustment
using ImagePhaseCongruency

## Noise images with amplitude decay exponents of 1.5 and 2.5
img1 = noiseonf(512, 1.5)
img2 = noiseonf(512, 2.5)

mosaic(
adjust_histogram(Gray.(img1), LinearStretching()),
adjust_histogram(img2, LinearStretching());
nrow=1
)

# save cover image #src
isdir("assets") || mkdir("assets") #src
save(joinpath("assets", "noiseonf.png"), adjust_histogram(Gray.(img1), LinearStretching())) #src
19 changes: 19 additions & 0 deletions docs/examples/test_images/starsine.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# ---
# title: starsine
# id: demo_starsine
# cover: assets/starsine.png
# author: Peter Kovesi
# date: 2018-10-26
# ---

using Images
using ImagePhaseCongruency

## Circular features at a phase congruent angle of pi/2 and
## an amplitude decay exponent of 2
img = starsine(offset = pi/4, ampexponent = -2)
adjust_histogram(Gray.(img), LinearStretching())

# save cover image #src
isdir("assets") || mkdir("assets") #src
save(joinpath("assets", "starsine.png"), adjust_histogram(Gray.(img), LinearStretching())) #src
Loading

0 comments on commit e847f1b

Please sign in to comment.