This post shows how to visualize MRI scans with the Image3D function and two-dimensional slices presented with a Video object. The sample MRI images are in the popular FreeSurfer format. This format is not yet supported natively in the Wolfram Language, so we can use a bit of code encapsulation to import this data:
ImportFreeSurfer[file_String]:=Module[{session,obj,na},​​session=StartExternalSession[<|"System""Python","ID""3d330484-690d-471d-9c5b-97ce5e5ef91c","Evaluator"<|"Dependencies"{"nibabel"}|>,"SessionProlog"{"import nibabel as nib"}|>];​​obj=ExternalEvaluate[session,"nib.load"->{file}];​​na=obj["get_fdata"->{}];​​NumericArray[Rescale[Normal[na]]]​​]
This ImportFreeSurfer function takes a file name as its argument. It starts an external session with StartExternalSession. It uses one Python package named nibabel which provides access to various neuroimaging formats, specifically the FreeSurfer format that we’re interested in for this post. The ExternalEvaluate command loads the file and returns an ExternalObject object that can then be used to obtain the actual data in the form of a NumericArray. As the final step, we Rescale the imported data so it can be used with the image processing functions to be used later.
The sample data is coming from another Python package called mne. We only use this package because it has some interesting sample data. The first image we will import is an MRI scan of a person, let’s call him Mr. Beardie Man:
In[]:=
voxels=ImportFreeSurfer["/Users/arnoudb/mne_data/MNE-sample-data/subjects/sample/mri/T1.mgz"]
Out[]=
NumericArray
Type: Real64
Dimensions: {256,256,256}
Data not saved. Save now

A voxel is a pixel, but for 3D images. It is tiny part of the 3D image, which in this case has
3
256
voxels. The concept of ViewPoint is a bit complex here because the source data of Mr. Beardie Man is not aligned with the Image3D concepts of Front, Left, Top, etc.
In[]:=
image=Image3D[voxels];​​Row[{Image3D[image,ViewPoint->Front,ImageSize->Medium],Image3D[image,ViewPoint->Left,ImageSize->Medium]}]​​
​
This can be fixed by using Transpose at the right Level of the voxels source data (note that with ViewPoint set to Left you are still staring at Mr. Beardie Man’s right ear, and I am not sure this is correct or not...):
In[]:=
image=Image3D[Transpose[voxels,2]];​​Row[{Image3D[image,ViewPoint->Front,ImageSize->Medium],Image3D[image,ViewPoint->Left,ImageSize->Medium]}]​​
In[]:=
image=Image3D[Transpose[voxels,2]];​​Row[{Image3D[image,ViewPoint->Top,ImageSize->Medium],Image3D[image,ViewPoint->Right,ImageSize->Medium]}]​​
Now we can use Image3DSlices and FrameListVideo to make a video that slices and dices in various directions. To be more precise the video shows three images side by side: The first image show the top to bottom slices (eyeballs and nose show in the middle of the video, the second image shows back to front (eyeballs and nose come last), and the third image shows left to right (so one ear, then brain, then the other ear):
In[]:=
image=Image3D[Transpose[voxels,2]];video=FrameListVideo[ImageAssemble[{#}]&/@Transpose[{Image3DSlices[image],Image3DSlices[image,All,2],Image3DSlices[image,All,3]}],FrameRate->10]
Out[]=
I hope that with this post I have shown a few useful techniques to visualize MRI data scans. Especially the External Evaluation framework is useful when you need to quickly use functionality that the Wolfram Language does not already have. It provides a powerful way to access more functionality from other programming languages, while still being able to use the Wolfram Language for all its built-in capabilities.

CITE THIS NOTEBOOK

Visualizing MRI scans in FreeSurfer format​
by Arnoud Buzing​
Wolfram Community, STAFF PICKS, July 9, 2025
​https://community.wolfram.com/groups/-/m/t/3496326