Skip to main content
Version: v1.4.0

Dataset format: 3D Image semantic segmentation

Dataset format

The data for a 3D image semantic segmentation experiment needs to be structured as follows: A zip file (1) containing a Parquet file (2) and an image folder (3):

folder_name.zip (1)
│ └───pq_name.pq (2)
│ │
│ └───image_folder_name (3)
│ └───name_of_image.image_extension
│ └───name_of_image.image_extension
│ └───name_of_image.image_extension
│ ...
Note

You can have multiple Parquet files in the zip file that you can use as train, validation, and test dataframes:

  • A train Parquet file needs to follow the format described above
  • A validation Parquet file needs to follow the same format as a train Parquet file
  • A test Parquet file needs to follow the same format as a train Parquet file, but does not need a class_id and rle_mask column
  1. The available dataset connectors require the data for a 3D image semantic segmentation experiment to be in a zip file.
    Note

    To learn how to upload your zip file as your dataset in H2O Hydrogen Torch, see Dataset connectors.

  2. A Parquet file containing the following columns:
    • An image column containing the names of the images for the experiment, where each image has an image extension specified
      Note
      • Images can contain a mix of supported image extensions. To learn about supported image extensions, see Supported 3D image extensions for 3D image processing.
      • The names of the image files do not specify the data directory (location of the images in the zip file). You can specify the data directory (data folder) when uploading the dataset or before the dataset is used for an experiment. For more information, see Import dataset settings.
    • A class_id column containing the class names of each mask. Each row of the dataset should contain a list of all possible class names
    • A rle_mask column containing run-length-encoded (RLE) masks for each class from the class_id column. If there is no mask for a given class, an empty string has to be provided
      Note

      The length of each class_id and rle_mask list must be equal while referring to the total number of classes.

    • An optional fold column containing cross-validation fold indexes
      Note

      The fold column can include integers (0, 1, 2, … , N-1 values or 1, 2, 3… , N values) or categorical values.

  3. An image folder that contains all the images specified in the image column; H2O Hydrogen Torch uses the images in this folder to run the 3D image semantic segmentation experiment.
    Note

    All images need to specified an image extension. To learn about supported 3D image extensions, see Supported 3D image extensions for 3D image processing.

Example

The covid_ct_image_semantic_segmentation_3d.zip file is a preprocessed dataset in H2O Hydrogen Torch and was formatted to solve a 3D image semantic segmentation problem. The structure of the zip file is as follows:

covid_ct_image_semantic_segmentation_3d.zip
│ └───train.pq
│ │
│ └───images
| └───coronacases_org_001.npy
| └───coronacases_org_002.npy
│ └───coronacases_org_003.npy
│ ...

As follows, three random rows from the Parquet file:

imageclass_idrle_mask
coronacases_org_001.npy['lung']['171087 6 171095 7 171...
coronacases_org_002.npy['lung']['6439 8 6563 15 6689...
coronacases_org_003.npy['lung']['103983 1 119580 9 119...
Note
  • In this example, the data directory in the image column is not specified. Therefore, it needs to be specified when uploading the dataset, and the images folder needs to be selected as the value for the Data folder setting. For more information, see Import dataset settings.
  • To learn how to access one of the preprocessed datasets in H2O Hydrogen Torch, see Demo (preprocessed) datasets.

Helper functions

RLE encoding and decoding functions

from typing import Tuple

import numpy as np


def mask2rle(x: np.ndarray) -> str:
"""
Converts input masks into RLE-encoded strings.

Args:
x: numpy array of shape (height, width), 1 - mask, 0 - background
Returns:
RLE string
"""

pixels = x.T.flatten()
pixels = np.concatenate([[0], pixels, [0]])
runs = np.where(pixels[1:] != pixels[:-1])[0] + 1
runs[1::2] -= runs[::2]
return " ".join(str(x) for x in runs)


def rle2mask_3d(mask_rle: str, shape: Tuple) -> np.ndarray:
"""
Converts RLE-encoded string into the binary mask (3D version).

Args:
mask_rle: RLE-encoded string
shape: (height, width, depth) of array to return
Returns:
binary mask: 1 - mask, 0 - background
"""
shape = [shape[1], shape[0], shape[2]]
s = mask_rle.split()
starts, lengths = [np.asarray(x, dtype=int) for x in (s[0:][::2], s[1:][::2])]
starts -= 1
ends = starts + lengths
img = np.zeros(shape[0] * shape[1] * shape[2], dtype=np.uint8)
for lo, hi in zip(starts, ends):
img[lo:hi] = 1
return img.reshape(shape).transpose(2, 1, 0)


Feedback