diff --git a/src/ij-plugins/Ipr/Lipase/Compute_Globules_Area.py b/src/ij-plugins/Ipr/Lipase/Compute_Globules_Area.py
index bc6ef1e..e7a93bc 100644
--- a/src/ij-plugins/Ipr/Lipase/Compute_Globules_Area.py
+++ b/src/ij-plugins/Ipr/Lipase/Compute_Globules_Area.py
@@ -4,6 +4,7 @@
#@output ImagePlus OUTPUT_PLOT
"""This script is supposed to be launched from fiji's jython interpreter
+This plugin estimates the global area of globules
"""
@@ -15,16 +16,41 @@ print('python version %s' % sys.version) # prints python version
from lipase.settings import UserSettings
# from lipase import Lipase, ImageLogger
-from lipase.imageengine import IImageEngine, PixelType, StackImageFeeder
+from lipase.imageengine import IImageEngine, PixelType, StackImageFeeder, IImageProcessingDebugger
from lipase.imagej.ijimageengine import IJImageEngine
from lipase.lipase import UserProvidedBackground, GlobulesAreaEstimator
-
+# from lipase.improc.improlis import IMovieProcessListener
# from ij import IJ # pylint: disable=import-error
# from ij.gui import GenericDialog, DialogListener # pylint: disable=import-error
# from java.awt.event import ItemListener # pylint: disable=import-error
import ij.gui
from jarray import zeros, array
+
+class IsParticleCollector(IImageProcessingDebugger):
+
+ def __init__(self, num_frames):
+ IImageProcessingDebugger.__init__(self)
+ ie = IImageEngine.get_instance()
+ self.is_particle = None
+ self.num_frames = num_frames
+ self.frame_index = 0
+
+ def on_image(self, image, image_id):
+ # print('IsParticleCollector.on_image : image_id = %s' % image_id)
+ if image_id == 'is_particle':
+ ie = IImageEngine.get_instance()
+ if self.is_particle is None:
+ self.is_particle = ie.create_hyperstack(width=image.get_width(), height=image.get_height(), num_channels=1, num_slices=1, num_frames=self.num_frames, pixel_type=PixelType.U8)
+ self.is_particle.set_image(image=image, frame_index=self.frame_index)
+ print("IsParticleCollector.on_image : %f %f" % image.get_value_range())
+ self.is_particle.set_image(image=image, frame_index=self.frame_index)
+ self.frame_index += 1
+
+ def on_hyperstack(self, hyperstack, hyperstack_id):
+ # print('IsParticleCollector.on_hyperstack : hyperstack_id = %s' % hyperstack_id)
+ pass
+
def run_script():
global INPUT_STACK # pylint:disable=global-variable-not-assigned
global INPUT_BACKGROUND # pylint:disable=global-variable-not-assigned
@@ -41,8 +67,8 @@ def run_script():
background_estimator = UserProvidedBackground(background_image=src_background)
processor = GlobulesAreaEstimator(background_estimator=background_estimator, particle_threshold=PARTICLE_THRESHOLD) # pylint: disable=undefined-variable
-
- results = processor.detect_particles(src_hyperstack)
+ is_particle_collector = IsParticleCollector(num_frames = src_hyperstack.num_frames())
+ results = processor.detect_particles(src_hyperstack, image_proc_debugger=is_particle_collector)
# save_hdf5_file('results.h5', results)
# results file could be checked with "h5dump --xml ./lipase.git/results.h5"
@@ -50,8 +76,16 @@ def run_script():
x = array(results['frame index'].elements, 'f')
y = array(results['globules_area_ratio'].elements, 'f')
- plot = ij.gui.Plot('my_title', 'frame', 'globules area ratio', x, y)
+ plot = ij.gui.Plot('globules area graph', 'frame', 'globules area ratio', x, y)
plot.show()
+
+ print("Compute_Globules_Area is_particle_collector.is_particle size : %d" % (is_particle_collector.is_particle.num_frames()))
+ first_frame = is_particle_collector.is_particle.get_image(frame_index=0, slice_index=0, channel_index=0)
+ print("Compute_Globules_Area is_particle_collector.is_particle size : %f %f" % first_frame.get_value_range())
+
+ is_particle_collector.is_particle.hyperstack.setTitle('is_particle')
+ is_particle_collector.is_particle.hyperstack.show()
+
OUTPUT_PLOT = plot
diff --git a/src/lipase/improc/__init__.py b/src/lipase/improc/__init__.py
deleted file mode 100644
index 3130f1a..0000000
--- a/src/lipase/improc/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from .improlis import MovieProcessDebugger
diff --git a/src/lipase/improc/graphing.py b/src/lipase/improc/graphing.py
deleted file mode 100644
index 382351a..0000000
--- a/src/lipase/improc/graphing.py
+++ /dev/null
@@ -1,106 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
- installation des modules nécéssaires sur macos x :
- sudo port install opencv +python27
- sudo port install py-pyqt4
- sudo port install py-matplotlib
-
-"""
-from matplotlib import pyplot
-from matplotlib.backends.backend_pdf import PdfPages
-
-def setLatexLookingFonts():
- import matplotlib
- matplotlib.rcParams['mathtext.fontset'] = 'stix'
- matplotlib.rcParams['font.family'] = 'STIXGeneral'
- #matplotlib.pyplot.title(r'ABC123 vs $\mathrm{ABC123}^{123}$')
-
-class Signal:
- def __init__(self, signal, name=None):
- self.m_signalValues = signal
- self.m_name = name
-
-class Point2D(object):
- def __init__(self, x, y):
- self.m_x = x
- self.m_y = y
- @property
- def x(self):
- return self.m_x
- @property
- def y(self):
- return self.m_y
-
-class ScatterPlot(object):
- def __init__(self, xAxisDesc = None, yAxisDesc = None):
- self.m_points = []
- self.m_xAxisDesc = xAxisDesc
- self.m_yAxisDesc = yAxisDesc
- def append(self, point2d ):
- self.m_points.append(point2d)
- @property
- def xAxisDesc(self):
- return self.m_xAxisDesc
- @property
- def yAxisDesc(self):
- return self.m_yAxisDesc
-
- def setXAxisDesc(self, description):
- self.m_xAxisDesc = description
- def setYAxisDesc(self, description):
- self.m_yAxisDesc = description
- def __iter__(self):
- return iter(self.m_points)
-
-def saveScatterPlot( scatterPlot, pdfFileName):
- setLatexLookingFonts()
- fig = pyplot.figure()
- pyplot.subplot(1,1,1)
- x = []
- y = []
- for point in scatterPlot:
- x.append( point.x )
- y.append( point.y )
- pyplot.scatter(x, y, marker='x')
- if scatterPlot.xAxisDesc is not None:
- pyplot.xlabel(scatterPlot.xAxisDesc)
- if scatterPlot.yAxisDesc is not None:
- pyplot.ylabel(scatterPlot.yAxisDesc)
-
- #print('saving to '+pdfFileName)
- pp = PdfPages(pdfFileName)
- pp.savefig( fig )
- pp.close()
- pyplot.close(fig)
-
-
-def saveGraph(signal, pdfFileName):
- setLatexLookingFonts()
- fig = pyplot.figure()
- pyplot.subplot(1,1,1)
- pyplot.plot(signal, marker='x')
-
- print('saving to '+pdfFileName)
- pp = PdfPages(pdfFileName)
- pp.savefig( fig )
- pp.close()
- pyplot.close(fig)
-
-def saveMultiGraph(signals, pdfFileName):
- setLatexLookingFonts()
- fig = pyplot.figure()
- pyplot.subplot(1,1,1)
- for signal in signals:
- print('plotting signal %s' % str(signal.m_signalValues.shape))
- pyplot.plot(signal.m_signalValues, label=signal.m_name)
- print('saving to '+pdfFileName)
- pyplot.legend()
- pp = PdfPages(pdfFileName)
- pp.savefig( fig )
- pp.close()
- pyplot.close(fig)
-
-
-
-
-
diff --git a/src/lipase/improc/improlis.py b/src/lipase/improc/improlis.py
deleted file mode 100644
index eb0458c..0000000
--- a/src/lipase/improc/improlis.py
+++ /dev/null
@@ -1,238 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
- installation des modules nécéssaires sur macos x :
- sudo port install opencv +python27
- sudo port install py-pyqt4
- sudo port install py-matplotlib
-
-"""
-#from PyQt4.QtGui import *
-#from PyQt4.QtCore import *
-#import sys
-
-import cv2
-#from cv2 import cv
-import numpy
-import os
-import sys
-#from matplotlib import pyplot as plt
-#from matplotlib.backends.backend_pdf import PdfPages
-
-sys.path.append('../Libraries/python')
-import scene2d
-import graphing
-
-class Line2D(object):
- def __init__( self, point1, point2 ):
- self.m_point1 = point1
- self.m_point2 = point2
-
-class IImageProcessListener(object):
- """
- an abstract base class that handle events that happen during an image processing. This provides a flexible way to debug image processing
- """
- def __init__(self):
- self.m_imageIndex = 0
- def onSignal(self, signal, signalName):
- """
- a new signal (1d array) has just been computed
- """
- assert( False )
- def onImage(self, image, imageName):
- """
- a new image has just been computed
- """
- assert( False )
-
-class NullImageProcessListener(IImageProcessListener):
- def __init__(self):
- IImageProcessListener.__init__( self )
- def onSignal(self, signal, signalName):
- pass
- def onBaseImage(self, image, imageName=''):
- pass
- def onImage(self, image, imageName):
- pass
- def onPoint(self, point, layerPath, label=None ):
- pass
- def onLine(self, line, layerPath, label=None ):
- pass
- def onCircle(self, circle, layerPath, label=None ):
- pass
-
-class ImageProcessDebugger(IImageProcessListener):
- def __init__(self, outputFolder='./debug'):
- IImageProcessListener.__init__( self )
- self.m_scene = None
- self.m_baseImageName = None
- self.setOutputFolder(outputFolder)
-
- def __del__(self):
- #assert( self.m_scene is not None )
- if self.m_scene:
- self.m_scene.saveAsSvg('%s/%s.svg' % (self.m_outputFolder, self.m_baseImageName))
- self.m_scene = None
- def setOutputFolder(self, outputFolderPath):
- if self.m_scene:
- self.m_scene.saveAsSvg('%s/%s.svg' % (self.m_outputFolder, self.m_baseImageName))
- self.m_scene = None
- self.m_outputFolder = outputFolderPath
- pathParts = self.m_outputFolder.split('/')
- path = ''
- for i in range(len(pathParts)):
- if i != 0:
- path += '/'
- path += pathParts[i]
- try:
- os.mkdir(path)
- except (OSError): # this exception is raised if the folder already exists
- pass
- def onSignal(self, signal, signalName):
- graphing.saveGraph(signal, '%s/%s.pdf' % (self.m_outputFolder, signalName))
- def onSignals(self, signals, signalName):
- graphing.saveMultiGraph(signals, '%s/%s.pdf' % (self.m_outputFolder, signalName))
- def onImage(self, image, imageName):
- #plt.subplot(1,1,1),plt.imshow(contourImage,cmap = 'gray')
- #plt.title('Sobel X'), plt.xticks([]), plt.yticks([])
- #plt.show()
- filePath = '%s/%s.tif' % (self.m_outputFolder, imageName)
- saveImage( image, filePath )
- def onBaseImage(self, image, imageName=''):
- assert(imageName != '')
- self.m_baseImageName=imageName
- filePath = '%s/%s.png' % (self.m_outputFolder, imageName)
- saveImage( image, filePath )
- self.m_scene = scene2d.Scene()
- assert( self.m_scene is not None )
- if self.m_scene:
- self.m_scene.setBaseImage(scene2d.Image(filePath))
- def onPoint(self, point, layerPath, label=None ):
- assert( self.m_scene )
- self.m_scene.getLayer(layerPath).addChild(scene2d.Point(point, label))
- def onLine(self, line, layerPath, label=None ):
- assert( self.m_scene )
- self.m_scene.getLayer(layerPath).addChild(scene2d.Line(line, label))
- def onCircle(self, circle, layerPath, label=None ):
- assert( self.m_scene )
- self.m_scene.getLayer(layerPath).addChild(scene2d.Circle(circle, label))
-
-
-class IMovieProcessListener(object):
- """
- an abstract base class that handle events that happen durin a movie image processing. This provides a flexible way to debug imageprocessing
- """
- def __init__(self, imageProcessListener ):
- self.m_imageIndex = 0
- self.m_imageProcessListener = imageProcessListener
- def onImageProcessingStart(self):
- """
- the processing of a new image starts
- """
- self.m_imageIndex += 1
- def onImageProcessingEnd(self):
- """
- the processing of a new image ends
- """
- pass
- def onSignal(self, signal, signalName):
- """
- a new signal (1d array) has just been computed
- """
- self.m_imageProcessListener.onSignal( signal, signalName )
- def onImage(self, image, imageName):
- """
- a new image has just been computed
- """
- self.m_imageProcessListener.onImage( image, imageName )
-
-class NullMovieProcessListener(IMovieProcessListener):
- def __init__(self):
- IMovieProcessListener.__init__( self, NullImageProcessListener() )
- def onSignal(self, signal, signalName):
- pass
- def onImage(self, image, imageName):
- pass
-
-def saveImage(image, filePath):
- print('%s original image type : %s range=(%f:%f)' % (filePath, str(image.dtype), image.min(), image.max()))
- if image.dtype == numpy.bool:
- cv2.imwrite(filePath, image.astype(numpy.uint8)*255)
- elif image.dtype == numpy.uint16:
- fileExt = filePath.split('.')[-1]
- if fileExt == 'tif':
- # tif file format supports 16 bits per pixel
- cv2.imwrite(filePath, image)
- else:
- u8Image = cv2.normalize(image, alpha=0.0, beta=255.0, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)
- cv2.imwrite(filePath, u8Image)
- elif image.dtype == numpy.float32 or image.dtype == numpy.float64:
- print('image range : %d-%d' % (image.min(), image.max()))
- u8Image = cv2.normalize(image, numpy.array(image.shape, dtype=numpy.uint8), alpha=0.0, beta=255.0, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)
- print('u8Image range : %d-%d' % (u8Image.min(), u8Image.max()))
- cv2.imwrite(filePath, u8Image)
- elif image.dtype == numpy.int32:
- print('image range : %d-%d' % (image.min(), image.max()))
- u8Image = cv2.normalize(image, numpy.array(image.shape, dtype=numpy.uint8), alpha=0.0, beta=255.0, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)
- print('u8Image range : %d-%d' % (u8Image.min(), u8Image.max()))
- cv2.imwrite(filePath, u8Image)
- else:
- #assert( False )
- cv2.imwrite(filePath, image)
-
-
-
-class MovieProcessDebugger(IMovieProcessListener):
- def __init__(self):
- IMovieProcessListener.__init__( self, ImageProcessDebugger() )
- self.m_outputFolder='./debug'
- self.m_scene = None
- try:
- os.mkdir(self.m_outputFolder)
- except (OSError): # this exception is raised if the folder already exists
- pass
- def onImageProcessingStart(self):
- """
- the processing of a new image starts
- """
- IMovieProcessListener.onImageProcessingStart(self)
- self.m_imageProcessListener.setOutputFolder( '%s/image%d' % (self.m_outputFolder, self.m_imageIndex) )
-
- def onImageProcessingEnd(self):
- IMovieProcessListener.onImageProcessingEnd(self)
- self.m_imageProcessListener.setOutputFolder( None )
- def onSignal(self, signal, signalName):
- self.m_imageProcessListener.onSignal( signal, signalName )
- def onSignals(self, signals, signalName):
- self.m_imageProcessListener.onSignal( signals, signalName )
- def onImage(self, image, imageName):
- self.m_imageProcessListener.onImage( image, imageName )
- def onBaseImage(self, image, imageName):
- self.m_imageProcessListener.onBaseImage( image, imageName )
- def onPoint(self, point, layerPath, label=None ):
- self.m_imageProcessListener.onPoint( image, point, layerPath, label )
- def onCircle(self, circle, layerPath, label=None ):
- self.m_imageProcessListener.onPoint( image, circle, layerPath, label )
-
-
-class IImageProcessor(object):
-
- def __init__(self, movieProcessListener = NullMovieProcessListener()):
- self.m_movieProcessListener = movieProcessListener
-
- def processImage(self, image):
- assert( False ) # this method is not supposed to be called
-
- def get_image_process_listener(self):
- return self.m_movieProcessListener
-
-
-def findEdges(image):
- sx = cv2.Sobel(image, cv2.CV_32F, dx=1, dy=0, ksize=3)
- sy = cv2.Sobel(image, cv2.CV_32F, dx=0, dy=1, ksize=3)
- return numpy.sqrt(sx*sx + sy*sy)
-
-
-
-
-
-
diff --git a/src/lipase/improc/scene2d.py b/src/lipase/improc/scene2d.py
deleted file mode 100644
index 3e5269c..0000000
--- a/src/lipase/improc/scene2d.py
+++ /dev/null
@@ -1,166 +0,0 @@
-# -*- coding: utf-8 -*-
-import cv2
-
-class ISceneNodeVisitor(object):
- def __init__(self):
- pass
-
- def visitPoint(self, point):
- assert( False )
-
- def visitImage(self, image):
- assert( False )
-
- def visitLayer(self, layer):
- assert( False )
-
- def visitScene(self, scene):
- assert( False )
-
- def visitLine(self, line):
- assert( False )
-
-
-
-class ISceneNode(object):
- def __init__(self):
- pass
-
- def onVisit(self, visitor ):
- assert( False )
-
-class Point(ISceneNode):
- def __init__(self, coords, label = None):
- self.m_coords = coords
- self.m_label = label
-
- def onVisit( self, visitor ):
- visitor.visitPoint( self )
-
-class Line(ISceneNode):
- def __init__(self, line, label = None):
- self.m_from = line[0]
- self.m_to = line[1]
- self.m_label = label
-
- def onVisit( self, visitor ):
- visitor.visitLine( self )
-
-class Circle(ISceneNode):
- def __init__(self, circle, label = None):
- self.m_center = (circle[0], circle[1])
- self.m_radius = circle[2]
- self.m_label = label
-
- def onVisit( self, visitor ):
- visitor.visitCircle( self )
-
-class Image(ISceneNode):
- def __init__(self, imageFilePath):
- self.m_imageFilePath = imageFilePath
-
- def onVisit(self, visitor ):
- visitor.visitImage( self )
-
- def getFilePath(self):
- return self.m_imageFilePath
-
- def getSize(self):
- cv_img = cv2.imread(self.m_imageFilePath, cv2.IMREAD_ANYDEPTH)
- return cv_img.shape
-
-class Layer(ISceneNode):
- def __init__(self, layerName):
- self.m_name = layerName
- self.m_children = []
- self.m_layers = {}
-
- def getName(self):
- return self.m_name
-
- def addChild(self, childNode):
- self.m_children.append( childNode )
-
- def onVisit(self, visitor ):
- visitor.visitLayer( self )
-
- def addLayer(self, layer):
- print('adding layer %s' % layer.getName())
- self.m_layers[ layer.getName() ] = layer
-
-
-
-class Scene(ISceneNode):
- def __init__(self):
- self.m_image = None
- self.m_rootLayer = Layer('root')
-
- def onVisit(self, visitor ):
- visitor.visitScene( self )
-
- def setBaseImage( self, image ):
- self.m_image = image
-
- def getLayer(self, layerPath):
- pathParts = layerPath.split('/')
- parentLayer = self.m_rootLayer
- for layerName in pathParts:
- if layerName not in parentLayer.m_layers:
- parentLayer.addLayer( Layer(layerName) )
- parentLayer = parentLayer.m_layers[layerName]
- return parentLayer
-
- def saveAsSvg(self, filePath):
- visitor = SvgExporter( filePath )
- self.onVisit(visitor)
-
-class SvgExporter(ISceneNodeVisitor):
- def __init__(self, svgFilePath):
- self.m_svgFilePath = svgFilePath
-
- def visitPoint(self, point):
- radius = 1.0
- self.m_f.write('\n' % (point.m_coords[0], point.m_coords[1], radius) )
- if point.m_label is not None :
- self.m_f.write('%s\n' % (point.m_coords[0], point.m_coords[1], point.m_label) )
-
- def visitLine(self, line):
- radius = 1.0
- self.m_f.write('\n' % (line.m_from[0], line.m_to[0], line.m_from[1], line.m_to[1]) )
- if line.m_label is not None :
- self.m_f.write('%s\n' % (line.m_from[0], line.m_from[1], point.m_label) )
-
- def visitCircle(self, circle):
- radius = 1.0
- self.m_f.write('\n' % (circle.m_center[0], circle.m_center[1], circle.m_radius) )
- if circle.m_label is not None :
- self.m_f.write('%s\n' % (circle.m_center[0], circle.m_center[1], point.m_label) )
-
- def visitImage(self, image):
- imageSize = image.getSize()
- self.m_f.write('\n' % (image.getFilePath().split('/')[-1], imageSize[1], imageSize[0]) )
-
- def visitLayer(self, layer):
- self.m_f.write('\n' % layer.getName())
- for child in layer.m_children:
- child.onVisit( self )
- for layer in layer.m_layers.itervalues():
- layer.onVisit( self )
- self.m_f.write('\n')
-
- def visitScene(self, scene):
- with open(self.m_svgFilePath, 'wt') as self.m_f:
- print('exporting scene2d as %s' % self.m_svgFilePath)
- self.m_f.write('')
- self.m_f.write('')
-
-
diff --git a/src/lipase/lipase.py b/src/lipase/lipase.py
index 2296129..b30c262 100644
--- a/src/lipase/lipase.py
+++ b/src/lipase/lipase.py
@@ -173,7 +173,6 @@ class EmptyFrameBackgroundEstimator(IBackgroundEstimator):
background_estimate = visible_traps_sequence.get_image(frame_index=self.empty_frame_index).clone()
return background_estimate
-
class GlobulesAreaEstimator(object):
""" An image processing suite targetted to visible images of traps with moving particles (globules)
"""
@@ -186,7 +185,7 @@ class GlobulesAreaEstimator(object):
self.background_estimator = background_estimator
self.particle_threshold = particle_threshold
- def detect_particles(self, visible_traps_sequence):
+ def detect_particles(self, visible_traps_sequence, image_proc_debugger=NullDebugger()):
"""
:param IHyperStack visible_traps_sequence:
:rtype: hdf5_data.Group
@@ -206,6 +205,7 @@ class GlobulesAreaEstimator(object):
particle_image = ie.subtract(visible_traps_sequence.get_image(frame_index=frame_index), background_image)
abs_particle_image = ie.abs( particle_image )
is_particle = ie.threshold(abs_particle_image, self.particle_threshold)
+ image_proc_debugger.on_image(is_particle, 'is_particle')
measured_mean_value = is_particle.get_mean_value()
particle_pixel_value = 255.0
num_pixels = is_particle.get_width() * is_particle.get_height()