Repository: Lightning-Universe/lightning-flash

Issue:
MasksRecordComponent does not exist in icevision
This line: 

https://github.com/PyTorchLightning/lightning-flash/blob/4f608b0b53a9b7004a71a6c0bcc4195ca4644008/flash/core/integrations/icevision/transforms.py#L34

is commented in:

https://github.com/airctic/icevision/blob/e5503f7fc7d0548dbc222494e436998aab4145e0/icevision/core/record_components.py#L453


Discussion:
Use `BaseMasksRecordComponent` can make the https://lightning-flash.readthedocs.io/en/stable/reference/object_detection.html example work. But I am not sure this will case other error in other case.
Hi @aisensiy thanks for reporting this. As IceVision is an unstable API I think we may need to pin our requirements to only support a specific version. It looks like they will make a release soon so maybe after that we should update and drop support for older versions. We could also perhaps add some testing with IceVision master so that we avoid bugs like this in future. What do you think? Interested to hear your thoughts :smiley: 

Resolving patch:
diff --git a/flash/core/integrations/icevision/transforms.py b/flash/core/integrations/icevision/transforms.py
--- a/flash/core/integrations/icevision/transforms.py
+++ b/flash/core/integrations/icevision/transforms.py
@@ -16,7 +16,7 @@
 from torch import nn
 
 from flash.core.data.io.input import DataKeys
-from flash.core.utilities.imports import _ICEVISION_AVAILABLE, requires
+from flash.core.utilities.imports import _ICEVISION_AVAILABLE, _ICEVISION_GREATER_EQUAL_0_11_0, requires
 
 if _ICEVISION_AVAILABLE:
     from icevision.core import tasks
@@ -31,12 +31,17 @@
         ImageRecordComponent,
         InstancesLabelsRecordComponent,
         KeyPointsRecordComponent,
-        MasksRecordComponent,
         RecordIDRecordComponent,
     )
     from icevision.data.prediction import Prediction
     from icevision.tfms import A
 
+if _ICEVISION_AVAILABLE and _ICEVISION_GREATER_EQUAL_0_11_0:
+    from icevision.core.mask import MaskFile
+    from icevision.core.record_components import InstanceMasksRecordComponent
+elif _ICEVISION_AVAILABLE:
+    from icevision.core.record_components import MasksRecordComponent
+
 
 def to_icevision_record(sample: Dict[str, Any]):
     record = BaseRecord([])
@@ -65,11 +70,28 @@ def to_icevision_record(sample: Dict[str, Any]):
         component.set_bboxes(bboxes)
         record.add_component(component)
 
-    if "masks" in sample[DataKeys.TARGET]:
-        mask_array = MaskArray(sample[DataKeys.TARGET]["masks"])
-        component = MasksRecordComponent()
-        component.set_masks(mask_array)
-        record.add_component(component)
+    if _ICEVISION_GREATER_EQUAL_0_11_0:
+        mask_array = sample[DataKeys.TARGET].get("mask_array", None)
+        masks = sample[DataKeys.TARGET].get("masks", None)
+
+        if mask_array is not None or masks is not None:
+            component = InstanceMasksRecordComponent()
+
+            if masks is not None:
+                masks = [MaskFile(mask) for mask in masks]
+                component.set_masks(masks)
+
+            if mask_array is not None:
+                mask_array = MaskArray(mask_array)
+                component.set_mask_array(mask_array)
+
+            record.add_component(component)
+    else:
+        mask_array = sample[DataKeys.TARGET].get("mask_array", None)
+        if mask_array is not None:
+            component = MasksRecordComponent()
+            component.set_masks(mask_array)
+            record.add_component(component)
 
     if "keypoints" in sample[DataKeys.TARGET]:
         keypoints = []
@@ -118,16 +140,26 @@ def from_icevision_detection(record: "BaseRecord"):
             for bbox in detection.bboxes
         ]
 
-    if hasattr(detection, "masks"):
-        masks = detection.masks
-
-        if isinstance(masks, EncodedRLEs):
-            masks = masks.to_mask(record.height, record.width)
+    mask_array = (
+        getattr(detection, "mask_array", None) if _ICEVISION_GREATER_EQUAL_0_11_0 else getattr(detection, "masks", None)
+    )
+    if mask_array is not None:
+        if isinstance(mask_array, EncodedRLEs):
+            mask_array = mask_array.to_mask(record.height, record.width)
 
-        if isinstance(masks, MaskArray):
-            result["masks"] = masks.data
+        if isinstance(mask_array, MaskArray):
+            result["mask_array"] = mask_array.data
         else:
-            raise RuntimeError("Masks are expected to be a MaskArray or EncodedRLEs.")
+            raise RuntimeError("Mask arrays are expected to be a MaskArray or EncodedRLEs.")
+
+    masks = getattr(detection, "masks", None)
+    if masks is not None and _ICEVISION_GREATER_EQUAL_0_11_0:
+        result["masks"] = []
+        for mask in masks:
+            if isinstance(mask, MaskFile):
+                result["masks"].append(mask.filepath)
+            else:
+                raise RuntimeError("Masks are expected to be MaskFile objects.")
 
     if hasattr(detection, "keypoints"):
         keypoints = detection.keypoints
diff --git a/flash/core/utilities/imports.py b/flash/core/utilities/imports.py
--- a/flash/core/utilities/imports.py
+++ b/flash/core/utilities/imports.py
@@ -121,6 +121,7 @@ class Image:
     _PL_GREATER_EQUAL_1_4_3 = _compare_version("pytorch_lightning", operator.ge, "1.4.3")
     _PL_GREATER_EQUAL_1_5_0 = _compare_version("pytorch_lightning", operator.ge, "1.5.0")
     _PANDAS_GREATER_EQUAL_1_3_0 = _compare_version("pandas", operator.ge, "1.3.0")
+    _ICEVISION_GREATER_EQUAL_0_11_0 = _compare_version("icevision", operator.ge, "0.11.0")
 
 _TEXT_AVAILABLE = all(
     [


Test patch: