Skip to content

Commit

Permalink
started refactoring of the extraction of gt
Browse files Browse the repository at this point in the history
  • Loading branch information
volker-baecker committed Sep 10, 2024
1 parent e09829e commit 0692f57
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 69 deletions.
80 changes: 11 additions & 69 deletions volker/toolsets/tree_ring_segmentation/extract_masks.py
Original file line number Diff line number Diff line change
@@ -1,82 +1,24 @@
from java.awt import Color
from ij import IJ
from ij.gui import NewImage
from ij import ImagePlus
from ij.gui import Roi
from ij.gui import PolygonRoi
from ij.gui import Overlay
from ij.plugin.filter import ThresholdToSelection
from inra.ijpb.morphology import Strel
from inra.ijpb.morphology.filter import Closing
from inra.ijpb.morphology.filter import InternalGradient
from inra.ijpb.morphology.filter import Dilation

from fr.cnrs.mri.cialib.tree_rings import TreeTrunkGroundTruthHelper

INTERVAL = 50
CLOSING = 2
GRADIANT = 2
DILATION = 1
RING_MASKS_ONLY = True


def main():
image = IJ.getImage()
mask = createMask(image)
treeTrunkGTHelper = TreeTrunkGroundTruthHelper(image)
treeTrunkGTHelper.interval = INTERVAL
treeTrunkGTHelper.closing_radius = CLOSING
treeTrunkGTHelper.gradiant_radius = GRADIANT
treeTrunkGTHelper.dilation_radius = DILATION
treeTrunkGTHelper.ringsOnly = RING_MASKS_ONLY
mask = treeTrunkGTHelper.createMaskFromRois()
mask.show()

def createMask(image):
mask = NewImage.createByteImage ("mask of rings", image.getWidth(), image.getHeight(), 1, NewImage.FILL_BLACK)
mask.setOverlay(Overlay())
overlay = image.getOverlay()
rois = []

closing = Closing(Strel.Shape.OCTAGON.fromRadius(2))
internalGradient = InternalGradient(Strel.Shape.DISK.fromRadius(2))
dilation = Dilation(Strel.Shape.DISK.fromRadius(1))

for i in range(0, overlay.size()):
tmp = NewImage.createByteImage ("tmp mask of rings", image.getWidth(), image.getHeight(), 1, NewImage.FILL_BLACK)
roi = overlay.get(i)
print("roi " + str(i) + ", type: ", roi.getTypeAsString())
poly = roi.getInterpolatedPolygon(50, True)
if not poly.xpoints[-1] == poly.xpoints[0] or not poly.ypoints[-1] == poly.ypoints[0]:
poly.addPoint(poly.xpoints[0], poly.ypoints[0])
roi = PolygonRoi(poly, Roi.POLYGON)
tmp.setRoi(roi)
tmpMask = tmp.createRoiMask()
ip = closing.process(tmpMask)
tmp.setProcessor(ip)
ip = internalGradient.process(ip)
ip = dilation.process(ip)
ip.setThreshold(1, 255)
tmp.setProcessor(ip)
roi = ThresholdToSelection().run(tmp)
print("roi", roi)
rois.append(roi)


smallestIndex = -1
biggestIndex = -1
smallestLength = image.getWidth() * image.getHeight()
biggestLength = 0

if RING_MASKS_ONLY:
for index, roi in enumerate(rois):
length = roi.getLength()
if length < smallestLength:
smallestLength = length
smallestIndex = index
if length > biggestLength:
biggestLength = length
biggestIndex = index

toBeRemoved = [smallestIndex, biggestIndex]
for index, roi in enumerate(rois):
if index in toBeRemoved:
continue
mask.getOverlay().add(roi)


mask.setRoi(None)
mask.getOverlay().fill(mask, Color.WHITE, Color.BLACK)
mask.setOverlay(None)
return mask

main()
18 changes: 18 additions & 0 deletions volker/toolsets/tree_ring_segmentation/mri_tree_ring_tools.ijm
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
* Tools to measure pith, bark and annual rings in stained sections of tree trunks.
*
* (c) 2024, INSERM
* written by Volker Baecker (INSERM) at Montpellier RIO Imaging (www.mri.cnrs.fr)
*
**
*/

var _URL = "https://github.com/MontpellierRessourcesImagerie/imagej_macros_and_scripts/wiki/Tree-Ring-Tools";

macro "MRI Tree Ring Tool Help Action Tool - C000D16D17D18D19D24D25D26D27D28D29D2aD2bD33D34D3bD3cD42D43D4cD4dD52D57D58D5dD61D62D65D66D67D68D69D6aD6dD6eD71D72D75D76D79D7aD7dD7eD81D82D85D8aD8dD8eD91D92D95D96D99D9aD9dD9eDa1Da2Da6Da7Da8Da9DadDb2Db3DbcDbdDc2Dc3Dc4DcbDccDd3Dd4Dd5Dd6Dd7Dd8Dd9DdaDdbDe5De6De7De8De9" {
run('URL...', 'url='+_URL);
}

macro "extract masks Action Tool - C000T4b12e" {
run("extract masks")
}
92 changes: 92 additions & 0 deletions volker/toolsets/tree_ring_segmentation/tree_rings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
from java.awt import Color
from ij.gui import NewImage
from ij.gui import Roi
from ij.gui import PolygonRoi
from ij.gui import Overlay
from ij.plugin.filter import ThresholdToSelection
from inra.ijpb.morphology import Strel
from inra.ijpb.morphology.filter import Closing
from inra.ijpb.morphology.filter import InternalGradient
from inra.ijpb.morphology.filter import Dilation



class TreeTrunkGroundTruthHelper:


def __init__(self, image):
self.image = image
self.ringsOnly = True
self.closing_radius = 2
self.gradiant_radius = 2
self.dilation_radius = 1
self.interval = 50
self.closing = Closing(Strel.Shape.OCTAGON.fromRadius(self.closing_radius))
self.internalGradient = InternalGradient(Strel.Shape.DISK.fromRadius(self.gradiant_radius))
self.dilation = Dilation(Strel.Shape.DISK.fromRadius(self.dilation_radius))


def createMaskFromRois(self):
mask, overlay = self.createMaskWithOverlay()
rois = []
for i in range(0, overlay.size()):
roi = self.interpolateAndMakeBand(overlay.get(i))
rois.append(roi)
if self.ringsOnly:
rois = self.removeSmallestAndBiggestRing(rois)
for roi in rois:
overlay.add(roi)
mask.setRoi(None)
mask.getOverlay().fill(mask, Color.WHITE, Color.BLACK)
mask.setOverlay(None)
return mask


def removeSmallestAndBiggestRing(self, rois):
newRois = []
smallestIndex = -1
biggestIndex = -1
smallestLength = self.image.getWidth() * self.image.getHeight()
biggestLength = 0
for index, roi in enumerate(rois):
length = roi.getLength()
if length < smallestLength:
smallestLength = length
smallestIndex = index
if length > biggestLength:
biggestLength = length
biggestIndex = index
toBeRemoved = [smallestIndex, biggestIndex]
for index, roi in enumerate(rois):
if index in toBeRemoved:
continue
newRois.append(roi)
return newRois


def interpolateAndMakeBand(self, roi):
tmp = NewImage.createByteImage ("tmp mask of rings", image.getWidth(), image.getHeight(), 1, NewImage.FILL_BLACK)
poly = roi.getInterpolatedPolygon(self.interval, True)
self.closePolygon(poly)
roi = PolygonRoi(poly, Roi.POLYGON)
tmp.setRoi(roi)
tmpMask = tmp.createRoiMask()
ip = self.closing.process(tmpMask)
ip = self.internalGradient.process(ip)
ip = self.dilation.process(ip)
ip.setThreshold(1, 255)
tmp.setProcessor(ip)
roi = ThresholdToSelection().run(tmp)
return roi


def createMaskWithOverlay(self):
mask = NewImage.createByteImage ("mask of rings", self.image.getWidth(), self.image.getHeight(), 1, NewImage.FILL_BLACK)
overlay = Overlay()
mask.setOverlay(overlay)
return mask, overlay


def closePolygon(self, polygon):
if not polygon.xpoints[-1] == polygon.xpoints[0] or not polygon.ypoints[-1] == polygon.ypoints[0]:
polygon.addPoint(poly.xpoints[0], poly.ypoints[0])

0 comments on commit 0692f57

Please sign in to comment.