by

Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
    Christian "Tischi" Tischer
    @tischi

    ...and I have a question (as always ;-)

    I developed a rather long imglib2 image registration workflow:
    https://github.com/tischi/fiji-plugin-imageRegistration/blob/master/src/main/java/de/embl/cba/registration/commands/DrosophilaRegistration.java#L85
    ... and am now having the issue that I might want to debug/optimize the last step. As IntelliJ is no Jupyter Notebook it is not so easy to only work on the last (say 10th) step without always running all the 9 steps before. How do you guys deal with this? Is the "Evaluate expression" option of the debugger the way to go...?

    Florian Jug
    @fjug
    Its certainly an option. If possible I tend to store all results falling ou of step 9 and load them in order to perform step 10. This requires writing same save-load stuff that will be trashed later, but it can be worth it.
    Not sure if this helps.
    Another option: KNIME (but that does also not always apply, of course)
    Curtis Rueden
    @ctrueden
    @tischi KNIME and Jupyter are both great options. Otherwise, if the result of step 9 is open image(s) and/or table(s), you can just have a second script in the Script Editor—or an expression in the Script Interpreter—to repeatedly execute step 10 on that input image. It's only a problem if step 10 mutates the input, in which case you have to make a copy first.
    Christian "Tischi" Tischer
    @tischi
    @ctrueden and @fjug Thank you for the suggestions!
    Christian "Tischi" Tischer
    @tischi

    As I learned in the course when using imglib2 for object segmentation your friends are:

    import net.imglib2.algorithm.labeling.ConnectedComponents;
    import net.imglib2.roi.labeling.ImgLabeling;

    What is the recommended workflow to do object related things like

    (i) measuring the volume of the objects, or
    (ii) filtering objects, e.g make a new mask image that contains only the largest object; and
    (iii) getting more complex shape descriptors (e.g. surface or perimeter).

    Are there "convenience" functions (maybe based on the new ROIs) for such "object-based operations" or does one have to loop through all the pixels and then write code like below to, e.g., filter out one object (code is also taken from the course):

            final RandomAccessibleInterval< UnsignedByteType > l30 = Converters.convert(
                    ( RandomAccessibleInterval< LabelingType< String > > ) labeling,
                    ( i, o ) -> {
                        o.set( i.contains( "l30" ) ? 255 : 0 );
                    }, new UnsignedByteType() );
    Jan Eglinger
    @imagejan

    (i) the Segment Features node in KNIME
    (ii) the Segment Features node in KNIME
    (iii) the Segment Features node in KNIME
    ;) @tischi

    re (ii) you might also want to use the Row Filter and the GroupBy with aggregation method "Create Labeling" in combination, or for other use cases the Labeling filter node

    re (iii) alternatively, the Feature Calculator (BETA) node

    tpietzsch
    @tpietzsch
    @tischi have a look at LabelRegions
    tpietzsch
    @tpietzsch
    that should allow to do anything (i), (ii) related in imglib2
    for (iii) I don't know if anything is there
    Christian "Tischi" Tischer
    @tischi
    @imagejan Thanks, I got the message :) But I want to also learn how to use imglib2!
    @tpietzsch thanks a lot!
    Christian "Tischi" Tischer
    @tischi
    ...and I am having already another question :-)
    I would like to do down-scaling of images in imglib2 in such a way that the pixels in the down-scaled images are averages values of pixels in the original image. Basically what in IJ1 would be [ Image > Scale...]. Simplest application would be "average 2x2x2 binning", which would correspond to scaling of 0.5 x 0.5 x 0.5. Is below code the right thing to do?
    // input rai from somewhere
    AffineTransform3D scalingTransform3D = new AffineTransform3D();
    scalingTransform3D.scale( 0.5 );
    RealRandomAccessible rra = Views.interpolate(  Views.extendZero( rai ), new NLinearInterpolatorFactory() );
    rra = RealViews.transform( rra, scalingTransform3D );
    RandomAccessible binnedRA = Views.raster( rra );
    tpietzsch
    @tpietzsch
    almost right
    imglib2 puts integer samples coordinates in "pixel centers"
    so bilinear downscaled pixel (0,0,0) lands at (0,0,0) of original image and will not see any other pixel
    you should also translate by 0.5 so that downscaled (0,0,0) lands at (.5,.5,.5) of original image
    then bilinear interpolation will give you original voxels (0,0,0), (1,0,0), ..., (1,1,1) in equal proportions
    which gives you what you want
    there is also some explicit averaging of voxel blocks somewhere in bigdataviewer-core (for exporting mipmap levels)
    Curtis Rueden
    @ctrueden
    @tischi Why not simply transform.scaleView op? Am I missing something?
    Christian "Tischi" Tischer
    @tischi
    @tpietzsch:
    (i) where shall I add the translation: into the scalingTransform3D?
    (ii) does this also work for other factors than 0.5, e.g. 0.25 where it would have to average over 4 pixels in each dimension? Or does it always only see the nearest neighbors?
    Christian "Tischi" Tischer
    @tischi
    @ctrueden: Thanks for the hint! But I'd really like to learnathon imglib2!
    Christian "Tischi" Tischer
    @tischi
    @ctrueden, @tpietzsch I had a look at the code for the scaleView op and, to me, it looks pretty much like my code: https://github.com/imagej/imagej-ops/blob/master/src/main/java/net/imagej/ops/transform/scaleView/DefaultScaleView.java#L84
    In particular, the shifting away from integer pixel coordinates is also missing. Does that mean that the scaleView op in its current implementation would maybe a also rather do sub-sampling than averaging?
    Curtis Rueden
    @ctrueden
    @tischi Sure. But why not read the source code of transform.scaleView to see how it does it using ImgLib2?
    Oh, right, that's what you just said above. OK, great.
    I defer to @tpietzsch on whether he would recommend changes to the op along the lines of those discussed above.
    @tischi Have you had a chance to try the revamped single instance listener CLI flags yet?
    Vladimír Ulman
    @xulman
    @tischi, regarding iii), you can have a look into ops/geom/geom3d...
    one would need to convert your binary mask into a mesh (with MarchingCubes) and then query its geom. parameters... the folder essentially list available options
    tpietzsch
    @tpietzsch
    @tischi @ctrueden it only works for averaging over 2 pixels in each dimension
    it is simply bilinear interpolation
    shifting by 0.25 in each dim would mix neighbors by factor 0.25 and 0.75 respectively
    Whether the op should change depends on what it is supposed to do
    As it is, it would with scale factor 0.5 and Nlinear interpolator factor just pick every second pixel (i.e., no bilinear interpolation happening really)
    tpietzsch
    @tpietzsch
    However, I would not shift by 0.5 here.
    This only works for factor 0.5, by accident so to say.
    in the op you could pick scale 1.3 etc
    Curtis Rueden
    @ctrueden
    @tpietzsch Thanks, that makes sense. As for what the op is supposed to do: I don't think it is thoroughly formalized (yet). My weak preference is to keep it simple here and not do any translation. But we ought to document what will happen to the min/offset of the input image.
    tpietzsch
    @tpietzsch
    The way to improve the quality of the results would be implementing a better InterpolatorFactory
    Curtis Rueden
    @ctrueden
    *nod*
    Christian "Tischi" Tischer
    @tischi
    @ctrueden Regarding the single instance listeners: should it work after updating Fiji? I have an up-to-date Fiji and it throws: [WARNING] Ignoring invalid argument: --force-single-instance
    Curtis Rueden
    @ctrueden
    @tischi Did you put it to the right of a -- separator argument, as I described?
    The launcher is unfortunately a bit stupid about which arguments belong to the JVM itself vs. main methods.
    Christian "Tischi" Tischer
    @tischi

    ...just to make sure I have the latest Fiji:
    /Applications/Fiji.app/Contents/MacOS/ImageJ-macosx --update update
    ...and I just copy and pasted your code:
    /Applications/Fiji.app/Contents/MacOS/ImageJ-macosx -Dscijava.log.level:net.imagej.legacy=debug --force-single-instance -port2 --ij2 --open /Users/tischer/Desktop/blobs.tif

    [WARNING] Ignoring invalid argument: -Dscijava.log.level:net.imagej.legacy=debug [WARNING] Ignoring invalid argument: --force-single-instance [ERROR] Skipping unsupported option -port2

    btw: what does the port* do?
    Curtis Rueden
    @ctrueden
    Agh, did I leave it off? Shoot.
    Contents/Home/ImageJ-macosx -Dscijava.log.level:net.imagej.legacy=debug -- --force-single-instance -port2 --ij2 --open ~/Desktop/General_EduRes_Heart_BloodVessels_0.jpg