We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Stop using dataclass for masks
Using `@dataclass` has proven to have more disadvantages than advantages, switching to normal classes should be very straight forward. 

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `icevision/core/mask.py`
Content:
```
1 __all__ = [
2     "Mask",
3     "MaskArray",
4     "MaskFile",
5     "VocMaskFile",
6     "RLE",
7     "Polygon",
8     "EncodedRLEs",
9 ]
10 
11 from icevision.imports import *
12 from icevision.utils import *
13 from PIL import Image
14 
15 
16 class Mask(ABC):
17     @abstractmethod
18     def to_mask(self, h, w) -> "MaskArray":
19         pass
20 
21     @abstractmethod
22     def to_erles(self, h, w) -> "EncodedRLEs":
23         pass
24 
25 
26 class EncodedRLEs(Mask):
27     def __init__(self, erles: List[dict] = None):
28         self.erles = erles or []
29 
30     def __repr__(self):
31         return f"<{self.__class__.__name__} with {len(self)} objects>"
32 
33     def __len__(self):
34         return len(self.erles)
35 
36     def __eq__(self, other):
37         if isinstance(other, self.__class__):
38             return self.erles == other.erles
39         return False
40 
41     def append(self, v: "EncodedRLEs"):
42         self.erles.extend(v.erles)
43 
44     def extend(self, v: List["EncodedRLEs"]):
45         for o in v:
46             self.append(o)
47 
48     def pop(self, i: int):
49         self.erles.pop(i)
50 
51     def to_mask(self, h, w) -> "MaskArray":
52         mask = mask_utils.decode(self.erles)
53         mask = mask.transpose(2, 0, 1)  # channels first
54         return MaskArray(mask)
55 
56     def to_erles(self, h, w) -> "EncodedRLEs":
57         return self
58 
59 
60 # TODO: Assert shape? (bs, height, width)
61 @dataclass
62 class MaskArray(Mask):
63     """Binary numpy array representation of a mask.
64 
65     (num_instances, height, width)
66     """
67 
68     data: np.ndarray
69 
70     def __post_init__(self):
71         self.data = self.data.astype(np.uint8)
72 
73     def __len__(self):
74         return len(self.data)
75 
76     def __getitem__(self, i):
77         return type(self)(self.data[i])
78 
79     def to_tensor(self):
80         return tensor(self.data, dtype=torch.uint8)
81 
82     def to_mask(self, h, w):
83         return self
84 
85     def to_erles(self, h, w) -> EncodedRLEs:
86         return EncodedRLEs(
87             mask_utils.encode(np.asfortranarray(self.data.transpose(1, 2, 0)))
88         )
89 
90     def to_coco_rle(self, h, w) -> List[dict]:
91         """From https://stackoverflow.com/a/49547872/6772672"""
92         assert self.data.shape[1:] == (h, w)
93         rles = []
94         for mask in self.data:
95             counts = []
96             flat = itertools.groupby(mask.ravel(order="F"))
97             for i, (value, elements) in enumerate(flat):
98                 if i == 0 and value == 1:
99                     counts.append(0)
100                 counts.append(len(list(elements)))
101             rles.append({"counts": counts, "size": (h, w)})
102         return rles
103 
104     @property
105     def shape(self):
106         return self.data.shape
107 
108     @classmethod
109     def from_masks(cls, masks: Union[EncodedRLEs, Sequence[Mask]], h: int, w: int):
110         # HACK: check for backwards compatibility
111         if isinstance(masks, EncodedRLEs):
112             return masks.to_mask(h, w)
113         else:
114             masks_arrays = [o.to_mask(h=h, w=w).data for o in masks]
115             return cls(np.concatenate(masks_arrays))
116 
117 
118 @dataclass
119 class MaskFile(Mask):
120     filepath: Union[str, Path]
121 
122     def __post_init__(self):
123         self.filepath = Path(self.filepath)
124 
125     def to_mask(self, h, w):
126         mask = open_img(self.filepath, gray=True)
127         obj_ids = np.unique(mask)[1:]
128         masks = mask == obj_ids[:, None, None]
129         return MaskArray(masks)
130 
131     def to_coco_rle(self, h, w) -> List[dict]:
132         return self.to_mask(h=h, w=w).to_coco_rle(h=h, w=w)
133 
134     def to_erles(self, h, w) -> EncodedRLEs:
135         return self.to_mask(h, w).to_erles(h, w)
136 
137 
138 @dataclass
139 class VocMaskFile(MaskFile):
140     """Extension of `MaskFile` for VOC masks.
141     Removes the color pallete and optionally drops void pixels.
142 
143     Args:
144           drop_void (bool): drops the void pixels, which should have the value 255.
145     """
146 
147     drop_void: bool = True
148 
149     def to_mask(self, h, w) -> MaskArray:
150         mask_arr = np.array(Image.open(self.filepath))
151         obj_ids = np.unique(mask_arr)[1:]
152         masks = mask_arr == obj_ids[:, None, None]
153 
154         if self.drop_void:
155             masks = masks[:-1, ...]
156 
157         return MaskArray(masks)
158 
159 
160 @dataclass(frozen=True)
161 class RLE(Mask):
162     counts: List[int]
163 
164     def to_mask(self, h, w) -> "MaskArray":
165         return self.to_erles(h=h, w=w).to_mask(h=h, w=w)
166         # Convert kaggle counts to mask
167         # "From https://www.kaggle.com/julienbeaulieu/imaterialist-detectron2"
168         # mask = np.full(h * w, 0, dtype=np.uint8)
169         # for start, ones in zip(self.counts[::2], self.counts[1::2]):
170         #     # counting starts on one
171         #     start -= 1
172         #     if ones:
173         #         mask[start : start + ones] = 1
174         # mask = mask.reshape((h, w), order="F")
175         # return MaskArray(mask)
176 
177     def to_coco(self) -> List[int]:
178         return self.counts
179 
180     def to_erles(self, h, w) -> EncodedRLEs:
181         return EncodedRLEs(
182             mask_utils.frPyObjects([{"counts": self.to_coco(), "size": [h, w]}], h, w)
183         )
184 
185     @classmethod
186     def from_string(cls, s, sep=" "):
187         return cls(lmap(int, s.split(sep)))
188 
189     @classmethod
190     def from_kaggle(cls, counts: Sequence[int]):
191         """Described [here](https://www.kaggle.com/c/imaterialist-fashion-2020-fgvc7/overview/evaluation)"""
192         if len(counts) % 2 != 0:
193             raise ValueError("Counts must be divisible by 2")
194 
195         current = 1
196         coco_counts = []
197         for start, count in zip(counts[::2], counts[1::2]):
198             coco_counts.append(start - current)  # zeros
199             coco_counts.append(count)  # ones
200             current = start + count
201 
202         # remove trailing zero
203         if coco_counts[-1] == 0:
204             coco_counts.pop(-1)
205 
206         return cls.from_coco(coco_counts)
207 
208     @classmethod
209     def from_coco(cls, counts: Sequence[int]):
210         """Described [here](https://stackoverflow.com/a/49547872/6772672)"""
211         return cls(counts)
212         # Convert from kaggle to coco
213         # when counts is odd, round it with 0 ones at the end
214         # if len(counts) % 2 != 0:
215         #     counts = counts + [0]
216         #
217         # kaggle_counts, total = [], 0
218         # for zeros, ones in zip(counts[::2], counts[1::2]):
219         #     start = zeros + total + 1
220         #     kaggle_counts.extend([start, ones])
221         #     total += zeros + ones
222         # return cls.from_kaggle(kaggle_counts)
223 
224 
225 @dataclass(frozen=True)
226 class Polygon(Mask):
227     points: List[List[int]]
228 
229     def to_mask(self, h, w):
230         return self.to_erles(h=h, w=w).to_mask(h=h, w=w)
231 
232     def to_erles(self, h, w) -> EncodedRLEs:
233         erles = mask_utils.frPyObjects(self.points, h, w)
234         erle = mask_utils.merge(erles)  # make unconnected polygons a single mask
235         return EncodedRLEs([erle])
236
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/icevision/core/mask.py b/icevision/core/mask.py
--- a/icevision/core/mask.py
+++ b/icevision/core/mask.py
@@ -58,17 +58,15 @@
 
 
 # TODO: Assert shape? (bs, height, width)
-@dataclass
 class MaskArray(Mask):
     """Binary numpy array representation of a mask.
 
-    (num_instances, height, width)
+    # Arguments
+        data: Mask array, with the dimensions: (num_instances, height, width)
     """
 
-    data: np.ndarray
-
-    def __post_init__(self):
-        self.data = self.data.astype(np.uint8)
+    def __init__(self, data: np.uint8):
+        self.data = data.astype(np.uint8)
 
     def __len__(self):
         return len(self.data)
@@ -115,12 +113,15 @@
             return cls(np.concatenate(masks_arrays))
 
 
-@dataclass
 class MaskFile(Mask):
-    filepath: Union[str, Path]
+    """Holds the path to mask image file.
+
+    # Arguments
+        filepath: Path to the mask image file.
+    """
 
-    def __post_init__(self):
-        self.filepath = Path(self.filepath)
+    def __init__(self, filepath: Union[str, Path]):
+        self.filepath = Path(filepath)
 
     def to_mask(self, h, w):
         mask = open_img(self.filepath, gray=True)
@@ -135,16 +136,18 @@
         return self.to_mask(h, w).to_erles(h, w)
 
 
-@dataclass
 class VocMaskFile(MaskFile):
     """Extension of `MaskFile` for VOC masks.
     Removes the color pallete and optionally drops void pixels.
 
-    Args:
-          drop_void (bool): drops the void pixels, which should have the value 255.
+    # Arguments
+        drop_void (bool): drops the void pixels, which should have the value 255.
+        filepath: Path to the mask image file.
     """
 
-    drop_void: bool = True
+    def __init__(self, filepath: Union[str, Path], drop_void: bool = True):
+        super().__init__(filepath=filepath)
+        self.drop_void = drop_void
 
     def to_mask(self, h, w) -> MaskArray:
         mask_arr = np.array(Image.open(self.filepath))
@@ -157,9 +160,15 @@
         return MaskArray(masks)
 
 
-@dataclass(frozen=True)
 class RLE(Mask):
-    counts: List[int]
+    """Run length encoding of a mask.
+
+    Don't instantiate this class directly, instead use the classmethods
+    `from_coco` and `from_kaggle`.
+    """
+
+    def __init__(self, counts: List[int]):
+        self.counts = counts
 
     def to_mask(self, h, w) -> "MaskArray":
         return self.to_erles(h=h, w=w).to_mask(h=h, w=w)
@@ -222,9 +231,15 @@
         # return cls.from_kaggle(kaggle_counts)
 
 
-@dataclass(frozen=True)
 class Polygon(Mask):
-    points: List[List[int]]
+    """Polygon representation of a mask
+
+    # Arguments
+        points: The vertices of the polygon in the COCO standard format.
+    """
+
+    def __init__(self, points: List[List[int]]):
+        self.points = points
 
     def to_mask(self, h, w):
         return self.to_erles(h=h, w=w).to_mask(h=h, w=w)

{"golden_diff": "diff --git a/icevision/core/mask.py b/icevision/core/mask.py\n--- a/icevision/core/mask.py\n+++ b/icevision/core/mask.py\n@@ -58,17 +58,15 @@\n \n \n # TODO: Assert shape? (bs, height, width)\n-@dataclass\n class MaskArray(Mask):\n     \"\"\"Binary numpy array representation of a mask.\n \n-    (num_instances, height, width)\n+    # Arguments\n+        data: Mask array, with the dimensions: (num_instances, height, width)\n     \"\"\"\n \n-    data: np.ndarray\n-\n-    def __post_init__(self):\n-        self.data = self.data.astype(np.uint8)\n+    def __init__(self, data: np.uint8):\n+        self.data = data.astype(np.uint8)\n \n     def __len__(self):\n         return len(self.data)\n@@ -115,12 +113,15 @@\n             return cls(np.concatenate(masks_arrays))\n \n \n-@dataclass\n class MaskFile(Mask):\n-    filepath: Union[str, Path]\n+    \"\"\"Holds the path to mask image file.\n+\n+    # Arguments\n+        filepath: Path to the mask image file.\n+    \"\"\"\n \n-    def __post_init__(self):\n-        self.filepath = Path(self.filepath)\n+    def __init__(self, filepath: Union[str, Path]):\n+        self.filepath = Path(filepath)\n \n     def to_mask(self, h, w):\n         mask = open_img(self.filepath, gray=True)\n@@ -135,16 +136,18 @@\n         return self.to_mask(h, w).to_erles(h, w)\n \n \n-@dataclass\n class VocMaskFile(MaskFile):\n     \"\"\"Extension of `MaskFile` for VOC masks.\n     Removes the color pallete and optionally drops void pixels.\n \n-    Args:\n-          drop_void (bool): drops the void pixels, which should have the value 255.\n+    # Arguments\n+        drop_void (bool): drops the void pixels, which should have the value 255.\n+        filepath: Path to the mask image file.\n     \"\"\"\n \n-    drop_void: bool = True\n+    def __init__(self, filepath: Union[str, Path], drop_void: bool = True):\n+        super().__init__(filepath=filepath)\n+        self.drop_void = drop_void\n \n     def to_mask(self, h, w) -> MaskArray:\n         mask_arr = np.array(Image.open(self.filepath))\n@@ -157,9 +160,15 @@\n         return MaskArray(masks)\n \n \n-@dataclass(frozen=True)\n class RLE(Mask):\n-    counts: List[int]\n+    \"\"\"Run length encoding of a mask.\n+\n+    Don't instantiate this class directly, instead use the classmethods\n+    `from_coco` and `from_kaggle`.\n+    \"\"\"\n+\n+    def __init__(self, counts: List[int]):\n+        self.counts = counts\n \n     def to_mask(self, h, w) -> \"MaskArray\":\n         return self.to_erles(h=h, w=w).to_mask(h=h, w=w)\n@@ -222,9 +231,15 @@\n         # return cls.from_kaggle(kaggle_counts)\n \n \n-@dataclass(frozen=True)\n class Polygon(Mask):\n-    points: List[List[int]]\n+    \"\"\"Polygon representation of a mask\n+\n+    # Arguments\n+        points: The vertices of the polygon in the COCO standard format.\n+    \"\"\"\n+\n+    def __init__(self, points: List[List[int]]):\n+        self.points = points\n \n     def to_mask(self, h, w):\n         return self.to_erles(h=h, w=w).to_mask(h=h, w=w)\n", "issue": "Stop using dataclass for masks\nUsing `@dataclass` has proven to have more disadvantages than advantages, switching to normal classes should be very straight forward. \n", "before_files": [{"content": "__all__ = [\n    \"Mask\",\n    \"MaskArray\",\n    \"MaskFile\",\n    \"VocMaskFile\",\n    \"RLE\",\n    \"Polygon\",\n    \"EncodedRLEs\",\n]\n\nfrom icevision.imports import *\nfrom icevision.utils import *\nfrom PIL import Image\n\n\nclass Mask(ABC):\n    @abstractmethod\n    def to_mask(self, h, w) -> \"MaskArray\":\n        pass\n\n    @abstractmethod\n    def to_erles(self, h, w) -> \"EncodedRLEs\":\n        pass\n\n\nclass EncodedRLEs(Mask):\n    def __init__(self, erles: List[dict] = None):\n        self.erles = erles or []\n\n    def __repr__(self):\n        return f\"<{self.__class__.__name__} with {len(self)} objects>\"\n\n    def __len__(self):\n        return len(self.erles)\n\n    def __eq__(self, other):\n        if isinstance(other, self.__class__):\n            return self.erles == other.erles\n        return False\n\n    def append(self, v: \"EncodedRLEs\"):\n        self.erles.extend(v.erles)\n\n    def extend(self, v: List[\"EncodedRLEs\"]):\n        for o in v:\n            self.append(o)\n\n    def pop(self, i: int):\n        self.erles.pop(i)\n\n    def to_mask(self, h, w) -> \"MaskArray\":\n        mask = mask_utils.decode(self.erles)\n        mask = mask.transpose(2, 0, 1)  # channels first\n        return MaskArray(mask)\n\n    def to_erles(self, h, w) -> \"EncodedRLEs\":\n        return self\n\n\n# TODO: Assert shape? (bs, height, width)\n@dataclass\nclass MaskArray(Mask):\n    \"\"\"Binary numpy array representation of a mask.\n\n    (num_instances, height, width)\n    \"\"\"\n\n    data: np.ndarray\n\n    def __post_init__(self):\n        self.data = self.data.astype(np.uint8)\n\n    def __len__(self):\n        return len(self.data)\n\n    def __getitem__(self, i):\n        return type(self)(self.data[i])\n\n    def to_tensor(self):\n        return tensor(self.data, dtype=torch.uint8)\n\n    def to_mask(self, h, w):\n        return self\n\n    def to_erles(self, h, w) -> EncodedRLEs:\n        return EncodedRLEs(\n            mask_utils.encode(np.asfortranarray(self.data.transpose(1, 2, 0)))\n        )\n\n    def to_coco_rle(self, h, w) -> List[dict]:\n        \"\"\"From https://stackoverflow.com/a/49547872/6772672\"\"\"\n        assert self.data.shape[1:] == (h, w)\n        rles = []\n        for mask in self.data:\n            counts = []\n            flat = itertools.groupby(mask.ravel(order=\"F\"))\n            for i, (value, elements) in enumerate(flat):\n                if i == 0 and value == 1:\n                    counts.append(0)\n                counts.append(len(list(elements)))\n            rles.append({\"counts\": counts, \"size\": (h, w)})\n        return rles\n\n    @property\n    def shape(self):\n        return self.data.shape\n\n    @classmethod\n    def from_masks(cls, masks: Union[EncodedRLEs, Sequence[Mask]], h: int, w: int):\n        # HACK: check for backwards compatibility\n        if isinstance(masks, EncodedRLEs):\n            return masks.to_mask(h, w)\n        else:\n            masks_arrays = [o.to_mask(h=h, w=w).data for o in masks]\n            return cls(np.concatenate(masks_arrays))\n\n\n@dataclass\nclass MaskFile(Mask):\n    filepath: Union[str, Path]\n\n    def __post_init__(self):\n        self.filepath = Path(self.filepath)\n\n    def to_mask(self, h, w):\n        mask = open_img(self.filepath, gray=True)\n        obj_ids = np.unique(mask)[1:]\n        masks = mask == obj_ids[:, None, None]\n        return MaskArray(masks)\n\n    def to_coco_rle(self, h, w) -> List[dict]:\n        return self.to_mask(h=h, w=w).to_coco_rle(h=h, w=w)\n\n    def to_erles(self, h, w) -> EncodedRLEs:\n        return self.to_mask(h, w).to_erles(h, w)\n\n\n@dataclass\nclass VocMaskFile(MaskFile):\n    \"\"\"Extension of `MaskFile` for VOC masks.\n    Removes the color pallete and optionally drops void pixels.\n\n    Args:\n          drop_void (bool): drops the void pixels, which should have the value 255.\n    \"\"\"\n\n    drop_void: bool = True\n\n    def to_mask(self, h, w) -> MaskArray:\n        mask_arr = np.array(Image.open(self.filepath))\n        obj_ids = np.unique(mask_arr)[1:]\n        masks = mask_arr == obj_ids[:, None, None]\n\n        if self.drop_void:\n            masks = masks[:-1, ...]\n\n        return MaskArray(masks)\n\n\n@dataclass(frozen=True)\nclass RLE(Mask):\n    counts: List[int]\n\n    def to_mask(self, h, w) -> \"MaskArray\":\n        return self.to_erles(h=h, w=w).to_mask(h=h, w=w)\n        # Convert kaggle counts to mask\n        # \"From https://www.kaggle.com/julienbeaulieu/imaterialist-detectron2\"\n        # mask = np.full(h * w, 0, dtype=np.uint8)\n        # for start, ones in zip(self.counts[::2], self.counts[1::2]):\n        #     # counting starts on one\n        #     start -= 1\n        #     if ones:\n        #         mask[start : start + ones] = 1\n        # mask = mask.reshape((h, w), order=\"F\")\n        # return MaskArray(mask)\n\n    def to_coco(self) -> List[int]:\n        return self.counts\n\n    def to_erles(self, h, w) -> EncodedRLEs:\n        return EncodedRLEs(\n            mask_utils.frPyObjects([{\"counts\": self.to_coco(), \"size\": [h, w]}], h, w)\n        )\n\n    @classmethod\n    def from_string(cls, s, sep=\" \"):\n        return cls(lmap(int, s.split(sep)))\n\n    @classmethod\n    def from_kaggle(cls, counts: Sequence[int]):\n        \"\"\"Described [here](https://www.kaggle.com/c/imaterialist-fashion-2020-fgvc7/overview/evaluation)\"\"\"\n        if len(counts) % 2 != 0:\n            raise ValueError(\"Counts must be divisible by 2\")\n\n        current = 1\n        coco_counts = []\n        for start, count in zip(counts[::2], counts[1::2]):\n            coco_counts.append(start - current)  # zeros\n            coco_counts.append(count)  # ones\n            current = start + count\n\n        # remove trailing zero\n        if coco_counts[-1] == 0:\n            coco_counts.pop(-1)\n\n        return cls.from_coco(coco_counts)\n\n    @classmethod\n    def from_coco(cls, counts: Sequence[int]):\n        \"\"\"Described [here](https://stackoverflow.com/a/49547872/6772672)\"\"\"\n        return cls(counts)\n        # Convert from kaggle to coco\n        # when counts is odd, round it with 0 ones at the end\n        # if len(counts) % 2 != 0:\n        #     counts = counts + [0]\n        #\n        # kaggle_counts, total = [], 0\n        # for zeros, ones in zip(counts[::2], counts[1::2]):\n        #     start = zeros + total + 1\n        #     kaggle_counts.extend([start, ones])\n        #     total += zeros + ones\n        # return cls.from_kaggle(kaggle_counts)\n\n\n@dataclass(frozen=True)\nclass Polygon(Mask):\n    points: List[List[int]]\n\n    def to_mask(self, h, w):\n        return self.to_erles(h=h, w=w).to_mask(h=h, w=w)\n\n    def to_erles(self, h, w) -> EncodedRLEs:\n        erles = mask_utils.frPyObjects(self.points, h, w)\n        erle = mask_utils.merge(erles)  # make unconnected polygons a single mask\n        return EncodedRLEs([erle])\n", "path": "icevision/core/mask.py"}], "after_files": [{"content": "__all__ = [\n    \"Mask\",\n    \"MaskArray\",\n    \"MaskFile\",\n    \"VocMaskFile\",\n    \"RLE\",\n    \"Polygon\",\n    \"EncodedRLEs\",\n]\n\nfrom icevision.imports import *\nfrom icevision.utils import *\nfrom PIL import Image\n\n\nclass Mask(ABC):\n    @abstractmethod\n    def to_mask(self, h, w) -> \"MaskArray\":\n        pass\n\n    @abstractmethod\n    def to_erles(self, h, w) -> \"EncodedRLEs\":\n        pass\n\n\nclass EncodedRLEs(Mask):\n    def __init__(self, erles: List[dict] = None):\n        self.erles = erles or []\n\n    def __repr__(self):\n        return f\"<{self.__class__.__name__} with {len(self)} objects>\"\n\n    def __len__(self):\n        return len(self.erles)\n\n    def __eq__(self, other):\n        if isinstance(other, self.__class__):\n            return self.erles == other.erles\n        return False\n\n    def append(self, v: \"EncodedRLEs\"):\n        self.erles.extend(v.erles)\n\n    def extend(self, v: List[\"EncodedRLEs\"]):\n        for o in v:\n            self.append(o)\n\n    def pop(self, i: int):\n        self.erles.pop(i)\n\n    def to_mask(self, h, w) -> \"MaskArray\":\n        mask = mask_utils.decode(self.erles)\n        mask = mask.transpose(2, 0, 1)  # channels first\n        return MaskArray(mask)\n\n    def to_erles(self, h, w) -> \"EncodedRLEs\":\n        return self\n\n\n# TODO: Assert shape? (bs, height, width)\nclass MaskArray(Mask):\n    \"\"\"Binary numpy array representation of a mask.\n\n    # Arguments\n        data: Mask array, with the dimensions: (num_instances, height, width)\n    \"\"\"\n\n    def __init__(self, data: np.uint8):\n        self.data = data.astype(np.uint8)\n\n    def __len__(self):\n        return len(self.data)\n\n    def __getitem__(self, i):\n        return type(self)(self.data[i])\n\n    def to_tensor(self):\n        return tensor(self.data, dtype=torch.uint8)\n\n    def to_mask(self, h, w):\n        return self\n\n    def to_erles(self, h, w) -> EncodedRLEs:\n        return EncodedRLEs(\n            mask_utils.encode(np.asfortranarray(self.data.transpose(1, 2, 0)))\n        )\n\n    def to_coco_rle(self, h, w) -> List[dict]:\n        \"\"\"From https://stackoverflow.com/a/49547872/6772672\"\"\"\n        assert self.data.shape[1:] == (h, w)\n        rles = []\n        for mask in self.data:\n            counts = []\n            flat = itertools.groupby(mask.ravel(order=\"F\"))\n            for i, (value, elements) in enumerate(flat):\n                if i == 0 and value == 1:\n                    counts.append(0)\n                counts.append(len(list(elements)))\n            rles.append({\"counts\": counts, \"size\": (h, w)})\n        return rles\n\n    @property\n    def shape(self):\n        return self.data.shape\n\n    @classmethod\n    def from_masks(cls, masks: Union[EncodedRLEs, Sequence[Mask]], h: int, w: int):\n        # HACK: check for backwards compatibility\n        if isinstance(masks, EncodedRLEs):\n            return masks.to_mask(h, w)\n        else:\n            masks_arrays = [o.to_mask(h=h, w=w).data for o in masks]\n            return cls(np.concatenate(masks_arrays))\n\n\nclass MaskFile(Mask):\n    \"\"\"Holds the path to mask image file.\n\n    # Arguments\n        filepath: Path to the mask image file.\n    \"\"\"\n\n    def __init__(self, filepath: Union[str, Path]):\n        self.filepath = Path(filepath)\n\n    def to_mask(self, h, w):\n        mask = open_img(self.filepath, gray=True)\n        obj_ids = np.unique(mask)[1:]\n        masks = mask == obj_ids[:, None, None]\n        return MaskArray(masks)\n\n    def to_coco_rle(self, h, w) -> List[dict]:\n        return self.to_mask(h=h, w=w).to_coco_rle(h=h, w=w)\n\n    def to_erles(self, h, w) -> EncodedRLEs:\n        return self.to_mask(h, w).to_erles(h, w)\n\n\nclass VocMaskFile(MaskFile):\n    \"\"\"Extension of `MaskFile` for VOC masks.\n    Removes the color pallete and optionally drops void pixels.\n\n    # Arguments\n        drop_void (bool): drops the void pixels, which should have the value 255.\n        filepath: Path to the mask image file.\n    \"\"\"\n\n    def __init__(self, filepath: Union[str, Path], drop_void: bool = True):\n        super().__init__(filepath=filepath)\n        self.drop_void = drop_void\n\n    def to_mask(self, h, w) -> MaskArray:\n        mask_arr = np.array(Image.open(self.filepath))\n        obj_ids = np.unique(mask_arr)[1:]\n        masks = mask_arr == obj_ids[:, None, None]\n\n        if self.drop_void:\n            masks = masks[:-1, ...]\n\n        return MaskArray(masks)\n\n\nclass RLE(Mask):\n    \"\"\"Run length encoding of a mask.\n\n    Don't instantiate this class directly, instead use the classmethods\n    `from_coco` and `from_kaggle`.\n    \"\"\"\n\n    def __init__(self, counts: List[int]):\n        self.counts = counts\n\n    def to_mask(self, h, w) -> \"MaskArray\":\n        return self.to_erles(h=h, w=w).to_mask(h=h, w=w)\n        # Convert kaggle counts to mask\n        # \"From https://www.kaggle.com/julienbeaulieu/imaterialist-detectron2\"\n        # mask = np.full(h * w, 0, dtype=np.uint8)\n        # for start, ones in zip(self.counts[::2], self.counts[1::2]):\n        #     # counting starts on one\n        #     start -= 1\n        #     if ones:\n        #         mask[start : start + ones] = 1\n        # mask = mask.reshape((h, w), order=\"F\")\n        # return MaskArray(mask)\n\n    def to_coco(self) -> List[int]:\n        return self.counts\n\n    def to_erles(self, h, w) -> EncodedRLEs:\n        return EncodedRLEs(\n            mask_utils.frPyObjects([{\"counts\": self.to_coco(), \"size\": [h, w]}], h, w)\n        )\n\n    @classmethod\n    def from_string(cls, s, sep=\" \"):\n        return cls(lmap(int, s.split(sep)))\n\n    @classmethod\n    def from_kaggle(cls, counts: Sequence[int]):\n        \"\"\"Described [here](https://www.kaggle.com/c/imaterialist-fashion-2020-fgvc7/overview/evaluation)\"\"\"\n        if len(counts) % 2 != 0:\n            raise ValueError(\"Counts must be divisible by 2\")\n\n        current = 1\n        coco_counts = []\n        for start, count in zip(counts[::2], counts[1::2]):\n            coco_counts.append(start - current)  # zeros\n            coco_counts.append(count)  # ones\n            current = start + count\n\n        # remove trailing zero\n        if coco_counts[-1] == 0:\n            coco_counts.pop(-1)\n\n        return cls.from_coco(coco_counts)\n\n    @classmethod\n    def from_coco(cls, counts: Sequence[int]):\n        \"\"\"Described [here](https://stackoverflow.com/a/49547872/6772672)\"\"\"\n        return cls(counts)\n        # Convert from kaggle to coco\n        # when counts is odd, round it with 0 ones at the end\n        # if len(counts) % 2 != 0:\n        #     counts = counts + [0]\n        #\n        # kaggle_counts, total = [], 0\n        # for zeros, ones in zip(counts[::2], counts[1::2]):\n        #     start = zeros + total + 1\n        #     kaggle_counts.extend([start, ones])\n        #     total += zeros + ones\n        # return cls.from_kaggle(kaggle_counts)\n\n\nclass Polygon(Mask):\n    \"\"\"Polygon representation of a mask\n\n    # Arguments\n        points: The vertices of the polygon in the COCO standard format.\n    \"\"\"\n\n    def __init__(self, points: List[List[int]]):\n        self.points = points\n\n    def to_mask(self, h, w):\n        return self.to_erles(h=h, w=w).to_mask(h=h, w=w)\n\n    def to_erles(self, h, w) -> EncodedRLEs:\n        erles = mask_utils.frPyObjects(self.points, h, w)\n        erle = mask_utils.merge(erles)  # make unconnected polygons a single mask\n        return EncodedRLEs([erle])\n", "path": "icevision/core/mask.py"}]}