Illustrate separable 2D low-pass filtering of an image using the convolution matrix generated in HW1.

  • 2017-09-11, Jeff Fessler, University of Michigan
  • 2021-08-20 Julia 1.6.2
  • 2023-07-24 Julia 1.9.2
In [1]:
using MIRTjim: jim # image display
using ImagePhantoms: shepp_logan, SheppLoganEmis # test image
using Random: seed!
In [2]:
# replace with the path to your own function, or paste your function code here
mydir = ENV["hw551test"] # change path
include(joinpath(mydir, "convolution.jl"))
Out[2]:
convolution
In [3]:
# make a 2D image binary test image of a simple disk and display it
Xtrue = shepp_logan(128, SheppLoganEmis())[15:114,:]
@show (M,N) = size(Xtrue)
seed!(0)
X = Xtrue + 0.5 * randn(size(Xtrue)) # add some noise
jim(X, xlabel="x", ylabel="y", "original noisy image") # jiffy image display
(M, N) = size(Xtrue) = (100, 128)
Out[3]:
In [4]:
# 1D moving-average filter represented as a matrix
hx = ones(9)/9 # 9-pt moving average filter for x (along cols)
hy = ones(5)/5 # 5-pt moving average filter for y (along rows)
Hx,_ = convolution(hx, zeros(M))
Hy,_ = convolution(hy, zeros(N));
In [5]:
# display one of the 1D convolution matrices
# transpose to show it like a matrix H[i,j], rather than as an image f[x,y]
jim(Hx', ylabel="i", xlabel="j")
Out[5]:
In [6]:
Y = Hx * X * Hy'; # apply 1D filters via convolution to both cols and rows
Out[6]:
108×132 Matrix{Float64}:
 -0.00257677  -0.0206421   -0.00767311  …  -0.00397224   0.0030805
  0.00787201   0.00844404   0.0262408       0.0214908    0.00679686
  0.0145027    0.0200168    0.0493157       0.0266018    0.00732171
  0.0367007    0.0446188    0.0793691       0.0216086    0.00470401
  0.0361278    0.0498685    0.0887079       0.00458403   0.00466568
  0.0491528    0.0815829    0.114309    …  -0.00860285  -0.00400734
  0.0302993    0.0707573    0.0987219      -0.0279319   -0.010768
  0.00678657   0.0404505    0.0550015      -0.0395837   -0.0121229
  0.0129906    0.0509701    0.0713035      -0.0531062   -0.0324273
  0.00595929   0.0483376    0.0639169      -0.0474207   -0.0506563
 -0.00748821   0.0106229    0.0144423   …  -0.0385348   -0.0224872
 -0.00769664   0.00047256   0.0132527      -0.0384577   -0.0171543
 -0.017002     0.00517072  -0.00254913     -0.0172232   -0.0117298
  ⋮                                     ⋱   ⋮           
  0.00704558   0.0129943    0.0246091       0.0361487    0.0106162
  0.00257304   0.0313128    0.0336542       0.00763115   0.00919462
  0.0351666    0.0466529    0.0168849      -0.013725     0.00638164
  0.0225107    0.0586934    0.0143609      -0.00334957   0.0216003
  0.0306753    0.0651815    0.0200469   …   0.0133513    0.0206108
  0.0377842    0.0663619    0.0346944       0.0112373    0.0186413
  0.0366688    0.0770434    0.0544112       0.0413998    0.0411758
  0.0255729    0.058697     0.0514822       0.0315853    0.040534
  0.0184104    0.0273777    0.0139405       0.00379197   0.017222
  0.0207398    0.047654     0.0401811   …   0.0199572    0.0238924
  0.0194597    0.0299036    0.0185431       0.0325106    0.0285589
 -0.00542108   0.00550313   0.00936459      0.0254431    0.0183262
In [7]:
# If the following line fails for you,
# or if the result is unrelated to your name on Canvas,
# then edit it to be `user =  "(your name)"`
user = Sys.iswindows() ? ENV["USERNAME"] : ENV["USER"]
Out[7]:
"fessler"
In [8]:
# Display filtered image - the noise is greatly reduced!
# It is "smeared out" (filtered or smoothed) more along x than y.
# Do you know why?
jim(Y, xlabel="x", ylabel="y", "filtered image by '$user'")
Out[8]:
In [9]:
#using Plots: savefig
#savefig("hs003jf-fig.pdf")