Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor imresize using Interpolations #7

Merged
merged 2 commits into from
Feb 23, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 1 addition & 1 deletion REQUIRE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
julia 0.5
ImageCore 0.1.2
CoordinateTransformations
CoordinateTransformations 0.4.0
Interpolations 0.3.7
OffsetArrays
StaticArrays
Expand Down
1 change: 1 addition & 0 deletions src/ImageTransformations.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
__precompile__()
module ImageTransformations

using CoordinateTransformations, Interpolations, OffsetArrays, StaticArrays, Colors, ColorVectorSpace, ImageCore
Expand Down
55 changes: 28 additions & 27 deletions src/resizing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ function restrict{T,N}(A::AbstractArray{T,N}, dim::Integer)
return A
end
newsz = ntuple(i->i==dim?restrict_size(size(A,dim)):size(A,i), Val{N})
out = Array{typeof(A[1]/4+A[2]/2),N}(newsz)
# FIXME: The following line fails for interpolations because
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting. I haven't coded with Interpolations recently, but if it supports what we need then

R = CartesianRange(indices(A))
f = A[first(R)]

should work. Though perhaps the better strategy would to add support for first to Interpolations.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

first(A) works for interpolations. A[1] does not. For extrapolations neither work

# interpolations can be accessed linearily A[i].
# out = Array{typeof(A[1]/4+A[2]/2),N}(newsz)
out = Array{typeof(first(A)/4+first(A)/2),N}(newsz)
restrict!(out, A, dim)
out
end
Expand Down Expand Up @@ -78,7 +81,7 @@ for N = 1:5
oneeighth = convert(eltype(T), 0.125)
indx = 0
if dim == 1
z = convert(T, zero(A[1]))
z = convert(T, zero(first(A)))
@inbounds @nloops $N i d->(d==1 ? (1:1) : (1:size(A,d))) d->(j_d = i_d) begin
c = d = z
for k = 1:size(out,1)-1
Expand Down Expand Up @@ -125,32 +128,30 @@ end

restrict_size(len::Integer) = isodd(len) ? (len+1)>>1 : (len>>1)+1

## imresize
function imresize!(resized, original::AbstractMatrix)
scale1 = (size(original,1)-1)/(size(resized,1)-0.999f0)
scale2 = (size(original,2)-1)/(size(resized,2)-0.999f0)
for jr = 0:size(resized,2)-1
jo = scale2*jr
ijo = trunc(Int, jo)
fjo = jo - oftype(jo, ijo)
@inbounds for ir = 0:size(resized,1)-1
io = scale1*ir
iio = trunc(Int, io)
fio = io - oftype(io, iio)
tmp = (1-fio)*((1-fjo)*original[iio+1,ijo+1] +
fjo*original[iio+1,ijo+2]) +
+ fio*((1-fjo)*original[iio+2,ijo+1] +
fjo*original[iio+2,ijo+2])
resized[ir+1,jr+1] = convertsafely(eltype(resized), tmp)
end
end
resized
# imresize
imresize(original::AbstractArray, dim1, dimN...) = imresize(original, (dim1,dimN...))

function imresize{T,N}(original::AbstractArray{T,N}, short_size::NTuple)
len_short = length(short_size)
new_size = ntuple(i -> (i > len_short ? size(original,i) : short_size[i]), N)
imresize(original, new_size)
end

imresize(original, new_size) = size(original) == new_size ? copy!(similar(original), original) : imresize!(similar(original, new_size), original)
function imresize{T,N}(original::AbstractArray{T,N}, new_size::NTuple{N})
if size(original) == new_size
copy!(similar(original), original)
else
imresize!(similar(original, new_size), original)
end
end

convertsafely{T<:AbstractFloat}(::Type{T}, val) = convert(T, val)
convertsafely{T<:Integer}(::Type{T}, val::Integer) = convert(T, val)
convertsafely{T<:Integer}(::Type{T}, val::AbstractFloat) = round(T, val)
convertsafely{T}(::Type{T}, val) = convert(T, val)
function imresize!{T,S,N}(resized::AbstractArray{T,N}, original::AbstractArray{S,N})
itp = interpolate(original, BSpline(Linear()), OnGrid())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might want to dispatch to a version of imresize! that accepts original::AbstractInterpolation. That way if people want higher-order interpolation they can get it easily.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea

sf = map(/, size(original), size(resized))
for I in CartesianRange(size(resized))
I_o = map(*, I.I, sf)
resized[I] = itp[I_o...]
end
resized
end

38 changes: 19 additions & 19 deletions test/runtests.jl
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
using ImageTransformations, CoordinateTransformations, TestImages, ImageCore, Colors, FixedPointNumbers
using Base.Test

#img = testimage("camera")
#tfm = recenter(RotMatrix(-pi/8), center(img))
#imgr = warp(img, tfm)
#@test indices(imgr) == (-78:591, -78:591)
img = testimage("camera")
tfm = recenter(RotMatrix(-pi/8), center(img))
imgr = warp(img, tfm)
@test indices(imgr) == (-78:591, -78:591)
#imgr2 = warp(imgr, inv(tfm)) # this will need fixes in Interpolations
#@test imgr2[indices(img)...] ≈ img

@testset "Restriction" begin
imgcol = colorview(RGB, rand(3,5,6))
A = reshape([convert(UInt16, i) for i = 1:60], 4, 5, 3)
B = restrict(A, (1,2))
Btarget = cat(3, [ 0.96875 4.625 5.96875;
2.875 10.5 12.875;
1.90625 5.875 6.90625],
[ 8.46875 14.625 13.46875;
17.875 30.5 27.875;
9.40625 15.875 14.40625],
[15.96875 24.625 20.96875;
32.875 50.5 42.875;
16.90625 25.875 21.90625])
Btarget = cat(3, [ 0.96875 4.625 5.96875;
2.875 10.5 12.875;
1.90625 5.875 6.90625],
[ 8.46875 14.625 13.46875;
17.875 30.5 27.875;
9.40625 15.875 14.40625],
[ 15.96875 24.625 20.96875;
32.875 50.5 42.875;
16.90625 25.875 21.90625])
@test B ≈ Btarget
Argb = reinterpret(RGB, reinterpret(N0f16, permutedims(A, (3,1,2))))
B = restrict(Argb)
Expand All @@ -31,12 +31,12 @@ using Base.Test
@test isapprox(reinterpret(eltype(eltype(B)), B), restrict(A, (2,3))/reinterpret(one(N0f16)), atol=1e-12)
A = reshape(1:60, 5, 4, 3)
B = restrict(A, (1,2,3))
@test cat(3, [ 2.6015625 8.71875 6.1171875;
4.09375 12.875 8.78125;
3.5390625 10.59375 7.0546875],
[10.1015625 23.71875 13.6171875;
14.09375 32.875 18.78125;
11.0390625 25.59375 14.5546875]) ≈ B
@test cat(3, [ 2.6015625 8.71875 6.1171875;
4.09375 12.875 8.78125;
3.5390625 10.59375 7.0546875],
[ 10.1015625 23.71875 13.6171875;
14.09375 32.875 18.78125;
11.0390625 25.59375 14.5546875]) ≈ B
#imgcolax = AxisArray(imgcol, :y, :x)
#imgr = restrict(imgcolax, (1,2))
#@test pixelspacing(imgr) == (2,2)
Expand Down