deepmib helpers

deepmib.augmentAndCrop2dPatchMultiGPU(patchIn, info, inputPatchSize, outputPatchSize, mode, options)

AUGMENTANDCROP2DPATCHMULTIGPU - Augment 2D training patches using operations in options.AugOpt2D and/or crop the response to the network’s output size.

Syntax:
[patchOut, info, augList, augPars] = augmentAndCrop2dPatchMultiGPU( ...
    patchIn, info, inputPatchSize, outputPatchSize, mode, options)
Input Arguments:
  • patchIn - table with InputImage and ResponsePixelLabelImage fields (semantic segmentation) or a matrix (classification)

  • info - additional info struct about the input patch

  • inputPatchSize - [1×4] input patch size as [height, width, depth, color]

  • outputPatchSize - [1×4] output patch size as [height, width, depth, classes]

  • mode - [char] operation mode:

    • 'show' - pass through without augmentation or cropping

    • 'crop' - crop only, no augmentation

    • 'aug' - augment, then crop

  • options - struct with additional parameters:

    • .Workflow - [string] workflow name (obj.BatchOpt.Workflow{1})

    • .Aug2DFuncNames - copy of mibDeepController.Aug2DFuncNames

    • .AugOpt2D - copy of mibDeepController.AugOpt2D

    • .Aug2DFuncProbability - copy of mibDeepController.Aug2DFuncProbability; per-function trigger probabilities

    • .T_ConvolutionPadding - [string] convolution padding type (mibDeepController.BatchOpt.T_ConvolutionPadding{1})

Output Arguments:
  • patchOut - two-column table as required by trainNetwork for single-input networks

  • info - additional info struct about the input patch

  • augList - cell array with the names of applied augmentation operations

  • augPars - matrix of applied parameter values (NaN when not used); second column holds the blend parameter for Hue+Sat jitter

deepmib.augmentAndCrop3dPatchMultiGPU(patchIn, info, inputPatchSize, outputPatchSize, mode, options)

AUGMENTANDCROP3DPATCHMULTIGPU - Augment 3D training patches using operations in options.AugOpt3D and/or crop the response to the network’s output size.

Syntax:
[patchOut, info, augList, augPars] = augmentAndCrop3dPatchMultiGPU( ...
    patchIn, info, inputPatchSize, outputPatchSize, mode, options)
Input Arguments:
  • patchIn - table with InputImage and ResponsePixelLabelImage fields (semantic segmentation) or a matrix (classification)

  • info - additional info struct about the input patch

  • inputPatchSize - [1×4] input patch size as [height, width, depth, color]

  • outputPatchSize - [1×4] output patch size as [height, width, depth, classes], or [height, width, classes] for 2.5D Z2C networks

  • mode - [char] operation mode:

    • 'show' - pass through without augmentation or cropping

    • 'crop' - crop only, no augmentation

    • 'aug' - augment, then crop

  • options - struct with additional parameters:

    • .Workflow - [string] workflow name (options.Workflow)

    • .Aug3DFuncNames - copy of mibDeepController.Aug3DFuncNames

    • .AugOpt3D - copy of mibDeepController.AugOpt3D

    • .Aug3DFuncProbability - per-function trigger probabilities

    • .O_PreviewImagePatches - [logical] show image patches during augmentation (mibDeepController.BatchOpt.O_PreviewImagePatches)

    • .O_FractionOfPreviewPatches - [numeric] fraction of patches to preview (mibDeepController.BatchOpt.O_FractionOfPreviewPatches{1})

    • .T_ConvolutionPadding - [string] convolution padding type (mibDeepController.BatchOpt.T_ConvolutionPadding{1})

Output Arguments:
  • patchOut - two-column table as required by trainNetwork for single-input networks

  • info - additional info struct about the input patch

  • augList - cell array with the names of applied augmentation operations

  • augPars - matrix of applied parameter values (NaN when not used); second column holds the blend parameter for Hue+Sat jitter

deepmib.augmentInstanceData2D(dataIn, options)

AUGMENTINSTANCEDATA2D - Augment a 2D instance-segmentation observation for SOLOv2 training.

Syntax:
dataOut = deepmib.augmentInstanceData2D(dataIn, options)

Applies the augmentations enabled in options.AugOpt2D to a single instance observation. Geometric transforms (reflections, 90/arbitrary rotation, scale, shear) are applied identically to the image and every instance mask; the bounding boxes are then recomputed from the warped masks so that boxes, masks and labels stay in sync. Intensity/colour augmentations (noise, blur, hue/saturation/brightness/contrast jitter) are applied to the image only.

Used as a datastore transform in mibDeepController.startTrainingInstances:

labelsDS = transform(labelsDS, @(d)deepmib.augmentInstanceData2D(d, options));

Input Arguments:
  • dataIn - 1×4 cell as returned by deepmib.matReadInstanceLabels:

    • dataIn{1} - image [H×W×3]

    • dataIn{2} - bounding boxes [M×4] in [x y width height] format

    • dataIn{3} - labels [M×1 categorical]

    • dataIn{4} - instance masks [H×W×M logical]

  • options - struct with augmentation settings:

    • .AugOpt2D - copy of mibDeepController.AugOpt2D (per-augmentation .Min/.Max limits plus global .Fraction and .FillValue)

    • .Aug2DFuncNames - cell array with names of enabled augmentations

    • .Aug2DFuncProbability - matching per-augmentation trigger probabilities

Output Arguments:
  • dataOut - 1×4 cell with the augmented {image, boxes, labels, masks}; instances whose mask vanished after a geometric transform are dropped.

deepmib.convertAbsoluteToRelativePath(absolutePath, relativePath, templateText)

CONVERTABSOLUTETORELATIVEPATH - convert absolute path into relative path, where the part of the absolute.

Syntax:
function result = convertAbsoluteToRelativePath(absolutePath, relativePath, templateText)

path that is matching the relative path is replaced with the templateText.

Input Arguments:
  • absolutePath - string with the absolute path, for example “c:myfilesdir1subdir1”

  • relativePath - string with the relative path, for example “c:myfilesdir2subdir2”

  • templateText - string with the template text to be inserted instead of the relativePath, for example “[RELATIVE]”

Output Arguments:
  • result - string with the replaced string. When relativePath is not found in the absolutePath, result is equal to absolutePath. Otherwise, the result = “[RELATIVE]....dir1subdir1”

Usage:

Note

The reverse operation is done using deepmib.convertRelativeToAbsolutePath.

Example 1 - convert an absolute path to a relative one

absolutePath = 'c:\myfiles\dir1\subdir1';
relativePath = 'c:\myfiles\dir2\subdir2';
templateText = '[RELATIVE]';
result = deepmib.convertAbsoluteToRelativePath(absolutePath, relativePath, templateText);
% result = '[RELATIVE]\..\..\dir1\subdir1'
deepmib.convertRelativeToAbsolutePath(relativePath, absolutePath, templateText)

MIBGETMIBVERSIONNUMBERIC - Convert a relative path back to an absolute path, where templateText in the relative path is replaced with absolutePath.

Syntax:
result = convertRelativeToAbsolutePath(relativePath, absolutePath, templateText)
Input Arguments:
  • relativePath - [string] relative path containing the template, e.g. '[RELATIVE]\..\..\dir1\subdir1'

  • absolutePath - [string] absolute base path, e.g. 'c:\myfiles\dir2\subdir2'

  • templateText - [string] placeholder to replace, e.g. '[RELATIVE]'

Output Arguments:
  • result - [string] reconstructed absolute path

Usage:

Note

The reverse operation is done using deepmib.convertAbsoluteToRelativePath.

Example 1 - convert a relative path back to an absolute one

relativePath = '[RELATIVE]\..\..\dir1\subdir1';
absolutePath = 'c:\myfiles\dir2\subdir2';
templateText = '[RELATIVE]';
result = convertRelativeToAbsolutePath(relativePath, absolutePath, templateText);
% result = 'c:\myfiles\dir1\subdir1'
deepmib.createAnisotropic3dUnet(inputPatchSize, numClasses, filterSize, numFirstFilters, convPadding, encoderDepth, numAnisotropicBlocks)

CREATEANISOTROPIC3DUNET - Create a 3D U-Net with N initial anisotropic (2D) downsampling blocks.

Syntax:
function [lgraph, outputPatchSize] = createAnisotropic3dUnet(inputPatchSize, numClasses,  filterSize, numFirstFilters, convPadding, encoderDepth, numAnisotropicBlocks)

For anisotropic datasets where Z voxel spacing is coarser than XY, the first numAnisotropicBlocks encoder stages use 2D convolution kernels ([filterSize filterSize 1]) and 2D max-pooling ([2 2 1]), downsampling only in the XY plane. The corresponding decoder stages are also made 2D. After those stages, the remaining encoder/decoder stages use the standard 3D kernels.

Input Arguments:
  • inputPatchSize - 4-element vector [height width depth channels]

  • numClasses - number of segmentation classes

  • filterSize - convolution kernel size for the 3D U-Net template

  • numFirstFilters - number of output channels for the first encoder stage

  • convPadding - ‘same’ or ‘valid’

  • encoderDepth - total number of encoder stages

  • numAnisotropicBlocks - (optional) number of initial 2D stages; default 1

Output Arguments:
  • lgraph - layerGraph (MATLAB < R2026a) or dlnetwork (MATLAB >= R2026a) with the requested anisotropic modifications applied

  • outputPatchSize - 4-element vector [height width depth classes], or [] when convPadding is ‘valid’

Usage:

Example 1 - 3D U-Net with 2 initial 2D downsampling stages

[lgraph, outputPatchSize] = deepmib.createAnisotropic3dUnet( ...
    [64 64 32 1], 3, 3, 32, 'same', 3, 2);
deepmib.customDiceForwardLoss(Y, T, dataDimension, useClasses)

CUSTOMDICEFORWARDLOSS - Compute Dice loss between network predictions and training targets.

Syntax:
loss = customDiceForwardLoss(Y, T, dataDimension, useClasses)

Used with trainnet as a custom loss function:

[net, info] = trainnet(AugTrainDS, net, @customDiceForwardLoss, TrainingOptions);
Input Arguments:
  • Y - dlarray of network predictions (provided by trainnet)

  • T - dlarray of training targets (provided by trainnet)

  • dataDimension - [numeric] dataset dimensionality: 2, 2.5, or 3

  • useClasses - [numeric] indices of classes to include in the loss; pass [] to use all classes

deepmib.customTrainingProgressDisplay(progressStruct, trainingProgressOptions)

CUSTOMTRAININGPROGRESSDISPLAY - Show custom progress dialog for DeepMIB training.

Syntax:
stopState = customTrainingProgressDisplay(progressStruct, trainingProgressOptions)
Input Arguments:
  • progressStruct - struct with current training progress (provided by trainNetwork):

    • .Epoch - current epoch number

    • .Iteration - current iteration number, e.g. 2

    • .TimeSinceStart - elapsed time in seconds, e.g. 4.5219

    • .TrainingLoss - current training loss, e.g. 0.7802

    • .ValidationLoss - validation loss ([] if no validation)

    • .BaseLearnRate - current learning rate, e.g. 0.0100

    • .TrainingAccuracy - training accuracy (%), e.g. 26.9975

    • .TrainingRMSE - training RMSE (regression tasks), e.g. 164.7408

    • .ValidationAccuracy - validation accuracy ([] if no validation)

    • .ValidationRMSE - validation RMSE ([] if no validation)

    • .State - training phase string, e.g. 'iteration'

  • trainingProgressOptions - struct with display/training parameters:

    • .O_NumberOfPoints - [numeric] max points in the progress plot (mibDeepController.BatchOpt.O_NumberOfPoints{1})

    • .NetworkFilename - [char] network file path (mibDeepController.BatchOpt.NetworkFilename)

    • .noColorChannels - [numeric] number of colour channels (str2num(obj.BatchOpt.T_InputPatchSize)(4))

    • .Workflow - [char] active workflow (obj.BatchOpt.Workflow{1})

    • .Architecture - [char] network architecture (obj.BatchOpt.Architecture{1})

    • .refreshRateIter - [numeric] UI refresh rate in iterations (obj.BatchOpt.O_RefreshRateIter{1})

    • .matlabVersion - [numeric] MATLAB release number (obj.mibController.matlabVersion)

    • .iterPerEpoch - [numeric] iterations per epoch

    • .sendNextReportAtEpoch - [numeric] epoch at which to send the next e-mail report

    • .TrainingOpt.MaxEpochs - maximum number of training epochs

    • .TrainingOpt.solverName - optimiser name string

    • .TrainingOpt.Shuffle - dataset shuffle strategy

    • .TrainingOpt.LearnRateSchedule - learning-rate schedule type

    • .TrainingOpt.OutputNetwork - which network to save on each checkpoint

    • .TrainingOpt.InitialLearnRate - initial learning rate

    • .TrainingOpt.LearnRateDropPeriod - period (epochs) for learning-rate drop

    • .TrainingOpt.ValidationPatience - early-stop patience (epochs)

    • .TrainingOpt.ValidationFrequency - validation frequency (iterations)

deepmib.customTrainingProgressDisplayTrainNet(progressStruct, trainingProgressOptions)

CUSTOMTRAININGPROGRESSDISPLAYTRAINNET - Show custom progress dialog for DeepMIB training (alternative version for the trainnet engine).

Syntax:
stopState = customTrainingProgressDisplayTrainNet(progressStruct, trainingProgressOptions)
Input Arguments:
  • progressStruct - struct with current training progress (provided by trainnet):

    • .Epoch - current epoch number

    • .Iteration - current iteration number

    • .TimeElapsed - elapsed time as duration, e.g. 00:00:02 (called TimeSinceStart in trainNetwork)

    • .LearnRate - current learning rate, e.g. 0.0050 (called BaseLearnRate in trainNetwork)

    • .TrainingLoss - current training loss, e.g. 0.7802

    • .ValidationLoss - validation loss ([] when training without validation)

    • .TrainingAccuracy - training accuracy (%), e.g. 26.9975

    • .ValidationAccuracy - validation accuracy ([] when training without validation)

    • .State - training phase string, e.g. 'iteration'

  • trainingProgressOptions - struct with display/training parameters:

    • .O_NumberOfPoints - [numeric] max points in the progress plot (mibDeepController.BatchOpt.O_NumberOfPoints{1})

    • .NetworkFilename - [char] network file path (mibDeepController.BatchOpt.NetworkFilename)

    • .noColorChannels - [numeric] number of colour channels (str2num(obj.BatchOpt.T_InputPatchSize)(4))

    • .Workflow - [char] active workflow (obj.BatchOpt.Workflow{1})

    • .Architecture - [char] network architecture (obj.BatchOpt.Architecture{1})

    • .refreshRateIter - [numeric] UI refresh rate in iterations (obj.BatchOpt.O_RefreshRateIter{1})

    • .matlabVersion - [numeric] MATLAB release number (obj.mibController.matlabVersion)

    • .iterPerEpoch - [numeric] iterations per epoch

    • .sendNextReportAtEpoch - [numeric] epoch at which to send the next e-mail report

    • .TrainingOpt.MaxEpochs - maximum number of training epochs

    • .TrainingOpt.solverName - optimiser name string

    • .TrainingOpt.Shuffle - dataset shuffle strategy

    • .TrainingOpt.LearnRateSchedule - learning-rate schedule type

    • .TrainingOpt.OutputNetwork - which network to save on each checkpoint

    • .TrainingOpt.InitialLearnRate - initial learning rate

    • .TrainingOpt.LearnRateDropPeriod - period (epochs) for learning-rate drop

    • .TrainingOpt.ValidationPatience - early-stop patience (epochs)

    • .TrainingOpt.ValidationFrequency - validation frequency (iterations)

deepmib.generateDefaultAugmentations(mode)

GENERATEDEFAULTAUGMENTATIONS - generate default augmentation settings from MIB 2.8455.

Syntax:
function augmentationSettings = generateDefaultAugmentations(mode)
Input Arguments:
  • mode - string ‘2D’, ‘3D’ specifying type of augmentation settings

Output Arguments:
  • augmentationSettings - structure with augmentation settings

Usage:

Example 1 - generate default 2D augmentation settings

deepmib.generateDefaultAugmentations('2D');

Example 2 - generate default 2.5D / 3D augmentation settings

deepmib.generateDefaultAugmentations('3D');
deepmib.getBoxFromMask(masks)

GETBOXFROMMASK - Compute axis-aligned bounding boxes from a stack of instance masks.

Syntax:
boxes = deepmib.getBoxFromMask(masks)
Input Arguments:
  • masks - [H×W×N logical] binary mask stack, one slice per object instance

Output Arguments:
  • boxes - [N×4 double] bounding boxes in [x y width height] format (one row per mask slice). Empty mask slices produce a row of NaN, so the caller can filter them together with the corresponding masks and labels.

Used when augmenting instance-segmentation data: after a geometric transform is applied to the mask stack the bounding boxes must be recomputed from the warped masks to keep boxes and masks in sync (see deepmib.augmentInstanceData2D).

deepmib.matReadInstanceLabels(filename, getImageOptions)

MATREADINSTANCELABELS - Read preprocessed instance-segmentation labels from a MAT file and return them as a cell array.

Syntax:
out = matReadInstanceLabels(filename, getImageOptions)
Input Arguments:
  • filename - [string] full path to the MAT file containing three variables:

    • instanceBoxes - [N×4 double] bounding-box coordinates (one row per object)

    • instanceNames - [N×1 categorical] object class labels

    • instanceMasks - [H×W×N logical] binary mask stack (one slice per object)

  • getImageOptions - struct passed to deepmib.storeLoadImages for loading the corresponding image file; see that function for field details

Output Arguments:
  • out - cell array:

    • out{1} - loaded image (grayscale converted to RGB)

    • out{2} - instanceBoxes matrix

    • out{3} - instanceNames categorical array

    • out{4} - instanceMasks logical stack

deepmib.oldAugSettingsToNew(augSettingsOld, mode)

OLDAUGSETTINGSTONEW - Convert old DeepMIB augmentation settings to the new format (MIB 2.8455+).

Syntax:
augSettingsNew = oldAugSettingsToNew(augSettingsOld, mode)
Input Arguments:
  • augSettingsOld - struct with old augmentation settings

  • mode - [char] augmentation type: '2D' or '3D'

Output Arguments:
  • augSettingsNew - struct with updated augmentation settings

deepmib.readInstancePatch(filename, options)

READINSTANCEPATCH - Read one native-resolution training patch for 2D instance segmentation (SOLOv2).

Syntax:
out = deepmib.readInstancePatch(filename, options)

Loads a preprocessed instance label map (see deepmib.saveInstanceLabelsParFor) and its corresponding image, then crops a single native-resolution patch and rebuilds the SOLOv2 ground truth for that patch. Cropping from the 2D label map on-the-fly (rather than from a pre-generated full-image mask stack) keeps memory usage low for large / whole-slide images.

Patch sampling is a mix of object-seeded and uniform-random windows:
  • with probability options.objectFraction a random object is picked and the patch is placed with a random offset (coordinate jitter) so the object lands anywhere in the patch - never forced to the centre (which would teach a false “object-in-centre” prior);

  • otherwise a uniform-random window is taken (may be pure background).

Input Arguments:
  • filename - [string] full path to the preprocessed *.mat (imageFilename + instanceLabelMap)

  • options - struct with fields:

    • .imageDir - folder holding the source images (e.g. TrainImages)

    • .patchSize - [height width] patch size (= network input H×W)

    • .objectFraction - fraction of patches that are object-seeded (e.g. 0.9)

    • .minObjectArea - minimum object area (pixels) kept after cropping

    • .getImageOptions - struct passed to deepmib.storeLoadImages

    • .patchSeed - optional seed for a private random stream. When present the same call always crops the same window, which is what the validation set needs: its loss is only comparable between evaluations if the patches do not change underneath it. Training leaves this out, so every epoch re-samples fresh windows from the global stream (that resampling is a large part of what “patches per image” buys). The private stream is used instead of rng so that seeding a validation read never disturbs the global stream feeding the training patches.

Output Arguments:
  • out - 1×4 cell {image HxWx3, boxes Kx4 [x y w h], labels Kx1 categorical, masks HxWxK logical} as required by trainSOLOV2.

deepmib.saveImageParFor(fn, imgOut, compressImage, options)

SAVEIMAGEPARFOR - Save an image matrix from inside a parfor loop.

Syntax:
saveImageParFor(fn, imgOut, compressImage)
saveImageParFor(fn, imgOut, compressImage, options)

Used by mibDeepController to preprocess images; save cannot be called directly inside parfor.

Input Arguments:
  • fn - [string] full output filename

  • imgOut - image matrix to save

  • compressImage - [logical] true to enable MAT-file compression

  • options (optional) - struct with additional parameters:

    • .dimOrder - [char] axis order string, e.g. 'yxzct' meaning [height, width, depth, color, time]

    • .modelType - [double] label model type: 63, 255, or 65536

    • .modelMaterialNames - cell array of class name strings

    • .modelMaterialColors - [N×3 double] RGB colour matrix per class

deepmib.saveInstanceLabelsParFor(fn, imageFilename, instanceLabelMap, compressModels)

SAVEINSTANCELABELSPARFOR - Save a preprocessed 2D instance label map from inside a parfor loop.

Syntax:
saveInstanceLabelsParFor(fn, imageFilename, instanceLabelMap, compressModels)

Used by mibDeepController.processImagesForInstanceSegmentation; save cannot be called directly inside parfor.

For 2D instance segmentation the label map (each object painted with its own unique index, background 0) is stored as a compact 2D array. Training crops native-resolution patches from it on-the-fly (see deepmib.readInstancePatch), which is far more memory-efficient than storing a full H×W×N binary mask stack - essential for large / whole-slide microscopy images.

Input Arguments:
  • fn - [string] full output filename

  • imageFilename - [string] corresponding source image filename

  • instanceLabelMap - [H×W uint16] label map, one unique index per object instance

  • compressModels - [logical] true to enable MAT-file compression

deepmib.saveTrainingPlot(src, evnt, trainingProgressStruct, outputFilename)

SAVETRAININGPLOT - Save the custom training progress plot to an image file.

Syntax:
saveTrainingPlot(src, evnt, trainingProgressStruct, outputFilename)
Input Arguments:
  • src - source object that triggered the callback (e.g. menu item)

  • evnt - event data (unused; pass [] when calling manually)

  • trainingProgressStruct - mibDeepTrainingProgressStruct with fields:

    • .UIFigure - handle to the training progress uifigure

    • .NetworkFilename - [char] path to the network file (used to suggest a save name)

  • outputFilename (optional) - [char] full output path; when empty or omitted a file-save dialog is presented

deepmib.segmentBlockedImage(block, net, dataDimension, patchwiseWorkflowSwitch, generateScoreFiles, executionEnvironment, padShift)

SEGMENTBLOCKEDIMAGE - Segment a blocked image using a trained network.

Syntax:
[outputLabeledImageBlock, scoreBlock] = segmentBlockedImage( ...
    block, net, dataDimension, patchwiseWorkflowSwitch, ...
    generateScoreFiles, executionEnvironment, padShift)

The input block is provided as a batch of blocks from a blockedImage.

Input Arguments:
  • block - struct provided by blockedImage/apply; the first two iterations have BatchSize == 1, subsequent ones use the user-selected batch size:

    • .BlockSub - block subscript index, e.g. [1 1 1]

    • .Start - block start position in the image, e.g. [1 1 1]

    • .End - block end position, e.g. [224 224 3]

    • .Level - resolution level

    • .ImageNumber - index of the source image

    • .BorderSize - border padding, e.g. [0 0 0]

    • .BlockSize - block dimensions, e.g. [224 224 3]

    • .BatchSize - number of blocks in the batch

    • .Data - pixel data array, e.g. [224×224×3 uint8]

  • net - trained DAGNetwork or dlnetwork

  • dataDimension - [numeric] dataset dimensionality: 2, 2.5, or 3

  • patchwiseWorkflowSwitch - [logical] true for patch-wise classification, false for semantic segmentation

  • generateScoreFiles - [integer] score file format to generate:

    • 0 - do not generate score files

    • 1 - AM format

    • 2 - MATLAB non-compressed format

    • 3 - MATLAB compressed format

    • 4 - MATLAB non-compressed format (range 0-1)

  • executionEnvironment - [char] execution environment for prediction (e.g. 'auto', 'gpu', 'cpu')

  • padShift - [numeric] [y, x] or [y, x, z] padding to crop output during overlap-mode prediction

deepmib.segmentBlockedImageInstances(block, net, threshold, executionEnvironment)

SEGMENTBLOCKEDIMAGEINSTANCES - Segment one tile of a blocked image with SOLOv2 (centroid-in-core).

Syntax:
coreLabel = deepmib.segmentBlockedImageInstances(block, net, threshold, executionEnvironment)

Per-block function for blockedImage/apply used to tile large / whole-slide images for 2D instance segmentation. Each tile is read with a surrounding border of context (BorderSize = overlap). segmentObjects is run on the bordered tile, and only the instances whose centroid falls inside the tile core (the non-border region that apply writes back) are kept - so each object is emitted by exactly the tile that owns its centroid, with no duplicates and no seam-splitting.

Globally unique instance IDs are assigned via the global counter mibInstanceIdCounter, which the caller must reset to 0 before apply (apply runs blocks sequentially with UseParallel=false). The final label map is relabelled to a contiguous range by the caller.

Limitation: an object larger than the overlap band is truncated (never fully contained in one tile’s field of view). Set the overlap ≥ the largest expected object, or switch the stitching mode (BatchOpt.P_OverlapInstancesMode) to ‘IoU merge’ (deepmib.segmentImageInstancesIoUMerge), which lifts this restriction.

Input Arguments:
  • block - struct from blockedImage/apply with .Data (bordered tile), .BlockSize (core size), .BorderSize (overlap)

  • net - trained solov2 detector

  • threshold - confidence threshold for segmentObjects

  • executionEnvironment - 'auto' | 'gpu' | 'cpu'

Output Arguments:
  • coreLabel - [BlockSize(1) × BlockSize(2)] uint32 label map of the tile core (each kept instance a unique index, background 0)

deepmib.segmentImageInstancesIoUMerge(img, net, options)

SEGMENTIMAGEINSTANCESIOUMERGE - Tile an image, segment instances per tile and IoU-merge across seams.

Syntax:
labelMap = deepmib.segmentImageInstancesIoUMerge(img, net, options)

Alternative to the centroid-in-core stitching (deepmib.segmentBlockedImageInstances) for 2D instance segmentation of large / whole-slide images. The image is split into a grid of core tiles, each read with a surrounding border of context so that neighbouring tile extents share an overlap band. segmentObjects runs on every bordered tile and all detections are kept (not only the centroid-in-core ones). Detections from neighbouring tiles are then compared inside the shared overlap band: if both tiles detected the same object, their masks are nearly identical within the band, so an in-band IoU (or intersection-over-smaller-area, IoA) above the threshold links them into one instance. Links are resolved globally with union-find and each merged group is painted with a single label.

Compared with centroid-in-core, this lifts the “overlap must exceed the largest object” restriction: an object spanning several tiles is detected piecewise and its fragments are merged, so only the band width (not the object size) matters for correct stitching. The overlap band must still be wide enough for the network to produce consistent masks in it (a few tens of pixels in practice).

Input Arguments:
  • img - [height, width, 3] uint8 image to segment (RGB, native resolution)

  • net - trained solov2 detector

  • options - structure of parameters:

    • .coreSize - [h, w] tile core size (grid stride), as used by the centroid-in-core mode

    • .borderSize - [h, w] border (overlap) added on each side of the core; neighbouring tile extents share a band of 2*borderSize pixels

    • .threshold - confidence threshold for segmentObjects

    • .executionEnvironment - 'auto' | 'gpu' | 'cpu'

    • .iouThreshold - (optional, default 0.5) link two detections when their in-band IoU exceeds this

    • .ioaThreshold - (optional, default 0.8) link when the in-band intersection over the smaller in-band area exceeds this (catches a truncated fragment fully contained in the neighbour’s complete mask). Applied only when the smaller detection is itself truncated by its tile, see the note below

    • .minOverlapPixels - (optional, default 5) absolute minimum in-band intersection to consider a link, guards against spurious 1-2 px overlaps

    • .minSplitArea - (optional, default 100) after painting, each label is split into its connected components so that one index never covers two separate objects; components smaller than this many pixels are dropped as speckle. Set to 0 to keep every component

    • .segmentFcn - (optional) [masks, labels, scores] = fcn(tileImg) override of the segmentObjects call, used by unit tests to validate the stitching without a trained network

Why the IoA criterion is restricted to truncated detections: SOLOv2 occasionally returns a single detection whose mask spans two neighbouring objects. Containment (IoA) is 1.0 for every smaller detection that falls inside such a mask, no matter how little of it that explains, so an unrestricted IoA link lets one spanning detection bridge two unrelated objects through the union-find - measured on a mitochondria dataset, this welded objects up to 500 px apart and hid ~3-5% of all instances. IoA exists only to rescue a fragment cut off by a tile edge, and such a fragment always touches its own tile extent; a detection lying clear of the tile border is a different object, not a truncation, so for it only the symmetric IoU criterion applies.

Output Arguments:
  • labelMap - [height, width] uint32 instance label map (background 0). Each ID is exactly one connected object; the final component split also renumbers the IDs to 1..N, so the relabelling the caller does (startPredictionInstances) is a no-op here

deepmib.stopTrainingCallback(hButton, varargin)

STOPTRAININGCALLBACK - Stop the DeepMIB training process via the Stop or Emergency Brake button.

Syntax:
stopTrainingCallback(hButton)
Input Arguments:
  • hButton - handle to the button that triggered the callback, or a matlab.ui.dialog.ProgressDialog handle when called from a progress dialog

deepmib.stopTrainingWithoutPlots(progressStruct)

STOPTRAININGWITHOUTPLOTS - Stop training when running without a training plot.

Syntax:
stopTrainingSwitch = stopTrainingWithoutPlots(progressStruct)
Input Arguments:
  • progressStruct - training progress struct (unused; required by trainNetwork callback signature)

Output Arguments:
  • stopTrainingSwitch - [logical] true when the global mibDeepStopTraining flag is set

deepmib.storeLoadCategorical(filename)

STORELOADCATEGORICAL - Load a categorical dataset from a MAT file for use with pixelLabelDatastore.

Syntax:
data = storeLoadCategorical(filename)
Input Arguments:
  • filename - [string] full path to the MAT file

Output Arguments:
  • data - cell array containing the loaded categorical variable

deepmib.storeLoadImages(fn, getDataOptions)

STORELOADIMAGES - Load an image file for use with imageDatastore in DeepMIB.

Syntax:
imOut = storeLoadImages(fn, getDataOptions)
Input Arguments:
  • fn - [string] full path to the image file

  • getDataOptions - struct with load options:

    • .mibBioformatsCheck - [logical] true to use the BioFormats reader, false for the standard reader

    • .BioFormatsIndices - [numeric] series index for BioFormats, or slice index within a TIF file (default: 1)

    • .Workflow - [char] active workflow (obj.BatchOpt.Workflow{1})

    • .randomCrop - [cropH cropW] for random cropping; [0 0] to disable

Output Arguments:
  • imOut - loaded image array

deepmib.storeLoadModel(filename)

STORELOADMODEL - Load a MIB label model from a MAT file for use with pixelLabelDatastore.

Syntax:
model = storeLoadModel(filename)
Input Arguments:
  • filename - [string] full path to the MAT file containing the model

Output Arguments:
  • model - loaded model array

deepmib.suspendCheckpointSaving(action)

SUSPENDCHECKPOINTSAVING - move the checkpoint folder aside while a stopped run spins down.

Syntax:
deepmib.suspendCheckpointSaving(action)
Input Arguments:
  • action - [char] 'suspend' to move the checkpoint folder out of the way, 'restore' to move it back, or 'restoreOrphaned' to move back a folder left behind by a run that never reached its restore step (Ctrl+C, crash, MATLAB restart)

Notes

trainSOLOV2 (the 2D Instance workflow) trains via images.dltrain.internal.dltrain. Its SerialTrainer/ParallelTrainer honour a stop request by ending the inner per-epoch iteration loop only - the outer for epoch = 1:MaxEpochs loop still runs to completion. Each of those idle epochs fires an EpochEnd event and, when a CheckpointPath is configured, that event saves the whole network to disk again. Stopping a long run early therefore blocked MATLAB for hours while it rewrote hundreds of megabytes per idle epoch.

images.dltrain.internal.CheckpointSaver wraps its save in a try/catch that only issues a “Checkpoint failed to save.” warning, so making the checkpoint folder temporarily unreachable turns every one of those saves into an instant no-op. The folder is renamed rather than deleted, so checkpoints written before the stop survive.

The rename is driven from the training OutputFcn, which runs on the same thread as the checkpoint save, so no save can be in flight while the folder is moved. The pair of paths is held in a persistent variable rather than in mibDeepTrainingProgressStruct so that 'restore' still works when that global is reset mid-run (for example by a second press of the stop button, see deepmib.stopTrainingCallback).

See also

deepmib.customTrainingProgressDisplay, deepmib.stopTrainingWithoutPlots, controllers.MibDeep/startTrainingInstances

deepmib.trainingStructUpdateAxes(hMenu, actionData, parameter)

TRAININGSTRUCTUPDATEAXES - Handle context-menu callbacks for mibDeepTrainingProgressStruct.UILossAxes.

Syntax:
trainingStructUpdateAxes(hMenu, actionData, parameter)
deepmib.updateGpuMemoryStatus(iteration, elapsedSeconds)

UPDATEGPUMEMORYSTATUS - Report GPU memory headroom and warn when the card is overcommitted.

Syntax:
deepmib.updateGpuMemoryStatus(iteration, elapsedSeconds)
Input Arguments:
  • iteration - [numeric] current training iteration number

  • elapsedSeconds - [numeric] wall-clock seconds since the run started

Output Arguments:

(none) - the GPU name label in the training progress window is updated in place, and a one-off message is printed to the command window when the card looks overcommitted

Called once per refresh from customTrainingProgressDisplay() and customTrainingProgressDisplayTrainNet(). All state lives in the global mibDeepTrainingProgressStruct and is initialized where the progress window is built, which also means each phase of the two-phase instance schedule measures its own baseline (a trainable phase is legitimately slower than a frozen one).

What is reported, and what it is worth. Two measurements taken on an RTX 3080 Ti (12 GB, WDDM) decide the design:

  1. This function runs between iterations, where the forward/backward activations have already been freed. Measured against a deliberate 4.96 GB transient, the reading taken here was 1.96 GB - it under-reports the true peak by 60%. The figure shown is therefore a lower bound on peak usage, useful for headroom but not a batch-size calculator. Sampling mid-iteration is not possible: a MATLAB timer cannot preempt the main thread while the trainer holds it.

  2. On Windows (WDDM) the driver does not fail when the working set exceeds VRAM - it pages GPU memory to system RAM. 24 GB was allocated on the 12 GB card with no error at all. So “mini-batch slightly too large” is not a crash, it is a silent slowdown.

Why the warning uses timing and not memory. In the calibration sweep, AvailableMemory read 1.09 GB (used 10.91 GB, 91% of VRAM) both in the last healthy configuration and in every spilled one - identical on both sides of the cliff, so it cannot discriminate. Iteration time can, and by a wide margin:

ballast

used peak

sec/iteration

vs baseline

8 GB

10.91 GB (91%)

0.0088

0.8x

10 GB

10.91 GB (91%)

0.2968

27.7x

14 GB

10.91 GB (91%)

0.3064

28.6x

Healthy iterations spanned 0.0088 to 0.0107 s (a 1.2x spread) while spilling costs ~28x, so the trigger factor below sits in a very wide empty band.

Important limitation. The comparison is against the run’s own early iterations, so this catches a run that becomes overcommitted - growing fragmentation, another process taking the card, a dataset whose later images are larger. It does not catch a run that was overcommitted from iteration 1, because the baseline is then measured in the slow state and nothing stands out. Detecting that case needs an external reference: either the Windows \GPU Process Memory(pid_*)\Shared Usage counter, which measures paging to host RAM directly (0.07 GB idle against 9.90 GB while oversubscribed, readable in 0.24 ms through .NET), or a startup probe that times the same network at two mini-batch sizes and compares samples per second. Neither is implemented yet - see development/deepmib/potential_improvements.md.