Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
Longhao-Chen committed Aug 4, 2021
2 parents b9d7f59 + 2cf0300 commit 96d67a3
Show file tree
Hide file tree
Showing 12 changed files with 84 additions and 44 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/Documentation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1.0.0
- uses: actions/checkout@v2
- name: Cache artifacts
uses: actions/cache@v1
env:
Expand Down
22 changes: 17 additions & 5 deletions .github/workflows/juliapackage.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
name: Unit test

on:
create:
tags:
push:
branches:
- master
Expand All @@ -10,29 +12,39 @@ jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
julia-version: ['1.0', '1', 'nightly']
os: [ubuntu-latest, windows-latest, macOS-latest]
julia-version: ['1.6', '1', 'nightly']
os: [ubuntu-latest]
arch: [x64]
include:
- os: windows-latest
julia-version: '1'
arch: x64
- os: macOS-latest
julia-version: '1'
arch: x64


steps:
- uses: actions/checkout@v1.0.0
- uses: actions/checkout@v2
- name: "Set up Julia"
uses: julia-actions/setup-julia@v1
with:
version: ${{ matrix.julia-version }}
arch: ${{ matrix.arch }}

- name: Cache artifacts
uses: actions/cache@v1
env:
cache-name: cache-artifacts
with:
path: ~/.julia/artifacts
path: ~/.julia/artifacts
key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }}
restore-keys: |
${{ runner.os }}-test-${{ env.cache-name }}-
${{ runner.os }}-test-
${{ runner.os }}-
- name: "Unit Test"
uses: julia-actions/julia-runtest@master

Expand Down
17 changes: 5 additions & 12 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,21 @@ authors = ["Johnny Chen <[email protected]>"]
version = "0.1.2"

[deps]
ColorVectorSpace = "c3611d14-8923-5661-9e6a-0046d554d3a4"
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
ImageCore = "a09fc81d-aa75-5fe9-8630-4744c3626534"
ImageFiltering = "6a3955dd-da59-5b1f-98d4-e7296123deb5"
MappedArrays = "dbb5928d-eab1-5f90-85c2-b9b0edb7c900"
OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
Reexport = "189a3867-3050-52da-a836-e630ba90ab69"
UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"

[compat]
ColorVectorSpace = "0.7, 0.8, 0.9"
Distributions = "0.19, 0.20, 0.21, 0.22, 0.23, 0.24"
ImageCore = "0.8.4"
ImageFiltering = "0.5, 0.6"
MappedArrays = "0.2, 0.3"
OffsetArrays = "0.10, 0.11, 1"
Distributions = "0.19, 0.20, 0.21, 0.22, 0.23, 0.24, 0.25"
ImageCore = "0.9"
Reexport = "0.2, 1.0"
julia = "1"
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"
ImageTransformations = "02fcd773-0e25-5acc-982a-7f6622650795"
Expand All @@ -34,4 +27,4 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
TestImages = "5e47fb64-e119-507b-a336-dd2b206d9990"

[targets]
test = ["BM3DDenoise", "ImageMagick", "ImageQualityIndexes", "ImageTransformations", "ReferenceTests", "Test", "TestImages"]
test = ["BM3DDenoise", "ImageIO", "ImageMagick", "ImageQualityIndexes", "ImageTransformations", "ReferenceTests", "Test", "TestImages"]
6 changes: 4 additions & 2 deletions docs/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549"
ImageCore = "a09fc81d-aa75-5fe9-8630-4744c3626534"
ImageDistances = "51556ac3-7006-55f5-8cb3-34580c88182d"
ImageIO = "82e4d734-157c-48bb-816b-45c225c6df19"
ImageMagick = "6218d12a-5da1-5696-b52f-db25d2ecc6d1"
ImageNoise = "2e361c58-64d7-11e9-3ab3-89c4c0b8f7db"
ImageQualityIndexes = "2996bd0c-7a13-11e9-2da2-2f5ce47296a9"
ImageShow = "4e3cecfd-b093-5904-9786-8bbb286a6a31"
ImageTransformations = "02fcd773-0e25-5acc-982a-7f6622650795"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
TestImages = "5e47fb64-e119-507b-a336-dd2b206d9990"

[compat]
Documenter = "0.24"
DemoCards = "0.2"
DemoCards = "0.4"
Documenter = "0.27"
19 changes: 12 additions & 7 deletions docs/examples/apply_noise/AWGN.jl
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
# ---
# title: White Additive Gaussian Noise
# id: wagn-demo
# cover: assets/awgn_cover.png
# description: This demo shows how to add white additive gaussian noise to an image
# description: Add white additive gaussian noise to an image
# date: 2019-12-22
# author: Johnny Chen
# ---

# Mathematically, adding a white additive gaussian noise to an image is as simple
# as $Y = X + N$ where $N \sim \mathcal{N}(\mu,\,\sigma^{2})\,.$

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

# Let's add noise to gray image first

gray_img = testimage("cameraman") .|> float32
gray_img = float.(imresize(testimage("cameraman"), ratio=0.5))
noise = AdditiveWhiteGaussianNoise(0.1)
Random.seed!(0) #src
gray_noisy_img = apply_noise(gray_img, noise)
Expand All @@ -22,7 +26,7 @@ gray_noisy_img = apply_noise(gray_img, noise)
# Adding noise channel by channel would indeed get a different distribution (but
# still a gaussian noise).

rgb_img = testimage("mandrill") .|> float32
rgb_img = float.(imresize(testimage("mandrill"), ratio=0.5))
Random.seed!(0) #src
rgb_noisy_img = apply_noise(rgb_img, noise)

Expand All @@ -35,7 +39,8 @@ hsv_noisy_img = apply_noise(hsv_img, noise)
incorrect_hsv_noisy_img = colorview(HSV, apply_noise(channelview(hsv_img), noise))

## If we compare their psnr, the second one is significantly lower than the first one
[psnr(rgb_noisy_img, RGB.(hsv_noisy_img))
psnr(rgb_noisy_img, RGB.(incorrect_hsv_noisy_img))]
[assess_psnr(rgb_noisy_img, RGB.(hsv_noisy_img))
assess_psnr(rgb_noisy_img, RGB.(incorrect_hsv_noisy_img))]

save("assets/awgn_cover.png", rgb_noisy_img) #src
mkpath("assets") #src
save("assets/awgn_cover.png", rgb_noisy_img) #src
22 changes: 15 additions & 7 deletions docs/examples/reduce_noise/nonlocal.jl
Original file line number Diff line number Diff line change
@@ -1,24 +1,32 @@
# ---
# title: Non-local Mean Filter
# id: nlmf-demo
# cover: assets/nlmean_cover.png
# description: This demo shows how to use Non-local Mean filter to reduce gaussian noise
# date: 2019-12-22
# author: Johnny Chen
# description: Use Non-local Mean filter to reduce gaussian noise
# ---

using ImageNoise, TestImages, ImageShow, ImageCore, ImageQualityIndexes
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 = testimage("cameraman") .|> float32
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_nlmean = NonlocalMean(0.1)
denoised_img = reduce_noise(noisy_img, f_nlmean)

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

#+
# Get the PSNR using ImageQualityIndexes package:

psnr(gray_img, denoised_img)
assess_psnr(gray_img, denoised_img)

save("assets/nlmean_cover.png", denoised_img) #src
mkpath("assets") #src
save("assets/nlmean_cover.png", denoised_img) #src
3 changes: 1 addition & 2 deletions src/ApplyNoise/ApplyNoise.jl
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
module ApplyNoise

using Random
using MappedArrays
using ImageCore
using ImageCore.MappedArrays
using ImageCore: NumberLike, GenericGrayImage, GenericImage
using ColorVectorSpace

import ..NoiseAPI: AbstractImageNoise, apply_noise, apply_noise!
import Base: show
Expand Down
15 changes: 11 additions & 4 deletions src/ReduceNoise/NonlocalMean.jl
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,14 @@ function (f::NonlocalMean)(out::AbstractArray{<:NumberLike, 2},
R = CartesianIndices(img) # indices without padding

oₚ = ntuple(_->r_p, ndims(img))
img = padarray(img, Pad(:symmetric, oₚ, oₚ))
padded_axes = map(axes(img), oₚ) do ax, o
first(ax)-o:last(ax)+o
end
img = PaddedView(zero(eltype(img)), img, padded_axes)
# PaddedView's `getindex` has some overhead so we collect it into a dense array
# and then pass to OffsetArray. Becuase we're doing a heavy amount of `getindex`
# operation, this extra memory allocation worths.
img = OffsetArray(collect(img), padded_axes)
Δₚ = CartesianIndex(oₚ)
Δₛ = CartesianIndex(ntuple(_->r_s, ndims(img)))

Expand Down Expand Up @@ -137,23 +144,23 @@ end

""" gaussian-like kernel """
function make_kernel(T, r)
kernel = centered(zeros(2r+1, 2r+1))
kernel = OffsetArrays.centered(zeros(2r+1, 2r+1))
R = CartesianIndices(kernel)
for d in 1:r
v = 1/(2d+1)^2
for i in R[-d:d, -d:d]
kernel[i] += v
end
end
centered(T.(kernel ./ sum(kernel)))
OffsetArrays.centered(T.(kernel ./ sum(kernel)))
end

""" weighted squared euclidean """
function wsqeucliean(W, X, Y)
rst = zero(eltype(W))
# use linear indexing
@inbounds @simd for i = 1:length(W)
rst += W[i] * abs2(X[i] - Y[i])
rst += W[i] * _abs2(X[i] - Y[i])
end
return rst
end
7 changes: 3 additions & 4 deletions src/ReduceNoise/ReduceNoise.jl
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
module ReduceNoise

using Base.Iterators
using MappedArrays
using OffsetArrays
using ImageCore
using ImageCore.MappedArrays
using ImageCore.OffsetArrays
using ImageCore.PaddedViews
using ImageCore: NumberLike, GenericGrayImage, GenericImage
using ImageFiltering
using ColorVectorSpace
import ..NoiseAPI: AbstractImageDenoiseAlgorithm, reduce_noise, reduce_noise!

include("compat.jl")
Expand Down
15 changes: 15 additions & 0 deletions src/ReduceNoise/compat.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,18 @@ if v"1.0" <= VERSION < v"1.1"
_colon(I::CartesianIndex{N}, J::CartesianIndex{N}) where N =
CartesianIndices(map((i,j) -> i:j, Tuple(I), Tuple(J)))
end

# patch for ColorVectorSpace 0.9
# for CVS < 0.9, we can just use the fallback solution in Distances
if isdefined(ImageCore.ColorVectorSpace, :)
# Because how abs2 calculated in color vector space is ambiguious, abs2(::RGB) is un-defined
# since ColorVectorSpace 0.9
# https:/JuliaGraphics/ColorVectorSpace.jl/pull/131
@inline _abs2(c::Colorant) = mapreducec(v->float(v)^2, +, 0, c)
@inline _abs2(x) = abs2(x)
@inline _abs(c::Colorant) = mapreducec(v->abs(float(v)), +, 0, c)
@inline _abs(x) = abs(x)
else
const _abs2 = abs2
const _abs = abs
end
Binary file modified test/ReduceNoise/References/NonlocalMean_Color3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/ReduceNoise/References/NonlocalMean_Gray.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 96d67a3

Please sign in to comment.