I am dealing with CT images that contain the head of the patient but also 'shadows' of the metalic cylinder.
These 'shadows' can appear down, left or right. In the image above it appears only on the lower side of the image. In the image below it appears in the left and the right directions. I don't have any prior knowledge of whether there is a shadow of the cylinder in the image. I must somehow detect it and remove it. Then I can proceed to segment out the skull/head.
To create a reproducible example I would like to provide the numpy array (128x128) representing the image but I don't know how to upload it to stackoverflow.
How can I achieve my objective?
I tried segmentation with ndimage and scikit-image but it does not work. I am getting too many segments.
12 Original Images
The 12 Images Binarized
The 12 Images Stripped (with dilation, erosion = 0.1, 0.1)
The images marked with red color can not help create a rectangular mask that will envelop the skull, which is my ultimate objective.
Please note that I will not be able to inspect the images one by one during the application of the algorithm.
You could use a combination of erosion (with an appropriate number of iterations) to remove the thin details, followed by dilation (also with an appropriate number of iterations) to restore the non-thin details to approximately the original size.
In code, this would look like:
import io
import requests
import numpy as np
import scipy as sp
import matplotlib as mpl
import PIL as pil
import scipy.ndimage
import matplotlib.pyplot as plt
# : load the data
url = 'https://i.sstatic.net/G4cQO.png'
response = requests.get(url)
img = pil.Image.open(io.BytesIO(response.content)).convert('L')
arr = np.array(img)
mask_arr = arr.astype(bool)
# : strip thin objects
struct = None
n_erosion = 6
n_dilation = 7
strip_arr = sp.ndimage.binary_dilation(
sp.ndimage.binary_erosion(mask_arr, struct, n_erosion),
struct, n_dilation)
plt.imshow(mask_arr, cmap='gray')
plt.imshow(strip_arr, cmap='gray')
plt.imshow(mask_arr ^ strip_arr, cmap='gray')
Starting from this image (mask_arr
):
One would get to this image (strip_arr
):
The difference being (mask_arr ^ strip_arr
):
(addressing the issues raised in the comments)
Using a different input image, for example a binarization of the input with a much lower threshold will help having larger and non-thin details of the head that will not disappear during erosion.
Alternatively, you may get more robust results by fitting an ellipse to the head.