more work related to graffy/lipase#3: for each pixel, the profile of variance along the circle is now computed. This image basically measures the non-roundedness for each pixel.
This commit is contained in:
parent
5a144f1907
commit
bfca19e039
|
@ -1,8 +1,10 @@
|
|||
#@ ImagePlus (label="the input image") INPUT_IMAGE
|
||||
#@ Float (label="maximal radius", value=10.0, min=0.0, max=100.0, style="slider") MAX_RADIUS
|
||||
#@ Int (label="number of angular sectors", value=4, min=0, max=100, style="slider") NUM_ANGULAR_SECTORS
|
||||
#@ Float (label="maximal radius", value=32.0, min=0.0, max=100.0, style="slider") MAX_RADIUS
|
||||
#@ Integer (label="number of radial sectors", value=8, min=0, max=100, style="slider") NUM_RADIAL_SECTORS
|
||||
#@ Integer (label="number of angular sectors", value=4, min=0, max=100, style="slider") NUM_ANGULAR_SECTORS
|
||||
|
||||
#@output ImagePlus RADIAL_PROFILE
|
||||
#@output ImagePlus RADIAL_PROFILES
|
||||
#@output ImagePlus ANGULAR_VARIANCE_AVG_IMAGE
|
||||
"""This script is supposed to be launched from fiji's jython interpreter
|
||||
|
||||
This imagej plugin computes the radial profile of each pixel of the input image. The resulting profiles are stored in a single hyperstack, where the profile data are stored along the channel axis
|
||||
|
@ -25,17 +27,20 @@ from jarray import zeros, array # pylint: disable=import-error
|
|||
def run_script():
|
||||
global INPUT_IMAGE # pylint:disable=global-variable-not-assigned
|
||||
global MAX_RADIUS # pylint:disable=global-variable-not-assigned
|
||||
global RADIAL_PROFILE # pylint:disable=global-variable-not-assigned
|
||||
global NUM_RADIAL_SECTORS # pylint:disable=global-variable-not-assigned
|
||||
global NUM_ANGULAR_SECTORS # pylint:disable=global-variable-not-assigned
|
||||
global RADIAL_PROFILES # pylint:disable=global-variable-not-assigned
|
||||
global ANGULAR_VARIANCE_AVG_IMAGE # pylint:disable=global-variable-not-assigned
|
||||
IImageEngine.set_instance(IJImageEngine())
|
||||
|
||||
src_image = IImageEngine.get_instance().create_image(width=1, height=1, pixel_type=PixelType.U8)
|
||||
src_image.ij_image = INPUT_IMAGE # pylint: disable=undefined-variable
|
||||
|
||||
detector = CircularSymmetryDetector(max_radius=MAX_RADIUS, num_angular_sectors=NUM_ANGULAR_SECTORS) # pylint: disable=undefined-variable
|
||||
radial_profiles = detector.compute_radial_profiles(src_image)
|
||||
detector = CircularSymmetryDetector(max_radius=MAX_RADIUS, num_angular_sectors=NUM_ANGULAR_SECTORS, num_radial_sectors=NUM_RADIAL_SECTORS) # pylint: disable=undefined-variable
|
||||
radial_profiles, angular_variance_avg_image = detector.compute_radial_profiles(src_image)
|
||||
|
||||
RADIAL_PROFILE = radial_profiles.hyperstack
|
||||
RADIAL_PROFILES = radial_profiles.hyperstack
|
||||
ANGULAR_VARIANCE_AVG_IMAGE = angular_variance_avg_image.ij_image
|
||||
|
||||
|
||||
# note : when launched from fiji, __name__ doesn't have the value "__main__", as when launched from python
|
||||
|
|
|
@ -168,12 +168,17 @@ class CircularSymmetryDetector:
|
|||
""" Computes for each pixel the radial profile (with this pixel as center)
|
||||
|
||||
:param IImage src_image:
|
||||
:rtype IHyperstack: each radial profile is stored in the channel coordinate of the hyperstack
|
||||
:rtype IHyperstack, Image :
|
||||
:returns:
|
||||
- radial_profiles (:py:class:`IHyperstack`) - each radial profile is stored in the channel coordinate of the hyperstack
|
||||
- angular_variance_avg (:py:class:`IImage`) - each pixel stores the average variance of signal along the circles of different diameters in the neighborhood
|
||||
"""
|
||||
# https://stackoverflow.com/questions/39759503/how-to-document-multiple-return-values-using-restructuredtext-in-python-2
|
||||
ie = IImageEngine.get_instance()
|
||||
ie.debugger.on_image(src_image, 'src_image')
|
||||
projector_base = CircularSymmetryProjectorBase(self.max_radius, num_angular_sectors=self.num_angular_sectors, num_radial_sectors=self.num_radial_sectors, oversampling_scale=1)
|
||||
radial_profile_image = ie.create_hyperstack(width=src_image.get_width(), height=src_image.get_height(), num_channels=projector_base.num_radial_sectors, num_slices=1, num_frames=1, pixel_type=PixelType.F32)
|
||||
angular_variances_image = ie.create_hyperstack(width=src_image.get_width(), height=src_image.get_height(), num_channels=projector_base.num_radial_sectors, num_slices=1, num_frames=1, pixel_type=PixelType.F32)
|
||||
for radius_index in range(projector_base.num_radial_sectors):
|
||||
circle_stack = ie.create_hyperstack(width=src_image.get_width(), height=src_image.get_height(), num_channels=projector_base.num_angular_sectors, num_slices=1, num_frames=1, pixel_type=PixelType.F32)
|
||||
for angular_sector_index in range(projector_base.num_angular_sectors):
|
||||
|
@ -184,6 +189,15 @@ class CircularSymmetryDetector:
|
|||
circle_stack.set_image(projection, frame_index=0, slice_index=0, channel_index=angular_sector_index)
|
||||
# compute the image in which each pixel contains the mean value of the source image in the given circular region around the pixel
|
||||
circle_mean_image = ie.compute_mean(StackImageFeeder(circle_stack))
|
||||
|
||||
radial_profile_image.set_image(circle_mean_image, frame_index=0, slice_index=0, channel_index=radius_index)
|
||||
return radial_profile_image
|
||||
|
||||
square_diffs_stack = circle_stack # note : circle_stack is reused to store square_diffs_stack
|
||||
for angular_sector_index in range(projector_base.num_angular_sectors):
|
||||
angular_sector_image = circle_stack.get_image(frame_index=0, slice_index=0, channel_index=angular_sector_index)
|
||||
diff_image = ie.subtract(angular_sector_image, circle_mean_image)
|
||||
square_diff_image = ie.multiply(diff_image, diff_image)
|
||||
square_diffs_stack.set_image(square_diff_image, frame_index=0, slice_index=0, channel_index=angular_sector_index)
|
||||
variance_image = ie.compute_mean(StackImageFeeder(square_diffs_stack))
|
||||
angular_variances_image.set_image(variance_image, frame_index=0, slice_index=0, channel_index=radius_index)
|
||||
angular_variance_avg_image = ie.compute_mean(StackImageFeeder(angular_variances_image))
|
||||
return radial_profile_image, angular_variance_avg_image
|
||||
|
|
|
@ -170,7 +170,6 @@ class IImageFeeder(ABC):
|
|||
creates an hyperstack from this image feeder
|
||||
:rtype IHyperStack
|
||||
"""
|
||||
|
||||
it = iter(self)
|
||||
|
||||
image = it.next()
|
||||
|
@ -235,6 +234,9 @@ class StackImageFeeder(IImageFeeder):
|
|||
raise StopIteration
|
||||
else:
|
||||
image = self.hyperstack.get_image(frame_index=self.next_frame_index, slice_index=self.next_slice_index, channel_index=self.next_channel_index)
|
||||
# mean_value = image.get_mean_value()
|
||||
# print("mean_value", mean_value)
|
||||
# assert mean_value > 0.001
|
||||
|
||||
# compute next image index
|
||||
self.next_slice_index += 1
|
||||
|
@ -380,7 +382,17 @@ class IImageEngine(ABC):
|
|||
:param IImage image2:
|
||||
:rtype IImage: image1-image2
|
||||
"""
|
||||
|
||||
|
||||
@abc.abstractmethod
|
||||
def multiply(self, image1, image2):
|
||||
"""
|
||||
computes the difference image1-image2
|
||||
|
||||
:param IImage image1:
|
||||
:param IImage image2:
|
||||
:rtype IImage: image1*image2
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def divide(self, numerator_image, denominator_image):
|
||||
"""
|
||||
|
|
|
@ -290,6 +290,11 @@ class IJImageEngine(IImageEngine):
|
|||
result_image = ic.run("Subtract create float", image1.ij_image, image2.ij_image)
|
||||
return IJImage(self, result_image)
|
||||
|
||||
def multiply(self, image1, image2):
|
||||
ic = ImageCalculator()
|
||||
result_image = ic.run("Multiply create float", image1.ij_image, image2.ij_image)
|
||||
return IJImage(self, result_image)
|
||||
|
||||
def divide(self, numerator_image, denominator_image):
|
||||
ic = ImageCalculator()
|
||||
result_image = ic.run("Divide create float", numerator_image.ij_image, denominator_image.ij_image)
|
||||
|
|
Loading…
Reference in New Issue