-
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
Consider changing sense of transformation #25
Comments
Let's also CC @tejus-gupta and @animesh2809, since they're not watching this repo but it may be relevant for them too. |
Oops, try again: @annimesh2809 |
I agree on all points. Furthermore I think we should make this breaking change sooner rather than later. (Would probably also need a fix in your blog post?) I prototyped the changes to I think I can propose a complete switch by the end of today (its ~17:00 right now here). This way we may have some code to inform us |
What you've written here about ϕ vs ϕ⁻¹ makes a lot of sense Tim. I've not had a huge amount of experience with image registration itself, but I've seen papers in the area where people compute ϕ as a thin plate spline, for example. In practical situations I expect this can be close to non-invertible. Especially if you're registering an image of a real 3D object in a complex environment - complete with 3D rotation and occlusion - the true warp will fail to be any of invertible, 1:1 or differentiable! @Evizero is right that this need not stop you, as long as the user specifies the desired output resampling by giving a bounding box in the domain of ϕ rather than the range of ϕ. Personally, the only thing I find unfortunate about changing this is that I prefer thinking about transformations as moving an object in space and therefore imagining ϕ as the forward warp; warping an image like a bedsheet. Maybe this is just a matter of documentation: if you wanted to keep discussing transformations in the active sense, you could discuss the action of warp in terms of ϕ, but just document that the input of Ah, discussing this stuff brings back some fun memories of old projects :-) |
Requiring the inverse transformation to "warp" an image also seems backwards to me. If one wishes to be artistic, say, then non-invertible transformations might be desirable. I'm thinking something like mirroring an image about it's centre - to achieve this unambiguously, clearly the transformation must be a map from the new coordinate system to the old one. Here's one from Google: I always loved that image @c42f ! |
Since there hasn't yet been disagreement, perhaps we should discuss deprecation strategy. This package may not have a huge number of users yet, but it's been sufficiently advertised by now that there are surely some, and I think that changing the meaning of an argument needs to be done in a way that won't trigger catastrophe. So, some options:
I'm not very fond of the first option because I think Here's a demo of how the 2nd option might work: tim@diva:~$ julia -q
julia> module W
export w
wold() = (warn("switch to wnew"); 1)
wnew() = 2
const w = wold
end
W
julia> using W
julia> w()
WARNING: switch to wnew
1
julia>
tim@diva:~$ julia -q
julia> module W
export w
wold() = (warn("switch to wnew"); 1)
wnew() = 2
const w = wold
end
W
julia> using W
julia> const w = W.wnew
wnew (generic function with 1 method)
julia> w()
2 On balance I suspect the I should say that I'm traveling and will need to focus on the conference and my own (belated) talk preparations. @Evizero, if you're in a hurry, know that I trust your judgment as much as my own. If the blog post needs a rapid update, I should be able to put some time in by Wednesday, or others are authorized to make changes. |
I am not in a hurry. Just trying to be productive when my time allows it. How about we temporarily deprecate @deprecate warp(img, tform) warp(Backward(), img, inv(tform))
warp(::Backward, img, tform) = ...
warp(::Forward, img, tform) = ... So for a while we keep the default to backward warping while specifying the forward transform (it is not really "forward warping" because in forward warping we would iterate over the source image, while right now we still iterate over the output image using the inverse of the forward transform) And at some point in the future we make a switch to default to "proper" backward warping or forward warping. Whatever we decide then |
I think I slightly prefer using That is, unless we can use this to solve the passive vs. active transformation situation within CoordinateTransformations itself - e.g. letting users describe whether a For 2D images |
FYI I created an issue in CoordinateTransformations. |
I've thought about this some more - this package is really young, and my opinion is that it seems simplest to just make a breaking change. We would need to document quite strongly that |
As much as I dislike the prospect of two rounds of deprecation warnings, I am not sure it's fair to just change it to its opposite without any mechanism for warning users. |
closed with #24 |
In #24 we began discussing a possible breaking change: inverting the "sense" in which a transformation is used/applied. Currently pixel values are computed as
img[inv(tfm)(x)]
, but perhaps we should consider switching toimg[tfm(x)]
. For a rotation, the former can be thought of as rotating the image, whereas the latter is rotating the coordinate axes. Let me acknowledge that I was the one who established the current convention; if we decide that the current system is a mess (I fear it may be), you know who to blame...At the outset, let's acknowledge that from a standpoint of pure mathematics, either choice is viable. This is because (in my opinion) we should focus on diffeomorphisms and all diffeomorphisms are invertible. However, from a practical standpoint some are easier to invert than others. For example, affine transformations are easy to invert, but diffeomorphisms like this one are less straightforward. The latter might arise from a deformable image registration algorithm, so I think we have to take such seriously.
So, let me make the case for switching. Note here that I'm assuming that the goal of registration is to find a diffeomorphism
ϕ
such thatfixed[x] ≈ moving[ϕ(x)]
; if someone has a preferred framework for thinking about registration, now is a really, really good time to mention it.For the function
warp
in general you need both the forward and inverse, because (given that framework above)and consequently
warped
should be defined for allx
such thatϕ(x)
is within the domain ofmoving
, i.e., the bounding box ofϕ⁻¹(y)
for ally
within the domain ofmoving
. Since we need both the forward and the reverse, again it doesn't make a great deal of difference which we choose, with one exception: given thatϕ
is a diffeomorphism, we can compute that bounding box using only the edges ofmoving
, and so consequently the inversion only needs to be computed for a small fraction of points. If the inversion is computationally expensive (e.g., invokes a nonlinear solver), then it would be a win to supplyϕ
rather thanϕ⁻¹
However, for image registration we are likely to only care about
warped
over the domain offixed
, in which case we can allocate an emptywarped
and then callwarp!(warped, moving, ϕ)
. In this case, the behavior should be to iterate over all entries inwarped
, in which case we don't even needϕ⁻¹
. In this case, imposing the requirement that we can (and do) computeϕ⁻¹
seems like an unnecessary burden.The text was updated successfully, but these errors were encountered: