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
Improve ContourTracing performance #1520
Conversation
Alternative approach that relies more heavily on JTS and Polygonize.
This makes `ContourTracing` much faster in some circumstances - especially when labeled images were involved. There are two main differences: 1. Previously, the code would tend to loop through all pixels to generate the contour for each label; now it generates bounding boxes in a single loop, and then iterates only through the relevant bounding box for each label (when using `createROIs`) 2. The tracing algorithm has been replaced by a reliance on JTS's `Polygonizer` class; this was already used before, but now we rely on it more heavily. The second of these makes this *slightly* risky - I encountered exceptions and infinite loops along the way, so this needs to be tested very carefully.
qupath-core/src/main/java/qupath/lib/analysis/images/ContourTracing.java
Show resolved
Hide resolved
Speed improvement is really noticable! There is a non-zero chance that I'm misunderstanding this, but I strongly dislike this if/else block. First, I'd prefer to get the short block out of the way first by an early return. qupath/qupath-core/src/main/java/qupath/lib/analysis/images/ContourTracing.java Lines 608 to 647 in a9e4c5c
Second, is this for loop doing anything? qupath/qupath-core/src/main/java/qupath/lib/analysis/images/ContourTracing.java Lines 642 to 646 in a9e4c5c
If |
Thanks! I've just pushed some changes that I was working on while you were reviewing... since it basically rewrites |
The I was having trouble with locationtech/jts#874 but these problems seem to have disappeared... slightly concerningly as I'm not entirely sure what I changed to make them disappear. That's my main worry about this PR. |
if (p > maxValue) | ||
maxValue = p; | ||
var envelopes = new HashMap<Number, Envelope>(); | ||
if (minLabel != maxLabel) { |
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.
Can we invert this if/else? Keeps the start of the two branches closer to the relevant condition
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 don't mind. I thought it was easier to read to show the use of envelopes before showing their non-use in a special case.
Yeah, I didn't come across that myself yet trying a few images, are we using a version of JTS that at least has the exception code to avoid infinite loops? Aside from style it all looks good and correct to me, but I wouldn't necessarily use that as strong evidence that it is :) |
As far as I can tell, there isn't a version of JTS that has the exception bit merged - just a commit on a fork. An infinite loop was what I was seeing, unfortunately. Was wondering if we should reinstate the old code and activate it via a system properly, but since the old code also uses |
This makes
ContourTracing
much faster in some circumstances - especially when labeled images were involved.There are two main differences:
createROIs
)Polygonizer
class; this was already used before, but now we rely on it more heavily.The second of these makes this slightly risky - I encountered exceptions and infinite loops along the way, so this needs to be tested very carefully.