-
Notifications
You must be signed in to change notification settings - Fork 27
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
specialize imrotate for 0, 90, 180, 270 degrees #79
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -112,7 +112,7 @@ By default, rotated image `imgr` will not be cropped. Bilinear interpolation wil | |
```julia | ||
julia> img = testimage("cameraman") | ||
|
||
# rotate with bilinear interpolation but without cropping | ||
# rotate with bilinear interpolation but without cropping | ||
julia> imrotate(img, π/4) | ||
|
||
# rotate with bilinear interpolation and with cropping | ||
|
@@ -124,8 +124,28 @@ julia> imrotate(img, π/4, Constant()) | |
|
||
See also [`warp`](@ref). | ||
""" | ||
function imrotate(img::AbstractArray{T}, θ::Real, args...) where T | ||
θ = floor(mod(θ,2pi)*typemax(Int16))/typemax(Int16) # periodic discretezation | ||
tform = recenter(RotMatrix{2}(θ), center(img)) | ||
warp(img, tform, args...) | ||
function imrotate(img::AbstractMatrix{T}, θ::Real, args...) where T | ||
# 1. discretize periodic for numerical stability to make sure | ||
# imrotate(img, θ+2pi) == imrotate(img, θ) | ||
# 2. typemax(Int16) is 32767, we choose 32760 to make sure the | ||
# discretization result of pi/2 is exactly pi/2 (or 90°) | ||
max_num_angles = 32760 | ||
θ = round(Int, 180*floor(mod(θ, 2pi)/pi*max_num_angles)/max_num_angles) | ||
tform = recenter(RotMatrix{2}(θ/180*pi), center(img)) | ||
Comment on lines
+133
to
+134
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't use the θ! 😱 |
||
if θ == 0 | ||
return img | ||
elseif θ == 90 | ||
idx = StepRange.(axes(img)) | ||
perm_img = PermutedDimsArray(img, (2, 1)) | ||
return view(perm_img, idx[2], reverse(idx[1])) | ||
elseif θ == 180 | ||
idx = map(i->1:1:length(i), axes(img)) | ||
return view(img, reverse(idx[1]), reverse(idx[2])) | ||
elseif θ == 270 | ||
idx = StepRange.(axes(img)) | ||
perm_img = PermutedDimsArray(img, (2, 1)) | ||
return view(perm_img, reverse(idx[2]), idx[1]) | ||
Comment on lines
+137
to
+147
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. any reason to not use some of the tools in base? https://docs.julialang.org/en/v1/base/arrays/#Base.rot180 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think @johnnychen94 want to reallocate the memory and relocate the elements.:smile: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. True, and there won't be type stability issues if we collect them and return an I don't have a good fix in mind for this at the moment. |
||
else | ||
return warp(img, tform, args...) | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -427,15 +427,26 @@ ref_img_pyramid_grid = Float64[ | |
@test_nowarn imrotate(img, π/4, Linear()) | ||
@test_nowarn imrotate(img, π/4, axes(img)) | ||
@test_nowarn imrotate(img, π/4, axes(img), Constant()) | ||
@test isequal(channelview(imrotate(img,π/4)), channelview(imrotate(img, π/4, Linear()))) # TODO: if we remove channelview the test will break for Float | ||
@test isequal(channelview(imrotate(img, π/4)), channelview(imrotate(img, π/4, Linear()))) # NaN != NaN | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The meaning of this comment is unclear. Do you mean that you wanted to write |
||
end | ||
|
||
# check special rotation degrees | ||
img = rand(Gray{N0f8}, 100, 50) | ||
@test size(imrotate(img, pi/2)) == (50, 100) | ||
@test size(imrotate(img, pi)) == (100, 50) | ||
@test size(imrotate(img, 3pi/2)) == (50, 100) | ||
@test size(imrotate(img, 2pi)) == (100, 50) | ||
rotated_img = imrotate(imrotate(imrotate(imrotate(img, pi/2), pi/2), pi/2), pi/2) | ||
@test rotated_img == img | ||
rotated_img = imrotate(imrotate(img, pi), pi) | ||
@test rotated_img == img | ||
end | ||
|
||
@testset "numerical" begin | ||
for T in test_types | ||
img = Gray{T}.(graybar) | ||
for θ in range(0,stop=2π,length = 100) | ||
@test isequal(channelview(imrotate(img,θ)), channelview(imrotate(img,θ+2π))) # TODO: if we remove channelview the test will break for Float | ||
@test isequal(channelview(imrotate(img,θ)), channelview(imrotate(img,θ+2π))) # NaN != NaN | ||
end | ||
end | ||
end | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Although the same goes for the current code, why don't you use 32768?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well... It's like I randomly chose the first number I found that meets the requirement, and I feel this choice doesn't matter for image processing tasks.