-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
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
Add nD rotation matrix generation #3125
base: main
Are you sure you want to change the base?
Conversation
Hello @kne42! Thanks for updating this PR. We checked the lines you've touched for PEP 8 issues, and found:
Comment last updated at 2020-01-23 21:58:18 UTC |
Codecov Report
@@ Coverage Diff @@
## master #3125 +/- ##
=========================================
- Coverage 87.89% 86.1% -1.79%
=========================================
Files 325 340 +15
Lines 27490 27477 -13
=========================================
- Hits 24163 23660 -503
- Misses 3327 3817 +490
Continue to review full report at Codecov.
|
About 3D rotations, did you see that a GSoC student is working on this for Scipy? https://mail.python.org/pipermail/scipy-dev/2018-May/022831.html |
I did not see that! @kne42 the blog linked there looks like a good resource! Thanks @emmanuelle! |
ff77ab7
to
23fc618
Compare
23fc618
to
c43990b
Compare
@emmanuelle @jni @soupault @stefanv This PR is (finally) ready for review! :) |
@kne42 Wow! I will do a proper review tomorrow as part of the scikit-image Paris sprint, but on first glance: 😍😍😍 |
This looks great, thanks @kne42. Questions: what is the situation around rotations in SciPy after their GSoC? How would this typically be used in image processing, i.e. can we come up with a good gallery example? |
Sorry for the late reply, I keep forgetting about this 😅 So briefly, there are two rotation-centric utilities in SciPy: an nD angle-plane rotation in ndimage and the new Rotation object from GSoC. This new object offers conversion between angle-axis, vector-vector, matrix, quarternion, and (I think) euler angle rotations in 3 dimensions. Internally, everything is stored as a quaternion. This proposed addition is an nD implementation of a vector-vector -> rotation matrix conversion. E.g. generate the matrix to rotate one vector to point in the same direction as the other. This is probably most useful internally as a building block for nD algorithms that require rotation, but I’m sure users will be able to find direct use cases. Since I’m largely a beginner when it comes to image processing, the first example that comes to my mind would be with a rotation variant feature detector that outputs features in a plottable format. In this case, one could first rotate the image using the rotation matrix to the desired direction, then rotate the output features using the matrix transpose and plot them on the original image. |
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.
Hey @kne42, thank you very much for your contribution! I am reading the code and for now I have some small changes to ask.
303d7e6
to
5e8854d
Compare
this is ready for re-review @alexdesiqueira |
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.
Damn, this is great work, @kne42! It's crazy what a bit of mulling over time will do, this went from being quite arcane to me to being crystal clear! I've made some very minor suggestions that should be easy to fix, if you can get them done soon I can push that green button! 🎉
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 previously implemented an ND rotation algorithm for polytope
, so I'd like to point out that there is more than one rotation that aligns start and end vectors. For N > 2, not only are there multiple rotations, but these rotations do not all leave the space in the same orientation. Therefore, I'm not sure that this API allows sufficient control over the returned rotation matrix for the desired application.
As an example, if you want to rotate a pencil from pointing up to pointing down, you can flip the pencil way from you or rotate it to the right. These two rotations align the start vector with the end vector, so they could be valid matrices returned by compute_rotation_matrix
. However, the pencil ends in different orientations, so which one will you get?
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.
LGTM, despite some comments. Thank you for this contribution @kne42 ;-)
skimage/transform/_orientation.py
Outdated
|
||
Parameters | ||
---------- | ||
unit_vector : (N, ) array |
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.
unit_vector : (N, ) array | |
unit_vector : (N, ) ndarray |
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.
changed to array-like
skimage/transform/_orientation.py
Outdated
|
||
Parameters | ||
---------- | ||
src : (N, ) array |
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.
src : (N, ) array | |
src : (N, ) ndarray |
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.
changed to array-like
skimage/transform/_orientation.py
Outdated
---------- | ||
src : (N, ) array | ||
Vector to rotate. | ||
dst : (N, ) array |
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.
dst : (N, ) array | |
dst : (N, ) ndarray |
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.
changed to array-like
This is ready for re-review. @carterbox Honestly, I'm not a mathy person so idk. I just took an algorithm from some paper I kinda understood and implemented it here. |
@carterbox thank you so much for chiming in! nD rotations have been a headache for us for a long time. 😅 Looking at polytope might be very useful for us. @kne42 does the paper not discuss this problem at all? |
@jni Well here's how I understood @carterbox's comment:
These vectors are not aligned nor face the same direction
These vectors are aligned but do not face the same direction
These vectors are aligned and face the same direction. The paper does say that it makes both vectors face the same direction (see section II): for any vectors of the same dimension so assuming that the algorithm is right (which I do not have the skills to verify) and I implemented it correctly, yes, it should handle direction correctly sidenote: I'm pretty sure using the term "coincide" is wrong (as I have been putting it in some of the docs). what is the correct mathematical term for when a vector has the same direction as another? |
@kne42 no, the comment is more subtle than that, and you can't illustrate it with "point" vectors. Think now about rotating not a vector, but a human, 180 degrees. If you flip forward, your head will point towards the ground, but you will be facing backwards. If you flip right, your head will still point down, but you will be facing forward. So there is actually an infinite number of rotation matrices that will make your head point down, but the algorithm only returns one. |
@jni Ohhhhhhhhhhh I see. I just skimmed over the paper again and I do not see anything mentioning this. @carterbox what are your suggestions? I can implement a different algorithm or maybe someone who understands math can help me out... |
@jni, Yes! That's what I meant. Thanks for clarifying. @kne42, My suggestions are to address the following edge cases:
|
@jni @carterbox How often do you think this would be an issue for someone? Does this warrant a warning over including something about this in the notes instead? @carterbox So would the instructions be: M_halfway = compute_rotation_matrix(X, Y_halfway)
M = M_halfway @ M_halfway ? |
From the python docs:
I think a warning is appropriate because I'm not sure that the half-angle approach is compatible with homogeneous coordinates. If |
@carterbox the thing is, if I read the implementation correctly, it is almost never the shortest rotation: all rotations go via (1,0, ..., 0). I don't know what happens when you try to rotate (1, 0, 0) to (-1, 0, 0), but that would be an interesting test case, @kne42! =) |
@jni I don't understand what you mean by "never the shortest rotation". All of the rotations are expressed as matrices of the same size, so they are all 'equally short' (computationally speaking). |
I didn't mean to kill the momentum of this pull request! 😅 I just wanted to point out that there should be some extra checking of the inputs and because the solution to the rotation problem is non-unique when the start and end vectors are parallel. |
@carterbox 😂 sometimes, complete discussion can have this effect. =D The problem is that the issue you identified is in no way unique to anti-parallel rotations. For example, to point my head to the right, I can simply roll right, then my head will point right and I will face forward, or I can pitch forward and then roll (my reference frame) / yaw (external reference frame) right. Then I will be facing down, but head pointing right as before. Unless I'm mistaken, for any rotation, there is an infinite number of ways to get there, and they will all leave the object/space in a different orientation. This PR always rotates from the source vector to the 0th axis, then to the target vector, which is different from going from source to target directly. |
@kne42 @jni Let's back up to my earliest question about the desired application. This function claims to align two vectors in an ND space. If the final orientation of the space doesn't matter, and it only matters that the vectors are aligned. Then, just add some documentation for people not familiar with the non-uniqueness of this problem, and that's it. The function does what it claims. Done. If the purpose of this function is to provide a general API for rotating ND spaces, then have a look at the docstring I wrote for polytope. In those docs, I note that for N>3 dimensions and when using only two vectors, it is only possible to unambiguously define simple rotations (rotations whose motion can be projected into a single plane). Because the polytope API only promises simple rotations, using the half-rotation end-vector is enough to avoid the only ambiguous case for defining a plane (the case when the start and end vectors are co-linear). For simple rotations, the rotation matrix generating algorithm should be generating a rotation matrix in which all motion can be projected into a single plane of rotation. (I feel like there may be an easy test for this which involves row reduction or principal component analysis.) If the user has a fully defined mapping from one orientation to another, a rotation function isn't even necessary because one can trivially construct the reorientation matrix by mapping the basis vectors the starting space to the ending space. |
Description
Add function for the generation of a matrix to rotate a vector to coincide with another.
Checklist
[It's fine to submit PRs which are a work in progress! But before they are merged, all PRs should provide:]
./doc/examples
(new features only)[For detailed information on these and other aspects see scikit-image contribution guidelines]
References
For reviewers
(Don't remove the checklist below.)
later.
__init__.py
.doc/release/release_dev.rst
.