-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
41d8ffb
commit e847f1b
Showing
17 changed files
with
454 additions
and
394 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Oops, something went wrong.