ImageAsset#
- class rapidtools.core.ImageAsset(*, path: Path, id: str | None = None, properties: dict[str, ~typing.Any]=<factory>, semantic_map: dict[int, str] | None=None, instance_map: dict[int, ~typing.Any] | None=None, allow_missing_file: bool = False)[source]#
Bases:
objectA single image asset, its location, metadata, and segmentation info.
- Variables:
path (Path) – Absolute path of the image file on disk.
id (str | None) – Unique identifier. Defaults to the file stem when omitted.
properties (dict[str, Any]) – Free-form metadata (e.g.
latitude,longitude,url).semantic_map (dict[int, str] | None) – Pixel value to class name mapping for the semantic mask.
instance_map (dict[int, Any] | None) – Instance ID to metadata mapping for the instance mask.
allow_missing_file (bool) – If
True, the file does not need to exist yet (deferred download).
Example
>>> from rapidtools.core import ImageAsset >>> >>> img = ImageAsset( ... id='img_001', ... path='images/img_001.jpg', ... properties={'url': 'https://example.com/img_001.jpg'}, ... allow_missing_file=True, ... ) >>> img.is_downloaded False >>> img.filename 'img_001.jpg'
Methods
Download the image file to self.path.
Rebuild an asset from
to_dict()output or a parsed JSON object.Determine the filename for the mask.
Safely retrieve one or more metadata properties from the asset.
Load the image from disk using Pillow and caches it.
Download the image into memory and cache it.
Lazy-load the segmentation mask from disk into a NumPy array.
Merge data from another ImageAsset.
Saves the cached PIL image to disk.
Create an interactive HMTL file to view segmentation masks.
Save the specified image mask to disk as a PNG image.
Manually attaches a segmentation mask from memory.
Show the asset in the system's default image viewer.
Print a human-readable summary of the image asset.
Serialize the asset to a JSON-friendly dictionary.
- to_dict() dict[str, Any][source]#
Serialize the asset to a JSON-friendly dictionary.
Only the constructor arguments are included; the lazily loaded image and mask caches are not, and
pathis written as a string. The result round-trips throughfrom_dict()andjson.dumps().- Returns:
dict[str, Any] – Keyword arguments accepted by
from_dict().
Example
>>> from rapidtools.core import ImageAsset >>> img = ImageAsset(id='a', path='/tmp/a.jpg', allow_missing_file=True) >>> sorted(img.to_dict()) ['allow_missing_file', 'id', 'instance_map', 'path', 'properties', 'semantic_map']
- classmethod from_dict(data: Mapping[str, Any], allow_missing_file: bool | None = None) ImageAsset[source]#
Rebuild an asset from
to_dict()output or a parsed JSON object.Unknown keys (including the private cache fields that older exports contained) are ignored, and mask-map keys that JSON turned into strings are converted back to integers.
- Parameters:
- Returns:
ImageAsset – The rebuilt asset.
- Raises:
ValueError – If
'path'is missing, or the file is missing andallow_missing_fileisFalse.
Example
>>> from rapidtools.core import ImageAsset >>> img = ImageAsset.from_dict( ... {'id': 'a', 'path': '/tmp/a.jpg', 'semantic_map': {'1': 'road'}} ... ) >>> img.semantic_map {1: 'road'}
- property directory: Path#
The parent directory of the image file.
- Returns:
Path – The directory containing the image as a Path object.
Example
In the example below, we set
allow_missing_file=True. This is useful for lazy-loading assets from an API or database where the local file may not yet exist, allowing for metadata manipulation without disk overhead.>>> from rapidtools.core import ImageAsset >>> image = ImageAsset( ... path='/projects/data/image.jpg', ... allow_missing_file=True ... )
The property returns a standard
pathlib.Pathobject:>>> image.directory PosixPath('/projects/data')
This allows for seamless path manipulation, such as joining related files in the same folder:
>>> image.directory / 'metadata.json' PosixPath('/projects/data/metadata.json')
- property filename: str#
The filename of the image, including its extension.
- Returns:
str – The image filename as a string.
Example
In the example below, we set
allow_missing_file=True. This allows the asset to be initialized and its naming metadata to be accessed even if the file has not yet been downloaded to the local file system.>>> from rapidtools.core import ImageAsset >>> image = ImageAsset( ... path='/data/projects/panoramas/image_001.jpg', ... allow_missing_file=True ... )
The
filenameproperty extracts only the final component of the path:>>> image.filename 'image_001.jpg'
This property is useful for generating logs, status reports, or matching image data with external database records:
>>> print(f'Processing asset: {image.filename}') Processing asset: image_001.jpg
- property is_downloaded: bool#
Check whether the image file exists on disk and is non-empty.
This property verifies that:
The path exists.
The path points to a regular file (not a directory).
The file size is greater than zero bytes.
- Returns:
bool –
Trueif a non-empty image file exists at image path, otherwiseFalse.
Examples
is_downloadedis essential for workflows where assets are initialized lazily. Here, by usingallow_missing_file=True, we can work with an asset’s metadata and only trigger a download if this property returnsFalse.Case 1: The file exists on the local file system:
>>> from rapidtools.core import ImageAsset >>> image = ImageAsset('exists.jpg') >>> image.is_downloaded True
Case 2: The file is missing or has not been downloaded yet. We use
allow_missing_file=Trueto avoid an initialization error:>>> image = ImageAsset(path='missing.jpg', allow_missing_file=True) >>> image.is_downloaded False
This allows for simple conditional logic in processing pipelines.
>>> if not image.is_downloaded: ... image.download( ... url=r'https://upload.wikimedia.org/wikipedia/commons/1' ... r'/1e/Suzzallo_Reading_Room%2C_May_2016.jpg' ... ) ... print(f'Downloaded: {image.is_downloaded}') INFO: Downloading missing... INFO: Successfully downloaded: missing.jpg Downloaded: True
- property stem: str#
The filename of the image without its extension.
- Returns:
str – The filename stem as a string.
Examples
>>> from rapidtools.core import ImageAsset >>> >>> asset = ImageAsset( ... id='scene', ... path='/data/images/scene_01.tif', ... allow_missing_file=True ... ) >>> asset.stem 'scene_01' >>> >>> asset = ImageAsset( ... id='photo', ... path='photo.jpg', ... allow_missing_file=True ... ) >>> asset.stem 'photo'
- download(url: str | None = None, url_key: str = 'thumb_original_url', overwrite: bool = False, session: Session | None = None)[source]#
Download the image file to self.path.
- Parameters:
url (str, optional) – The direct download link. If provided, this takes precedence over properties.
url_key (str) – The key in self.properties to look for if
'url'isNone. Defaults to'thumb_original_url'. Useful for downloading specific sizes (e.g.'thumb_2048_url').overwrite (bool) – If True, forces download even if file exists.
session (requests.Session, optional) – An existing requests session to speed up connections.
- Raises:
ValueError – If no URL is provided or found in properties.
IOError – If the download fails.
Examples
Basic usage through automatic URL Lookup:
>>> from rapidtools.core import ImageAsset >>> >>> asset = ImageAsset( ... id='img_01', ... path='data/img_01.jpg', ... properties={ ... 'thumb_original_url': ... r'https://upload.wikimedia.org/wikipedia/commons/1' ... r'/1e/Suzzallo_Reading_Room%2C_May_2016.jpg' ... }, ... allow_missing_file=True ... ) >>> asset.download() INFO: Downloading 'img_01' from https://upload.wikimedia.org/ wikipedia/commons/1/1e/Suzzallo_Reading_Room%2C_May_2016.jpg... INFO: Successfully downloaded: img_01.jpg
Usage through providing explicit URL:
>>> asset.download( ... url=r'https://upload.wikimedia.org/wikipedia/commons/1' ... r'/1e/Suzzallo_Reading_Room%2C_May_2016.jpg' ... ) INFO: Downloading 'img_01' from https://upload.wikimedia.org/ wikipedia/commons/1/1e/Suzzallo_Reading_Room%2C_May_2016.jpg... INFO: Successfully downloaded: img_01.jpg
Download using a session (recommended for batch operations):
>>> import requests >>> >>> assets = [ ... ImageAsset( ... id='wiki_A', ... path='data/wiki_a.jpg', ... allow_missing_file=True, ... properties={ ... 'src': ( ... 'https://upload.wikimedia.org/wikipedia/commons/' ... 'a/a9/Example.jpg' ... ), ... }, ... ), ... ImageAsset( ... id='wiki_B', ... path='data/wiki_b.jpg', ... allow_missing_file=True, ... properties={ ... 'src': ( ... 'https://upload.wikimedia.org/wikipedia/commons/5' ... '/50/Smile_Image.png' ... ), ... }, ... ) ... ] >>> >>> with requests.Session() as s: ... s.headers.update({'User-Agent': 'RapidTools/1.0'}) ... for asset in assets: ... asset.download(url_key='src', session=s) INFO: Downloading 'wiki_A' from https://upload.wikimedia.org/ wikipedia/commons/a/a9/Example.jpg... INFO: Successfully downloaded: wiki_a.jpg INFO: Downloading 'wiki_B' from https://upload.wikimedia.org/ wikipedia/commons/5/50/Smile_Image.png... INFO: Successfully downloaded: wiki_b.jpg
- get_mask_path(mask_type: MaskType, override_path: Path | str | None = None) Path[source]#
Determine the filename for the mask.
- Default Convention:
Image: photo.jpg
Semantic: photo_semantic.png
Instance: photo_instance.png
- Parameters:
mask_type – The type of mask (
'semantic'or'instance').override_path – If provided, this specific path is used instead of the automatic naming convention.
- Returns:
Path – The resolved path object for the mask.
- Raises:
ValueError – If
mask_typeis not a validMaskType.
Examples
Create an
ImageAsset:>>> from rapidtools.core import ImageAsset >>> from rapidtools.config import MaskType >>> asset = ImageAsset( ... id='A1', ... path='/tmp/scene_01.jpg', ... allow_missing_file=True ... )
Getting mask path by providing a mask type:
>>> path = asset.get_mask_path('instance') >>> print(path) /tmp/scene_01_instance.png
Getting mask path using a manual override. This option is useful when masks are stored in a completely different folder:
>>> path = asset.get_mask_path( ... 'semantic', ... override_path='/masks/custom_01.png' ... ) >>> print(path) /masks/custom_01.png
- get_property(key: str | Iterable[str], default: Any = None) Any | dict[str, Any][source]#
Safely retrieve one or more metadata properties from the asset.
This method is polymorphic:
If
keyis astr, it returns the single value.If
keyis a list/tuple, it returns a dictionary of{key: value}.
- Parameters:
- Returns:
Any or dict[str, Any] – - The value (if input was a single string). - A dictionary of values (if input was an iterable).
Examples
Set up an
ImageAsset>>> from rapidtools.core import ImageAsset >>> asset = ImageAsset( ... id='img_01', ... path='photo.jpg', ... properties={'width': 1920, 'height': 1080, 'iso': 100}, ... allow_missing_file=True ... )
Request the values of individual properties:
>>> asset.get_property('width') 1920 >>> asset.get_property('shutter_speed', default='Auto') 'Auto'
Request the values of multiple properties at once:
>>> asset.get_property(['width', 'height']) {'width': 1920, 'height': 1080}
Request the values of multiple properties, including some that exist and some that are missing:
>>> asset.get_property(['iso', 'aperture'], default='Unknown') {'iso': 100, 'aperture': 'Unknown'}
- load_image_from_disk(force_reload: bool = False, convert_mode: str | None = None, apply_exif_orientation: bool = True) Image[source]#
Load the image from disk using Pillow and caches it.
Behavior:
Lazy-caches by default (returns cached image if present).
Always fully decodes and then closes the underlying file handle. Optionally converts to a target mode (e.g.,
'RGB').Optional force reload to bypass cache.
- Parameters:
force_reload – If
True, re-reads the file from disk even if an image is currently cached. Defaults toFalse.convert_mode – If provided, converts image to the specified PIL mode. Some options are
L(Grayscale),1(Black and White),CMYK(Cyan, Magenta, Yellow, Key/Black),I(32-bit signed integer pixels), andHSV(Hue, Saturation, Value color space).apply_exif_orientation (bool) – If
True, reads the EXIF tags and rotates the image to appear upright (e.g., fixing sideways smartphone photos). Defaults toTrue.
- Returns:
PillowImage.Image – The loaded PIL image.
- Raises:
FileNotFoundError – If the file does not exist or has not been downloaded.
OSError – If the file exists but cannot be opened (corruption/permissions).
Examples
Create a dummy red 100x100 RGB image for testing:
>>> import os >>> from PIL import Image >>> from rapidtools.core import ImageAsset >>> >>> temp_path = 'temp_example.jpg' >>> Image.new('RGB', (100, 100), color='red').save(temp_path) >>> >>> asset = ImageAsset(id='img_01', path=temp_path)
Basic loading from a file. The first call reads the file from disk, subsequent calls return the cached result:
>>> img1 = asset.load_image_from_disk() >>> print(f'{img1.format} {img1.size} {img1.mode}') INFO: Loading image data from: temp_example.jpg None (100, 100) RGB >>> >>> img2 = asset.load_image_from_disk() >>> print(img1 is img2) True
Loading an image with mode conversion and force reload. Here force reload is enabled to ignore the cache, and the image is converted to Grayscale (
'L'):>>> img_gray = asset.load_image_from_disk( ... force_reload=True, ... convert_mode='L' ... ) INFO: Loading image data from: temp_example.jpg >>> print(img_gray.mode) L
load_image_from_diskraises aFileNotFoundErrorif the file does not exist locally (or has not yet been downloaded) or raises anOSErrorif the file exists but cannot be opened (e.g., due to corruption or insufficient permissions). The following example shows a sample error handling situation:>>> missing_asset = ImageAsset( ... id=1, ... path='ghost.jpg', ... allow_missing_file=True, ... ) >>> try: ... missing_asset.load_image_from_disk() ... except FileNotFoundError as e: ... print('Caught error') Caught error
Finally, run the following line to delete the temporary image file created for this example:
>>> os.remove(temp_path)
- load_image_from_url(url: str | None = None, url_key: str = 'thumb_original_url', convert_mode: str | None = None, force_reload: bool = False, apply_exif_orientation: bool = True, verbose: bool = True, session: Session | None = None) Image[source]#
Download the image into memory and cache it.
This method bypasses
pathfor the image entirely. Note that theis_downloadedproperty of the image will remainFalseafter this method completes execution (unless the file happened to exist previously).- Parameters:
url (str, optional) – Direct URL to download from. If
None, checks image properties to find the URL.url_key (str) – Property key to use for URL if direct url is
None. Defaults to ‘thumb_original_url’.convert_mode (str, optional) – Mode to convert the loaded image to (e.g.,
'RGB').force_reload (bool) – If
True, re-downloads even if _pil_image is already set.apply_exif_orientation (bool) – If
True, rotates the image based on EXIF data (e.g., fixing sideways phone photos). Defaults toTrue.verbose (bool) – If
True, logs standard info messages. Set toFalseto suppress the “Downloading into memory” log. Defaults toTrue.session (requests.Session, optional) – Session for efficient connection pooling during download.
- Returns:
PillowImage.Image – The loaded PIL image object.
- Raises:
ValueError – If the URL cannot be determined.
requests.RequestException – If the network request fails.
IOError – If the bytes cannot be decoded as an image.
Examples
Setup an asset defined only by metadata (no local file yet):
>>> from rapidtools.core import ImageAsset >>> asset = ImageAsset( ... id='wiki_cat', ... path='virtual_cat.jpg', ... allow_missing_file=True, ... properties={ ... 'thumb_original_url': ( ... 'https://upload.wikimedia.org/wikipedia/commons/' ... '3/3a/Cat03.jpg' ... ), ... 'backup_url': ( ... 'https://upload.wikimedia.org/wikipedia/commons/' ... '4/47/PNG_transparency_demonstration_1.png' ... ), ... }, ... )
Loading image from the URL in properties (loads from
'thumb_original_url'by default) into memory:>>> img = asset.load_image_from_url() INFO: Downloading wiki_cat into memory... >>> print(img.size) (1600, 1598) >>> print(asset.is_downloaded) False
Load from a specific key, convert to Grayscale (
'L'), force a re-download, and suppress the log message:>>> img_small = asset.load_image_from_url( ... url_key='backup_url', ... convert_mode='L', ... force_reload=True, ... verbose=False ... ) >>> print(img_small.mode) L
Load an image using a Session (recommended for batch processing. This example uses the TCP connection for speed:
>>> import requests >>> with requests.Session() as session: ... asset.load_image_from_url(session=session)
- load_mask(mask_type: MaskType, force_reload: bool = False, custom_path: Path | str | None = None) ndarray[source]#
Lazy-load the segmentation mask from disk into a NumPy array.
This method handles caching automatically. It checks if the mask is already loaded in memory (e.g. _semantic_mask) before attempting file I/O.
- Parameters:
mask_type (str) – The type of mask to load. Standard values are
'semantic'or'instance'. Defaults to'semantic'.force_reload (bool) – If
True, ignores the internal cache and re-reads the file from disk. Defaults toFalse.custom_path (Path, or str, or None) – If provided, loads the mask from this specific path instead of deriving the filename from the image asset’s path.
- Returns:
np.ndarray – The segmentation mask data as a NumPy array.
- Raises:
ValueError – If
mask_typeis invalid.FileNotFoundError – If the mask file does not exist at the calculated or provided path.
OSError – If the file exists but cannot be opened or decoded (e.g. corruption).
Examples
Create a mock environment with a real mask file by creating a dummy asset and a semantic mask file matching the expected naming convention:
>>> import os >>> import numpy as np >>> from PIL import Image >>> from rapidtools.config import MaskType >>> from rapidtools.core import ImageAsset >>> >>> asset = ImageAsset( ... id='scene_01', ... path='test_scene.jpg', ... allow_missing_file=True ... ) >>> >>> mask_data = np.zeros((10, 10), dtype=np.uint8) >>> mask_data[0:5, :] = 1 # Top half is class 1 >>> mask_path = 'test_scene_semantic.png' >>> Image.fromarray(mask_data).save(mask_path)
Load the semantic segmentation mask from ‘test_scene_semantic.png’ Please note that the
load_maskmethod infers this filename automatically from the image filename and the provided mask_type by appending _semantic before the file extension (e.g., test_scene.png turns into test_scene_semantic.png):>>> loaded_mask = asset.load_mask(MaskType.SEMANTIC) >>> print(loaded_mask.shape) (10, 10) >>> print(loaded_mask[0, 0]) 1
To delete the generated mask file, please run:
>>> os.remove(mask_path)
- merge(other: ImageAsset, ignore_id_mismatch: bool = False, overwrite_path: bool = False, overwrite_properties: bool = True) None[source]#
Merge data from another ImageAsset.
By default, this method ensures IDs match before merging to prevent accidental data corruption.
- Parameters:
other (ImageAsset) – The source asset to merge data from.
ignore_id_mismatch (bool) – If
True, allows merging even if self.id != other.id. Defaults toFalse.overwrite_path (bool) – If
True, updates self.path with other.path and adopts its internal caches (images/masks). Defaults toFalse(preserves original path).overwrite_properties (bool) – If
True, other.properties, semantic_map, and instance_map will overwrite existing values in self. IfFalse, only missing values are filled. Defaults toTrue.
- Raises:
TypeError – If
otheris not anImageAsset.ValueError – If IDs do not match and
ignore_id_mismatchisFalse.
Examples
Create two ImageAsset objects:
>>> from rapidtools.core import ImageAsset >>> >>> asset_a = ImageAsset( ... id='1', ... path='a.jpg', ... properties={'temp': 20}, ... allow_missing_file=True, ... ) >>> asset_b = ImageAsset( ... id='1', ... path='b.jpg', ... properties={'temp': 25, 'gps': [0, 0]}, ... allow_missing_file=True, ... )
Merge
asset_b’s properties intoasset_ausing the default behavior that overwrites conflicts:>>> asset_a.merge(asset_b, overwrite_properties=True) >>> print(asset_a.properties) {'temp': 25, 'gps': [0, 0]}
Merge without overwriting existing keys. Here,
'gps'is added (it was not present onasset_a),'temp'is NOT overwritten (stays 20):>>> asset_a = ImageAsset( ... id='1', ... path='a.jpg', ... properties={'temp': 20}, ... allow_missing_file=True, ... ) >>> asset_a.merge(asset_b, overwrite_properties=False) >>> print(asset_a.properties) {'temp': 20, 'gps': [0, 0]}
- save_interactive_html(output_path: Path | str | None = None, mask_type: MaskType = MaskType.SEMANTIC, opacity: float = 0.5, min_area: int = 10) None[source]#
Create an interactive HMTL file to view segmentation masks.
Generates an interactive HTML file where masks are converted to SVG polygons. Hovering over a polygon shows its label from the asset’s mapping data.
This method converts the raster NumPy mask into vector polygons on the fly.
- Args:
- output_path (Path, or str, or None):
File path to save the HTML. Defaults to {filename}_{mask_type}.html.
- mask_type (str):
Type of segmentation mask displayed, i.e., ‘semantic’ or ‘instance’.
- opacity (float):
Opacity of the polygon fill (0.0 to 1.0).
- min_area (int):
Minimum number of vertices to generate a polygon for. Helps reduce noise/dust in the SVG.
Examples
Create a dummy image and a corresponding mask:
>>> import os >>> import numpy as np >>> from PIL import Image >>> from rapidtools.core import ImageAsset >>> from rapidtools.config import MaskType >>> >>> img_path = 'html_test.jpg' >>> Image.new('RGB', (100, 100), color='white').save(img_path) >>> mask_data = np.zeros((100, 100), dtype=np.uint8) >>> mask_data[10:50, 10:50] = 1 # Square object >>> >>> asset = ImageAsset(id='viz', path=img_path, allow_missing_file=True) >>> asset.set_mask(mask_data, MaskType.SEMANTIC, map_data={1: 'Square'})
Create an interactive HTML:
>>> asset.save_interactive_html(mask_type=MaskType.SEMANTIC) INFO: Loading image data from: html_test.jpg INFO: Generating HTML polygons for 1 semantics... INFO: Saved interactive HTML to: html_test_semantic.html >>> print(os.path.exists('html_test_semantic.html')) True
Please run the following lines to remove the created files:
>>> for f in [img_path, 'html_test_semantic.html']: ... if os.path.exists(f): os.remove(f)
- save_image(output_path: Path | str | None = None, format: str | None = None, quality: int = 100) None[source]#
Saves the cached PIL image to disk.
This method writes the in-memory image data to a file. It automatically creates any necessary parent directories.
- Parameters:
output_path (Path, or str, or None) – The file path where the image will be saved. If
None, defaults toself.path, which will overwrite the original image file.format (str, or None) – The image format to use (e.g.,
'JPEG','PNG'). IfNone, the format is inferred from the file extension of the output path.quality (int) – The compression quality (1-100) for lossy formats like JPEG. Higher numbers mean better quality but larger file size. Defaults to 100.
- Raises:
ValueError – If no image is currently loaded in memory (i.e.,
load_image_from_disk(),load_image_from_urlhas not been called).OSError – If the file cannot be written (e.g., permission errors).
Examples
Create an asset with a cached image:
>>> import os >>> from PIL import Image >>> from rapidtools.core import ImageAsset >>> >>> asset = ImageAsset(id='A1', path='input.jpg', allow_missing_file=True) >>> asset._pil_image = Image.new('RGB', (100, 100), color='blue')
Example 1: Save to a new path
>>> asset.save_image(output_path='output.png') INFO: Saving image to output.png >>> print(os.path.exists('output.png')) True
Example 2: Save as JPEG with specific quality
>>> asset.save_image(output_path='compressed.jpg', quality=50) INFO: Saving image to compressed.jpg
Cleanup
>>> for f in ['output.png', 'compressed.jpg']: ... if os.path.exists(f): os.remove(f)
- save_mask(mask_type: MaskType, output_path: Path | str | None = None) None[source]#
Save the specified image mask to disk as a PNG image.
This method retrieves the mask (from memory cache or by reloading the source file) and writes it to the specified location. It strictly enforces the PNG format to ensure lossless storage of integer class IDs.
- Parameters:
mask_type (MaskType) – The type of mask to save (e.g.,
'instance'or'semantic').output_path (Path, or str, or None) – The destination path. If
None, the method calculates the default path (e.g.,image_name_semantic.png) in the same directory as the source image.
- Raises:
ValueError – If
mask_typeis invalid or if the mask data cannot be found (neither in memory nor on disk).OSError – If the file cannot be written (e.g., permission denied).
Examples
Create an
ImageAssetwith an in-memory dummy mask (10x10 numpy array):>>> import os >>> import numpy as np >>> from rapidtools.core import ImageAsset >>> from rapidtools.config import MaskType >>> >>> asset = ImageAsset( ... id='A1', ... path='temp_asset.jpg', ... allow_missing_file=True, ... ) >>> >>> mask_data = np.zeros((10, 10), dtype=np.uint8) >>> asset.set_mask(mask_data, MaskType.SEMANTIC)
Save the mask using the default naming convention:
>>> asset.save_mask('semantic') INFO: Saving semantic mask to temp_asset_semantic.png >>> print(os.path.exists('temp_asset_semantic.png')) True
Save to a specific custom path:
>>> asset.save_mask('semantic', output_path='custom_mask.png') INFO: Saving semantic mask to custom_mask.png
Remove the created files:
>>> for f in ['temp_asset_semantic.png', 'custom_mask.png']: ... if os.path.exists(f): os.remove(f)
- set_mask(data: ndarray, mask_type: MaskType, map_data: dict[int, Any] | None = None) None[source]#
Manually attaches a segmentation mask from memory.
Use this when you have generated a mask in code (e.g., model inference) instead of loading it from a file.
- Parameters:
data – The array containing the mask.
mask_type – Mask type, i.e.,
'semantic'or'instance'.map_data – Optional dictionary to update the class/instance mapping. If provided, it replaces the existing map for this asset.
- Raises:
TypeError – If
datais not a NumPy array.ValueError – If
mask_typeis not ‘semantic’ or ‘instance’.
Example
Setup a virtual asset and mock segmentation data (representing output from an AI model):
>>> import numpy as np >>> from rapidtools.core import ImageAsset >>> >>> asset = ImageAsset( ... id='img_01', ... path='virtual.jpg', ... allow_missing_file=True ... )
Create a dummy 10x10 mask where 1=Sky, 2=Grass:
>>> fake_mask = np.zeros((10, 10), dtype=np.uint8) >>> fake_mask[:5, :] = 1 # Top half is Sky >>> fake_mask[5:, :] = 2 # Bottom half is Grass
Define what the numbers mean (i.e., a segmentation map):
>>> labels = {1: 'Sky', 2: 'Grass'}
Attach the mask and the labels to the asset:
>>> asset.set_mask(fake_mask, 'semantic', map_data=labels) >>> print(asset.semantic_map) {1: 'Sky', 2: 'Grass'}
Verify the mask is cached and retrievable:
>>> retrieved = asset.load_mask('semantic') >>> print(retrieved.shape) (10, 10)
- show(output_type: Literal['image', 'semantic', 'instance', 'overlay_semantic', 'overlay_instance'] = 'image', alpha: float = 0.5, cmap: str | None = None) None[source]#
Show the asset in the system’s default image viewer.
- Parameters:
output_type (str) –
The type of visualization to generate. Options:
'image': Show raw image only.'semantic': Show semantic mask only (colored).'instance': Show instance mask only.'overlay_semantic': Image + Semantic Mask.'overlay_instance': Image + Instance Mask.
alpha (float) – Transparency of the mask in overlay modes (0.0 to 1.0), where 0 is fully transparent, 0.5 is 50% Transparent (see-through), and 1 is a solid color (blocks anything underneath it)
cmap (str, optional) – Matplotlib colormap name (e.g.,
'tab20','jet').
- Raises:
ValueError – If the provided
cmapis not a valid Matplotlib colormap name.OSError – If a mask file exists but cannot be opened (e.g., file corruption), as this method only catches
FileNotFoundErrorfor masks.
Examples
Create a dummy base image (100x100 gray square) and dummy semantic mask (inner square is class 1) and initialize an
ImageAssetwith this image and its mask:>>> import os >>> import numpy as np >>> from PIL import Image >>> from rapidtools.core import ImageAsset >>> from rapidtools.config import MaskType >>> >>> img_path = "temp_viz_test.jpg" >>> Image.new('RGB', (100, 100), color='gray').save(img_path) >>> >>> mask_path = "temp_viz_test_semantic.png" >>> mask_data = np.zeros((100, 100), dtype=np.uint8) >>> mask_data[25:75, 25:75] = 1 >>> Image.fromarray(mask_data).save(mask_path) >>> >>> asset = ImageAsset(id='viz_test', path=img_path)
View base image:
>>> asset.show(output_type='image') Loading image data from: temp_viz_test.jpg
View semantic mask:
>>> asset.show(output_type='semantic')
Overlay the semantic mask with custom settings:
>>> asset.show( ... output_type='overlay_semantic', ... alpha=0.3, ... cmap='viridis' ... )
Remove dummy image and mask files:
>>> os.remove(img_path) >>> os.remove(mask_path)
- summary() None[source]#
Print a human-readable summary of the image asset.
This method prints details including the asset’s ID, filename, path, status (downloaded/in-memory), file size (if available), and segmentation mask availability.
Example
>>> from rapidtools.core import ImageAsset >>> >>> img = ImageAsset( ... id='img_01', ... path='/tmp/photo.jpg', ... allow_missing_file=True ... ) >>> img.summary() --- ImageAsset Summary --- ID: img_01 Filename: photo.jpg Status: Missing (Virtual) Path: /tmp/photo.jpg Masks: Semantic [Not Loaded], Instance [Not Loaded] Properties (0): (No properties) --------------------------