-
-
Couldn't load subscription status.
- Fork 18
Unified Scale projections and fixed black border #103
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
base: master
Are you sure you want to change the base?
Conversation
|
This fixes #102 |
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.
Thank you, this is great. Consolidating the scale projections makes a lot of sense. I added just one comment/question.
test/projective/affine.jl
Outdated
| tkeypoints = apply(tfm, keypoints) | ||
| @test getbounds(timage).rs == (0:25, 0:25) | ||
| @test !any(isnan.(timage |> itemdata)) | ||
| @test getbounds(timage).rs == (2:26, 2:26) |
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.
Transforming a 50x50 image with ScaleRatio((1/2, 1/2)), I would expect this to be (1:25, 1:25). With your other fixes, and using a 0.5 offset instead of 1.0 in projectionbounds, this can be adjusted to (1:25, 1:25):
--- a/src/projective/affine.jl
+++ b/src/projective/affine.jl
@@ -88,7 +88,7 @@ end
function projectionbounds(tfm::ScaleFixed{N}, P, bounds::Bounds{N}; randstate = nothing) where N
bounds_ = transformbounds(bounds, P)
- return offsetcropbounds(tfm.sizes, bounds_, ntuple(_ -> 1., N))
+ return offsetcropbounds(tfm.sizes, bounds_, ntuple(_ -> 0.5, N))
endWould this reintroduce the black border you are trying to fix? (it does look like all the other unit tests pass with this change).
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.
Thanks for checking out the PR. I'm fine with this change. I've just sticked to an offset of 1.0 as it has been used before and is still used for the translation in getprojection. I guess they don't have to be consistent?
See:
DataAugmentation.jl/src/projective/affine.jl
Lines 52 to 65 in 3437276
| upperleft = SVector{N, Float32}(minimum.(bounds.rs)) .- 0.5 | |
| P = scaleprojection(Tuple(ratio for _ in 1:N)) | |
| if any(upperleft .!= 0) | |
| P = P ∘ Translation((Float32.(P(upperleft)) .+ 0.5f0)) | |
| end | |
| return P | |
| end | |
| function projectionbounds(tfm::ScaleKeepAspect{N}, P, bounds::Bounds{N}; randstate = nothing) where N | |
| origsz = length.(bounds.rs) | |
| ratio = maximum((tfm.minlengths) ./ origsz) | |
| sz = round.(Int, ratio .* origsz) | |
| bounds_ = transformbounds(bounds, P) | |
| bs_ = offsetcropbounds(sz, bounds_, ntuple(_ -> 0.5, N)) |
vs.
DataAugmentation.jl/src/projective/affine.jl
Lines 84 to 95 in 3437276
| upperleft = SVector{N, Float32}(minimum.(bounds.rs)) .- 1 | |
| P = scaleprojection(ratios) | |
| if any(upperleft .!= 0) | |
| P = P ∘ Translation(-upperleft) | |
| end | |
| return P | |
| end | |
| function projectionbounds(tfm::ScaleFixed{N}, P, bounds::Bounds{N}; randstate = nothing) where N | |
| bounds_ = transformbounds(bounds, P) | |
| return offsetcropbounds(tfm.sizes, bounds_, ntuple(_ -> 1., N)) |
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.
I've added it but it somehow screws up two consecutive scalings. I will try to resolve the issue.
…ling transformations
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.
Thanks for digging into the bounds ranges, this is really great. I just left a couple of small comments and tweaks. But this is looking ready to go.
| timg = apply(tfm, Image(img)) |> itemdata | ||
| @test timg |> size == (32, 48) | ||
| @test !any(isnan.(timg)) |
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.
Check bounds ranges here too:
| timg = apply(tfm, Image(img)) |> itemdata | |
| @test timg |> size == (32, 48) | |
| @test !any(isnan.(timg)) | |
| timg = apply(tfm, Image(img)) | |
| @test getbounds(timg).rs == (1:32, 1:48) | |
| @test !any(isnan.(timg |> itemdata)) |
| timg = apply(tfm, Image(img)) |> itemdata | ||
| @test timg |> size == (32, 32) | ||
| @test !any(isnan.(timg)) |
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.
Same here
| timg = apply(tfm, Image(img)) |> itemdata | |
| @test timg |> size == (32, 32) | |
| @test !any(isnan.(timg)) | |
| timg = apply(tfm, Image(img)) | |
| @test getbounds(timg).rs == (1:32, 1:32) | |
| @test !any(isnan.(timg |> itemdata)) |
|
|
||
| @testset ExtendedTestSet "ScaleRatioTwice" begin | ||
| tfm = ScaleRatio((4/5, 4/5)) |> ScaleRatio((1/2, 1/2)) | ||
| @show getbounds(image).rs |
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.
Please remove the @show
| @assert length(composed.tfms) == length(randstate) | ||
| P = CoordinateTransformations.IdentityTransformation() | ||
| for (tfm, r) in zip(composed.tfms, randstate) | ||
| P_tfm = getprojection(tfm, bounds; randstate = r) | ||
| bounds = projectionbounds(tfm, P_tfm, bounds; randstate = r) | ||
| P = P_tfm ∘ P | ||
| end | ||
| return bounds |
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.
Oh wow, ok. Nice catch here. We might eventually want to think about just writing an apply for ComposedProjectiveTransform so we don't calculate P twice (here and in getprojection), but your approach is probably the safest way forward.
| timage = apply(tfm, image) | ||
| tkeypoints = apply(tfm, keypoints) | ||
| @test !any(isnan.(timage |> itemdata)) | ||
| @test length.(getbounds(timage).rs) == (25, 25) |
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.
Would you mind adding checks to the full range range in these tests, not just the size. Down the road, I can image the ranges becoming incorrect again without a test
| @test length.(getbounds(timage).rs) == (25, 25) | |
| @test getbounds(timage).rs == (1:25, 1:25) |
Scale projections had seperate implementations where the black border was only fixed for
ScaleFixed. Unified implementations and fixed black borders for all projections.PR Checklist