2

I would like to remove CT bed from the image. Basically I would want to remove everything below the red line in this image and subsequent ones (i would fill with 0 zeros or something)

enter image description here

Is there a way to get the location of the highest non zero number on the y-axis? Or the height of longest horizontal non zero number? Then I could just replace all values below with zero. Or is there a better way to do this? Thanks!

I get the image data from

df = pydicom.dcmread(img)
plt.imshow(df.pixel_array, vmax=dicom_max_pixel)
plt.show()
finefoot
  • 9,914
  • 7
  • 59
  • 102
MikeDoho
  • 552
  • 2
  • 5
  • 18

2 Answers2

1

IIUC, have a look at the following minimal example:

First, we're importing the modules.

import matplotlib.pyplot as plt
import numpy as np

Creating an example image, 1 representing the bed.

image = np.zeros((10, 10))
image[6, 2:8] = image[7, 4:6] = 1
print(image)
plt.imshow(image)
plt.show()

It prints and shows:

[[0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 1. 1. 1. 1. 1. 1. 0. 0.]
 [0. 0. 0. 0. 1. 1. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]]

Figure_1

We use np.all to find out for each line if it is all zeros. Afterwards, we use np.where to get the index of the first False.

zero_lines = np.all(image == 0, axis=1)
first_false = np.where(zero_lines == False)[0][0]
print(zero_lines)
print(first_false)

This prints:

[ True  True  True  True  True  True False False  True  True]
6

We use this information to crop the image accordingly.

image = image[:first_false]
print(image)
plt.imshow(image)
plt.show()

It prints and shows:

[[0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]]

Figure_2

finefoot
  • 9,914
  • 7
  • 59
  • 102
  • Thank you! This works for the question I asked. I tested it on 7 CT scans and noticed that there was additional variably in images. Like 5/7 images this worked perfectly but in 2/7 it cut off like 20 (nonessential) pixels. I dont need these pixels for the project I am doing. As an aside, the approach I also tried was incorporated a threshold value (through trial an error) I think my approach could be prone to errors as well. Thanks again!! – MikeDoho Dec 24 '19 at 02:28
1

I still agree with above but this is how I tried it.

#loading image
single_image = image[1,:,:]
single_image_2 = single_image.copy()
#using np.where
single_image_bi = binary_image_2(single_image_2)
single_image_pd = pd.DataFrame(single_image_bi)
#summing across row
single_image_sum = pd.DataFrame(np.sum(single_image_pd, axis=1))
#find index
max_index = single_image_sum.idxmax()
print(f"max_index: {max_index}")

plt.imshow(single_image[0:max_index[0]:,:])
plt.show()

enter image description here

mine VS above way (not one of the 2/7) enter image description here

def binary_image_2(img, threshold=.04):
    single_image = img
    print(np.shape(single_image))
    nn, mm = np.shape(single_image)
    for n in range(nn):
            single_image[n, :] = np.where(single_image[n, :]> threshold*single_image.max(),
                                           1, 0)
MikeDoho
  • 552
  • 2
  • 5
  • 18