Skip to content

Commit 3c2bf22

Browse files
committed
update Filter_Multiple_Images.py
1 parent b3bde98 commit 3c2bf22

File tree

1 file changed

+90
-81
lines changed

1 file changed

+90
-81
lines changed
Lines changed: 90 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,102 +1,111 @@
11
# @ImageJ ij
2-
# @String(value="<HTML>This script applies the Frangi Vesselness filter to all TIFF images in a directory.<br>Only 2D or 3D grayscale images are supported. Processing log is shown in Console.", visibility="MESSAGE") msg
2+
# @String(value="<HTML>This script applies the Tubeness filter to all TIFF images in a directory.<br>Only 2D or 3D grayscale images are supported. Processing log is shown in Console.", visibility="MESSAGE") msg
33
# @File(label="Directory containing your images", style="directory") input_dir
44
# @String(label="Consider only filenames containing",description="Clear field for no filtering",value="") name_filter
55
# @boolean(label="Include subdirectories") recursive
6-
# @float(label="Size of structures to be filtered (spatially calibrated units)",description="The filter kernel will be determined from the average voxel size") scale
6+
# @String(label="Size of structures to be filtered (multiple of avg. voxel spacing)",description="The filter kernel will be determined from the average voxel spacing") scales
77
# @LogService log
88
# @StatusService status
99
# @UIService uiservice
10+
# @DatasetIOService dio
11+
# @IOService io
12+
# @Context context
1013

1114
"""
12-
file: Filter_Multiple_Images.py
13-
author: Tiago Ferreira, Cameron Arshadi
14-
version: 20190525
15-
info: Bulk filtering of image files using Frangi Vesselness
15+
file: Filter_Multiple_Images.py
16+
author: Tiago Ferreira, Cameron Arshadi
17+
version: 20190525
18+
info: Bulk filtering of image files using Frangi Vesselness
1619
"""
1720

18-
from net.imagej.axis import Axes
19-
2021
import os
22+
from java.lang import Runtime
23+
from net.imglib2.type.numeric.real import FloatType
24+
from net.imglib2.img.display.imagej import ImageJFunctions
25+
from net.imagej.axis import Axes
26+
from sc.fiji.snt.filter import Tubeness
27+
from io.scif.img import ImgSaver
2128

2229

2330
def get_image_files(directory, filtering_string, extension):
24-
"""Returns a list containing the paths of files in the specified
25-
directory. The list will only include files with the supplied
26-
extension whose filename contains the specified string."""
27-
files = []
28-
for (dirpath, dirnames, filenames) in os.walk(directory):
29-
for f in filenames:
30-
if os.path.basename(f).startswith('.'):
31-
continue
32-
if filtering_string in f and f.lower().endswith(extension):
33-
files.append(os.path.join(dirpath, f))
34-
if not recursive:
35-
break # do not process subdirectories
36-
37-
return files
31+
"""Returns a list containing the paths of files in the specified
32+
directory. The list will only include files with the supplied
33+
extension whose filename contains the specified string."""
34+
files = []
35+
for (dirpath, dirnames, filenames) in os.walk(directory):
36+
for f in filenames:
37+
if os.path.basename(f).startswith('.'):
38+
continue
39+
if filtering_string in f and f.lower().endswith(extension):
40+
files.append(os.path.join(dirpath, f))
41+
if not recursive:
42+
break # do not process subdirectories
43+
44+
return files
3845

3946

4047
def run():
41-
# First check that scale parameter is > 0, exiting if not
42-
if scale <= 0:
43-
log.error('Please select a value > 0 for the scale parameter. Exiting...')
44-
return
45-
46-
# Get all files with specified name filter and extension in the input directory
47-
d = str(input_dir)
48-
extension = ".tif"
49-
files = get_image_files(d, name_filter, extension)
50-
if not files or len(files) == 0:
51-
uiservice.showDialog("No files matched the specified criteria", "Error")
52-
return
53-
54-
processed = 0
55-
skipped = 0
56-
for f in files:
57-
58-
basename = os.path.basename(f)
59-
msg = 'Processing file %s: %s...' % (processed + skipped + 1, basename)
60-
status.showStatus(msg)
61-
print(msg)
62-
63-
# Load the input image
64-
input_image = ij.io().open(f)
65-
66-
# Verify that the image is 2D/3D and grayscale, skipping it if not
67-
num_dimensions = input_image.numDimensions()
68-
if num_dimensions > 3 or int(input_image.getChannels()) > 1:
69-
log.error('Could not process %s...Only 2D/3D grayscale images are supported' % basename)
70-
skipped += 1
71-
continue
72-
73-
# Convert input image to float, since we are dealing with derivatives
74-
float_input = ij.op().run("convert.float32", input_image)
75-
76-
# Obtain spatial calibration of the image
77-
x_spacing = float_input.averageScale(0)
78-
y_spacing = float_input.averageScale(1)
79-
spacing = [x_spacing, y_spacing]
80-
81-
if num_dimensions == 3 and float_input.axis(2).type() == Axes.Z:
82-
z_spacing = float_input.averageScale(2)
83-
spacing.append(z_spacing)
84-
85-
# Create placeholder image for the output then run the Frangi Vesselness op
86-
output = ij.op().run("create.img", float_input)
87-
pixel_scale = scale / (sum(spacing) / len(spacing)) # average voxel size: convert scale to pixel units
88-
ij.op().run("frangiVesselness", output, float_input, spacing, pixel_scale)
89-
90-
# Save the result using the same basename as the image, adding "[Frangi].tif"
91-
# For example, the output for "OP_1.tif" would be named "OP_1[Frangi].tif"
92-
l = len(f)
93-
el = len(extension)
94-
output_filepath = f[0:l - el] + "[Frangi].tif"
95-
ij.io().save(output, output_filepath)
96-
97-
processed += 1
98-
99-
print('Done. %s file(s) processed. %s file(s) skipped...' % (processed, skipped))
48+
# First check that scale parameters are > 0, exiting if not
49+
global scales
50+
scales = [float(s) for s in scales.split(',')]
51+
if not scales or any(s <= 0 for s in scales):
52+
log.error('Please select values > 0 for the scale parameter. Exiting...')
53+
return
54+
55+
# Get all files with specified name filter and extension in the input directory
56+
d = str(input_dir)
57+
extension = ".tif"
58+
files = get_image_files(d, name_filter, extension)
59+
if not files or len(files) == 0:
60+
uiservice.showDialog("No files matched the specified criteria", "Error")
61+
return
62+
63+
processed = 0
64+
skipped = 0
65+
for f in files:
66+
67+
basename = os.path.basename(f)
68+
msg = 'Processing file %s: %s...' % (processed + skipped + 1, basename)
69+
status.showStatus(msg)
70+
71+
# Load the input image
72+
input_image = dio.open(f)
73+
74+
# Verify that the image is 2D/3D and grayscale, skipping it if not
75+
num_dimensions = input_image.numDimensions()
76+
if num_dimensions > 3 or input_image.getChannels() > 1:
77+
log.error('Could not process %s...Only 2D/3D grayscale images are supported' % basename)
78+
skipped += 1
79+
continue
80+
81+
# Obtain spatial calibration of the image
82+
x_spacing = input_image.averageScale(0)
83+
y_spacing = input_image.averageScale(1)
84+
spacing = [x_spacing, y_spacing]
85+
86+
if num_dimensions == 3 and input_image.axis(2).type() == Axes.Z:
87+
z_spacing = input_image.averageScale(2)
88+
spacing.append(z_spacing)
89+
90+
avgsep = sum(spacing) / len(spacing)
91+
scales = [s * avgsep for s in scales]
92+
# Create placeholder image for the output then run the Frangi Vesselness op
93+
output = ij.op().create().img(input_image, FloatType())
94+
# Pass scales in physical units (e.g., um)
95+
op = Tubeness(scales, spacing, Runtime.getRuntime().availableProcessors())
96+
op.compute(input_image, output)
97+
98+
# Save the result using the same basename as the image, adding "[Frangi].tif"
99+
# For example, the output for "OP_1.tif" would be named "OP_1[Frangi].tif"
100+
l = len(f)
101+
el = len(extension)
102+
output_filepath = f[0:l - el] + "[Tubeness].tif"
103+
saver = ImgSaver(context)
104+
saver.saveImg(output_filepath, output)
105+
106+
processed += 1
107+
108+
print('Done. %s file(s) processed. %s file(s) skipped...' % (processed, skipped))
100109

101110

102111
run()

0 commit comments

Comments
 (0)