DICOM: Multiplanar reconstruction
In This Topic
DICOM study often contains a set of images, which represent the planar slices of analyzed object made in one plane. Multiplanar reconstruction (MPR) allows to reconstruct the object image in a linear or curvilinear plane from a series of planar object slices.
The SDK implements the DICOM MPR, which allows to reconstruct the object image in planar planes (coronal, sagittal, axial or oblique) or curvilinear planes from a series of parallel 2D DICOM images.
Source data for DICOM MPR
For multiplanar reconstruction the SDK requires a set of DICOM frames.
MprDicomImagePlanarSlice class allows to specify the DICOM frame, which can be used for DICOM MPR.
Here is C#/VB.NET code that demonstrates how to create source data for DICOM MPR.
/// <summary>
/// Creates the <see cref="Vintasoft.Imaging.Dicom.Mpr.MprDicomImagePlanarSlice"/> for DICOM MPR.
/// </summary>
/// <param name="sourceDicomFiles">The source DICOM files.</param>
/// <returns>
/// The source data for DICOM MPR.
/// </returns>
/// <exception cref="System.ArgumentNullException">Thrown if <i>sourceDicomFiles</i> is <b>null</b>.</exception>
public static Vintasoft.Imaging.Dicom.Mpr.MprDicomImagePlanarSlice[] CreateSourceDicomFrames(
params Vintasoft.Imaging.Codecs.ImageFiles.Dicom.DicomFile[] sourceDicomFiles)
{
// if source DICOM files are not specified
if (sourceDicomFiles == null)
throw new System.ArgumentNullException();
// a list of source MPR slices
System.Collections.Generic.List<Vintasoft.Imaging.Dicom.Mpr.MprDicomImagePlanarSlice> sourceMprSlices =
new System.Collections.Generic.List<Vintasoft.Imaging.Dicom.Mpr.MprDicomImagePlanarSlice>();
// for each DICOM file
foreach (Vintasoft.Imaging.Codecs.ImageFiles.Dicom.DicomFile sourceDicomFile in sourceDicomFiles)
{
// for each DICOM frame
foreach (Vintasoft.Imaging.Codecs.ImageFiles.Dicom.DicomFrame frame in sourceDicomFile.Pages)
{
// create MPR slice from DICOM frame
sourceMprSlices.Add(new Vintasoft.Imaging.Dicom.Mpr.MprDicomImagePlanarSlice(frame));
}
}
return sourceMprSlices.ToArray();
}
''' <summary>
''' Creates the <see cref="Vintasoft.Imaging.Dicom.Mpr.MprDicomImagePlanarSlice"/> for DICOM MPR.
''' </summary>
''' <param name="sourceDicomFiles">The source DICOM files.</param>
''' <returns>
''' The source data for DICOM MPR.
''' </returns>
''' <exception cref="System.ArgumentNullException">Thrown if <i>sourceDicomFiles</i> is <b>null</b>.</exception>
Public Shared Function CreateSourceDicomFrames(ParamArray sourceDicomFiles As Vintasoft.Imaging.Codecs.ImageFiles.Dicom.DicomFile()) As Vintasoft.Imaging.Dicom.Mpr.MprDicomImagePlanarSlice()
' if source DICOM files are not specified
If sourceDicomFiles Is Nothing Then
Throw New System.ArgumentNullException()
End If
' a list of source MPR slices
Dim sourceMprSlices As New System.Collections.Generic.List(Of Vintasoft.Imaging.Dicom.Mpr.MprDicomImagePlanarSlice)()
' for each DICOM file
For Each sourceDicomFile As Vintasoft.Imaging.Codecs.ImageFiles.Dicom.DicomFile In sourceDicomFiles
' for each DICOM frame
For Each frame As Vintasoft.Imaging.Codecs.ImageFiles.Dicom.DicomFrame In sourceDicomFile.Pages
' create MPR slice from DICOM frame
sourceMprSlices.Add(New Vintasoft.Imaging.Dicom.Mpr.MprDicomImagePlanarSlice(frame))
Next
Next
Return sourceMprSlices.ToArray()
End Function
DICOM MPR image
DICOM MPR image is a 3D cube, which is constructed from a set of DICOM frames of a DICOM study, and represented by
MprImage class. DICOM MPR image can be constructed from source DICOM frames if they satisfy the following requirements:
- Source DICOM frames must be parallel.
- The distance between neighbouring source DICOM frames must be the same with accuracy specified by MprImage.SliceIntervalMaxDelta property.
DICOM MPR image can be initialized by DICOM frames in constructor of
MprImage class or using
MprImage.Initialize method.
Initialized DICOM MPR image can provide information about location (
MprImage.Location,
MprImage.XAxis,
MprImage.YAxis,
MprImage.ZAxis) and size (
MprImage.XDataLength,
MprImage.YDataLength,
MprImage.ZDataLength,
MprImage.DiagonalLength) of DICOM MPR image in 3D-space.
Initialized DICOM MPR image must be filled for getting information about pixel values of 3D cube.
MprImage.FillDataSync method allows to fill MPR image data synchronously,
MprImage.FillDataAsync method allows to fill MPR image data asynchronously.
MprImage.FillDataProgress event allows to obtain information about the filling progress of MPR data.
MprImage.FillDataFinished event allows to determine when the filling process of MPR data is finished.
MprImage.FillDataError property allows to determine if error occurs during the filling process of MPR data.
MprImage.FillDataThreadCount property allows to set maximum count of threads, which should be used for filling MPR data.
Here is C#/VB.NET code that demonstrates how to create, initialize and synchronously fill DICOM MPR image.
/// <summary>
/// Creates the initialized <see cref="Vintasoft.Imaging.Dicom.Mpr.MprImage"/>
/// from <see cref="Vintasoft.Imaging.Codecs.ImageFiles.Dicom.DicomFile"/> array.
/// </summary>
/// <param name="sourceDicomFiles">The source DICOM files.</param>
/// <returns>
/// The initialized <see cref="Vintasoft.Imaging.Dicom.Mpr.MprImage"/>.
/// </returns>
/// <exception cref="System.ArgumentNullException">Thrown if <i>sourceDicomFiles</i> is <b>null</b>.</exception>
public static Vintasoft.Imaging.Dicom.Mpr.MprImage CreateInitAndSyncFill(
params Vintasoft.Imaging.Codecs.ImageFiles.Dicom.DicomFile[] sourceDicomFiles)
{
// if source DICOM files are not specified
if (sourceDicomFiles == null)
throw new System.ArgumentNullException();
// a list of source MPR slices
System.Collections.Generic.List<Vintasoft.Imaging.Dicom.Mpr.MprDicomImagePlanarSlice> sourceMprSlices =
new System.Collections.Generic.List<Vintasoft.Imaging.Dicom.Mpr.MprDicomImagePlanarSlice>();
// for each DICOM file
foreach (Vintasoft.Imaging.Codecs.ImageFiles.Dicom.DicomFile sourceDicomFile in sourceDicomFiles)
{
// for each DICOM frame
foreach (Vintasoft.Imaging.Codecs.ImageFiles.Dicom.DicomFrame sourceDicomFrame in sourceDicomFile.Pages)
{
// create MPR slice from DICOM frame
sourceMprSlices.Add(new Vintasoft.Imaging.Dicom.Mpr.MprDicomImagePlanarSlice(sourceDicomFrame));
}
}
// create the MPR image
Vintasoft.Imaging.Dicom.Mpr.MprImage mprImage = new Vintasoft.Imaging.Dicom.Mpr.MprImage();
// initialize the source data
mprImage.Initialize(sourceMprSlices.ToArray());
// fill the MPR image data synchronously
mprImage.FillDataSync();
return mprImage;
}
''' <summary>
''' Creates the initialized <see cref="Vintasoft.Imaging.Dicom.Mpr.MprImage"/>
''' from <see cref="Vintasoft.Imaging.Codecs.ImageFiles.Dicom.DicomFile"/> array.
''' </summary>
''' <param name="sourceDicomFiles">The source DICOM files.</param>
''' <returns>
''' The initialized <see cref="Vintasoft.Imaging.Dicom.Mpr.MprImage"/>.
''' </returns>
''' <exception cref="System.ArgumentNullException">Thrown if <i>sourceDicomFiles</i> is <b>null</b>.</exception>
Public Shared Function CreateInitAndSyncFill(ParamArray sourceDicomFiles As Vintasoft.Imaging.Codecs.ImageFiles.Dicom.DicomFile()) As Vintasoft.Imaging.Dicom.Mpr.MprImage
' if source DICOM files are not specified
If sourceDicomFiles Is Nothing Then
Throw New System.ArgumentNullException()
End If
' a list of source MPR slices
Dim sourceMprSlices As New System.Collections.Generic.List(Of Vintasoft.Imaging.Dicom.Mpr.MprDicomImagePlanarSlice)()
' for each DICOM file
For Each sourceDicomFile As Vintasoft.Imaging.Codecs.ImageFiles.Dicom.DicomFile In sourceDicomFiles
' for each DICOM frame
For Each sourceDicomFrame As Vintasoft.Imaging.Codecs.ImageFiles.Dicom.DicomFrame In sourceDicomFile.Pages
' create MPR slice from DICOM frame
sourceMprSlices.Add(New Vintasoft.Imaging.Dicom.Mpr.MprDicomImagePlanarSlice(sourceDicomFrame))
Next
Next
' create the MPR image
Dim mprImage As New Vintasoft.Imaging.Dicom.Mpr.MprImage()
' initialize the source data
mprImage.Initialize(sourceMprSlices.ToArray())
' fill the MPR image data synchronously
mprImage.FillDataSync()
Return mprImage
End Function
DICOM MPR slice
The DICOM MPR slice can be created when DICOM MPR image is initialized, the filling of DICOM MPR image is not mandatory.
Orthogonal planar 2D slice of DICOM MPR image can be created using
MprImage.CreateAxialSlice,
MprImage.CreateCoronalSlice,
MprImage.CreateSagittalSlice methods or using a constructor of
MprPlanarSlice class.
Oblique planar 3D slice of DICOM MPR image can be created using
MprImage.CreatePlanarSlice method or using a constructor of
MprPlanarSlice class.
Curved 3D slice of DICOM MPR image can be created using
MprImage.CreateCurvilinearSlice method or using a constructor of
MprCurvilinearSlice or
MprPolylineSlice class.
MprSlice class is a base class for all DICOM MPR slices. The class allows to define the slice location, size and thickness in 3D space and also the mode of slice rendering.
The following modes of slice rendering are supported:
- MPR - Intensity value.
- MIP - Maximum intensity projection along thickness of a slice.
- MinIP - Minimum intensity projection along thickness of a slice.
- Avg - Average intensity value along thickness of a slice.
- Preview3D - Maximum intensity value along thickness of a slice, that dependents from distance within slice.
Here is C#/VB.NET code that demonstrates how to create the coronal and sagittal slices of DICOM MPR image.
/// <summary>
/// Creates the coronal and sagittal slices for MPR image.
/// </summary>
/// <param name="mprImage">The MPR image.</param>
/// <param name="coronalSlice">The coronal slice.</param>
/// <param name="sagittalSlice">The sagittal slice.</param>
public static void CreateCoronalAndSagittalSlices(
Vintasoft.Imaging.Dicom.Mpr.MprImage mprImage,
out Vintasoft.Imaging.Dicom.Mpr.MprPlanarSlice coronalSlice,
out Vintasoft.Imaging.Dicom.Mpr.MprPlanarSlice sagittalSlice)
{
// calculate the MPR image center
Vintasoft.Imaging.VintasoftPoint3D mprImageCenter =
new Vintasoft.Imaging.VintasoftPoint3D(
mprImage.XLength / 2.0,
mprImage.YLength / 2.0,
mprImage.ZLength / 2.0);
// the coronal slice location
Vintasoft.Imaging.VintasoftPoint3D coronalSliceLocation =
new Vintasoft.Imaging.VintasoftPoint3D(0, mprImageCenter.Y, mprImage.ZLength);
// the horizontal axis for the coronal slice
Vintasoft.Imaging.VintasoftVector3D coronalSliceXAxis = Vintasoft.Imaging.VintasoftVector3D.XAxis;
// the vertical axis for the coronal slice
// (invert vertical axis because Y-axis in screen coordinate system is going from top to bottom and
// Z-axis in DICOM coordinate system is going from bottom to top)
Vintasoft.Imaging.VintasoftVector3D coronalSliceYAxis = -Vintasoft.Imaging.VintasoftVector3D.ZAxis;
// create the coronal slice
coronalSlice = new Vintasoft.Imaging.Dicom.Mpr.MprPlanarSlice(
coronalSliceLocation, coronalSliceXAxis, coronalSliceYAxis,
mprImage.XLength, mprImage.ZLength);
// the sagittal slice location
Vintasoft.Imaging.VintasoftPoint3D sagittalSliceLocation =
new Vintasoft.Imaging.VintasoftPoint3D(mprImageCenter.X, 0, mprImage.ZLength);
// the horizontal axis for the sagittal slice
Vintasoft.Imaging.VintasoftVector3D sagittalSliceXAxis =
Vintasoft.Imaging.VintasoftVector3D.YAxis;
// the vertical axis for the sagittal slice
// (invert vertical axis because Y-axis in screen coordinate system is going from top to bottom and
// Z-axis in DICOM coordinate system is going from bottom to top)
Vintasoft.Imaging.VintasoftVector3D sagittalSliceYAxis = -Vintasoft.Imaging.VintasoftVector3D.ZAxis;
// create the sagittal slice
sagittalSlice = new Vintasoft.Imaging.Dicom.Mpr.MprPlanarSlice(
sagittalSliceLocation, sagittalSliceXAxis, sagittalSliceYAxis,
mprImage.YLength, mprImage.ZLength);
}
''' <summary>
''' Creates the coronal and sagittal slices for MPR image.
''' </summary>
''' <param name="mprImage">The MPR image.</param>
''' <param name="coronalSlice">The coronal slice.</param>
''' <param name="sagittalSlice">The sagittal slice.</param>
Public Shared Sub CreateCoronalAndSagittalSlices(mprImage As Vintasoft.Imaging.Dicom.Mpr.MprImage, ByRef coronalSlice As Vintasoft.Imaging.Dicom.Mpr.MprPlanarSlice, ByRef sagittalSlice As Vintasoft.Imaging.Dicom.Mpr.MprPlanarSlice)
' calculate the MPR image center
Dim mprImageCenter As New Vintasoft.Imaging.VintasoftPoint3D(mprImage.XLength / 2.0, mprImage.YLength / 2.0, mprImage.ZLength / 2.0)
' the coronal slice location
Dim coronalSliceLocation As New Vintasoft.Imaging.VintasoftPoint3D(0, mprImageCenter.Y, mprImage.ZLength)
' the horizontal axis for the coronal slice
Dim coronalSliceXAxis As Vintasoft.Imaging.VintasoftVector3D = Vintasoft.Imaging.VintasoftVector3D.XAxis
' the vertical axis for the coronal slice
' (invert vertical axis because Y-axis in screen coordinate system is going from top to bottom and
' Z-axis in DICOM coordinate system is going from bottom to top)
Dim coronalSliceYAxis As Vintasoft.Imaging.VintasoftVector3D = -Vintasoft.Imaging.VintasoftVector3D.ZAxis
' create the coronal slice
coronalSlice = New Vintasoft.Imaging.Dicom.Mpr.MprPlanarSlice(coronalSliceLocation, coronalSliceXAxis, coronalSliceYAxis, mprImage.XLength, mprImage.ZLength)
' the sagittal slice location
Dim sagittalSliceLocation As New Vintasoft.Imaging.VintasoftPoint3D(mprImageCenter.X, 0, mprImage.ZLength)
' the horizontal axis for the sagittal slice
Dim sagittalSliceXAxis As Vintasoft.Imaging.VintasoftVector3D = Vintasoft.Imaging.VintasoftVector3D.YAxis
' the vertical axis for the sagittal slice
' (invert vertical axis because Y-axis in screen coordinate system is going from top to bottom and
' Z-axis in DICOM coordinate system is going from bottom to top)
Dim sagittalSliceYAxis As Vintasoft.Imaging.VintasoftVector3D = -Vintasoft.Imaging.VintasoftVector3D.ZAxis
' create the sagittal slice
sagittalSlice = New Vintasoft.Imaging.Dicom.Mpr.MprPlanarSlice(sagittalSliceLocation, sagittalSliceXAxis, sagittalSliceYAxis, mprImage.YLength, mprImage.ZLength)
End Sub
DICOM MPR slice image
MprImage.RenderSlice method allows to get an image for DICOM MPR slice. The image of DICOM MPR slice can be get only if DICOM MPR image is initialized and filled.
Here is C#/VB.NET code that demonstrates how to get the images of coronal and sagittal slices of DICOM MPR image.
/// <summary>
/// Renders the coronal and sagittal slices.
/// </summary>
/// <param name="mprImage">The MPR image.</param>
/// <param name="coronalSliceImage">The coronal slice image.</param>
/// <param name="sagittalSliceImage">The sagittal slice image.</param>
public static void RenderSlice(
Vintasoft.Imaging.Dicom.Mpr.MprImage mprImage,
out Vintasoft.Imaging.Dicom.Mpr.MprImageSlice coronalSliceImage,
out Vintasoft.Imaging.Dicom.Mpr.MprImageSlice sagittalSliceImage)
{
// create the coronal slice
Vintasoft.Imaging.Dicom.Mpr.MprPlanarSlice coronalSlice = mprImage.CreateCoronalSlice(mprImage.YLength / 2.0);
// render the coronal slice
coronalSliceImage = mprImage.RenderSlice(coronalSlice);
// create the sagittal slice
Vintasoft.Imaging.Dicom.Mpr.MprPlanarSlice sagittalSlice = mprImage.CreateSagittalSlice(mprImage.XLength / 2.0);
// render the sagittal slice
sagittalSliceImage = mprImage.RenderSlice(sagittalSlice);
}
''' <summary>
''' Renders the coronal and sagittal slices.
''' </summary>
''' <param name="mprImage">The MPR image.</param>
''' <param name="coronalSliceImage">The coronal slice image.</param>
''' <param name="sagittalSliceImage">The sagittal slice image.</param>
Public Shared Sub RenderSlice(mprImage As Vintasoft.Imaging.Dicom.Mpr.MprImage, ByRef coronalSliceImage As Vintasoft.Imaging.Dicom.Mpr.MprImageSlice, ByRef sagittalSliceImage As Vintasoft.Imaging.Dicom.Mpr.MprImageSlice)
' create the coronal slice
Dim coronalSlice As Vintasoft.Imaging.Dicom.Mpr.MprPlanarSlice = mprImage.CreateCoronalSlice(mprImage.YLength / 2.0)
' render the coronal slice
coronalSliceImage = mprImage.RenderSlice(coronalSlice)
' create the sagittal slice
Dim sagittalSlice As Vintasoft.Imaging.Dicom.Mpr.MprPlanarSlice = mprImage.CreateSagittalSlice(mprImage.XLength / 2.0)
' render the sagittal slice
sagittalSliceImage = mprImage.RenderSlice(sagittalSlice)
End Sub
Here is screenshot of sagittal slice in MPR rendering mode:
Here is screenshot of sagittal slice in MIP rendering mode:
Here is screenshot of sagittal slice in MinIP rendering mode:
Here is screenshot of sagittal slice in Avg rendering mode:
Here is screenshot of sagittal slice in Preview3D rendering mode: