2

I would like to analyze only "Bone" regions extracted from Head CT.

For that, I read the DICOM files and masked regions where pixel values were less than 200 by filling in "0".

However, because "0" means "water" in the DICOM image, I don't know whether this is an appropriate way or not.

import pydicom
import numpy as np

dcm_img = pydicom.dcmread("0000200.dcm")
dcm_arr = dcm_img.pixel_array
masked_arr = np.where(dcm_arr < 200, 0, dcm_arr)
simon
  • 1,503
  • 8
  • 16
kodhoi
  • 23
  • 5
  • If you do not want to match the value of "water" - what speaks against a mask value of (-1000) that corresponds to "air" (="nothing")? – Markus Sabin Mar 07 '23 at 16:27

1 Answers1

3

From your question, it is not quite clear to me how exactly you want to analyze the bone regions in your CT image, so it is hard to provide a tailored answer. Generally though, I would not set values to zero in the image, because – as you said – each value in a CT image is associated with specific tissue properties (also, very generally in image processing, it is usually not a good idea to conflate image and masking information).

Instead, I would probably work with a masked array, masking out all the values that lie below the bone threshold, like so:

from numpy.ma import masked_array
...
masked_arr = masked_array(data=dcm_arr, mask=dcm_arr < 200)

With this, you could then use the operations that a masked array provides, such as masked_arr.mean(), which calculates the mean of all voxels that have not been masked out (which is why we masked the values below the threshold).

Alternatively, but very similar, I would probably create a new (regular) Numpy array, containing a boolean mask that marks all the values that do lie above the bone threshold (e.g. is_bone = dcm_arr >= 200), which I would later use for filtering values in my analyses.

In any case, I would try to keep the mask values and the actual CT voxel values separate.

simon
  • 1,503
  • 8
  • 16
  • Thanks. I would like to analyze the shape of the skull. For that, is it possible to use a masked array as input to CNN models? – kodhoi Mar 08 '23 at 10:33
  • 1
    Did you already find a specific CNN model that you want to use? Because then the answer depends pretty much on what input your model requires. Or is this for now only an idea? Because then your actual question is not "How to mask a DICOM image", but "How to do skull shape analysis with a convolutional neural network", and the answer to that would be very different. – simon Mar 08 '23 at 10:42
  • Thank you for your insightful opinion. Although it is only an idea, I would like to classify whether men or women based on the shape of the skull from DCM images. Because I want to use just only skull, I considered that other organs such as the brain should be masked or replaced by another value like "0" (water). In this case, masking some regions is appropriate? Or non-skull regions should be replaced by "-1000"(air) as another answerer suggested? – kodhoi Mar 09 '23 at 01:16
  • 1
    I have two suggestions for you, one methodical and one technical: (1) The methodical one: see how others approached the problem, e.g. have a look at the following publication and the methods described there: https://www.nature.com/articles/s41598-022-07415-w (it is open access), try understand the methods and maybe, if you are lucky, you may even find some code that the authors published. Then process your data accordingly. – simon Mar 09 '23 at 15:55
  • 1
    (2) The technical one: if you are really just interested in the *shape* of the skull, then the actual CT values of your image are not needed (in fact, using them would give your CNN information other than the shape to help it solve its task) – all you are actually interested in is whether a pixel/voxel belongs to the skull or not. In this case, I would work with a mask *only*, like `is_bone` above, marking voxels `true` if they belong to the skull and `false` if they don't. For processing with a CNN, you would then probably need to convert it to floats (i.e. 1.0 for `true`, 0.0 for `false`). – simon Mar 09 '23 at 16:02