Skip to content
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

Integrate LabKit in TrackMate to edit segmentation results #302

Draft
wants to merge 46 commits into
base: master
Choose a base branch
from

Conversation

tinevez
Copy link
Member

@tinevez tinevez commented Jul 10, 2024

No description provided.

tinevez and others added 30 commits July 7, 2024 12:34
And remove Gson from now. Apparently there are incompatibilities
from the (same) declaration in LabKit pom, which triggers the
errors I complained about today on the forum.
This launcher catches what time-point is currently diplayed,
and wrap all information needed for LabKit to edit the spot
it contains, as labels.

While the user edits the labels in LabKit, the TrackMate UI is
disabled.

Once the user closes the LabKit window, the modifications they
made are inspected. This class compares the new labels with the
previous ones, and can determine whether a spot has
been added, removed or modified. In the last case it updates the
model with the modified spots, and reintroduces it in the tracks
as it should.

All features of modified spots and their edges are recomputed.

If a label has several connected components, they are added as
separate spots. The one closest to the original spot is reintroduced
in the tracks.

The label names are important: they are used to retrieve the original
spot id and the original spot shape for comparison.
If the user modifies a label, it will be perceived as a
new spot instead of a modified one.

Tested in 2D so far.
…ard.

But because the other table, trackscheme and bvv buttons take
too much place, we don't see it without resizing the window.
Otherwise the button for the editor is not visible without
resizing the window. I also had to programmatically resize the
main TrackMate frame after display so that components are
properly aligned. Such a hack for something simple...

Also give the editor button a proper name and a temporary icon.
- We don't depend on labels anymore, but directly operate and compare
the index images (before modification and after). Because the index
is directly related to the spot ID, we can get a match from previous
spot to novel spot in an easy manner.

- The spots from the edited version are created directly from the
novel index image, using something adapted from the label image
detector code, so again, just one pass. We use the fact that we can
provide it with a 'quality' image, and read the index of the label
image 'under' the spot and write it into its quality value.
This way we can retrieve the id of the matching previous
spot in an easy manner.

- The price to pay for not working with labels anymore
is that we don't have access to the label name, but that's life.

- We make only one pass over the image to collect the ids of the spots
that have been modified, instead of one pass per spot. Also, this
pass is multithreaded (thanks LoopBuilder).

- I have also learned that I should not use weakListeners() if I
am doing something with threads inside the listener. Using listeners()
instead works, but I do not know why the other one does not.
Probably something arcane with Java WeakReferences being collected.

- As a result of all this the performance is much better than before
and the 'return to TrackMate' should happen without the user noticing
the process.
I wanted to use it to check whether the user has activated the
'LabKit' update site, but apparently the labkit jars are included
with vanilla Fiji.
Let them choose to discard or commit the changes.
So that the image in the LabKit window opens with the same
display settings than in the ImagePlus main view.
We don't need the Labeling wrapper.
The LabKit editor worked fine foe us but only in 2D.
In 3D the labels imported from the spots into LabKit were off along
the Z axis, as if the Z caibration was not handled properly. This
was caused by the custom BDV showable I made missing some important
preparation steps. I simply copied these steps from the working
version of BDVShowabble in the core LabKit code.
And remove debug code.
I am not so sure it is a good idea for the color...
and use the white LUT when the imp is not displayed as a Composite.
Otherwise we get crashes when we have more than 4k labels. Which is not
what Labkit is optimized for but we will see that in a second time.
In case we change our minds on the backing integer type, right now
the labkit launcher and importer classes are generic.
The re-importing of labels from Tabkit to TrackMate could fail for
2D images and labels with a large index. For instance, it failed
consistently when trying to re-import labels with an index larger
than 65643.

This problem roots in the getSpots() method of LabkitImporter. It
relies on a trick: We get the new label image, and create spots from
this label image. But we want the new spots to keep track of the index
in the label image they were generated from.

For this, in 2D, we use the MaskUtils.fromLabelingWithRoi()
method. These methods accept an image as last argument used to
read a value in the label image within the spot, that is normally
used for the quality value of the new spot.

But the SpotRoiUtils.from2DLabelingWithRoi() method converted the
extra image to ImagePlus (because I was lazy). So the label image
was effectively cast on ushort for an IntegerType image, hence
the problem with the max label being 65453.

The solution is to rewrite the from2DLabelingWithRoi() so that
it does not rely on converting to ImagePlus, but on good old
iteration with imglib2.
Provided that the detector that is called is cancelable.
@tinevez tinevez marked this pull request as draft July 10, 2024 13:14
tinevez and others added 13 commits July 10, 2024 20:53
The bug was causing weird issues with unedited spots being deleted,
unedited spots being duplicated etc.

It took me really long to understand the cause. It was hidden in the
step where we go from a label image to a collection of spots. Because
spots are polygons, with simplified contours, there might be some pixels
on the edges of the object that are not strictly inside the label.

In this importer, we read the label value in one go, by storing it
in the QUALITY value of the spot, in the MaskUtils class. But since
the spots have simplified contours, and since the QUALITY value is
the maximal value iterated over, our approach might fail on border cases:
- when the contout is approximated and include pixels from another
object
- and when this object has a label value higher than the lael of
the spot.

This commit include a temporary fix: we reiterate over the spot
but takes the median value iterated over, to make sure we read
the correct value for the label.

Other attempts will follow, for reference. But a true fix involves
making a method that returns a map from label value to spot.
This time we fix it by creating spots that do not have a simplified
contours. In that case we strictly iterate over the pixels inside
label and get the correct value.
However the created spots have a pixelated aspect (contours are
not simplified), which might not be what the user wants. We should
let them choose.

Still not the perfect solution, as mentionned in the previous
commmit.
Use the new label immg to spot method to get spots AND the
label they come from.
Also better message when closing the editor.
If a ROI exists in the input image when launching the LabKit editor,
only the image and the spots present in the ROI are sent to the
editor. Spots touching the borders are not imported.
Normally pressing space and dragging should move the view, as
for normal ImageJ tools. The removed line was preventing it.
When editing a sub-portion of the image, the spots outside the ROI
are not imported in the editor. It is possible that the user creates
a new label in LabKit that will have the same id that an existing
spot outside the ROI.
Before this fix, the spots in that case were replaced by the new ones,
creating a mess.
The fix consists in reminding what spots are imported in the LabKit
editor, then compariing to this list the new ids when reimporting
from the editor.
Simplified, removing the menu, the segmentation features and the
segmenter features.
Somply done by copy-pasting Matthias classes and removing the lines
with the features to prune.
This time it was due to confusion between a map from spot ID to spots,
and a map from label value to spot.
I fixed it by rewriting everything in terms of label values in the
labeling. So we do not need to keep track of the spot ID anymore. The
labels could be anything. They are still equal to spot ID + 1, because
it is convenient to debug.
When editing the whole movie, if the label of a new spot was using
the label of an existing spot in another time-point, the existing
one was removed. Because the new spot was identified as a modification
of the existing one.
The solution is to pass to the importer only the list of existing
spots in the current time-frame.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant