Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
ImageCore = "a09fc81d-aa75-5fe9-8630-4744c3626534"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
Reexport = "189a3867-3050-52da-a836-e630ba90ab69"
UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"

[compat]
Distributions = "0.19, 0.20, 0.21, 0.22, 0.23, 0.24, 0.25"
Expand All @@ -16,6 +17,7 @@ Reexport = "0.2, 1.0"
julia = "1.6"

[extras]
BM3DDenoise = "95fb3b36-088a-43fb-bb1b-b1f34fadbd7d"
ImageIO = "82e4d734-157c-48bb-816b-45c225c6df19"
ImageMagick = "6218d12a-5da1-5696-b52f-db25d2ecc6d1"
ImageQualityIndexes = "2996bd0c-7a13-11e9-2da2-2f5ce47296a9"
Expand All @@ -25,4 +27,4 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
TestImages = "5e47fb64-e119-507b-a336-dd2b206d9990"

[targets]
test = ["ImageIO", "ImageMagick", "ImageQualityIndexes", "ImageTransformations", "ReferenceTests", "Test", "TestImages"]
test = ["BM3DDenoise", "ImageIO", "ImageMagick", "ImageQualityIndexes", "ImageTransformations", "ReferenceTests", "Test", "TestImages"]
1 change: 1 addition & 0 deletions docs/Project.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
[deps]
BM3DDenoise = "95fb3b36-088a-43fb-bb1b-b1f34fadbd7d"
DemoCards = "311a05b2-6137-4a5a-b473-18580a3d38b5"
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549"
Expand Down
31 changes: 31 additions & 0 deletions docs/examples/reduce_noise/BM3D.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# title: The BM3D(sparse 3D transform-domain collaborative filtering) denoising algorithm.
# id: bm3d-demo
# cover: assets/bm3d_cover.png
# date: 2021-08-04
# author: Longhao Chen <Longhao.Chen@outlook.com>
# description: This demo shows how to use the BM3D denoising algorithm to reduce gaussian noise
# ---
Comment thread
Longhao-Chen marked this conversation as resolved.

using ImageNoise
using TestImages, ImageShow, ImageCore, ImageQualityIndexes, ImageTransformations
using FileIO, Random #src

# First, load an image and and add gaussian noise to it

gray_img = float.(imresize(testimage("cameraman"), ratio=0.5))
n = AdditiveWhiteGaussianNoise(0.1)
noisy_img = apply_noise(gray_img, n)

# Then calling the standard `reduce_noise` API

f_bm3d = BM3D(0.1)
denoised_img = reduce_noise(noisy_img, f_bm3d)

mosaicview(gray_img, noisy_img, denoised_img; nrow=1)

# Get the PSNR using ImageQualityIndexes package:

assess_psnr(gray_img, denoised_img)

mkpath("assets") #src
save("assets/bm3d_cover.png", denoised_img) #src
65 changes: 65 additions & 0 deletions src/ReduceNoise/BM3DDenoise.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using UUIDs
const BM3DDenoise = Base.PkgId(UUID("95fb3b36-088a-43fb-bb1b-b1f34fadbd7d"), "BM3DDenoise")

# Rewrite from ImageIO.jl
function checked_import(pkgid)
Base.root_module_exists(pkgid) && return Base.root_module(pkgid)
# If not available, load the library or throw an error.
Base.require(pkgid)
end


@doc raw"""
BM3D(σ [, config=bm3d_config()])

The BM3D(sparse 3D transform-domain collaborative filtering) denoising algorithm.

!!! info

This feature depends on the package: `BM3DDenoise`

You can install it by `Pkg`:
```
using Pkg
Pkg.add("BM3DDenoise")
```
Comment thread
johnnychen94 marked this conversation as resolved.
Outdated

# Arguments

* `σ::Float64` is the variance of the noise.

* `config::bm3d_config` is `BM3DDenoise.bm3d_config`.

# Examples

```julia
img = testimage("lena_color_256")

n = AdditiveWhiteGaussianNoise(0.1)
noisy_img = apply_noise(img, n)

# use default arguments
f_denoise = BM3D(0.1)
denoised_img = reduce_noise(noisy_img, f_denoise)
```

See also: [`reduce_noise`](@ref), [`reduce_noise!`](@ref)
"""
struct BM3D <: AbstractImageDenoiseAlgorithm
"""degree of filtering"""
σ::Float64
"""bm3d_config"""
config
function BM3D(σ, config)
σ > 0 || @warn "σ is supposed to be positive"
new(σ, config)
end
end
BM3D(σ) = BM3D(σ, Base.invokelatest(checked_import(BM3DDenoise).bm3d_config))

function (f::BM3D)(out::AbstractArray{T},
img::AbstractArray) where T
axes(out) == axes(img) || ArgumentError("Images should have the same axes.")
out .= T.(Base.invokelatest(checked_import(BM3DDenoise).bm3d, img, f.σ, f.config))
return out
end
3 changes: 3 additions & 0 deletions src/ReduceNoise/ReduceNoise.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@ using ImageCore: NumberLike, GenericGrayImage, GenericImage
import ..NoiseAPI: AbstractImageDenoiseAlgorithm, reduce_noise, reduce_noise!

include("compat.jl")
include("BM3DDenoise.jl")
include("NonlocalMean.jl")

export
reduce_noise, reduce_noise!,

# BM3D
BM3D,
# Non-local mean filter for gaussian noise
NonlocalMean, get_NonlocalMean_rp

Expand Down
14 changes: 14 additions & 0 deletions test/ReduceNoise/BM3DDenoise.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
@testset "BM3DDenoise" begin
@info "Test: BM3DDenoise"
@testset "Numeric" begin
img_gray = n0f8.(imresize(testimage("lena_gray_256"); ratio=0.25))
n = AdditiveWhiteGaussianNoise(0.05)
noisy_img = apply_noise(img_gray, n; rng=MersenneTwister(0))

f = BM3D(0.05)
denoised_img = reduce_noise(noisy_img, f)
# further modification shall not decrease psnr and ssim
@test assess(PSNR(), denoised_img, img_gray) >= 28.
@test assess(SSIM(), denoised_img, img_gray) >= 0.9
end
end
1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ include("ApplyNoise/AdditiveWhiteGaussianNoise.jl")
# ReduceNoise
@info "Test: ReduceNoise"
include("ReduceNoise/NonlocalMean.jl")
include("ReduceNoise/BM3DDenoise.jl")
end

nothing