Project/[Landmark Detection] RL

[Medical Image] FOV와 Spacing Resolution

HJChung 2021. 1. 21. 22:04

Field-of-view (FOV) refers the distance (in cm or mm) over which an MR image is acquired or displayed. The FOV is typically divided into several hundred picture elements (pixels), each approximately 1 mm² in size. Although the field-of-view and pixel size may vary in each of the cardinal directions, for clarity of explanation we will consider only the symmetric, 2-dimensional case where FOVx = FOVy = FOV and Δx = Δy = Δw. 

 

 

 

 

https://youtu.be/qn5WhQ0jIY0

 

 

이렇게 FOV와 spatial resolution(또는 voxel size, spacing이라도고 하며 보통 코드에서도 이런 단어로 변수명을 짓는다.)의 개념을 알고 나니 MRIcroGL에서 보이는 이미지와 jupyter notebook에서 pixel 기준으로 시각화 했을 때가 왜 달랐는지 이해가 간다.

 

MRIcroGL 툴에서는 실제 인체비율에 맞게 잘 보여주는데, 내가 직접 plt.show한 것은 z축 방향으로 짜부된, 즉 비율이 맞지 않는 이미지가 출력되었던 것인데, 왜일까?

 

MRIcroGL은 툴 자체 내에서 1mmx1mmx1mm로 resample을 해주고 있었던 것이고, 

CT 이미지의 header 정보에서도 확인할 수 있듯이 내가 가진 데이터들의 original spacing은 (데이터마다 다 다르지만) 대표적으로

images_spacings: (0.62780267, 0.62780267, 3.0)

images_spacings: (0.742188, 0.742188, 3.75)

images_spacings: (0.841797, 0.841797, 3.75)

이 정도로 x, y는 0.6~0.8 사이, z는 3~4 사이 였다. 그러면? Z축 방향으로 짜부되어서 보이는 것이다.

 

그래서 jupyter notebook에서도 아래와 같이 resample을 위한 코드를 넣어주니 

from nilearn.image import resample_img #https://nilearn.github.io/modules/generated/nilearn.image.resample_img.html

# from nilearn.image import resample_img: input image,
# resampled to hace respectively target_shape and target_affine as shape and affine
image_resolution = [1, 1, 1] #Resampling 1mm x 1mm x 1mm

image_t = resample_img(
  img = data[field],
  target_affine = np.diag([resolution[0], resolution[1], resolution[2]]),#resolution = [1, 1, 1] #Resampling 1mm x 1mm x 1mm
  interpolation = interpolation                     
  )
 

동일하게 원래 크기로 보였다. 

 

 

 

 

 

이에 관련하여서, 현재 이틀이 걸리는 학습시간을 줄이고, agent가 상, 하, 좌, 우, 앞, 뒤로 이동하는 action을 취할 때 이동하는 거리(mm)을 통일시켜주기 위해 모든 데이터를 Input하자마자 2mmX2mmX2mm로 resample해주고, 그에 따라 모든 코드에서 인식하는 Spacing정보를 (2, 2, 2)로 인식하여 reward(두 거리간 euclidian distance)계산 시에도 착오가 없도록 하는 것이 좋을 것이다. 

 

현재 실제 강화학습을 위해 참고 및 작성 하고 있는 코드는 nilearn과 nibabel이 아닌 SimpleITK을 사용하여 데이터를 읽어드리고 preprocessing해주고 있기 때문에 앞선 resample_img 메서드가 아닌 SimpleITK를 이용하여 resample을 진행해주었다. 

out_spacing=[2.0, 2.0, 2.0] #Resampling 2mm x 2mm x 2mm

sitk_image = sitk.ReadImage(image.name)
original_spacing = sitk_image.GetSpacing()
original_size = sitk_image.GetSize()

out_size = [
int(original_size[0] * (original_spacing[0] / out_spacing[0])),
int(original_size[1] * (original_spacing[1] / out_spacing[1])),
int(original_size[2] * (original_spacing[2] / out_spacing[2]))]
print("out_size: ", out_size)  # out_size:  [190, 190, 281]. 즉, 2X2X2로 resolution했을 때 크

resample = sitk.ResampleImageFilter()
resample.SetOutputSpacing(out_spacing)
resample.SetSize(out_size)
resample.SetOutputDirection(sitk_image.GetDirection())
resample.SetOutputOrigin(sitk_image.GetOrigin())
resample.SetTransform(sitk.Transform())
resample.SetDefaultPixelValue(sitk_image.GetPixelIDValue())

sitk_image = resample.Execute(sitk_image)

 

An Introduction to Biomedical Image Analysis with TensorFlow and DLTK 해당 글의 도움을 많이 받았으며, 시간이 된다면 이 글을 꼼꼼하게 읽어보는게 좋을 것 같다. 

 

 

 

reference

교수님의 친절한 설명

FOV and k-space - How does k-space relate to field-of-view (FOV) and pixel width?  

Spatial resolution (CT)

Resolution and Image Quality