-
Notifications
You must be signed in to change notification settings - Fork 20
Add Hough transform #32
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
Conversation
|
Just as a note: The link to issue 465 is broken in your comment. I can c&p the text though. |
|
@hanslovsky fixed |
pom.xml
Outdated
| </dependency> | ||
| <dependency> | ||
| <groupId>net.imglib2</groupId> | ||
| <artifactId>imglib2-algorithm-gpl</artifactId> |
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 is a problem. The imglib2-algorithm-gpl component must not be a dependency here, both for legal reasons, as well as logistical/organizational ones.
pom.xml
Outdated
| </dependency> | ||
| <dependency> | ||
| <groupId>net.imglib2</groupId> | ||
| <artifactId>imglib2-ij</artifactId> |
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 is a problem. We must not depend on ImageJ 1.x here.
pom.xml
Outdated
| <!-- SCIFIO dependencies --> | ||
| <dependency> | ||
| <groupId>io.scif</groupId> | ||
| <artifactId>scifio</artifactId> |
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.
We must not depend on SCIFIO here. The imglib2-algorithm component should not need to read/write image formats.
| /.settings/ | ||
| /target/ | ||
|
|
||
| # IntelliJ |
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 should be a separate commit, with message like "Ignore IntelliJ metadata files"
| * | ||
| * rho = y * sin(theta) + x * cos(theta) | ||
| * @Override | ||
| * |
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.
Add yourself, as well as the original author(s), as @authors here.
| * For a given point, then, votes are placed along the curve | ||
| * | ||
| * rho = y * sin(theta) + x * cos(theta) | ||
| * @Override |
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.
The @Override annotation makes no sense here.
| private final double[] theta; | ||
| private ArrayList<double[]> rtPeaks; | ||
|
|
||
| final private static float computeLength(final long[] position) { |
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 apply the ImgLib2 style formatting to this class, so formatting is consistent with the rest of ImgLib2.
|
Thanks so much for working on this! It is looking really, really good! Three main concerns:
If you can address the above three things, I am happy. |
|
I notice that this PR covers hough line transform. Are there plans for hough circle transform? |
|
@ctrueden I really appreciate for the detailed code review, thanks! FIX:
TODO:
HELP:
|
OK. If the implementation would be more complicated without using this class, then I propose to add these Hough classes instead to imglib2-algorithm-gpl, to avoid circular dependency, and to have correct, legal licensing.
There are tons of unit tests across many components. We use JUnit. You could look at e.g. |
|
What exactly is the |
|
@panovr Did you try with |
|
@hanslovsky @ctrueden I will investigate |
|
I am taking care of the Hough circle transform. |
|
@tinevez OK, thank you very much! |
|
@tinevez are you planning to migrate your work in https://github.com/tinevez/CircleSkinner/tree/master/src/main/java/net/imagej/circleskinner/hough to |
|
Yes, before end of June. |
|
Christ I am late everywhere. |
|
@tinevez I'm sorry that I did not see this comment before, but I am just now beginning to move onto this project and would love to chat on Gitter! |
|
See also imagej/imagej-ops#526. |
|
@panovr did you have a look at |
|
@hanslovsky FYI, @panovr has moved on from LOCI (back to China, where has main project is machine learning classification and segmentation of bird species). But our student @gselzer could (will! 😉) work on completing this PR. |
|
Thanks for the update @ctrueden |
Ah okay now I understand what you mean by a high-level test. This is what
I think that the point @ctrueden and I are trying to make here is that this test has less to do with assuring the correctness of the algorithm and more to do with guaranteeing reproducability. This test will fail if any math changes and as such a success from this test is a sign that an output after an update to the algorithm is the same output that would have been given before. With that being said you are right in that it is not an indicator that the algorithm is working correctly; that is what |
|
|
||
| while ( imageCursor.hasNext() ) | ||
| { | ||
| double fRho; |
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.
No need to declare fRho and r outside the loop. Put declaration at initialization (line 393) and change r to long.
| for ( int t = 0; t < nTheta; ++t ) | ||
| { | ||
| fRho = Math.cos( theta[ t ] ) * imageCursor.getDoublePosition( 0 ) + Math.sin( theta[ t ] ) * imageCursor.getDoublePosition( 1 ); | ||
| r = Math.round( ( float ) ( ( fRho - minRho ) / dRho ) ); |
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.
- Do not cast to
floatbefore rounding. - Is rounding correct? That would mean that the value of each
rbin defines the center of said bin, not the min. If that is the desired behavior, ignore this second bullet point.
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.
@hanslovsky you are right about the cast. I do however think that this rounding is correct since we are using r to approximate our value of rho, meaning that we want to round up in the case that rho is closer to the r greater than it than it is to the r less than it, if that makes sense.
| { | ||
| for ( int t = 0; t < nTheta; ++t ) | ||
| { | ||
| fRho = Math.cos( theta[ t ] ) * imageCursor.getDoublePosition( 0 ) + Math.sin( theta[ t ] ) * imageCursor.getDoublePosition( 1 ); |
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.
x and y should be cached outside loop to avoid potential virtual method call overhead:
if ( filter.test( imageCursor.get() ) )
{
double x = imageCursor.getDoublePosition( 0 );
double y = imageCursor.getDoublePosition( 1 );
for () // continue as before.
}| final double minTheta = -Math.PI / 2; | ||
| final double dTheta = Math.PI / nTheta; | ||
|
|
||
| final double[] rho = new double[ nRho ]; |
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.
double[] rhois never used, can be removeddouble[] thetacaches theta but the expensive caclulations areMath.sin( theta )andMath.cos( theta ). Cache these instead.
this commit removes the unused rho[] LUT and refactors the theta[] LUT into two different LUTs for sin(theta) and cos(theta). This refactor speeds up later calculations
This commit changes the Predicate deciding whether to allow votespace population from being a strictly greater-than to a greater-than-or-equal-to comparison. This fix was made to prevent a bug in which no threshold is provided to the algorithm and at the same time the max value of the image is at the first index of the image. If the comparison is not <= then all pixels will fail the Predicate, since no pixel is greater than the max. This means that passing a value to the algorithm is still preferable but allows more scenarios where no value is given.
|
The build currently fails with JavaDoc errors. Most of those errors are unrelated and fixed in master. I locally merged with master and the only remaining JavaDoc error is this: This is an easy fix, just repleace |
| import net.imglib2.view.Views; | ||
|
|
||
| /** | ||
| * This abstract class provides some basic functionality for use with arbitrary |
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 documentation is not accurate anymore, should probably be something along the lines of:
This class provides static methods for the detection of lines in two-dimensional images via the Hough transform.
|
@hanslovsky I just fixed the error and the requested change in the most recent commit. Thanks for taking all the time and effort to get this project ready to merge! |
|
@gselzer I looked over it once more and it seems good to me. Thank you for putting the work in and bearing with me and all my pedantic requests. I will leave this open for a little bit longer (probably until the end of the week) to see if anyone else raises concerns, and then I will merge. Good work! |
|
@imglib/admins What is the appropriate merge strategy? Squash and merge? |
|
@hanslovsky I personally prefer "Create a merge commit" to preserve the history, assuming each commit compiles with passing tests. Otherwise, what is the point of making clean topic branches? That said, I am not an ImgLib admin—see Governance summary—so ultimately it is up to @tpietzsch and @axtimwalde and @StephanPreibisch. |
|
@ctrueden I was advised for my own (single-feature addition) PRs to rebase before a merge but I do not |
Doing that will do a fast-forward merge, which loses the fact that it was ever a branch. This is a bad thing which has caused social confusion and resentment in the past, where fingers were pointed and people were accused of "not working on a branch" even though they did at the time. I strongly encourage the ImgLib2 admins to use "Create a merge commit." This can still be combined with a rebase first, if you want the topic branch to sit on top the latest master. The goal is to avoid fast forward merges. |
|
@ctrueden sorry for the confusion. I was advised to rebase my branch, then the PR would be merged with a commit message. That was before github had options to rebase through the web interface. |
|
@ctrueden @hanslovsky the history of this pull request is painfully long and of limited educational value. It is certainly possible to ask @gselzer to rebase this post-fact into meaningful dissection supporting units but I also think that we all have a lot of stuff to do and this is not very helpful. I would therefore vote for squash and merge. |
|
@axtimwalde I don't see why further rebasing would be needed. The commits are already small and clean and granular. It sounds like your beef is really just that there are a lot of them but I think that helps bisectability, rather than harming it. There are no harmful intermediate states, are there? Why not just merge it? |
|
@axtimwalde @tpietzsch Should I go ahead and squash and merge? |
|
@hanslovsky yes. |
|
Thanks @gselzer |
This pull request is to port the Hough transform from ImgLib1 to ImgLib2, and also see this issue: imagej/imagej-ops#465