1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
|
# This is a CamiTK python action
#
# Using numpy to threshold an image
import numpy as np
import camitk
def print_numpy_array_info(msg, image_data, threshold):
# number of voxels below threshold but over 0
count = np.sum((image_data < threshold) & (image_data > 0))
# Mask values in range [0, threshold)
masked = image_data[(image_data > 0) & (image_data < threshold)]
# Get the number of unique values between 0 and threshold
num_unique = np.unique(masked).size
# full info
camitk.info(msg + ":\n- size: " +str(image_data.shape)
+ "\n- dim:" + str(image_data.ndim) + " of type " + str(type(image_data.ndim))
+ "\n- values: [" + str(image_data.min()) + ".." + str(image_data.max())
+ "]\n- nb of voxels < " + str(threshold) + ": " + str(count) + " voxels with " + str(num_unique) + " different values")
def init(self:camitk.Action):
camitk.info("CamiTK version: " + camitk.__version__)
# camitk.info("Opened components: " + str(len(camitk.Application.getTopLevelComponents())))
# # camitk.Application.open(camitk.Core.get_test_data_dir() + "/brain.mha")
# camitk.Application.open(camitk.Core.getTestDataDir() + "/amos_0336/amos_0336.mhd")
# for c in camitk.Application.getTopLevelComponents():
# print(c.getName()) # print will print to CamiTK console without timestamp, level and location in code
def process(self:camitk.Action):
image_component = self.getTargets()[-1] # last target (should be the same as [0])
image_data = image_component.getImageDataAsNumpy()
# use numpy to threshold (set values that are below the threshold to 0)
threshold = self.getParameterValue("Threshold")
image_data[image_data<threshold] = image_data.min()
# Test replace_image_data
# image_component.replace_image_data(image_data)
# Create image from data
new_image_component = camitk.newImageComponentFromNumpy(image_data, "Image From Python", image_component.getSpacing())
new_image_component.setFrameFrom(image_component)
# other ways to call
#camitk.newImageComponentFromNumpy(image_data) # default name="image", spacing=(1,1,1)
#camitk.newImageComponentFromNumpy(image_data, spacing=image_data_info["spacing"]) # default name="image", spacing=(1,1,1)
#camitk.newImageComponentFromNumpy(image_data, "label_map", spacing=(0.5, 0.5, 1.0))
#camitk.newImageComponentFromNumpy(image_data, spacing=(0.5, 0.5, 1.0), name="threshold image")
self.refreshApplication() # similar to what would be done in C++
# or camitk.refresh()
return True
def targetDefined(self:camitk.Action):
targets = self.getTargets()
image_component = self.getTargets()[-1] # last target (should be the same as [0])
image_data = image_component.getImageDataAsNumpy()
minValue = image_data.min()
maxValue = int(image_data.max())
step = (maxValue - minValue) / 255.0;
threshold = self.getProperty("Threshold")
threshold.setAttribute("minimum", int(minValue)) # int(minValue) otherwise pybind11 converts 'numpy.int16' to QMap<QString, QVariant>'
threshold.setAttribute("maximum", maxValue)
threshold.setAttribute("singleStep", int(step))
self.setParameterValue("Threshold", int(minValue + (maxValue - minValue)/2))
def parameterChanged(self:camitk.Action, name:str):
camitk.info("Parameter " + name + " changed, new value: " + str(self.getParameterValue(name)))
|