-
-
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
Move profile_line() out of viewer #865
Conversation
The profile_line function is currently part of the skimage LineProfile plugin. However, it's useful in non-interactive contexts, and importing it from the viewer is awkward, mostly hidden, and depends on PyQt for no good reason. By moving the function to `skimage.measure`, it is usable in many more contexts.
Note that the indices were inverted relative to previous use, which I believe was incorrect. (See example in docstring, which works, where it used to be inverted.)
Changes Unknown when pulling e24ae38 on jni:profile-line into * on scikit-image:master*. |
In theory I approve of both API changes (and then making the function public, it is handy). I need to play with it a bit to see if I can get it to break - horizontal and vertical lines are challenges for |
I haven't looked at the code, but if you struggle with vertical lines, you probably want to use a different parameterization for lines. See e.g. skimage.measure.LineModel. |
@jni My first thought when looking at the code examples was also that we should change the coordinates to row+column. |
+1 for 1D and 2D returns--then it is similar to a specialized slicing operator |
We have Brezenham's algorithm implemented--can we use that instead to find the line coordinates? Otherwise, in a case like this, the line can be parameterized as |
👍 on all these updates. BTW, I didn't actually write this implementation; I believe @blink1073 wrote the original, just in case he has any input. |
@JDWarner @ahojnnes, the function automatically detects vertical lines and treats them differently. I'll add a vertical test case anyway. =) @stefanv I'm not sure about other parameterizations, as they might make it more difficult to calculate the perpendicular scan lines? (Slightly out of my depth here.) |
@tonysyu, |
I'm suggesting you use the module in |
@stefanv, |
Changes Unknown when pulling 2a6ec20 on jni:profile-line into * on scikit-image:master*. |
channels = 3 | ||
|
||
# Quick calculation if perfectly vertical; shortcuts div0 error | ||
if x1 == x2: |
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.
This hack won't fly.
@stefanv, can you suggest a fix? As I mentioned, the functions in As an aside, I don't think it's reasonable to require PRs to address pre-existing hacks (if that's not the point of the PR). |
@jni Apologies if I wasn't clear: I don't think it is your responsibility to fix it, but I'd like for us all to have a closer look at this when you're done. That piece of code bothers me. |
@stefanv FINE, you win. I don't know why but you always inspire me to do work I don't actually want to do. =P I need to do a little bit more testing, but I think the current implementation is correct! |
Changes Unknown when pulling 3d93582 on jni:profile-line into * on scikit-image:master*. |
Changes Unknown when pulling 3d93582 on jni:profile-line into * on scikit-image:master*. |
More API questions: the order of the interpolation is important. Currently, it uses the default (cubic spline). However, this is a nightmare for testing, and, in my case at least, I'd rather just use nearest-neighbor or at most linear interpolation. My suggestion is:
Please let me know any thoughts. I'm working on the first point now for the test cases, but I'd love to hear your opinions on the second and third points, @stefanv @tonysyu @JDWarner. |
... Having spent a bit more time with the testing, I now prefer |
It's important to distinguish between pixels and points. A square set of points belongs to one pixel. When users type `linewidth=3`, they usually mean a line 3 pixels wide. The distance between the pixel center points, then, is 2.
The `if linewidth <= 1` was necessary because the coordinate systems (pixel/point) were all muddled up. Now that it has been clarified, `linewidth=1` works transparently!
Okely: it all works, hackish As far as I'm concerned this is ready to merge (pending passing the tests), but feel free to prove me wrong! =) And @stefanv, I learned a lot getting this done, and it looks way better than it used to, so, as usual, thanks for the nudges. =) |
Changes Unknown when pulling 040a21a on jni:profile-line into * on scikit-image:master*. |
As an added bonus, the LineProfile plugin now returns the line drawing as an overlay and the scan line as data, as per the API introduced in #810. |
Changes Unknown when pulling ec0079d on jni:profile-line into * on scikit-image:master*. |
@jni One just has to plant a seed in fertile ground and watch it grow ;) |
Parameters | ||
---------- | ||
img : 2d or 3d array | ||
The image, in grayscale (2d) or multichannel (2d + c) format. |
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.
2d -> 2D or 2-D; not sure what 2d + c means
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.
This used to say "2D RGB" but it works for any number of channels. I want to distinguish that from a 3D grayscale image, which wouldn't work. Suggestions?
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.
(M, N)
greyscale or (M, N, ...)
multi-channel perhaps?
Love it, thanks @jni ! |
@stefanv, thanks for the comments. =D The seed analogy is pretty good... It sat there and grew and grew in my head as I tried to focus on other stuff. =D Let me know if you want me to add the width to the returned line. I think the added code complexity wouldn't add much, but am open to adding it. |
Could we perhaps compute the vertices of the box in case of width > 1 and
|
Changes Unknown when pulling 01967e5 on jni:profile-line into * on scikit-image:master*. |
How about I create an issue to change this and deal with it in a later PR? I'd like to get on with actually using profile_line() for my research. =) |
Move `profile_line()` out of viewer and refactor
Cool, let's get on with it :) Thanks! |
Add Shaded Polygon to LineProfile Plugin Output Closes #865
The profile_line() function is actually quite useful outside of the viewer and interactive LineProfiler plugin. I've moved it to the
measure
package and imported it from there for use in the plugin.In addition, I fixed an apparent bug in its functionality: it appeared to return the profile in the wrong direction:
before:
after:
It also adds a
mode
parameter to be passed in to thendimage.map_coordinates
interpolation routine to estimate values outside the image.In addition, I'd like to request people's opinion about two additional proposed changes.
Currently, the API uses x and y as inputs, meaning the horizontal and vertical dimensions, meaning columns and rows, meaning exactly the opposite of typical numpy indexing. Since we use numpy indexing almost everywhere else, would people support changing this to expect numpy-style coordinates? Since it is not currently a public function, I think we could change this without worrying about API changes. In which case, I would actually support the syntax
profile_line(img, src_point, dst_point)
, where each of those is a valid numpy indexing tuple intoimg
.I would also change the return type to be a 1D array when input is a 2D, single channel image, and 2D array when input is a 2D + c image.
Thoughts? @tonysyu, @JDWarner?