User Tools

Site Tools


documents:120206pyip_cooking:python_imagej_cookbook

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
documents:120206pyip_cooking:python_imagej_cookbook [2025/05/21 03:59] kotadocuments:120206pyip_cooking:python_imagej_cookbook [2025/10/05 22:53] (current) – [Converting Java array types] kota
Line 3: Line 3:
 This page was last edited at: ~~LASTMOD~~ This page was last edited at: ~~LASTMOD~~
  
-For learning image processing using Fiji and Jython scripting, go to excellent tutorials written by Albert Cardona, such as [[https://www.ini.uzh.ch/~acardona/fiji-tutorial/ | here on his website]] or [[https://imagej.net/Jython_Scripting | here on ImageJ.net]]. The former is in a tutorial style, so if you want to learn scripting using Jython, that's where you go. Recently, there has been a perfect tutorial page for real beginners: [[https://learning.rc.virginia.edu/courses/fiji-image-processing/scripting/|here (UVA Research Computing Learning Portal).]]  +For learning image processing using Fiji and Jython scripting, go to excellent tutorials written by Albert Cardona, such as [[https://syn.mrc-lmb.cam.ac.uk/acardona/fiji-tutorial/ | here on his website]] or [[https://imagej.net/Jython_Scripting | here on ImageJ.net]]. The former is in a tutorial style, so if you want to learn scripting using Jython, that's where you go. Recently, there has been a perfect tutorial page for real beginners: [[https://learning.rc.virginia.edu/courses/fiji-image-processing/scripting/|here (UVA Research Computing Learning Portal).]]  
  
 This page is like a cookbook: there are no details about how to do programming, but more centered on how to use the Classes built into ImageJ and its plugins. This is because the style each algorithm is implemented is not consistent (they are written by 1000 different people!), so it takes a while to figure out how to use them when we are writing a bioimage analysis workflow. Examples below show how they are used in Jython scripts, to save us time for reading the source code of each.  This page is like a cookbook: there are no details about how to do programming, but more centered on how to use the Classes built into ImageJ and its plugins. This is because the style each algorithm is implemented is not consistent (they are written by 1000 different people!), so it takes a while to figure out how to use them when we are writing a bioimage analysis workflow. Examples below show how they are used in Jython scripts, to save us time for reading the source code of each. 
Line 719: Line 719:
 ==== ImagePlus Array ==== ==== ImagePlus Array ====
  
-Some arguments ask for an array of specific type. Since Python array is not java array, {{http://onlamp.com/pub/a/python/2002/04/11/jythontips.html?page=2|one should generate a Java array}}. For this, you could use jarray package. +Some arguments ask for an array of specific type. Since Python array is not Java array, {{https://www.tutorialspoint.com/jython/jython_using_java_collection_types.htm|one should generate a Java array}}. For this, you could use the jarray package. 
 <code python linenums:1> <code python linenums:1>
 import jarray import jarray
Line 748: Line 748:
 </code> </code>
  
 +==== Java native 2D Array from Python2D ====
 +To initialize a Java native 2D array (e.g. float[][]), create a Python 2D array first, then convert it to a Java 2D array using jarray. See the example code below. 
 +
 +<code python>
 +import jarray
 +import java.lang.Class
 +
 +#prepare 3x2 matrix
 +py2Dlist = [[float(0)]*2]*3
 +
 +print(py2Dlist)
 +# [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]
 +print(type(py2Dlist)) 
 +# <type 'list'>
 +
 +java2Dlist = jarray.array(py2Dlist,java.lang.Class.forName("[F"))
 +
 +print (java2Dlist)
 +# array([F, [array('f', [0.0, 0.0]), array('f', [0.0, 0.0]), array('f', [0.0, 0.0])])
 +
 +print(type(java2Dlist))
 +# <type 'array.array'>
 +
 +print(java2Dlist[1][1])
 +#0.0
 +
 +</code>
 +
 +"java.lang.Class.forName("[F")" is the reflection, and the name of the Java native float class is "[F".
 +
 +==== Creating floating point processor image ====
 +
 +Java float 2D array can also be made using jarray.zeros (like numpy.zeros). 
 +Here is an example of creating a floating-point image from 2D array. 
 +
 +<code python linenums:1>
 +from jarray import zeros
 +from ij import ImagePlus
 +from ij.process import FloatProcessor
 +
 +#generate 200 x 100 floating point matrix
 +matrix2D = [zeros(100, 'f')]*200
 +
 +# check the generated matrix
 +print(matrix2D)
 +#[array('f', [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ...
 +rows = len(matrix2D)
 +cols = len(matrix2D[0])
 +print("rows {} cols {}".format(rows, cols))
 +#rows 200 cols 100
 +
 +# instantiate FP image
 +fp = FloatProcessor(matrix2D)
 +
 +#check created FP image
 +print("image width {} height {}".format(fp.getWidth(), fp.getHeight()))
 +ImagePlus('fp', fp).show()
 +</code>
 +
 +In short, as simple as:
 +<code python linenums:1>
 +from jarray import zeros
 +from ij import ImagePlus
 +from ij.process import FloatProcessor
 +
 +matrix2D = [zeros(100, 'f')]*200
 +ImagePlus('fp', FloatProcessor(matrix2D)).show()
 +</code>
 +
 +
 + 
 ==== Converting Java array types ==== ==== Converting Java array types ====
  
-Sometimes we need to convert the type of Java array e.g. double[] to int[]. For this, there is no magic trick and need to run a loop. Below is a code fragment. +Sometimes we need to convert the type of Java array e.g. double[] to int[]. In Java we can do this by for-loop with casting from float to int, but in Jython we can use the map function 
  
 <code:py>  <code:py> 
 +from ij import IJ
 from ij.process import StackStatistics from ij.process import StackStatistics
 import jarray import jarray
  
 +imp = IJ.getImage() #stack
 stackstats = StackStatistics(imp) stackstats = StackStatistics(imp)
-histD = stackstats.histogram() +histD = stackstats.histogram() #double[] returned, taken as floats in python 
-hist = jarray.zeros(len(histD), 'i'+print(type(histD[0])) 
-for i in range(len(histD)): + 
-    hist[iint(histD[i])+hist = map(int, histD) 
 +histInt = jarray.array(hist, 'i'
 +print(type(histInt[0])) #Java int[]
 </code> </code>
  
Line 1208: Line 1283:
 # here is only listing mean intensity of ROIs # here is only listing mean intensity of ROIs
 # if you want more, see  # if you want more, see 
-# http://rsbweb.nih.gov/ij/developer/api/ij/process/ImageStatistics.html+# http://imagej.net/ij/developer/api/ij/process/ImageStatistics.html
 for r in ra: for r in ra:
  ip.setRoi(r)  ip.setRoi(r)
Line 1233: Line 1308:
 ==== Union of multiple ROIs ==== ==== Union of multiple ROIs ====
  
-For combining multiple ROIs, {{http://rsbweb.nih.gov/ij/developer/api/ij/gui/ShapeRoi.html|ShapeRoi}} class is useful. +For combining multiple ROIs, [[http://imagej.net/ij/developer/api/ij/gui/ShapeRoi.html|ShapeRoi]] class is useful. 
  
 <code python linenums:1> <code python linenums:1>
Line 1241: Line 1316:
 sr3 = sr1.or(sr2) sr3 = sr1.or(sr2)
 </code>  </code> 
-sr3 is then a combination of ROIs roi1 and roi2. In similar waythere are AND, XOR, NOT and so on, logical operations+sr3 is then a combination of ROIs roi1 and roi2. ShapeRoi allows upi to perform logical operations between ROIssuch as AND, XOR, NOTand so on. 
  
 ==== Mask to selection (Binary to Selection) ==== ==== Mask to selection (Binary to Selection) ====
Line 1260: Line 1335:
 </code> </code>
  
 +==== Mask to multi-points selection, then to segmented line ROI ====
 +
 +The code above converts the mask to an area ROI. Sometimes, like for a skeletonized binary image, the mask needs to be converted to a segmented line ROI instead of a bounded region. 
 +
 +Here is the way to do this conversion. The first step is to convert the mask to a multipoint ROI. 
 +The second step is to convert this multipoint ROI to a segmented line ROI. 
 +
 +<code python linenums:1>
 +''''
 +conversion of mask (skeltonized) to multipoint ROI 
 +and then to segmented ROI
 +'''
 +
 +from ij import IJ
 +from ij.measure import CurveFitter
 +from ij.gui import PolygonRoi, Roi, PointRoi
 +from fiji.util import IntArray
 +from java.awt import Color
 +
 +# convert mask (black background, white mask) to multipoint ROI
 +#https://github.com/fiji/Fiji_Plugins/blob/main/src/main/java/fiji/selection/Binary_to_Point_Selection.java
 +def Binary_to_Point_Selection(imp):
 + ip = imp.getProcessor()
 + w = ip.getWidth()
 + h = ip.getHeight()
 + x = IntArray();
 + y = IntArray();
 + for j in range(h):
 + for i in range(w):
 + if (ip.getf(i, j) > 127):
 + x.add(i)
 + y.add(j)
 + imp.setRoi(PointRoi(x.buildArray(), y.buildArray(), x.size()))
 +
 +def getSlopeByFitting(xcoords, ycoords):
 + cf = CurveFitter(xcoords, ycoords)
 + cf.doFit(CurveFitter.STRAIGHT_LINE)
 + print(cf.getFormula())
 + slope=cf.getParams()[1]
 + print("slope:"+str(slope))
 + return slope
 +
 +# avoid chaos when horizontal mask(line) is horizontal
 +# in such cases, points are in random positions along the line. 
 +# sorting by x value fixes this chaos. 
 +def sortCoordinates(xcoords, ycoords):
 + slope = getSlopeByFitting(xcoords, ycoords)
 + zipped = zip(xcoords, ycoords)
 + if abs(slope)<1:
 + sortedzip = sorted(zipped)
 + else:
 + sortedzip = sorted(zipped, key=lambda x: x[1])
 + return zip(*sortedzip)
 +
 +imp = IJ.getImage()
 +Binary_to_Point_Selection(imp)
 +
 +# multipoint ROI to segmented line ROI
 +xcoords = [aroi.x for aroi in imp.getRoi()]
 +ycoords = [aroi.y for aroi in imp.getRoi()]
 +#imp.setRoi(newRoi)
 +
 +xcoords, ycoords = sortCoordinates(xcoords, ycoords)
 +
 +segroi = PolygonRoi(xcoords, ycoords, len(xcoords), PolygonRoi.POLYLINE)
 +
 +# interpolate segmented line ROI (sparse)
 +interval = 9.0
 +smooth = True
 +adjust = True
 +if adjust:
 + adjustsign = -1
 +else:
 + adjustsign = 1
 +poly = segroi.getInterpolatedPolygon(adjustsign*interval, smooth)
 +newRoi = PolygonRoi(poly,PolygonRoi.POLYLINE)
 +newRoi.setColor(Color.RED)
 +imp.setRoi(newRoi)
 +</code>
 ==== Adding Overlay in 3D Stack (ROI to Overlay) ==== ==== Adding Overlay in 3D Stack (ROI to Overlay) ====
  
Line 1575: Line 1729:
 </code> </code>
  
-For more explanation about this processing, see [[http://rsbweb.nih.gov/ij/developer/api/ij/plugin/filter/GaussianBlur.html|the explanation in javadoc]].+For more explanation about this processing, see [[http://imagej.net/ij/developer/api/ij/plugin/filter/GaussianBlur.html|the explanation in javadoc]].
  
 ==== Background Subtraction (Rolling Ball) ==== ==== Background Subtraction (Rolling Ball) ====
Line 2473: Line 2627:
 The code below shows how to measure spherical 3D ROI in an image. We first create 3 3D spheres and then use them for measuring the mean pixel intensity of those 3D ROIs within a synthetic gradient 3D image.  The code below shows how to measure spherical 3D ROI in an image. We first create 3 3D spheres and then use them for measuring the mean pixel intensity of those 3D ROIs within a synthetic gradient 3D image. 
  
-<code:py>+<code py>
 from ij import IJ, ImagePlus from ij import IJ, ImagePlus
 from mcib3d.geom import ObjectCreator3D from mcib3d.geom import ObjectCreator3D
Line 2504: Line 2658:
 print "Obj3: ",obj3.getPixMeanValue(ima) print "Obj3: ",obj3.getPixMeanValue(ima)
 </code> </code>
 +
 +===== Plugin: Ridge Detection =====
 +
 +[[https://imagej.net/plugins/ridge-detection|RidgDetection Plugin]] is a Hessian Matrix-based detection of linear/curved filaments, lines. Quite robust outcome. 
 +[[https://github.com/thorstenwagner/ij-ridgedetection/tree/master|The GitHub repo is here]]. Measurements of the lengths of detexted lines are also a part of the plugin, but this part is not included in the code above. 
 +
 +<code python linenums:1>
 +from ij import IJ
 +from ij.process import ImageConverter
 +from ij.plugin.frame import RoiManager
 +from ij.gui import PolygonRoi
 +from de.biomedical_imaging.ij.steger import Lines, Position, Junctions, LinesUtil
 +from org.apache.commons.lang3.mutable import MutableInt
 +import jarray
 +import java.lang.Class
 +
 +# parameter settings
 +sigma = 2.8 #estimated radius of structure
 +high = 4.0 #eigenvalue upper threshold
 +low = 2.0 #eigenvalue lower threshold
 +minLength = 0.0 #length filter
 +maxLength = 0.0 #length filter
 +doCorrectPosition = False
 +doEstimateWidth = False
 +doExtendLine = False
 +mode = LinesUtil.MODE_LIGHT #white signal with black back
 +
 +
 +# start processing
 +imp = IJ.getImage()
 +imp32=imp.duplicate()
 +ImageConverter(imp32).convertToGray32()
 +in_img = imp32.getProcessor()
 +
 +cols = in_img.getWidth()
 +rows = in_img.getHeight()
 +
 +imgpxls2 = in_img.getPixels() #alredy float
 +
 +# prepare output data variables
 +contours = Lines(in_img.getSliceNumber())
 +resultJunction = Junctions(in_img.getSliceNumber())
 +hnum_cont = MutableInt()
 +
 +# detection
 +p = Position()
 +p.detect_lines(imgpxls2, cols, rows, contours, \\
 + hnum_cont, sigma, low, high, mode, doEstimateWidth, \\
 + doCorrectPosition, doExtendLine, resultJunction)
 +
 +# visualization of results
 +rm = RoiManager.getInstance()
 +if (rm is None):
 + rm = RoiManager()
 +else:
 + rm.reset()
 +for c in contours:
 + pr = PolygonRoi(c.getXCoordinates(), \\
 + c.getYCoordinates(), \\
 + PolygonRoi.POLYLINE)
 + rm.addRoi(pr)
 +rm.runCommand(imp, 'Show All')
 +
 +</code>
 +
  
  
documents/120206pyip_cooking/python_imagej_cookbook.1747799955.txt.gz · Last modified: 2025/05/21 03:59 by kota

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki