๐ŸŒŒ Deep Learning/Dataset

fastMRI ๋ฐ์ดํ„ฐ์…‹ ๋‹ค์šด๋กœ๋“œ ๋ฐ ์‚ฌ์šฉ๋ฒ• Tutorial

๋ณต๋งŒ 2022. 10. 24. 16:24

fastMRI๋Š” Facebook AI์™€ NYU Langone Health๊ฐ€ 2018๋…„ ๊ณต๊ฐœํ•œ MRI reconstruction์„ ์œ„ํ•œ ๋ฐ์ดํ„ฐ์…‹์ด๋‹ค.

 

  • ๊ณต์‹ ์‚ฌ์ดํŠธ: ๋ฐ์ดํ„ฐ์…‹ ๊ฐœ์š”์™€ file description, ๋ฆฌ๋”๋ณด๋“œ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋ฐ์ดํ„ฐ์…‹ ๋‹ค์šด๋กœ๋“œ: ๋ฐ์ดํ„ฐ์…‹์— ๋Œ€ํ•œ ๋ณด๋‹ค ์ž์„ธํ•œ ์„ค๋ช…์„ ํ™•์ธํ•˜๊ณ  ๋ฐ์ดํ„ฐ์…‹์„ ๋‹ค์šด๋กœ๋“œํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๊ณต์‹ Github repo: PyTorch ๋ฐ์ดํ„ฐ๋กœ๋”, ๋ชจ๋ธ ๋“ฑ ๊ด€๋ จ๋œ ์ฝ”๋“œ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.
  • Paper: ๋ฐ์ดํ„ฐ ํš๋“ ๋ฐฉ๋ฒ•๊ณผ ์ดฌ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ ๋“ฑ ๋ฐ์ดํ„ฐ์…‹์— ๋Œ€ํ•œ ์ž์„ธํ•œ ์„ค๋ช…์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

 

1. ๋ฐ์ดํ„ฐ์…‹ ๊ตฌ์„ฑ

 

๋ฐ์ดํ„ฐ์…‹์˜ ์ข…๋ฅ˜๋Š” ๋‹ค์„ฏ๊ฐ€์ง€๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ๋‹ค. ๋ณด๋‹ค ์ž์„ธํ•œ ์„ค๋ช…์€ Paper์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

  • Single-coil knee: 1594 scans (PD, PDFS)
  • Multi-coil knee: 1594 scans (PD, PDFS)
  • Multi-coil brain: 6970 scans (T1, T1 POST, T2, FLAIR)
  • knee DICOM: 10000 scans (PD COR, PDFS COR, PD SAG, T2FS SAG, T2FS AXI)
  • brain DICOM: 10000 scans (T1 AXI, T2 AXI, T2 FLAIR AXI)

 

์ด ์ค‘ single-coil knee ๋ฐ์ดํ„ฐ์…‹์€ multi-coil knee ๋ฐ์ดํ„ฐ์…‹์—์„œ ํ•ฉ์„ฑ๋œ ๋ฐ์ดํ„ฐ์…‹์ด๋‹ค (Emulated single-coil, ESC)).

 

knee/brain DICOM ๋ฐ์ดํ„ฐ์˜ ๊ฒฝ์šฐ multi-coil knee/brain ๋ฐ์ดํ„ฐ ๋ณด๋‹ค ๊ฐฏ์ˆ˜๊ฐ€ ํ›จ์”ฌ ๋งŽ๊ณ , ๋‹ค์–‘ํ•œ scanner์™€ sequence๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ๋‹ค.

 

 

๋ฐ์ดํ„ฐ์…‹์˜ ๋ถ„ํฌ์™€ ์˜ˆ์‹œ ์‚ฌ์ง„์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

 

 

knee dataset. (์ขŒ) PDFS / (์šฐ) PD
brain dataset. (a) FLAIR / (b) T1 / (c) T1 POST / (d) T2

 

 

2. ๋ฐ์ดํ„ฐ์…‹ ์‚ฌ์šฉ ์‹ ์ฒญ

 

๋ฐ์ดํ„ฐ์…‹ ๋‹ค์šด๋กœ๋“œ๋ฅผ ์œ„ํ•ด์„œ๋Š” ๋ฐ์ดํ„ฐ์…‹ ๋‹ค์šด๋กœ๋“œ ๋งํฌ์— ๋“ค์–ด๊ฐ€์„œ ๋ฐ์ดํ„ฐ์…‹ ์‚ฌ์šฉ ์‹ ์ฒญ์„ ํ•ด์•ผ ํ•œ๋‹ค.

๋งจ ์•„๋ž˜๋กœ ์Šคํฌ๋กค์„ ๋‚ด๋ฆฌ๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํผ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

์ด๋ฆ„, ์ด๋ฉ”์ผ, ๊ต์œก๊ธฐ๊ด€ (์†Œ์† ํ•™๊ต) ์ •๋ณด๋ฅผ ์ž…๋ ฅํ•˜๊ณ , Submit ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ๋œ๋‹ค.

์ฐธ๊ณ ๋กœ fastMRI ๋ฐ์ดํ„ฐ์…‹์€ ๊ต์œก/์—ฐ๊ตฌ ์šฉ๋„๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

์ธ์ ์‚ฌํ•ญ์„ ์ œ์ถœํ•˜๋ฉด ์ž…๋ ฅํ•œ ์ด๋ฉ”์ผ ์ฃผ์†Œ๋กœ ๋ฐ”๋กœ ๋ฉ”์ผ์ด ๋ฐœ์†ก๋œ๋‹ค.

 

 

์•ž์„œ ์„ค๋ช…ํ•œ 5๊ฐ€์ง€์˜ ๋ฐ์ดํ„ฐ์…‹์˜ train/val/test set์„ ๊ฐ๊ฐ ๋‹ค์šด๋กœ๋“œ ํ•  ์ˆ˜ ์žˆ๋Š” ๋งํฌ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

๋ถ€์—ฌ๋œ ๋งํฌ๋ฅผ ํ†ตํ•ด ์ตœ๋Œ€ 90์ผ๊นŒ์ง€ ๋‹ค์šด๋กœ๋“œํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

๋ฉ”์ผ์—๋Š” curl์„ ์ด์šฉํ•œ ๋‹ค์šด๋กœ๋“œ๋ฅผ ์ถ”์ฒœํ•˜๊ณ  ์žˆ์ง€๋งŒ, ๋‚˜์˜ ๊ฒฝ์šฐ curl์„ ์ด์šฉํ•ด ๋‹ค์šด๋กœ๋“œํ•˜๋ฉด connection reset error์ด ๋– ์„œ ๋‹ค์šด๋กœ๋“œ๊ฐ€ ์ค‘๊ฐ„์— ๋Š๊ฒผ๋‹ค.

 

 

๊ทธ๋ž˜์„œ wget์„ ์ด์šฉํ•ด ๋‹ค์šด๋กœ๋“œ ํ–ˆ๋‹ค. (์ค‘๊ฐ„์— ๋Š๊ธฐ๊ธด ํ–ˆ์ง€๋งŒ ์ž๋™์œผ๋กœ ๋‹ค์‹œ ์—ฐ๊ฒฐ๋จ)

 

wget "[URL]" -O [output_filename]

 

 

+) wget ์žฌ์—ฐ๊ฒฐ ํšŸ์ˆ˜์˜ default ๊ฐ’์€ 20์ธ๋ฐ 20๋ฒˆ ๋„˜๊ฒŒ ๋Š๊ฒผ๋‹ค.. ๋Š๊ธด ์—ฐ๊ฒฐ์€ -c option์œผ๋กœ ๋‹ค์‹œ ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ๊ณ , ์žฌ์—ฐ๊ฒฐ ํšŸ์ˆ˜ ์ œํ•œ์„ ๋Š˜๋ฆฌ๋ ค๋ฉด --tries option์œผ๋กœ ๋Š˜๋ฆด ์ˆ˜ ์žˆ๋‹ค.

 

wget -c --tries=100 "[URL]" -O [output_filename]

 

 

์‹œ๊ฐ„์€ ํ•œ๋‚˜์ ˆ ๊ฑธ๋ฆฐ๋‹ค (๋‚ด ๊ฒฝ์šฐ๋Š” 192G muilticoil knee val ๊ธฐ์ค€ 12์‹œ๊ฐ„ ์ •๋„ ๊ฑธ๋ ธ์Œ)..

 

 

 

3. ํŒŒ์ผ ๊ตฌ์„ฑ

 

๊ฐ ๋ฐ์ดํ„ฐ์…‹์€ train/val/test set์œผ๋กœ ๋‚˜๋‰˜์–ด์ ธ ์žˆ๋‹ค. ๊ฐ๊ฐ์€ tar.gz๋กœ ์••์ถ•๋˜์–ด ์žˆ์œผ๋ฉฐ, ์••์ถ•์„ ํ’€๋ฉด ๋‹ค์Œ ํŒŒ์ผ๋“ค๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ๋‹ค. Test ๋ฐ์ดํ„ฐ์…‹์˜ ๊ฒฝ์šฐ๋Š” ground truth ๋ฐ์ดํ„ฐ๊ฐ€ ์ œ๊ณต๋˜์ง€ ์•Š๋Š”๋‹ค.

 

  • Multi-coil train/val (brain/knee)
    • kspace : multi-coil k-space ๋ฐ์ดํ„ฐ์ด๋‹ค (#slices, #coils, height, width).
    • reconstruction_rss : root-sum-of-squares๋กœ reconstructionํ•œ ์ด๋ฏธ์ง€ ๋ฐ์ดํ„ฐ์ด๋‹ค (#slices, r_height, r_width). knee ๋ฐ์ดํ„ฐ์˜ ๊ฒฝ์šฐ 320x320์œผ๋กœ crop๋˜์–ด ์žˆ๋‹ค.

 

  • Multi-coil test (brain/knee)
    • kspace : undersample๋œ multi-coil k-space ๋ฐ์ดํ„ฐ์ด๋‹ค (#slices, #coils, height, width).
    • mask : undersampling mask์ด๋‹ค. Mask tensor์˜ element ๊ฐœ์ˆ˜๋Š” k-space ๋ฐ์ดํ„ฐ์˜ width์™€ ๊ฐ™๋‹ค.

 

  • Single-coil train/val (knee)
    • kspace : ํ•ฉ์„ฑ๋œ single-coil k-space ๋ฐ์ดํ„ฐ์ด๋‹ค (#slices, height, width).
    • reconstruction_rss : multi-coil k-space ๋ฐ์ดํ„ฐ์—์„œ root-sum-of-squares๋กœ reconstructionํ•œ ์ด๋ฏธ์ง€ ๋ฐ์ดํ„ฐ์ด๋‹ค (#slices, 320, 320).
    • reconstruction_esc : ํ•ฉ์„ฑ๋œ single-coil k-space ๋ฐ์ดํ„ฐ๋ฅผ 320x320 ํฌ๊ธฐ๋กœ crop ํ›„ inverse Fourier transform์„ ํ•œ reconstruction ์ด๋ฏธ์ง€ ๋ฐ์ดํ„ฐ์ด๋‹ค (#slices, 320, 320).

 

  • Single-coil test (knee)
    • kspace : undersample๋œ ํ•ฉ์„ฑ๋œ single-coil k-space ๋ฐ์ดํ„ฐ์ด๋‹ค (#slices, height, width).
    • mask : undersampling mask์ด๋‹ค. Mask tensor์˜ element ๊ฐœ์ˆ˜๋Š” k-space ๋ฐ์ดํ„ฐ์˜ width์™€ ๊ฐ™๋‹ค.

 

 

 

4. ์••์ถ• ํ’€๊ธฐ

 

๋‹ค์šด๋กœ๋“œ๊ฐ€ ๋๋‚ฌ์œผ๋ฉด ๋‹ค์Œ ๋ช…๋ น์–ด๋กœ ์••์ถ•์„ ํ•ด์ œํ•œ๋‹ค.

*tar -zxvf๊ฐ€ ์•„๋‹ˆ๋ผ tar -xvf๋กœ ์••์ถ•ํ•ด์ œ (์ฐธ๊ณ : tar.gz ์••์ถ• ํ•ด์ œ ์‹œ not in gzip ์—๋Ÿฌ)

 

tar -xvf [dataset.tar.gz]

 

์••์ถ•์„ ํ•ด์ œํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์—ฌ๋Ÿฌ ๊ฐœ์˜ h5 ํŒŒ์ผ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

 

 

5. Tutorial

 

์—ฌ๊ธฐ๋ถ€ํ„ฐ๋Š” fastMRI ๋ฐ์ดํ„ฐ์…‹์˜ ๊ฐ„๋‹จํ•œ ํŠœํ† ๋ฆฌ์–ผ์„ ๋‹ค๋ฃฌ๋‹ค. ํŠœํ† ๋ฆฌ์–ผ์€ ๊ณต์‹ Github repo์—์„œ๋„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

1) ํŒŒ์ผ ํ™•์ธํ•˜๊ธฐ

 

import os

data_dir = 'path/to/fastMRI_data/multicoil_val'
fnames = os.listdir(data_dir)

print(len(fnames))
>> 199

 

  • ๋ฐ์ดํ„ฐ์…‹ ๊ฒฝ๋กœ๋ฅผ ์ง€์ •ํ•˜๊ณ  ํŒŒ์ผ์„ ํ™•์ธํ•œ๋‹ค. knee multicoil val ๋ฐ์ดํ„ฐ์…‹์˜ ๊ฒฝ์šฐ 199๊ฐœ์˜ ๋ฐ์ดํ„ฐ๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ๋‹ค.

 

 

2) h5 ํŒŒ์ผ ์ฝ์–ด์˜ค๊ณ  key์™€ attribute ํ™•์ธํ•˜๊ธฐ

 

import h5py
hf = h5py.File(os.path.join(data_dir, fnames[0]))

print(list(hf.keys()))
print(list(hf.attrs))

>> ['ismrmrd_header', 'kspace', 'reconstruction_rss']
>> ['acquisition', 'max', 'norm', 'patient_id']

 

  • ๊ฐ๊ฐ์˜ ํŒŒ์ผ์€ h5 ํฌ๋งท์œผ๋กœ ๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— h5py ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ด์šฉํ•ด ์ฝ์–ด์˜ฌ ์ˆ˜ ์žˆ๋‹ค.
  • ์ฐธ๊ณ : hdf5 ์†Œ๊ฐœ, h5py ์‚ฌ์šฉ๋ฒ• ์ •๋ฆฌ

 

 

3) Attribute์™€ ๋ฐ์ดํ„ฐ ์ฝ์–ด์˜ค๊ธฐ

 

print(hf.attrs['max'], hf.attrs['norm'])

>> 0.000260911257462176 0.06668415659382805
volume_kspace = hf['kspace'][()]
print(volume_kspace.dtype)
print(volume_kspace.shape)

>> complex64
>> (40, 15, 640, 368)

 

  • Attribute๋Š” hf.attrs[key]์™€ ๊ฐ™์ด ์ฝ์„ ์ˆ˜ ์žˆ๊ณ ,
  • ๋ฐ์ดํ„ฐ๋Š” hf.[key]์™€ ๊ฐ™์ด ์ฝ์„ ์ˆ˜ ์žˆ๋‹ค.

 

 

4) k-space ์‹œ๊ฐํ™”

 

import numpy as np
import matplotlib.pyplot as plt

def show_coils(data, slice_nums, cmap=None):
    fig = plt.figure()
    for i, num in enumerate(slice_nums):
        plt.subplot(1, len(slice_nums), i+1)
        plt.imshow(data[num], cmap=cmap)
        
show_coils(np.log(np.abs(volume_kspace[20]) + 1e-9), [0, 5, 10]) # This shows coils 0, 5, 10

 

  • ๊ฐ coil ๋ฐ์ดํ„ฐ๋ฅผ log scale๋กœ ์‹œ๊ฐํ™”ํ•˜๋ฉด ์œ„์™€ ๊ฐ™๋‹ค.
  • Multi-coil k-space ๋ฐ์ดํ„ฐ๋Š” (num_slice, num_coils, height, width) ์˜ ํ˜•ํƒœ๋ฅผ ๋„๊ณ  ์žˆ๋‹ค.

 

 

5) image ์‹œ๊ฐํ™”

 

def ifft2(img, norm='ortho'):
    return np.fft.fftshift(np.fft.ifft2(np.fft.ifftshift(img), norm=norm))

show_coils(np.abs(ifft2(volume_kspace[20])), [0, 5, 10], cmap='gray')

 

  • ๊ฐ coil ๋ฐ์ดํ„ฐ์— ifft๋ฅผ ์ ์šฉํ•ด image domain์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋ฉด ์œ„์™€ ๊ฐ™๋‹ค.
  • ifft ์ฝ”๋“œ๋Š” fastMRI Github repo์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

volume_rss = hf['reconstruction_rss'][()]
print(volume_rss.dtype)
print(volume_rss.shape)

>> float32
>> (40, 320, 320)
plt.imshow(volume_rss[20], cmap='gray')

 

  • ์ฝ”์ผ ์ด๋ฏธ์ง€๋“ค์„ ๋ชจ๋‘ ํ•ฉ์ณ ๋งŒ๋“  ์ด๋ฏธ์ง€๋Š” reconstruction_rss๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ ์ €์žฅ๋˜์–ด ์žˆ๋‹ค.
  • ํฌ๊ธฐ๋Š” (num_slice, r_height, r_width)์ด๋ฉฐ, knee ๋ฐ์ดํ„ฐ์˜ ๊ฒฝ์šฐ r_height = r_width = 320์œผ๋กœ crop๋˜์–ด ์žˆ๋‹ค.
๋ฐ˜์‘ํ˜•