How to install and use plugins in jython imagej scripts?

Because this plugin https://imagej.net/MorphoLibJ is actually the only 3d implementation of mathematical morphology I have found, I need to use it through the imagej api. I am used to opencv and other python plugins but imagej is new for me…

I have managed to open a stack of images as a stack, but now I have really no idea how I am supposed to install and call the third party plugin…

Thank you very much, I am very late on my master thesis, any help would save my life…

Well the link to the API could help:

To use the MorpholibJ and OpenCV API make sure to enable their update sites (IJ-OpenCV for the last one). Help>Update>Manage Update sites

And this wiki page should help you getting started.
You can also look at the source codes in the github repositories of those 2 projects for examples of imports (similar between Java and Jython)

So I should try to update using the gui, that is how I should install it ?

@eizanprime Do you need to call the ImageJ API from a Python script, combining with other Python libraries? Or is Jython good enough for your purposes?

The ImageJ Ops library—included with ImageJ2—also has some N-dimensional mathematical morphology functions, including 8-bit grayscale morphology functions.

Here is tutorial code in 2D:

But should work in 3D as well.

If Ops doesn’t have what you need, and you still want to call MorphoLibJ, let us know and we can post some sample code for that, too. Though I suggest checking the documentation first:

Thank you so much for your help !

I could do everything via imagej in jython, but because I have very limited time and I don’t know well the framework at all.

My goal is quite simple, to use 3D mathematical morphology on dicom files, then to extract metrics, and also classical radiomic metrics from the modified images inside the ROI provided by a dicomRT I am sure it is possible to do all of this in imagej, but I think it will be faster for me to just open the modified image stacks into classical python and use other libraries for that.

So basically my goal now is just to find a way to do 3D mathematical morphology…

ImageJ Ops looks very promising, I will try to use it right now. But I would still like to know how to use Morpholibj as it has more functionalities, and if I know how to use one plugin I can figure out how to use others…

I am sad that I discovered imagej so late…

Thank you so much for your help, I am very grateful !!

1 Like

If your goal is to do 3D mathematical morphology MorphoLibJ is excellent.
However, if you are more fluent in the python/numpy field, scikit-image can also do 3D mathematical morphology and is worth a look. The latest version (0.15) integrated this pull request from Thomas Walter which also brought attribute operators to scikit image.

1 Like

Here is an example of using MorphoLibJ inside a python script from Fiji. Maybe it helps to get started.

# @File(label = "Image File", persist=True) FILENAME
# @Integer(label = "Select Channel", value=1, persist=True) CHANNEL2ANAlYSE
# @String(label = "Label Connectivity", choices={"6", "26"}, style="listBox", value="6", persist=True) LABEL_CONNECT
# @Integer(label = "MinVoxelSize", value=200, persist=True) MINVOXSIZE
# @Boolean(label = "Colorize Labels", value=True, persist=True) LABEL_COLORIZE
# @Boolean(label = "Save Particle Stack", value=True, persist=True) PASAVE
# @String(label = "Choose Save Format", choices={"ome.tiff", "png", "jpeg", "tiff"}, style="listBox", value="ome.tiff", persist=True) SAVEFORMAT
# @Boolean(label = "Save Result File as TXT", value=True, persist=True) RESULTSAVE
# @Boolean(label = "Run in headless mode", value=False, persist=False) HEADLESS
# @OUTPUT String FILENAME
# @OUTPUT Integer CHANNEL2ANAlYSE
# @OUTPUT String LABEL_CONNECT
# @OUTPUT Integer MINVOXSIZE
# @OUTPUT Boolean LABEL_COLORIZE
# @OUTPUT Boolean PASAVE
# @OUTPUT String SAVEFORMAT
# @OUTPUT Boolean RESULTSAVE
# @OUTPUT Boolean HEADLESS

#@UIService uiService
#@LogService log


"""
File: 3d_analytics_CH.py
Author: Sebastian Rhode
Date: 2019_03_14
Version: 0.5
"""

# append path
import os
import sys
scriptdir = os.path.join(os.getcwd(), 'Scripts')
sys.path.append(scriptdir)
log.info('Fiji Script Directory: ' + scriptdir)

from fijipytools import ExportTools, FilterTools, ImageTools, ImportTools
from fijipytools import AnalyzeTools, RoiTools, MiscTools, ThresholdTools
from java.lang import Double, Integer
from ij import IJ, ImagePlus, ImageStack, Prefs
from ij.process import ImageProcessor, ImageConverter, LUT, ColorProcessor
from ij.plugin import Thresholder, Duplicator
from ij.plugin.filter import GaussianBlur, RankFilters, BackgroundSubtracter, Binary
from ij.plugin.filter import ParticleAnalyzer as PA
from ij.plugin.frame import RoiManager
from ij.io import FileSaver
from ij.gui import Roi, Overlay
from ij.measure import ResultsTable
from ij.plugin import ChannelSplitter

import json
import os
import urllib
from java.awt import Color
from java.util import Random
from jarray import zeros
from org.scijava.vecmath import Point3f, Color3f

# MorphoLibJ imports
from inra.ijpb.binary import BinaryImages
from inra.ijpb.morphology import MinimaAndMaxima3D, Morphology, Strel3D
from inra.ijpb.watershed import Watershed
from inra.ijpb.label import LabelImages
from inra.ijpb.plugins import ParticleAnalysis3DPlugin, BoundingBox3DPlugin, ExtendBordersPlugin
from inra.ijpb.data.border import BorderManager3D, ReplicatedBorder3D
from inra.ijpb.util.ColorMaps import CommonLabelMaps
from inra.ijpb.util import CommonColors
from inra.ijpb.plugins import DistanceTransformWatershed3D

############################################################################


def run(imagefile):

    # Opening the image
    log.info('Opening Image: ' + imagefile)

    # open image file and get a specific series
    imp, MetaInfo = ImportTools.openfile(imagefile)

    log.info('File Extension   : ' + MetaInfo['Extension'])
    if 'ResolutionCount' in MetaInfo:
        log.info('Resolution Count : ' + str(MetaInfo['ResolutionCount']))
    if 'SeriesCount' in MetaInfo:
        log.info('SeriesCount      : ' + str(MetaInfo['SeriesCount']))
    if 'ChannelCount' in MetaInfo:
        log.info('Channel Count    : ' + str(MetaInfo['ChannelCount']))

    # do the processing
    log.info('Start Processing ...')

    # get the correct channel
    if MetaInfo['ChannelCount'] > 1:
        log.info('Extract Channel  : ' + str(MetaInfo['ChannelCount']))
        imps = ChannelSplitter.split(imp)
        imp = imps[CHINDEX-1]
   
    # extend borders
    log.info('Applying Border Extension ...')
    # create BorderManager and add Zeros in all dimensions
    bmType = BorderManager3D.Type.fromLabel("BLACK")
    bm = bmType.createBorderManager(imp.getStack())
    BorderExt = ExtendBordersPlugin()
    # extend border by always exb
    imp = BorderExt.process(imp.getStack(), EXB, EXB, EXB, EXB, EXB, EXB, bm)
    # convert back to ImgPlus
    pastack = ImagePlus('Particles', imp)

    # check for pixel in 3d by size
    log.info('Filtering VoxelSize - Minimum : ' + str(MINVOXSIZE))
    pastack = BinaryImages.volumeOpening(pastack.getStack(), MINVOXSIZE)
    imp = ImagePlus('Particles Filtered', pastack)
    pastack = BinaryImages.componentsLabeling(imp, LABEL_CONNECT, LABEL_BITDEPTH)

    # get the labels
    labels = LabelImages.findAllLabels(pastack)
    log.info('Labels Filtered : ' + str(len(labels)))

    # run 3D particle analysis
    log.info('3D Particle Analysis ...')
    PA3d = ParticleAnalysis3DPlugin()
    results = PA3d.process(pastack)

    # colorize the labels
    if LABEL_COLORIZE:
    
        log.info('Colorize Lables ...')
        #maxLabel = 255
        maxLabel = len(labels)
        bgColor = Color.BLACK
        shuffleLut = True
        lutName = CommonLabelMaps.GOLDEN_ANGLE.getLabel()

        # Create a new LUT from info in dialog
        lut = CommonLabelMaps.fromLabel(lutName).computeLut(maxLabel, shuffleLut)

        #  Create a new RGB image from index image and LUT options
        pastack_rgb = LabelImages.labelToRgb(pastack, lut, bgColor)

        # convert to rgb color
        IJ.run(pastack_rgb, "RGB Color", "slices")

    if LABEL_COLORIZE:
        return pastack_rgb, results, labels
    elif not LABEL_COLORIZE:
        return pastack, results, labels

################################################################################


if not HEADLESS:
    # clear the console automatically when not in headless mode
    uiService.getDefaultUI().getConsolePane().clear()

###### Define various parameters ######
MAXSIZE = Double.POSITIVE_INFINITY
CHINDEX = Integer.valueOf(CHANNEL2ANAlYSE)
SUFFIX_PA = '_PA'
SUFFIX_RT = '_RESULTS'
SAVEFORMAT_RT = 'txt'
IMAGESERIES = 0
LABEL_BITDEPTH = 16
LABEL_CONNECT = Integer.valueOf(LABEL_CONNECT)
EXB = 1

# get the FILENAME as string
imagefile = FILENAME.toString()

log.info('Starting pipeline ...')
log.info('Image Filename        : ' + imagefile)
log.info('Channel to Analyse    : ' + str(CHINDEX))
log.info('Label Connectivity    : ' + str(LABEL_CONNECT))
log.info('Label Output BitDepth : ' + str(LABEL_BITDEPTH))
log.info('Colorize Labels       : ' + str(LABEL_COLORIZE))
log.info('Minimun Voxel Size    : ' + str(MINVOXSIZE))
log.info('Headless Mode         : ' + str(HEADLESS))
log.info('------------  START IMAGE ANALYSIS ------------')


# run image analysis pipeline
objstack, results, labels = run(imagefile)


# show objects
log.info('Show Objects inside stack ...')
objstack.show()

log.info('Show ResultsTable ...')
results.show('3D Objects')

outputimagepath = os.path.splitext(imagefile)[0] + SUFFIX_PA + '.' + SAVEFORMAT

if PASAVE:
    log.info('Start Saving ...')
    savepath_objstack = ExportTools.savedata(objstack,
                                             outputimagepath,
                                             extension=SAVEFORMAT)

    log.info('Saved Processed Image to : ' + savepath_objstack)

# save the result file
if RESULTSAVE:
    # save the result table
    rtsavelocation = AnalyzeTools.create_resultfilename(imagefile,
                                                        suffix=SUFFIX_RT,
                                                        extension=SAVEFORMAT_RT)
    results.saveAs(rtsavelocation)
    log.info('Save Results to : ' + rtsavelocation)

# finish
log.info('Done.')
3 Likes