Functions¶
These are all the functions implemented in RETIMAT
File reading¶
- read_vol(file, varargin)¶
Read metadata, segmentation, OCT, and slo images contained in a from Spectralis OCT (Heidelberg Engineering)
Input arguments¶
file: String containing the path to the .vol file to be read.
varargin: Optional parameters from the list:
‘visu’: Visualize the scanning patter along with B-Scans and fundus image (slo).
‘full_header’: Retrieve the original header with all the parameters (by default only a few important parameters are retrieved).
‘get_coordinates’: retrieve fundus and A-Scan X, Y coordinates
‘raw_pixel’: return raw pixel reflectance instead of visualization-adapted values.
Output arguments¶
header: Structure with .vol file header values.
segment: Segmenation data stored in the .vol file.
bscan: 3D single image with B-Scans.
fundus: 2D fundus image.
Notes¶
Spectralis OCT data can be exported into both E2E and vol format. We recommend using the latter as it provides easier access to the header information.
Originally writen by Radim Kolar, Brno University, Czech Republic Modified by Markus Mayer, Pattern Recognition Lab, University of Erlangen-Nuremberg
Modified by Kris Sheets, Retinal Cell Biology Lab, Neuroscience Center of Excellence, LSU Health Sciences Center, New Orleans
Modified by Andrew Lang, Image Analysis and Communications Lab, Johns Hopkins University - Modifications to increase efficiency - 5/17/2012
Current version modified by David Romero-Bascones, Biomedical Engineering Department, Mondragon Unibertsitatea, 2023, dromero@mondragon.edu
Examples¶
Read all the information in a .vol file¶
[header, segment, bscan, fundus] = read_vol('my_oct.vol')
Read only the header of the .vol file (faster)¶
header = read_vol('my_oct.vol')
- read_e2e(file, varargin)¶
Read metadata, segmentation, OCT and fundus images in .e2e/.E2E files from Spectralis OCT (Heidelberg Engineering)
Input arguments¶
file: String containing the path to the .vol file to be read.
varargin: Optional parameters from the list:
‘verbose’: Display header info during read.
‘raw_pixel’: Display raw pixel intensities.
Output arguments¶
header: Structure with .vol file header values.
segment: Segmenation data stored in the .vol file.
bscan: 3D single image with B-Scans.
fundus: 2D fundus image.
Notes¶
This function was developed based on the previous reverse engineering attempts [1-3] and is not an official file reader. Therefore, some of the information retrieved can be incorrect/incomplete.
Scan focus, scale_x, scale_y and acquisition pattern are yet to be found.
Spectralis OCT data can be exported into both E2E and vol format. We recommend using the latter as it is easier to parse and it only stores a single eye and acquisition.
References¶
[1] uocte documentation https://bitbucket.org/uocte/uocte/wiki/Topcon%20File%20Format
[2] OCT-Converter, https://github.com/marksgraham/OCT-Converter
[3] LibE2E, https://github.com/neurodial/LibE2E
Examples¶
Read all the information in a .e2e/.E2E file¶
file = 'my_oct.e2e'; [header, segment, bscan, fundus] = read_e2e(file)
Read only the header of the .e2e/.E2E file (faster)¶
file = 'my_oct.e2e'; header = read_e2e(file)
- read_img(file, scan_size, varargin)¶
Read OCT images from Cirrus .img files
Input arguments¶
file: String with the path to the img file name to be read.
- scan_size: Array of 3 numeric values defining the size of the
scanned region. Sizes must be given following [x y z] convention. By default a cube of [6 6 2] mm is considered.
varargin: optional string flags from the list:
‘get_coordinates’: retrieve fundus and A-Scan X, Y coordinates. If the scan pattern is unknown coordinates cannot be computed.
Output arguments¶
header: struct with metadata retrieved from filename and volume dimensions.
bscan: 3D matrix of size [n_axial x n_ascan x n_bscan] with image data.
Notes¶
img files do not include any spatial or metadata information. Therefore, to correctly reconstruct the image volume this function relies on two strategies:
Inspection of the filename.
Matching of the voxel count with this known acquisition patterns:
Macular Cube: [200 x 200 x 1024] : 40960000
Opitic Disc Cube: [512 x 128 x 1024] : 67108864
5 Line Raster: [1024 x 5 x 1024]
Hidef: [512 x 2 x 1024] (not supported yet)
Scans differing from the previous protocols might not be read properly.
Info from previous function: hidef scan consists of 2 orthogonal bscans intersecting in the center of the volume. The first is in the y direction (across B-scans), the second is in the x direction (aligned with the center B-scan). Unfortunately, they are not in good alignment with the volumetric data.
Example¶
[header, bscan] = read_img('myfile.img')
- read_bin(file, im_size)¶
Read grayscale slo (fundus) images from Cirrus .bin files
Input arguments¶
file: path of the .bin file to read.
im_size: size of the slo image. If not provided it is assumed to be [664 512];
Output arguments¶
fundus: fundus grayscale image.
Notes¶
This code was developed by reverse engineering a few .bin files and may not work for every .bin image.
Example¶
I = read_bin('myfile.bin')
- read_fda(file, varargin)¶
Reads the header, segmentation and images (OCT + fundus) contained in an .fda Topcon file.
Input arguments¶
file: Path of the .fda file to read.
varargin: Optional flags from the list:
‘verbose’: If provided, reading info is displayed.
‘get_coordinates’: If provided A-scan coordinates are returned.
Output arguments¶
header Structure with .fda file header values.
segment Segmenation data stored in the .fda file.
bscan 3D single image with B-Scans.
fundus 2D fundus image.
Notes¶
This code is heavily based on [1,2], which were developed by reverse engineering fda files. Therefore, data read using this function may be incomplete/incorrect.
The reading process is as follows:
Identify data chunks present in file (not all are always present)
Read specific chunks with the relevant information
‘get_coordinates’ flag only works if the scanning pattern is horizontal raster (pending to implement others).
References¶
[1] uocte documentation https://bitbucket.org/uocte/uocte/wiki/Topcon%20File%20Format
[2] OCT-Converter: https://github.com/marksgraham/OCT-Converter
Example¶
[header, segment, bscan, fundus] = read_fda(file)
- read_xml_iowa(file, varargin)¶
Read segmentation computed by OCTExplorer (IOWA reference algorithm)
Input arguments¶
file: path to xml output file ending with Surfaces_Iowa.xml
varargin: different string flags:
‘get_coordinates’: to return A-Scan coordinates as part of the header.
‘keep_names’: to use layer naming convention from OCTExplorer instead of RETIMAT.
‘keep_nan’: to keep regions with noisy segmentation as numerical values instead of nan.
‘verbose’: to plot additional info on read layers.
Output arguments¶
header: struct with metadata related with the segmentation: version, resolution, dimensions.
seg: struct with point segmentation values (in pixels).
Notes¶
This function has been only tested for raster acquisitions and OCTExplorer version version 3.8.0.
The axes convention used in OCTExplorer differs from the one used here:
x: horizontal (temporal - nasal)
y: vertical (inferior - superior)
z: axial (depth)
Layer naming convention returned by this function differs from the one used by OCTExplorer.
OCTExplorer uses different ways to determine an invalid region:
Segmentation = 0
Segmentation NA (not sure)
Undefined region chunk (full square regions I believe)
References¶
[1] The Iowa Reference Algorithms (Retinal Image Analysis Lab, Iowa Institute for Biomedical Imaging, Iowa City, IA), https://www.iibi.uiowa.edu/oct-reference
[2] Abramoff MD et al., Retinal Imaging and Image Analysis. IEEE Reviews in Biomedical Engineering, 2010. doi:10.1109/RBME.2010.2084567
[3] Kang L et al., Optimal Surface Segmentation in Volumetric Images – A Graph-Theoretic Approach. IEEE Transactions on Pattern Analysis and Machine Intelligence, 2006. doi:10.1109/TPAMI.2006.19
[4] Garvin MK et al., Automated 3-D Intraretinal Layer Segmentation of Macular Spectral-Domain Optical Coherence Tomography Images. IEEE Trans Med. Imaging, 2009. doi:10.1109/TMI.2009.2016958
Example¶
[header, seg] = read_xml_iowa('my_file_Surfaces_Iowa.xml')
Visualization¶
- generate_report(bscan, seg, fundus, layers, varargin)¶
Create a summary figure with fundus, en-face reflectance map, thickness maps and bscans.
Input arguments (mandatory)¶
bscan: Raw b-scans with shape [n_axial, n_ascan, n_bscan]
seg: Struct with segmentation data. Each field corresponds to a different boundary. Expected shape of each field [n_bscan, n_ascan]
fundus: Fundus image.
layers: List of layers for which to plot thickness maps.
Input arguments (optional)¶
n_plot_bscan: How many bscans to plot. Default: maximum between 5 and n_bscan.
n_col_max: Maximum number of columns in the figure. Default: 5
file_name: File name to save the plot. Default: [] (plot is not saved).
visible: ‘on’ to show the figure window and ‘off’ to hide it. Default: ‘on’
title: text to us as title. Default: [] (no title).
Output arguments¶
fig: Created figure handle.
Notes¶
This reports are useful to identify segmentation errors or poor signal quality.
Example¶
[~, segment, bscan, fundus] = read_vol(file) generate_report(bscan, segment, fundus, {'TRT','RNFL'})
- plot_sectors(Z, Sectors, varargin)¶
Visualize sectorization results
Input arguments (mandatory)¶
Z: Values of each sector.
Sectors: Struct defining the sectorization. Either manually defined or obtained after using sectorize_map().
Input arguments (name/value pair)¶
n_point: Number of points in each non-straight line segment. Higher number increases resolution and computation time. Default: 50.
alpha: Transparency of patches. Range: [0,1]. Default: 1.
edge_color: Color of the edges of each patch. Default: ‘k’ (black).
axis_off: Set it to true to hide axis. Default: true.
axis_equal: Set it to true to set a aspect ratio of 1. Default: true.
Notes¶
- ETDRS sectorization is defined as a structure with fields:
type: ‘wedge’
radius: [0.5 1.5 3]
n_angle = 4
theta_0 = -pi/4
Example¶
Plot ETDRS sectorization¶
[header, seg] = read_vol(file, 'verbose', 'get_coordinates'); Thickness = compute_thickness(seg, 'TRT', header.scale_z); [TRT, Sectors] = sectorize_map(X, Y, TRT, 'mean', 'etdrs'); plot_sectors(TRT, Sectors);
- spider_plot(Data, varargin)¶
Visualize sectorization results
Input arguments (mandatory)¶
Data: matrix with N (observations)x M (angles)
Input arguments (name/value pair)¶
param: structure with parameters for plotting configuration.
center: ‘mean’ or ‘median’
superior: interval superior value % percentile (e.g. 75)
inferior: interval inferior value % percentile (e.g. 25)
circleRadius: radius of the radar outer circle. Change to hide outliers
plotDots: flag to overlay raw data points or not
Notes¶
This is a legacy function that should be updated at some point.
Reflectance¶
- compute_attenuation(bscan, scale_z, method, seg)¶
Compute voxelwise attenuation coefficient based on [1] or [3].
Input arguments¶
bscan: matrix with B-scans of dimensions n_axial x n_ascan x n_bscan. If 2D matrix it will be interpreted as a single B-scan.
scale_z: axial (depth) resolution in mm.
method: method used to compute the attenuation coefficient.
‘vermeer_2014’ (default)
‘vanderschoot_2012’
seg: struct with segmentation data used with the ‘vanderschoot_2012’ method [3]
Output arguments¶
att: attenuation coefficient per voxel.
Notes¶
The precise measurement of tissue attenuation coefficient is difficult and and still a research topic. This function provides an approximate value based on assumptions on optical tissue properties [1]. You may want to read [2] to check how this method compares to others.
The method in [3] is currently only supported for RNFL and returns a total attenuation value for each a-scan instead of a 3D matrix.
For the methods to work it is important to use raw voxel intensity. For instance reading .vol files with the ‘raw_pixel’ flag.
References¶
[1] Vermeer, Depth-resolved model-based reconstruction of attenuation coefficients in optical coherence tomography, Biomedical Optics Express 2014, https://doi.org/10.1364/BOE.5.000322
[2] Chang, Review of methods and applications of attenuation coefficient measurements with optical coherence tomography, Journal of Biomedical Optics, 2019, https://doi.org/10.1117/1.JBO.24.9.090901
[3] van der Schoot, The Effect of Glaucoma on the Optical Attenuation Coefficient of the Retinal Nerve Fiber Layer in Spectral Domain Optical Coherence Tomography Images, IOVS, 2012, https://doi.org/10.1167/iovs.11-8436
Example¶
Load a .vol file and compute the attenuation coefficient¶
[header,~,bscan] = read_vol('my_file.vol','raw_pixel'); att = compute_attenuation(bscan, header.scale_z);
- image_quality(I, metric, varargin)¶
Compute an image quality metric for each bscan in I.
Input arguments (mandatory)¶
I: 2D or 3D matrix with bscan data. If 3D data the 3rd dimension is assumed to be the bscan index.
metric: Metric used to compute image quality. Accepted options
‘mTCI’: maximum tissue contrast index [3].
‘snr’: signal to noise ratio.
‘psnr’: peak to noise ratio [1].
‘cnr’: contrast to noise ratio [2].
Input arguments (optional)¶
scanner: String defining the OCT scanner (when using mTCI). If not provided an arbitrary value will be used.
‘Cirrus’
‘RTVue’
‘Spectralis’
‘3D-OCT-1000’
seg: struct with segmentation used in ‘snr’,’psnr’,’cnr’.
Output arguments¶
iq: Image quality metric.
Notes¶
The definition of SNR, CNR varies across the literature. Check the references for the precise definition implemented here.
Here SNR, PSNR and CNR rely on an accurate segmentation of both the ILM and the BM. If the image is pure nois, highly ocluded, or the segmentation is wrong these metrics might not work.
A more accurate noise estimation procedure may require acquiring a NOISE profiling or reference image [4].
References¶
[1] Shirasawa, Objective Determination of Optimal Number of Spectral- Domain Optical Coherence Tomographic Images of Retina to Average, PLOS ONE, 2014. http://dx.doi.org/10.1371/journal.pone.0110550
[2] Rico-Jimenez J J, Real-time OCT image denoising using a self-fusion neural network,” Biomed. Opt. Express, 2022. https://doi.org/10.1364/BOE.451029
[3] Huang, Signal Quality Assessment of Retinal Optical Coherence Tomography Images, IOVS, 2012. Https://dx.doi.org/10.1167%2Fiovs.11-8755
[4] Sahu, Statistical modeling and Gaussianization procedure based de-speckling algorithm for retinal OCT images, Journal of Ambient Intelligence and Humanized Computing, 2018.
Example¶
Compute mTCI for a whole volume¶
[~, ~, bscan] = read_vol(file); mTCI = image_quality(bscan, 'mTCI', 'Spectralis');
- normalize_reflectance(bscan, seg, method)¶
Normalize the intensity (reflectance) of one or more bscans based on the reflectance of the RPE layer.
Input arguments¶
bscan: Matrix with B-scans of dimensions n_axial x n_ascan x N_bscan. If 2D matrix then it will be interpreted as a single B-scan.
seg: Struct with the segmentation of the ILM, IZ_RPE and BM.
method: Method used to normalize.
‘ascan’: to normalize each A-scan separately
‘bscan’: to normalize each B-scan as a whole (default).
Output arguments¶
bscan_norm: Normalized bscan images.
Notes¶
This function relies on an accurate segmentation of the ILM, IZ_RPE and BM.
The normalization sets the low and hight reflectance references to be the vitreous and the RPE, respectively. Can be thought as the % of deviation from those parametesr. Values outside [0,100] are expected.
The performance might be somewhat slow due to the necessity of looping through all the A-scans. There might be computational improvements using poly2mask but that needs to be adapted to handle NaNs properly (usual in segmentation). It might be also cleaner to use here reflectance_map to avoid duplicated code.
References¶
[1] Sharafeldeen, Precise higher‐order refectivity and morphology models for early diagnosis of diabetic retinopathy using OCT images, Scientific Reports, 2021. https://doi.org/10.1038/s41598-021-83735-7
Example¶
[~,seg,bscan] = read_vol('my_file.vol'); bscan_norm = normalize_reflectance(bscan, seg);
- reflectance_map(bscan, method, metric, seg, varargin)¶
Create a 2D map (en-face image) of each A-Scan reflectance
Input arguments (mandatory)¶
bscan: 3D Volume with b-scans images.
method: Method to compute reflectance.
‘raw’ (default)
‘normalized’
‘attenuation’
metric: Metric to be used.
‘mean’
‘total’
‘layer_index’
seg: Struct with boundary segmentation data (in voxel units measured from the top of each B-Scan). The dimensions must match the provided volume (bscan). If not provided, all the voxels in each A-scan are used.
Input arguments (optional)¶
scale_z: axial (depth) resolution of the image. Necessary if the metric is ‘total reflectance’.
top: Name of the upper boundary of the layer to be analyzed. It must correspond to a field in seg.
bottom: Name of the bottom boundary of the layer to be analyzed. It must correspond to a field in seg.
If only one optional argument is provided that is assumed to be scale_z. When two optionals are provided then those are considered as top/bottom boundaries. When the three are provided they are assumed in the order: scale_z, top and bottom.
Output arguments¶
R: 2D matrix with reflectance values.
Notes¶
Reflectance may be derived from raw voxel intensities, normalized intensities or attenuation coefficient.
When using ‘normalized’, reflectance is corrected based on the vitreous and the RPE layer. See normalize_reflectance.m for details.
Attenuation coefficient computation relies on several assumptions on the optical properties of the tissue. See compute_attenuation.m for details.
‘layer_index’ metric is described in [1]. It includes a sort of normalization at a bscan level (the 99 percentile is used for normalization).
References¶
[1] Varga et al., “Investigating Tissue Optical Properties and Texture Descriptors of the Retina in Patients with Multiple Sclerosis”, PLos One, 2015
Example¶
[header, seg, bscan] = read_vol('my_file.vol'); R = reflectance_map(bscan, 'raw', 'total', 'ILM', 'RPE')
- stack_bscans(bscan, seg, layers)¶
Stack the bscan portion showing the same layer into the a single image as proposed in [1].
Input arguments¶
bscan: Matrix with B-scans of dimensions n_axial x n_ascan x n_bscan.
seg: Struct with segmentation data.
- layers: String or a cell array of strings with the name of the layer to be stacked. Note that, depending on the layer of
interest, the segmentation must follow a certain naming convention (see the beggining of the function).
Output arguments¶
stacked: Struct with a stacked b-scan for each layer in layers.
Notes¶
The stacking process is sensitive to NaN values in the segmentation. This function performs a rough extrapolation of NaN values that may not work if the number of NaN values is high.
References¶
[1] Tazarjani, Retinal OCT Texture Analysis for Differentiating Healthy Controls from Multiple Sclerosis (MS) with/without Optic Neuritis, BioMed Research International, 2021. https://doi.org/10.1155/2021/5579018
Example¶
Generate stacked b-scans of RNFL and GCIPL layers¶
[~, seg, bscan] = read_vol(file); layers = {'RNFL', 'GCIPL'}; stacked = stack_bscans(bscan, seg, layers)
Structural analysis¶
- compute_thickness(seg, layers, scale_z)¶
Compute thickness the specified layers specified by using the segmentation data stored in ‘seg’ struct.
Input arguments¶
seg: struct with the segmentation of the boundaries. Each field must correspond to a specific boundary.
layers: string or a cell array of strings indicating the layers for which to compute thickness.
scale_z: (optional). Axial (depth) resolution of the images in mm. If provided, it is used to transform thicknes values from pixel to um units.
Output arguments¶
Thickness Struct with thickness values for each layer.
Notes¶
The naming convention of the boundaries and layers might differ both in the literature and in different segmentation algorithms. Here we mostly follow the APOSTEL 2.0 recommendations ([1]) as specified below:
BM: Bruch’s membrane
ELM: external limiting membrane
EZ: ellipsoid zone
GCL: ganglion cell layer
GCIPL: ganglion cell and inner plexiform layer (composite)
ILM: inner limiting membrane
INL: inner nuclear layer
IPL: inner plexiform layer
IRL: inner retinal layers (composite)
IZ: interdigitation zone
MZ: myoid zone
ONL: outer nuclear layer
ONPL: outer nuclear - plexiform layer (composite)
OPL: outer plexiform layer
OSP: outer segment of the photoreceptors
RNFL: retinal nerve fiber layer
RPE: retinal pigment epithelium
For boundaries and layer composites not specified in [1] we have used underscores to denote top/bottom boundaries. To consider the following naming case:
EZ_OSP: boundary between EZ and OSP
EZOSP: composite layer with EZ + OSP
References¶
[1] Aytulun et al., “APOSTEL 2.0 Recommendations for Reporting Quantitative Optical Coherence Tomography Studies”, Neurology, 2021 https://doi.org/10.1212/WNL.0000000000012125
Example¶
Compute thickness for the NFL and GCL layers¶
[header, seg, ~, ~] = read_vol(file,'verbose', 'coordinates'); Thickness = compute_thickness(seg, {'NFL','GCL'}, header.scale_z);
- fit_pit_model(theta, rho, Z, pit_model, varargin)¶
Fit a mathematical model to the foveal pit
Input arguments (mandatory)¶
theta: Matrix with theta coordinates (polar). It expects data in format n_directions x n_points/direction.
rho: Matrix with rho value of polar coordinates.It expects data in format n_directions x n_points/direction.
Z Thickness map.
pit_model String defining the mathematical model to be used:
‘Breher’
‘Ding’
‘Dubis’
‘Liu’
‘Scheibe’
‘Yadav’
Input arguments (name-value pairs)¶
max_iter: Maximum number of iterations for each fitting. Default: 1000
tol_x: Tolerance of the errors during fitting. Default: 1e-6
tol_fun: Tolerance of the function during fitting. Default: 1e-6
x0’: Initial iteration coefficient values. By default specific values related to the model are used.
‘x_low: Inferior limits of model coefficients.
x_sup: Superior limits of model coefficients.
Output arguments¶
Z_fit: Matrix with fitted values
Fit_coeff: Struct with estimated model coefficients
References¶
[1] Romero-Bascones et al., Foveal Pit Morphology Characterization: A Quantitative Analysis of the Key Methodological Steps, Entropy, 2021 https://doi.org/10.3390/e23060699
[2] Breher K. et al., Direct Modeling of Foveal Pit Morphology from Distortion-Corrected OCT Images, Biomedical Optics Express, 2019.
[3] Ding Y. et al., Application of an OCT Data-Based Mathematical Model of the Foveal Pit in Parkinson Disease, Journal fo Neural Transmission, 2014.
[4] Dubis A.M. et al., “Reconstructing Foveal Pit Morphology from Optical Coherence Tomography Imaging”, British Journal of Ophthalmology, 2009.
[5] Liu L. et al., Sloped Piecemeal Gaussian Model for Characterising Foveal Pit Shape, Ophthalmic Physiological Optics, 2016.
[6] Scheibe P. et al., Parametric Model for the 3D Reconstruction of Individual Fovea Shape from OCT Data, Experimental Eye Research, 2014.
[7] Yadav S. et al., CuBe: Parametric Modeling of 3D Foveal Shape Using Cubic Bézier, Biomedical Optics Express, 2017.
- get_morph_params(rho, Z, parameters, average)¶
Compute morphological parameters of the foveal pit
Input arguments¶
rho: Matrix with rho coordinates (polar coordinates). Each row is a different angular direction.
Z: Matrix with thickness profile values. Each row is a different angular direction.
parameters: String or cell array of strings with the name of the parameters to computed. By default all available parameters are returned.
average: If true then radial parameters such as max slope are averaged across angular directions. Default is true.
Output arguments¶
X: Struct with computed features.
Notes¶
This parameters are usually computed for the TRT profile but can be computed as well for layers with a convex thickness profile such as GCL, IPL or INL
References¶
[1] Scheibe P. et al., Parametric Model for the 3D Reconstruction of Individual Fovea Shape from OCT Data, Experimental Eye Research, 2014.
[2] Yadav S. et al., CuBe: Parametric Modeling of 3D Foveal Shape Using Cubic Bézier, Biomedical Optics Express, 2017.
- smooth_pit(rho, Z, span)¶
Smooth the foveal pit based on LOESS smoothing
Input arguments¶
rho: Matrix with radial coordinates of thickness values.
Z: Matrix with foveal pit values.
span: Percentage of samples included in each window.
Output arguments:
‘Z_smooth’ Smoothed version of the thickness map.
Notes¶
The function expects the data in radial format: [n_angle x n_points]. To use it for entire B-Scans convert data to radial format first.
References¶
[1] Romero-Bascones et al., Foveal Pit Morphology Characterization: A Quantitative Analysis of the Key Methodological Steps, Entropy, 2021 https://doi.org/10.3390/e23060699
Example¶
[header, seg] = read_vol('my_file.vol','coordinates'); Thickness = compute_thickness(seg, 'TRT'); [X, Y, TRT] = resample_map(header.X_oct, header.Y_oct, Thickness.TRT, ... 'star', 'n_point', 100, 'max_d', 2.4, 'n_angle', n_angle); [theta, rho] = cart2pol(X, Y); TRT_smooth = smooth_pit(rho, TRT, 20);
Spatial analysis¶
- find_fovea(X, Y, TRT, method, max_d)¶
Find foveal center based on total retinal thickness (TRT) map.
Input arguments¶
X: Matrix with X coordinates of each A-Scan.
Y: Matrix with Y coordinates of each A-Scan.
TRT: Matrix with total retinal thickness values.
method: Method used to find the foveal center. Options [‘flood’ (default), ‘min’, ‘resample_min’, ‘smooth_min’]
max_d: Maximum alignment error. Default: 0.85
Output arguments¶
x_fovea: X coordinate of the foveal center.
y_fovea: Y coordinate of the foveal center.
Notes¶
The
smooth+min
method is based on thefoveafinder.m
function of AURA tools. If you use it, please provide appropriate credit to the original work (https://www.nitrc.org/projects/aura_tools/).References¶
[1] Romero-Bascones et al., Foveal Pit Morphology Characterization: A Quantitative Analysis of the Key Methodological Steps, Entropy, 2021 https://doi.org/10.3390/e23060699
Example¶
file = '../data/raster.vol'; [header, seg, ~, ~] = read_vol(file, 'coordinates'); Thickness = compute_thickness(seg, 'TRT', header.scale_z); [x_fovea, y_fovea] = find_fovea(header.X, header.Y, Thickness.TRT)
- flip_coordinates(X, eye, eye_ref)¶
Flip X coordinates if eye is equal to eye_ref
Input arguments¶
X: input x coordinates (in any shape)
eye: string with eye to be tested
eye_ref: reference to decide when to flip (usually OS)
Output arguments¶
X: flipped coordinates
- get_ascan_coordinates(header)¶
Compute A-scan coordinates (X, Y) based on the scanning protocol
Input arguments¶
header: File header obtained when reading an OCT file.
Output arguments¶
X: 2D matrix with X coordinates pointing temporal to nasal.
Y: 2D matrix with Y coordinates pointing inferior to superior.
- resample_map(X, Y, Z, grid_type, varargin)¶
Resample a 2D map into a new grid by interpolation/extrapolation
Input arguments (mandatory)¶
X: Original X coordinates.
Y: Original Y coordinates.
Z: Original Z values (e.g., thickness values).
grid_type: String specifying the resampling grid type. Depending on the grid type it must be followed by specific extra arguments. Options: [‘regular’, ‘star’]
Input arguments (name/value pair)¶
max_d: Maximum X and Y values (‘regular’) or radius (‘star’)
n_point: If grid_type == ‘regular’, the number of points in X and Y directions. If ‘star’, the number points from 0 to max_d
n_angle: Number of directions to use (when the grid_type is ‘star’)
theta_0: Initial angle for star resampling
interp_method: Interpolation method [‘linear’ (default),’cubic’]
extrapolate If true then points with NaN outside the original range are extrapolated. Default: false
Output arguments¶
X1 New X coordinates.
Y1 New Y coordinates.
Z1 New Z values.
Notes¶
If the region to cover is bigger than the original data region it might not be possible to extrapolate values accurately.
Example¶
Resample original A-scans into a regular grid
[header, seg, ~, ~] = read_vol(myfile.vol, 'coordinates'); Thickness = compute_thickness(seg, 'TRT', header.scale_z); [X, Y, TRT] = resample_map(header.X_oct, header.Y_oct, Thickness.TRT, ... 'regular', 'n_point', 100, 'max_d', 2.5);
- sectorize_map(X, Y, Z, metric, sector_type, varargin)¶
Sectorize a 2D map into several sectors (e.g., ETDRS average)
Input arguments¶
X: X coordinates of map points
Y: Y coordinates of map points
Z: Z coordinates of map points
metric metric to be used to sectorize data. Options: [‘mean’, ‘std’, skewness’, ‘kurtosis’]
sector_type: sectorization definition. Two options:
String defining the sectorization type. It must be followed by appropriate arguments (see examples).
Struct with sectorization info created beforehand.
varargin: extra arguments to define the sectorization.
Output arguments¶
Zs: Sectorized values for each sector.
Sectors: Struct with spatial data defining the sectorization. Useful when the Sectors input variable is a string.
Notes¶
All angles are expected in radians. To convert from degrees to radians use deg2rad() function.
Examples¶
ETDRS sectorization¶
[header, seg, ~, ~] = read_vol(file,'verbose', 'get_coordinates'); Thickness = compute_thickness(seg, 'TRT', header.scale_z); [X, Y, TRT] = resample_map(header.X_oct, header.Y_oct, Thickness.TRT, ... 'regular', 'n_point', 100, 'max_d', 2.5); [Z, G] = sectorize_map(X, Y, TRT, 'mean', 'etdrs');
2 ring sectorization¶
[header, seg, ~, ~] = read_vol(file,'verbose', 'get_coordinates'); Thickness = compute_thickness(seg, 'TRT', header.scale_z); [X, Y, TRT] = resample_map(header.X_oct, header.Y_oct, Thickness.TRT, ... 'regular', 'n_point', 100, 'max_d', 2.5); [Z, G] = sectorize_map(X, Y, TRT, 'mean', 'ring', [0.5 1.5 3]);
- sectorize_peripapillar(X, Y, Z, sect_type, varargin)¶
Sectorize thickness values of a peripapillar circular scan
Input arguments¶
X: X coordinates of map points
Y: Y coordinates of map points
Z: Z coordinates of map points
sector_type: String defining the sectorization type:
‘average’
‘4_quadrant’
‘qustom’: must be followed by the number of angles and the initial angle (see examples).
varargin: Extra arguments to define the sectorization.
Output arguments¶
Zs: Sectorized values for each sector.
Notes¶
X and Y coordinates must follow the temporal-nasal and inferior-superior conventions.
‘4_quadrant’ sectorization returns values in the order: ‘nasal’, ‘superior’, ‘temporal’ and ‘inferior’.
Examples¶
4 quadrants sectorization¶
[header, seg, ~, ~] = read_vol(file,'verbose', 'get_coordinates'); Thickness = compute_thickness(seg, 'TRT', header.scale_z); Z = sectorize_peripapillar(X, Y, TRT, '4_quadrant');
Qustom number of quadrants sectorization¶
[header, seg, ~, ~] = read_vol(file,'verbose', 'get_coordinates'); Thickness = compute_thickness(seg, 'TRT', header.scale_z); Z = sectorize_peripapillar(X, Y, TRT, 'qustom', 8, -pi/8);
Texture analysis¶
- fractal_dimension(I, method, visu)¶
Compute Fractal Dimension of a grayscale image
Input arguments¶
I: Input image as a 2D matrix. Color images are converted to gray scale values.
method: String indicating the method to use for fractal dimension computation.
‘DBC’ [1]
‘IR_DBC’ (default) [2]
visu: If true a plot with the computed values is shown. Default = false
Output arguments¶
FD: Fractal dimension.
Notes¶
This implementation does not incorporate a procedure to compute the fractal dimension of neither color nor binary images. The ‘DBC’ method has several assumptions on image size so ‘IR_DBC’ method is prefered.
References¶
[1] Sarkar N. and Chaudhuri B. “An Efficient Differential Box-Counting Approach to Compute Fractal Dimension of Image”, IEEE Transactions On Systems, Man and Cybernetics, 1991
[2] Long M. and Peng F. “A Box-Counting Method with Adaptable Box Height for Measuring the Fractal Feature of Images”, Radioengineering, 2013
Example¶
I = imread('cameraman.tif'); FD = fractal_dimension(I);
- GLCM_features(GLCM, varargin)¶
Compute multiple features from a GLCM matrix
Input arguments (mandatory)¶
GLCM: 2D GLCM matrix obtained by graycomatrix()
Input arguments (optional)¶
features: Cell array of strings with the features to be computed. By default the full set of features are computed.
Output arguments¶
X: Structure with computed features.
Notes¶
Some features assume GLCM matrix to be symmetric
The naming convention of some parameters is messy in the literature. The following issues are important:
Homogeneity: equal to inverse difference and inverse difference moment.
Dissimilarity: equal to the difference average
Cluster tendency is equal to sum variance
Intertia is equal to contrast
Additional features not yet implemented: maximal correlation coefficient
References¶
[1] Haralick R. Shanmugam K. and Dinstein I. “Textural Features for Image Classification”, IEEE Transactions on Systems, Man and Cybernetics, 1973 http://haralick.org/journals/TexturalFeaturesHaralickShanmugamDinstein.pdf#page10
[2] Soh L. “Texture Analysis of SAR Sea Ice Imagery Using Gray Level Co-Ocurrence Matrices”, IEEE Transations on Gegoscience and Remote Sensing, 1999. https://doi.org/10.1109/36.752194
[3] Zwanenburg et al. The Image Biomarker Standardization Initiative: Standardized Quantitative Radiomics for High-Throughput Image-based Phenotyping, 2020, Radiology, https://pubs.rsna.org/doi/full/10.1148/radiol.2020191145 Implementation: https://pyradiomics.readthedocs.io/en/latest/features.html?highlight=imc#radiomics.glcm.RadiomicsGLCM.getImc1FeatureValue
Example¶
I = imread('cameraman.tif'); M = graycomatrix(I,'NumLevels',9,'G',[]) X = GLCM_features(M)
- lacunarity(I, method, r, visu)¶
Compute lacunarity of a gray-scale/binary image
Lacunarity is a measure of how an image covers the space. Images/masks with bigger gaps will show a higher lacunarity values. Instead of a single value lacunarity is often computed for a set of scales defined by the size of the box used to compute it. It is usually considered as a complementary metric to fractal dimension.
Input arguments¶
I: Input grayscale/binary image.
method: Method to compute lacunarity.
‘window’: (default) fast and simple. See [2] Section 2.2.
‘local_bin’: See [3] Section 3.1.
‘box_3d’: Slow. See [3] Section 3.2.
r: 1D array with window size values. By default 10 values from 1 to the minimum between rows and columns (min{M, N}) are used.
visu: If true a plot with the computed values is shown. Default = false
Output arguments¶
L: 1D array with lacunarity values.
r 1D array with box size values.
Notes¶
Color images will be converted to grayscale. There are multiple definitions of lacunarity, with different calculation methods. This function covers 3 methods with different approaches. The scale of each method is not directly comparable.
There is also a “normalized Lacunarity” proposed in [2] that may be interesting to implement in the future.
References¶
[1] Allain C. and Clitre M. “Charaterizing the lacunarity of random and deterministic fractal sets”, Physical Review, 1991. https://doi.org/10.1103/PhysRevA.44.3552
[2] Roy A. and Perfect E. “Lacunarity Analyses of Multifractal and Natural Grayscale Patterns”, Fractals, 2014 https://doi.org/10.1142/S0218348X14400039
[3] Backes A.R. “A new approach to estimate lacunarity of texture images”, Pattern Recognition Letters, 2013
Example¶
Compute lacunarity¶
I = imread('cameraman.tif'); [L, s] = lacunarity(I)
Compute Lacunarity choosing a method and custom r values¶
I = imread('cameraman.tif'); r = 2:10; [L, ~] = lacunarity(I, 'local_bin', r);
- LBP_features(I, n_neighbor, features)¶
Compute features using Local Binary Pattern
Input arguments¶
I: Input grayscale image to be analyzed.
n_neighbor: Number of neighbors. Default is 8.
features: String or a cell array of strings defining the nmerical features to be computed. By default all the features are returned. If ‘none’ then no features are computed and only the LBP histogram is returned.
Output arguments¶
X: Struct with features computed from LBP histogram.
H: LBP histogram.
Example¶
I = imread('cameraman.tif'); X = LBP_features(I, 8)