dmpelt / foam_ct_phantom

A Python package for generating foam-like phantoms for CT.
MIT License
18 stars 6 forks source link

Pixel sizes are not used? #7

Open ahendriksen opened 4 years ago

ahendriksen commented 4 years ago

Hi,

I have a question regarding the pixel/voxel sizes used in the geometry generation.

I have generated some cone beam phantoms using the code below. However, the pixel and voxel sizes do not seem to match the generated projections and/or are not saved to the ASTRA geometries.

In the code below, the projection pixels are 2/512 units wide and the voxels are 1/512 voxels wide. Judging from the obtained projection images, I expect that the cylinder is 512 projection pixels = 2 units wide. When I reconstruct, the cylinder fits perfectly in the reconstruction volume, which is 1 unit wide.

phantom = foam_ct_phantom.FoamPhantom('phantom.h5')

angles = np.linspace(0, 2*np.pi, 1024)

geom = foam_ct_phantom.ConeGeometry(
    768,                   
    768,                        # 768 pixels wide: has 128 pixels of padding on both sides
    angles,
    2/512,                      # pixel size
    sod=20,
    odd=0,
)

vol_geom = foam_ct_phantom.VolumeGeometry(
    512, 512, 512,
    1/512,                      # voxel size
)

phantom.generate_projections('projs_cone.h5',geom)

with open("volume_geometry.pickle", "wb") as f:
    pickle.dump(vol_geom.to_astra(), f)

with open("projection_geometry.pickle", "wb") as f:
    pickle.dump(geom.to_astra(), f)

When I load in the astra geometries, both pixels and voxels are 1 unit wide.

# projection geometry
{'type': 'cone',
 'DetectorSpacingX': 1,
 'DetectorSpacingY': 1,
 'DetectorRowCount': 768,
 'DetectorColCount': 768,
 'ProjectionAngles': array([0.00000000e+00, 6.14192112e-03, 1.22838422e-02, ...,
        6.27090146e+00, 6.27704339e+00, 6.28318531e+00]),
 'DistanceOriginSource': 5120.0,
 'DistanceOriginDetector': 0.0}

# volume geometry
{'option': {'WindowMinX': -256.0,
  'WindowMaxX': 256.0,
  'WindowMinY': -256.0,
  'WindowMaxY': 256.0,
  'WindowMinZ': -256.0,
  'WindowMaxZ': 256.0},
 'GridRowCount': 512,
 'GridColCount': 512,
 'GridSliceCount': 512}
dmpelt commented 4 years ago

Indeed, it seems that the pixel size is not used in the utility functions that convert to ASTRA (see here). I think the issue here is that both pixel sizes are measuring something different -- on the phantom generation side, it measures the pixel size wrt the phantom, whereas on the astra side it measures the detector pixel size wrt volume voxel size. This is probably fixable, but I'm not sure what the best way will be. Can we set arbitrary volume voxel sizes in astra already? If so, we could make astra use the same coordinate system as the phantom and fix it in that way...

ahendriksen commented 4 years ago

Can we set arbitrary volume voxel sizes in astra already?

As far as I am aware, this is possible. Maybe I am too young to remember the old situation..

If so, we could make astra use the same coordinate system as the phantom and fix it in that way...

I think that would be the most intuitive way to solve the issue. At least, that is how I expected it to work.

Perhaps, then this line should also receive some scrutiny:

        return astra.create_proj_geom('cone', 1, 1, self.ny, self.nx, self.angles, self.sod/self.pixsize, self.odd/self.pixsize)

Here, the source object distance is divided by the pixel size.