more work related to graffy/lipase#3

- the user can now use radial profile image processing through a new plugin (Radial Profile)
- improved the computation of the radial profile : the profile is now normalised (no longer bigger weights for big circles)
This commit is contained in:
Guillaume Raffy 2020-04-06 18:49:29 +02:00
parent 4daf2bfe91
commit f0a624fc2b
3 changed files with 53 additions and 7 deletions

View File

@ -0,0 +1,41 @@
#@ ImagePlus (label="the input image") INPUT_IMAGE
#@ Float (label="maximal radius", value=10.0, min=0.0, max=100.0, style="slider") MAX_RADIUS
#@output ImagePlus RADIAL_PROFILE
"""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
"""
# # note: fiji's jython doesn't support encoding keyword
import sys
print('python version %s' % sys.version) # prints python version
from lipase.settings import UserSettings
from lipase.imageengine import IImageEngine, PixelType
from lipase.imagej.ijimageengine import IJImageEngine
from lipase.circsymdetector import CircularSymmetryDetector
import ij.gui # pylint: disable=import-error
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
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) # pylint: disable=undefined-variable
radial_profiles = detector.compute_radial_profiles(src_image)
RADIAL_PROFILE = radial_profiles.hyperstack
# note : when launched from fiji, __name__ doesn't have the value "__main__", as when launched from python
run_script()

View File

@ -41,7 +41,7 @@ def create_circle_image(image_size, circle_radius, circle_pos, circle_thickness,
dx = x - circle_pos_x dx = x - circle_pos_x
dy = y - circle_pos_y dy = y - circle_pos_y
r_square = (dx * dx + dy * dy) r_square = (dx * dx + dy * dy)
if r_min_square < r_square < r_max_square: if r_min_square - 0.001 <= r_square < r_max_square:
pixel_value = circle_value pixel_value = circle_value
else: else:
pixel_value = background_value pixel_value = background_value
@ -86,11 +86,15 @@ class CircularSymmetryProjectorBase(IProjectorBase):
else: else:
if oversampling_is_handled: if oversampling_is_handled:
circle_image = oversampled_circle.resample(width=image_size, height=image_size) circle_image = oversampled_circle.resample(width=image_size, height=image_size)
# mean_value = circle_image.get_mean_value() mean_value = circle_image.get_mean_value()
# num_pixels = image_size * image_size assert mean_value > 0.0, "unexpected mean value of this circle image : this circle might be empty, or worse, have negative values, which doesn't make sense"
# sum_of_pixel_values = mean_value * num_pixels print(type(mean_value))
num_pixels = image_size * image_size
sum_of_pixel_values = mean_value * num_pixels
# we want each circle to have a total weight of 1.0, regardless their radius # we want each circle to have a total weight of 1.0, regardless their radius
# circle_image.scale_values(1.0/sum_of_pixel_values) circle_image.scale_values(1.0/sum_of_pixel_values)
anchor_point = {'x': int(circle_pos['x']), 'y': int(circle_pos['y'])} anchor_point = {'x': int(circle_pos['x']), 'y': int(circle_pos['y'])}
return circle_image, anchor_point return circle_image, anchor_point
@ -119,5 +123,5 @@ class CircularSymmetryDetector:
print(type(center_of_filter)) print(type(center_of_filter))
projection = ie.filter2D(src_image, dst_type=PixelType.F32, kernel=projector, anchor=(center_of_filter['x'], center_of_filter['y'])) projection = ie.filter2D(src_image, dst_type=PixelType.F32, kernel=projector, anchor=(center_of_filter['x'], center_of_filter['y']))
ie.debugger.on_image(projection, 'projection_%d' % (projector_index)) ie.debugger.on_image(projection, 'projection_%d' % (projector_index))
radial_profile_image.set_image(self, projection, frame_index=0, slice_index=0, channel_index=projector_index) radial_profile_image.set_image(projection, frame_index=0, slice_index=0, channel_index=projector_index)
return radial_profile_image return radial_profile_image

View File

@ -108,7 +108,8 @@ class IJImage(IImage):
return image_stats.mean return image_stats.mean
def scale_values(self, scale): def scale_values(self, scale):
raise NotImplementedError() processor = self.ij_image.getProcessor()
processor.multiply(scale)
class IJHyperStack(IHyperStack): class IJHyperStack(IHyperStack):